Commit c096fbb7 authored by Thomas Witkowski's avatar Thomas Witkowski
Browse files

Work on pdd

parent deafc91a
...@@ -14,7 +14,6 @@ ...@@ -14,7 +14,6 @@
#include "BoundaryCondition.h" #include "BoundaryCondition.h"
#include "BoundaryManager.h" #include "BoundaryManager.h"
#include "Assembler.h" #include "Assembler.h"
#include "Utilities.h"
namespace AMDiS { namespace AMDiS {
......
...@@ -276,6 +276,10 @@ namespace AMDiS { ...@@ -276,6 +276,10 @@ namespace AMDiS {
void ParallelDomainProblemBase::createInteriorBoundaryInfo(std::vector<const DegreeOfFreedom*>& rankDOFs, void ParallelDomainProblemBase::createInteriorBoundaryInfo(std::vector<const DegreeOfFreedom*>& rankDOFs,
std::map<const DegreeOfFreedom*, int>& boundaryDOFs) std::map<const DegreeOfFreedom*, int>& boundaryDOFs)
{ {
FUNCNAME("ParallelDomainProblemBase::createInteriorBoundaryInfo()");
// === First, create all the information about the interior boundaries. ===
TraverseStack stack; TraverseStack stack;
ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_NEIGH); ElInfo *elInfo = stack.traverseFirst(mesh, -1, Mesh::CALL_LEAF_EL | Mesh::FILL_NEIGH);
while (elInfo) { while (elInfo) {
...@@ -323,20 +327,86 @@ namespace AMDiS { ...@@ -323,20 +327,86 @@ namespace AMDiS {
/// === And add the part of the interior boundary. === /// === And add the part of the interior boundary. ===
AtomicBoundary& bound = AtomicBoundary& bound =
interiorBoundary.getNewAtomicBoundary(ranksBoundary ? mpiRank : (ranksBoundary ?
partitionVec[elInfo->getNeighbour(i)->getIndex()]); myIntBoundary.getNewAtomicBoundary(partitionVec[elInfo->getNeighbour(i)->getIndex()]) :
otherIntBoundary.getNewAtomicBoundary(partitionVec[elInfo->getNeighbour(i)->getIndex()]));
bound.rankObject.el = element; bound.rankObject.el = element;
bound.rankObject.subObjAtBoundary = EDGE; bound.rankObject.subObjAtBoundary = EDGE;
bound.rankObject.ithObjAtBoundary = i; bound.rankObject.ithObjAtBoundary = i;
bound.neighbourObject.el = elInfo->getNeighbour(i); bound.neighbourObject.el = elInfo->getNeighbour(i);
bound.neighbourObject.subObjAtBoundary = EDGE; bound.neighbourObject.subObjAtBoundary = EDGE;
bound.neighbourObject.ithObjAtBoundary = -1; bound.neighbourObject.ithObjAtBoundary = -1;
std::cout << "ADD IN " << mpiRank << ": " << element->getIndex() << " " << elInfo->getNeighbour(i)->getIndex() << std::endl;
} }
} }
} }
elInfo = stack.traverseNext(elInfo); elInfo = stack.traverseNext(elInfo);
} }
// === Once we have this information, we must care about their order. Eventually ===
// === all the boundaries have to be in the same order on both ranks (because ===
// === each boundary is shared by exactly two ranks). ===
std::vector<int*> sendBuffers;
std::vector<int*> recvBuffers;
for (std::map<int, std::vector<AtomicBoundary> >::iterator rankIt = myIntBoundary.boundary.begin();
rankIt != myIntBoundary.boundary.end();
++rankIt) {
int* buffer = new int[rankIt->second.size()];
for (int i = 0; i < static_cast<int>(rankIt->second.size()); i++)
buffer[i] = (rankIt->second)[i].rankObject.el->getIndex();
sendBuffers.push_back(buffer);
mpiComm.Isend(buffer, rankIt->second.size(), MPI_INT, rankIt->first, 0);
}
for (std::map<int, std::vector<AtomicBoundary> >::iterator rankIt = otherIntBoundary.boundary.begin();
rankIt != otherIntBoundary.boundary.end();
++rankIt) {
int *buffer = new int[rankIt->second.size()];
recvBuffers.push_back(buffer);
mpiComm.Irecv(buffer, rankIt->second.size(), MPI_INT, rankIt->first, 0);
}
mpiComm.Barrier();
int i = 0;
for (std::map<int, std::vector<AtomicBoundary> >::iterator rankIt = otherIntBoundary.boundary.begin();
rankIt != otherIntBoundary.boundary.end();
++rankIt) {
// === We have received from rank "rankIt->first" the ordered list of element ===
// === indices. We now have to sort the corresponding list in this rank to ===
// === get the same order. ===
for (int j = 0; j < static_cast<int>(rankIt->second.size()); j++) {
// If the expected object is not at place, search for it.
if ((rankIt->second)[j].neighbourObject.el->getIndex() != recvBuffers[i][j]) {
int k = j + 1;
for (; k < static_cast<int>(rankIt->second.size()); k++)
if ((rankIt->second)[k].neighbourObject.el->getIndex() == recvBuffers[i][j])
break;
// The element must always be found, because the list is just in another order.
TEST_EXIT(k < rankIt->second.size())("Should never happen!\n");
// Swap the current with the found element.
AtomicBoundary tmpBound = (rankIt->second)[k];
(rankIt->second)[k] = (rankIt->second)[j];
(rankIt->second)[j] = tmpBound;
}
}
delete [] recvBuffers[i++];
}
for (int i = 0; i < static_cast<int>(sendBuffers.size()); i++)
delete [] sendBuffers[i];
} }
...@@ -527,8 +597,10 @@ namespace AMDiS { ...@@ -527,8 +597,10 @@ namespace AMDiS {
void ParallelDomainProblemBase::updateLocalGlobalNumbering(int& nRankDOFs, void ParallelDomainProblemBase::updateLocalGlobalNumbering(int& nRankDOFs,
int& nOverallDOFs) int& nOverallDOFs)
{ {
FUNCNAME("ParallelDomainProblemBase::updateLocalGlobalNumbering()");
std::set<const DegreeOfFreedom*> rankDOFs; std::set<const DegreeOfFreedom*> rankDOFs;
std::set<const DegreeOfFreedom*> boundaryDOFs; std::map<const DegreeOfFreedom*, int> boundaryDOFs;
/// === Get all DOFs in ranks partition. === /// === Get all DOFs in ranks partition. ===
...@@ -545,20 +617,105 @@ namespace AMDiS { ...@@ -545,20 +617,105 @@ namespace AMDiS {
} }
// === Traverse on interior boundaries and move all not ranked owned DOFs from // === Traverse on interior boundaries and move all not ranked owned DOFs from ===
// rankDOFs to boundaryDOFs === // // === rankDOFs to boundaryDOFs ===
for (std::map<int, std::vector<AtomicBoundary> >::iterator it = for (std::map<int, std::vector<AtomicBoundary> >::iterator it =
interiorBoundary.boundary.begin(); myIntBoundary.boundary.begin();
it != interiorBoundary.boundary.end(); it != myIntBoundary.boundary.end();
++it) { ++it) {
for (int i = 0; i < it->second.size(); i++) { for (std::vector<AtomicBoundary>::iterator boundIt = it->second.begin();
boundIt != it->second.end();
++boundIt) {
const DegreeOfFreedom *dof1 = NULL;
const DegreeOfFreedom *dof2 = NULL;
switch (boundIt->rankObject.ithObjAtBoundary) {
case 0:
dof1 = boundIt->rankObject.el->getDOF(1);
dof2 = boundIt->rankObject.el->getDOF(2);
break;
case 1:
dof1 = boundIt->rankObject.el->getDOF(0);
dof2 = boundIt->rankObject.el->getDOF(2);
break;
case 2:
dof1 = boundIt->rankObject.el->getDOF(0);
dof2 = boundIt->rankObject.el->getDOF(1);
break;
default:
ERROR_EXIT("Should never happen!\n");
}
std::vector<const DegreeOfFreedom*> boundDOFs;
addAllDOFs(boundIt->rankObject.el, boundIt->rankObject.ithObjAtBoundary,
boundDOFs);
} }
} }
} }
void ParallelDomainProblemBase::addAllDOFs(Element *el, int ithEdge,
std::vector<const DegreeOfFreedom*>& dofs,
bool addVertices)
{
FUNCNAME("ParallelDomainProblemBase::addAllDOFs()");
const DegreeOfFreedom* boundDOF1 = NULL;
const DegreeOfFreedom* boundDOF2 = NULL;
if (addVertices) {
switch (ithEdge) {
case 0:
boundDOF1 = el->getDOF(1);
boundDOF2 = el->getDOF(2);
break;
case 1:
boundDOF1 = el->getDOF(0);
boundDOF2 = el->getDOF(2);
break;
case 2:
boundDOF1 = el->getDOF(0);
boundDOF2 = el->getDOF(1);
break;
default:
ERROR_EXIT("Should never happen!\n");
}
dofs.push_back(boundDOF1);
}
switch (ithEdge) {
case 0:
if (el->getSecondChild() && el->getSecondChild()->getFirstChild()) {
addAllDOFs(el->getSecondChild()->getFirstChild(), 0, dofs, false);
dofs.push_back(el->getSecondChild()->getFirstChild()->getDOF(2));
addAllDOFs(el->getSecondChild()->getSecondChild(), 1, dofs, false);
}
break;
case 1:
if (el->getFirstChild() && el->getFirstChild()->getFirstChild()) {
addAllDOFs(el->getFirstChild()->getFirstChild(), 0, dofs, false);
dofs.push_back(el->getFirstChild()->getFirstChild()->getDOF(2));
addAllDOFs(el->getFirstChild()->getSecondChild(), 1, dofs, false);
}
break;
case 2:
if (el->getFirstChild()) {
addAllDOFs(el->getFirstChild(), 0, dofs, false);
dofs.push_back(el->getFirstChild()->getDOF(2));
addAllDOFs(el->getSecondChild(), 1, dofs, false);
}
break;
default:
ERROR_EXIT("Should never happen!\n");
}
if (addVertices)
dofs.push_back(boundDOF2);
}
void ParallelDomainProblemBase::createDOFMemberInfo( void ParallelDomainProblemBase::createDOFMemberInfo(
std::map<const DegreeOfFreedom*, std::set<int> >& partitionDOFs, std::map<const DegreeOfFreedom*, std::set<int> >& partitionDOFs,
std::vector<const DegreeOfFreedom*>& rankDOFs, std::vector<const DegreeOfFreedom*>& rankDOFs,
......
...@@ -137,9 +137,15 @@ namespace AMDiS { ...@@ -137,9 +137,15 @@ namespace AMDiS {
void updateLocalGlobalNumbering(int& nRankDOFs, int& nOverallDOFs); void updateLocalGlobalNumbering(int& nRankDOFs, int& nOverallDOFs);
void addAllDOFs(Element *el, int ithEdge,
std::vector<const DegreeOfFreedom*>& dofs,
bool addVertices = true);
/** \brief /** \brief
* This function traverses the whole mesh, i.e. before it is really partitioned, * This function traverses the whole mesh, i.e. before it is really partitioned,
* and collects information about which DOF corresponds to which rank. * and collects information about which DOF corresponds to which rank. Can only
* be used, if \ref partitionVec is set correctly. This is only the case, when
* the macro mesh is partitioned.
* *
* @param[out] partionDOFs Stores to each DOF pointer the set of ranks the DOF is * @param[out] partionDOFs Stores to each DOF pointer the set of ranks the DOF is
* part of. * part of.
...@@ -215,10 +221,20 @@ namespace AMDiS { ...@@ -215,10 +221,20 @@ namespace AMDiS {
int nRankDOFs; int nRankDOFs;
/** \brief /** \brief
* Defines the interioir boundaries of the domain that result from partitioning * Defines the interior boundaries of the domain that result from partitioning
* the whole mesh. * the whole mesh. Contains only the boundaries, which are owned by the rank, i.e.,
* the object gives for every neighbour rank i the boundaries this rank owns and
* shares with rank i.
*/
InteriorBoundary myIntBoundary;
/** \brief
* Defines the interior boundaries of the domain that result from partitioning
* the whole mesh. Contains only the boundaries, which are not owned by the rank,
* i.e., the object gives for every neighbour rank i the boundaries that are
* owned by rank i and are shared with this rank.
*/ */
InteriorBoundary interiorBoundary; InteriorBoundary otherIntBoundary;
/** \brief /** \brief
* This map contains for each rank the list of dofs the current rank must send * This map contains for each rank the list of dofs the current rank must send
......
...@@ -51,7 +51,8 @@ namespace AMDiS { ...@@ -51,7 +51,8 @@ namespace AMDiS {
/** \brief /** \brief
* Returns a new UmfPackSolver object. * Returns a new UmfPackSolver object.
*/ */
OEMSolver* create() { OEMSolver* create()
{
return new UmfPackSolver(this->name); return new UmfPackSolver(this->name);
} }
}; };
...@@ -67,7 +68,11 @@ namespace AMDiS { ...@@ -67,7 +68,11 @@ namespace AMDiS {
} }
/// Destructor /// Destructor
~UmfPackSolver() { if (solver) delete solver;} ~UmfPackSolver()
{
if (solver)
delete solver;
}
/// Solves the system directly /// Solves the system directly
int solveSystem(const DOFMatrix::base_matrix_type& A, int solveSystem(const DOFMatrix::base_matrix_type& A,
......
// ============================================================================
// == ==
// == AMDiS - Adaptive multidimensional simulations ==
// == ==
// ============================================================================
// == ==
// == crystal growth group ==
// == ==
// == Stiftung caesar ==
// == Ludwig-Erhard-Allee 2 ==
// == 53175 Bonn ==
// == germany ==
// == ==
// ============================================================================
// == ==
// == http://www.caesar.de/cg/AMDiS ==
// == ==
// ============================================================================
/** \file Utilities.h */
#ifndef AMDIS_UTILITIES_H
#define AMDIS_UTILITIES_H
#include <vector>
#include <algorithm>
template <typename T>
std::vector<T> inline invert_reorder(const std::vector<T>& v)
{
T my_max= *std::max_element(v.begin(), v.end()) + 1;
std::vector<T> u(my_max, T(-1));
for (int i= 0; i < v.size(); i++)
if (v[i] >= 0) {
assert(u[v[i]] == -1); // check double insertion
u[v[i]]= T(i);
}
assert(find(u.begin(), u.end(), T(-1)) == u.end()); // check if all entries are set
return u;
}
#endif // AMDIS_UTILITIES_H
...@@ -29,18 +29,10 @@ ...@@ -29,18 +29,10 @@
#include "Flag.h" #include "Flag.h"
#include "Mesh.h" #include "Mesh.h"
#include "DataCollector.h" #include "DataCollector.h"
#include "AMDiS_fwd.h"
namespace AMDiS { namespace AMDiS {
class DOFAdmin;
class ElInfo;
template<typename T> class DOFVector;
// ============================================================================
// ===== class ValueWriter ====================================================
// ============================================================================
/** \ingroup Output /** \ingroup Output
* \brief * \brief
* ValueWriter is a static class which writes the values of a DOFVector * ValueWriter is a static class which writes the values of a DOFVector
...@@ -53,9 +45,7 @@ namespace AMDiS { ...@@ -53,9 +45,7 @@ namespace AMDiS {
class ValueWriter class ValueWriter
{ {
public: public:
/** \brief /// Writes DOFVector values to values->feSpace->mesh.
* Writes DOFVector values to values->feSpace->mesh.
*/
static void writeValues(DataCollector *dc, static void writeValues(DataCollector *dc,
const std::string filename, const std::string filename,
double time = 0.0, double time = 0.0,
...@@ -64,34 +54,22 @@ namespace AMDiS { ...@@ -64,34 +54,22 @@ namespace AMDiS {
bool (*writeElem)(ElInfo*) = NULL); bool (*writeElem)(ElInfo*) = NULL);
protected: protected:
/** \brief /// File to which the values should be written
* File to which the values should be written
*/
static FILE *valueFile; static FILE *valueFile;
/** \brief /// Global interpolation point indexing
* Global interpolation point indexing
*/
static DOFVector<int> *interpPointInd; static DOFVector<int> *interpPointInd;
/** \brief /// list of coords for each dof
* list of coords for each dof
*/
static DOFVector< std::list<WorldVector<double> > > *dofCoords; static DOFVector< std::list<WorldVector<double> > > *dofCoords;
/** \brief /// DOFAdmin of values
* DOFAdmin of values
*/
static const DOFAdmin *admin; static const DOFAdmin *admin;
/** \brief /// Pointer to have a global access to values
* Pointer to have a global access to values
*/
static DOFVector<double> *valueVec; static DOFVector<double> *valueVec;
/** \brief /// Total number of interpolation points.
* Total number of interpolation points.
*/
static int ni; static int ni;
}; };
......
...@@ -26,35 +26,27 @@ ...@@ -26,35 +26,27 @@
namespace AMDiS { namespace AMDiS {
/** \brief /// Stores coordinates and output index for one vertex.
* Stores coordinates and output index for one vertex.
*/
class VertexInfo class VertexInfo
{ {
public: public:
/** \brief /// Coordinates for this vertex.
* Coordinates for this vertex.
*/
WorldVector<double> coords; WorldVector<double> coords;
/** \brief /// Index for the output file.
* Index for the output file.
*/
int outputIndex; int outputIndex;
/** \brief /// Used to check, whether coords are already stored for a given dof.
* Used to check, whether coords are already stored for a given dof. bool operator==(const WorldVector<double>& c)
*/ {
bool operator==(const WorldVector<double>& c) {
return (c == coords); return (c == coords);
}; }
/** \brief /// Used to check, whether coords are already stored for a given dof.
* Used to check, whether coords are already stored for a given dof. bool operator!=(const WorldVector<double>& c)
*/ {
bool operator!=(const WorldVector<double>& c) {
return (c != coords); return (c != coords);
}; }
}; };
} }
......
...@@ -21,24 +21,27 @@ namespace AMDiS { ...@@ -21,24 +21,27 @@ namespace AMDiS {
~VertexVector(); ~VertexVector();
const DOFAdmin *getAdmin() { return admin; }; const DOFAdmin *getAdmin()
{
return admin;
}
void resize(int size) { void resize(int size)
int i, oldSize = static_cast<int>(vec.size()); {
int oldSize = static_cast<int>(vec.size());
vec.resize(size); vec.resize(size);
for(i = oldSize; i < size; i++) { for (int i = oldSize; i < size; i++)
vec[i] = i; vec[i] = i;
}
} }
void set(DegreeOfFreedom val); void set(DegreeOfFreedom val);
void compressDOFContainer(int size, std::vector<DegreeOfFreedom> &newDOF) { void compressDOFContainer(int size, std::vector<DegreeOfFreedom> &newDOF)
{
DOFContainer::compressDOFContainer(size, newDOF); DOFContainer::compressDOFContainer(size, newDOF);
int totalSize = getAdmin()->getSize(); int totalSize = getAdmin()->getSize();
for(int i = size; i < totalSize; i++) { for(int i = size; i < totalSize; i++)
vec[i] = i; vec[i] = i;
}
} }
protected: protected:
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment