Commit 7513d640 authored by Praetorius, Simon's avatar Praetorius, Simon
Browse files

Periodic BC implemented by Siqi Ling added to this branch

parent a877b6da
...@@ -1128,24 +1128,13 @@ namespace AMDiS { ...@@ -1128,24 +1128,13 @@ namespace AMDiS {
// === Write periodic associations. === // === Write periodic associations. ===
int mapSize = periodicAssociations.size(); int mapSize = periodicAssociations.size();
SerUtil::serialize(out, mapSize); SerUtil::serialize(out, mapSize);
for (map<BoundaryType, VertexVector*>::iterator it = periodicAssociations.begin(); for (map<BoundaryType, std::vector<VertexVector*> >::iterator it = periodicAssociations.begin();
it != periodicAssociations.end(); ++it) { it != periodicAssociations.end(); ++it) {
BoundaryType b = it->first; BoundaryType b = it->first;
// Check which DOFAdmin is used for the current VertexVector we want to serialize.
int ithAdmin = -1;
for (int i = 0; i < static_cast<int>(admin.size()); i++) {
if (admin[i] == it->second->getAdmin()) {
ithAdmin = i;
break;
}
}
TEST_EXIT(ithAdmin >= 0)
("No DOFAdmin found for serialization of periodic associations!\n");
SerUtil::serialize(out, b); SerUtil::serialize(out, b);
SerUtil::serialize(out, ithAdmin); for (int i = 0; i < size; i++)
it->second->serialize(out); (it->second)[i]->serialize(out);
} }
serializedDOFs.clear(); serializedDOFs.clear();
...@@ -1278,7 +1267,7 @@ namespace AMDiS { ...@@ -1278,7 +1267,7 @@ namespace AMDiS {
VertexVector *tmpvec = new VertexVector(admin[ithAdmin], ""); VertexVector *tmpvec = new VertexVector(admin[ithAdmin], "");
tmpvec->deserialize(in); tmpvec->deserialize(in);
periodicAssociations[b] = tmpvec; periodicAssociations[b].push_back(tmpvec);
} }
} }
...@@ -1514,38 +1503,55 @@ namespace AMDiS { ...@@ -1514,38 +1503,55 @@ namespace AMDiS {
#endif #endif
bool Mesh::associated(DegreeOfFreedom dof1, DegreeOfFreedom dof2) VertexVector& Mesh::getPeriodicAssociations(BoundaryType b, const DOFAdmin* admin)
{
FUNCNAME_DBG("Mesh::getPeriodicAssociations()");
TEST_EXIT_DBG(periodicAssociations.count(b) == 1)
("There are no periodic assoications for boundary type %d!\n", b);
return admin ? (*(periodicAssociations[b][getAdminIndex(admin)])) : (*(periodicAssociations[b][0]));
}
bool Mesh::associated(DegreeOfFreedom dof1, DegreeOfFreedom dof2, int iadmin)
{ {
map<BoundaryType, VertexVector*>::iterator it; FUNCNAME_DBG("Mesh::associated()");
map<BoundaryType, VertexVector*>::iterator end = periodicAssociations.end(); TEST_EXIT_DBG(iadmin < admin.size())("Wrong DOF admin index\n");
map<BoundaryType, std::vector<VertexVector*> >::iterator it;
map<BoundaryType, std::vector<VertexVector*> >::iterator end = periodicAssociations.end();
for (it = periodicAssociations.begin(); it != end; ++it) for (it = periodicAssociations.begin(); it != end; ++it)
if ((*(it->second))[dof1] == dof2) if ((*(it->second)[iadmin])[dof1] == dof2)
return true; return true;
return false; return false;
} }
bool Mesh::indirectlyAssociated(DegreeOfFreedom dof1, DegreeOfFreedom dof2) bool Mesh::indirectlyAssociated(DegreeOfFreedom dof1, DegreeOfFreedom dof2, int iadmin)
{ {
FUNCNAME_DBG("Mesh::indirectlyAssociated()");
TEST_EXIT_DBG(iadmin < admin.size())("Wrong DOF admin index\n");
vector<DegreeOfFreedom> associatedToDOF1; vector<DegreeOfFreedom> associatedToDOF1;
map<BoundaryType, VertexVector*>::iterator it; map<BoundaryType, std::vector<VertexVector*> >::iterator it;
map<BoundaryType, VertexVector*>::iterator end = periodicAssociations.end(); map<BoundaryType, std::vector<VertexVector*> >::iterator end = periodicAssociations.end();
DegreeOfFreedom dof, assDOF; DegreeOfFreedom dof, assDOF;
associatedToDOF1.push_back(dof1); associatedToDOF1.push_back(dof1);
for (it = periodicAssociations.begin(); it != end; ++it) { for (it = periodicAssociations.begin(); it != end; ++it) {
int size = static_cast<int>(associatedToDOF1.size()); int size = static_cast<int>(associatedToDOF1.size());
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
dof = associatedToDOF1[i]; dof = associatedToDOF1[i];
assDOF = (*(it->second))[dof]; assDOF = (*(it->second)[iadmin])[dof];
if (assDOF == dof2) { if (assDOF == dof2) {
return true; return true;
} else { } else {
if (assDOF != dof) if (assDOF != dof)
associatedToDOF1.push_back(assDOF); associatedToDOF1.push_back(assDOF);
} }
} }
} }
......
...@@ -192,6 +192,18 @@ namespace AMDiS { ...@@ -192,6 +192,18 @@ namespace AMDiS {
return *(admin[i]); return *(admin[i]);
} }
/// Returns the index of a given DOFMadmin pointer in the admin vector
inline int getAdminIndex(const DOFAdmin* dofAdmin) const
{
size_t i = 0;
for (; i < admin.size(); i++)
if (admin[i] == dofAdmin)
break;
TEST_EXIT_DBG(i < admin.size())("Wrong DOF admin index: %d\n", i);
return i;
}
/// Creates a DOFAdmin with name lname. nDof specifies how many DOFs /// Creates a DOFAdmin with name lname. nDof specifies how many DOFs
/// are needed at the different positions (see \ref DOFAdmin::nrDOF). /// are needed at the different positions (see \ref DOFAdmin::nrDOF).
/// A pointer to the created DOFAdmin is returned. /// A pointer to the created DOFAdmin is returned.
...@@ -549,25 +561,24 @@ namespace AMDiS { ...@@ -549,25 +561,24 @@ namespace AMDiS {
} }
/// ///
inline std::map<BoundaryType, VertexVector*>& getPeriodicAssociations() inline std::map<BoundaryType, std::vector<VertexVector*> >& getPeriodicAssociations()
{ {
return periodicAssociations; return periodicAssociations;
} }
/// Returns the periodic association for a specific boundary type. /// Returns the periodic association for a specific boundary type.
inline VertexVector& getPeriodicAssociations(BoundaryType b) VertexVector& getPeriodicAssociations(BoundaryType b, const DOFAdmin* admin = NULL);
{
FUNCNAME_DBG("Mesh::getPeriodicAssociations()");
TEST_EXIT_DBG(periodicAssociations.count(b) == 1)
("There are no periodic assoications for boundary type %d!\n", b);
return (*(periodicAssociations[b]));
}
inline void setPeriodicAssociations(BoundaryType b, VertexVector* vec) inline void setPeriodicAssociations(BoundaryType b, VertexVector* vec)
{ {
periodicAssociations[b] = vec; std::map<BoundaryType, std::vector<VertexVector*> >::iterator lb = periodicAssociations.lower_bound(b);
if (lb != periodicAssociations.end() && !periodicAssociations.key_comp()(b, lb->first)) {
lb->second.push_back(vec);
} else {
std::vector<VertexVector*> v;
v.push_back(vec);
periodicAssociations.insert(lb, std::make_pair(b, v));
}
} }
...@@ -579,10 +590,20 @@ namespace AMDiS { ...@@ -579,10 +590,20 @@ namespace AMDiS {
} }
/// ///
bool associated(DegreeOfFreedom dof1, DegreeOfFreedom dof2); bool associated(DegreeOfFreedom dof1, DegreeOfFreedom dof2, int iadmin = 0);
inline bool associated(DegreeOfFreedom dof1, DegreeOfFreedom dof2, const DOFAdmin* dofAdmin)
{
return associated(dof1, dof2, getAdminIndex(dofAdmin));
}
/// ///
bool indirectlyAssociated(DegreeOfFreedom dof1, DegreeOfFreedom dof2); bool indirectlyAssociated(DegreeOfFreedom dof1, DegreeOfFreedom dof2, int iadmin = 0);
inline bool indirectlyAssociated(DegreeOfFreedom dof1, DegreeOfFreedom dof2, const DOFAdmin* dofAdmin)
{
return indirectlyAssociated(dof1, dof2, getAdminIndex(dofAdmin));
}
/// Returns \macroFileInfo /// Returns \macroFileInfo
inline MacroInfo* getMacroFileInfo() inline MacroInfo* getMacroFileInfo()
...@@ -854,7 +875,7 @@ namespace AMDiS { ...@@ -854,7 +875,7 @@ namespace AMDiS {
bool initialized; bool initialized;
/// Map of managed periodic vertex associations. /// Map of managed periodic vertex associations.
std::map<BoundaryType, VertexVector*> periodicAssociations; std::map<BoundaryType, std::vector<VertexVector*> > periodicAssociations;
/// If the mesh has been created by reading a macro file, here the information /// If the mesh has been created by reading a macro file, here the information
/// are stored about the content of the file. /// are stored about the content of the file.
......
...@@ -106,13 +106,14 @@ namespace AMDiS { ...@@ -106,13 +106,14 @@ namespace AMDiS {
} }
PeriodicBC::PeriodicBC(BoundaryType type, const FiniteElemSpace *rowSpace) PeriodicBC::PeriodicBC(BoundaryType type, const FiniteElemSpace *rowSpace, bool diagonal)
: BoundaryCondition(type, rowSpace, NULL), : BoundaryCondition(type, rowSpace, NULL),
masterMatrix(NULL) masterMatrix(NULL),
isDiagonal(diagonal)
{ {
if (rowFeSpace->getMesh()->getDim() > 1) if (rowFeSpace->getMesh()->getDim() > 1)
periodicDOFMapping = periodicDOFMapping =
PeriodicDOFMapping::providePeriodicDOFMapping(rowFeSpace->getBasisFcts()); PeriodicDOFMapping::providePeriodicDOFMapping(rowFeSpace->getBasisFcts());
else else
periodicDOFMapping = NULL; periodicDOFMapping = NULL;
} }
...@@ -129,10 +130,10 @@ namespace AMDiS { ...@@ -129,10 +130,10 @@ namespace AMDiS {
if (!masterMatrix) { if (!masterMatrix) {
masterMatrix = matrix; masterMatrix = matrix;
Mesh *mesh = matrix->getRowFeSpace()->getMesh(); Mesh *mesh = matrix->getRowFeSpace()->getMesh();
associated = mesh->getPeriodicAssociations()[boundaryType]; associated = &(mesh->getPeriodicAssociations(boundaryType, rowFeSpace->getAdmin()));
TEST_EXIT(associated) TEST_EXIT(associated)
("No associations for periodic boundary condition %d!\n", boundaryType); ("No associations for periodic boundary condition %d!\n", boundaryType);
} }
} }
...@@ -153,6 +154,7 @@ namespace AMDiS { ...@@ -153,6 +154,7 @@ namespace AMDiS {
return; return;
DOFAdmin *admin = rowFeSpace->getAdmin(); DOFAdmin *admin = rowFeSpace->getAdmin();
int iadmin = rowFeSpace->getMesh()->getAdminIndex(admin);
FixVec<int, WORLD> elFace(dim, NO_INIT); FixVec<int, WORLD> elFace(dim, NO_INIT);
FixVec<int, WORLD> neighFace(dim, NO_INIT); FixVec<int, WORLD> neighFace(dim, NO_INIT);
DimVec<int> vertexPermutation(dim, NO_INIT); DimVec<int> vertexPermutation(dim, NO_INIT);
...@@ -186,7 +188,7 @@ namespace AMDiS { ...@@ -186,7 +188,7 @@ namespace AMDiS {
int j = 0; int j = 0;
for (; j < dim + 1; j++) for (; j < dim + 1; j++)
if (neigh->getDof(j, 0) == periodicDOF) if (neigh->getDof(j, iadmin) == periodicDOF)
break; break;
vertexPermutation[i] = j; vertexPermutation[i] = j;
...@@ -213,42 +215,71 @@ namespace AMDiS { ...@@ -213,42 +215,71 @@ namespace AMDiS {
FUNCNAME("PeriodicBC::exitMatrix()"); FUNCNAME("PeriodicBC::exitMatrix()");
TEST_EXIT(matrix)("No matrix\n"); TEST_EXIT(matrix)("No matrix\n");
TEST_EXIT(associated)("No associated vector!\n"); TEST_EXIT(associated)("No associated vector!\n");
if (matrix == masterMatrix) if (matrix == masterMatrix)
masterMatrix = NULL; masterMatrix = NULL;
using namespace mtl; using namespace mtl;
typedef DOFMatrix::base_matrix_type Matrix;
typedef mtl::traits::range_generator<mtl::tag::row, Matrix>::type c_type;
typedef mtl::traits::range_generator<mtl::tag::nz, c_type>::type ic_type;
DOFAdmin* admin = rowFeSpace->getAdmin(); DOFAdmin* admin = rowFeSpace->getAdmin();
std::vector<int> dofMap(admin->getUsedSize()); int adminSize = admin->getUsedSize();
for (int i = 0; i < admin->getUsedSize(); i++) Matrix &A= matrix->getBaseMatrix();
dofMap[i] = (*associated)[i];
mtl::traits::col<Matrix>::type c(A);
mtl::traits::value<Matrix>::type v(A);
std::vector<std::vector<std::pair<DegreeOfFreedom, double> > > row_values;
row_values.resize(adminSize);
// Compute reorder matrix (newRow and newCol yields transposed!!!) for (DegreeOfFreedom i = 0; i < adminSize; i++) {
matrix::traits::reorder<>::type R= matrix::reorder(dofMap); if (i < (*associated)[i]) {
DOFMatrix::base_matrix_type &A= matrix->getBaseMatrix(), C; c_type cursor(begin<mtl::tag::row>(A) + i);
C = R * A * trans(R) + A; for (ic_type icursor(begin<mtl::tag::nz>(cursor)), icend(end<mtl::tag::nz>(cursor));
A = 0.5 * C; icursor != icend; ++icursor) {
row_values[i].push_back(std::make_pair(c(*icursor), v(*icursor)));
v(*icursor, 0.0);
}
}
}
matrix::inserter<Matrix, update_plus<double> > ins(A);
if (isDiagonal) {
for (DegreeOfFreedom i = 0; i < adminSize; i++) {
if (i < (*associated)[i]) {
ins[i][i] << 1.0;
ins[i][(*associated)[i]] << -1.0;
}
}
}
for (DegreeOfFreedom i = 0; i < adminSize; i++) {
if (i < (*associated)[i]) {
for (size_t j = 0; j < row_values[i].size(); j++)
ins[(*associated)[i]][row_values[i][j].first] << row_values[i][j].second;
}
}
} }
void PeriodicBC::exitVector(DOFVectorBase<double>* vector) void PeriodicBC::exitVector(DOFVectorBase<double>* vector)
{ {
FUNCNAME("PeriodicBC::exitVector()");
TEST_EXIT(rowFeSpace == vector->getFeSpace())("Should not happen.\n");
DOFIterator<double> vecIt(vector, USED_DOFS); DOFIterator<double> vecIt(vector, USED_DOFS);
Mesh *mesh = vector->getFeSpace()->getMesh(); Mesh *mesh = vector->getFeSpace()->getMesh();
VertexVector *associated = mesh->getPeriodicAssociations()[boundaryType]; VertexVector *associated = &(mesh->getPeriodicAssociations(boundaryType, rowFeSpace->getAdmin()));
for (vecIt.reset(); !vecIt.end(); ++vecIt) { for (vecIt.reset(); !vecIt.end(); ++vecIt) {
DegreeOfFreedom dof = vecIt.getDOFIndex(); DegreeOfFreedom dof = vecIt.getDOFIndex();
DegreeOfFreedom newDOF = (*associated)[dof]; DegreeOfFreedom newDOF = (*associated)[dof];
if (dof < newDOF) { if (dof < newDOF) {
double entry = ((*vector)[dof] + (*vector)[newDOF]) * 0.5; (*vector)[newDOF] += (*vector)[dof];
(*vector)[dof] = entry; (*vector)[dof] = 0.0;
(*vector)[newDOF] = entry;
} }
} }
} }
......
...@@ -88,7 +88,7 @@ namespace AMDiS { ...@@ -88,7 +88,7 @@ namespace AMDiS {
{ {
public: public:
/// Constructor. /// Constructor.
PeriodicBC(BoundaryType type, const FiniteElemSpace *rowFeSpace); PeriodicBC(BoundaryType type, const FiniteElemSpace *rowFeSpace, bool diagonal);
~PeriodicBC(); ~PeriodicBC();
...@@ -116,6 +116,8 @@ namespace AMDiS { ...@@ -116,6 +116,8 @@ namespace AMDiS {
PeriodicDOFMapping *periodicDOFMapping; PeriodicDOFMapping *periodicDOFMapping;
DOFMatrix *masterMatrix; DOFMatrix *masterMatrix;
bool isDiagonal;
}; };
} }
......
...@@ -1549,7 +1549,7 @@ namespace AMDiS { ...@@ -1549,7 +1549,7 @@ namespace AMDiS {
void ProblemStatSeq::addPeriodicBC(BoundaryType type, int row, int col) void ProblemStatSeq::addPeriodicBC(BoundaryType type, int row, int col)
{ {
boundaryConditionSet = true; boundaryConditionSet = true;
PeriodicBC *periodic = new PeriodicBC(type, componentSpaces[row]); PeriodicBC *periodic = new PeriodicBC(type, componentSpaces[row], row == col);
if (systemMatrix && (*systemMatrix)[row][col]) if (systemMatrix && (*systemMatrix)[row][col])
(*systemMatrix)[row][col]->getBoundaryManager()->addBoundaryCondition(periodic); (*systemMatrix)[row][col]->getBoundaryManager()->addBoundaryCondition(periodic);
......
...@@ -74,9 +74,9 @@ namespace AMDiS { ...@@ -74,9 +74,9 @@ namespace AMDiS {
DegreeOfFreedom *last_edge[2] = {NULL, NULL}; DegreeOfFreedom *last_edge[2] = {NULL, NULL};
int n_neigh_periodic; int n_neigh_periodic;
DegreeOfFreedom newDOF = -1; DegreeOfFreedom *newDOF = NULL;
DegreeOfFreedom lastNewDOF = -1; DegreeOfFreedom *lastNewDOF = NULL;
DegreeOfFreedom firstNewDOF = -1; DegreeOfFreedom *firstNewDOF = NULL;
RCNeighbourList periodicList; RCNeighbourList periodicList;
...@@ -87,23 +87,25 @@ namespace AMDiS { ...@@ -87,23 +87,25 @@ namespace AMDiS {
newDOF = refinePatch(edge, periodicList, n_neigh_periodic, bound); newDOF = refinePatch(edge, periodicList, n_neigh_periodic, bound);
if (firstNewDOF == -1) if (firstNewDOF == NULL)
firstNewDOF = newDOF; firstNewDOF = newDOF;
if (lastNewDOF != -1) { if (lastNewDOF != NULL) {
for (std::map<int, VertexVector*>::iterator it = mesh->getPeriodicAssociations().begin(); for (std::map<int, std::vector<VertexVector*> >::iterator it = mesh->getPeriodicAssociations().begin();
it != mesh->getPeriodicAssociations().end(); ++it) { it != mesh->getPeriodicAssociations().end(); ++it) {
if (it->second) { if (!it->second.empty()) {
if (((*(it->second))[edge[0][0]] == last_edge[0][0] && for (size_t iadmin = 0; iadmin < mesh->getNumberOfDOFAdmin(); iadmin++) {
(*(it->second))[edge[1][0]] == last_edge[1][0]) || if (((*(it->second)[iadmin])[edge[0][iadmin]] == last_edge[0][iadmin] &&
((*(it->second))[edge[0][0]] == last_edge[1][0] && (*(it->second)[iadmin])[edge[1][iadmin]] == last_edge[1][iadmin]) ||
(*(it->second))[edge[1][0]] == last_edge[0][0])) { ((*(it->second[iadmin]))[edge[0][iadmin]] == last_edge[1][iadmin] &&
(*(it->second))[lastNewDOF] = newDOF; (*(it->second)[iadmin])[edge[1][iadmin]] == last_edge[0][iadmin])) {
(*(it->second))[newDOF] = lastNewDOF; (*(it->second)[iadmin])[lastNewDOF[iadmin]] = newDOF[iadmin];
} (*(it->second)[iadmin])[newDOF[iadmin]] = lastNewDOF[iadmin];
} }
} } // for
} } // if
} // for
} // if lastNewDOF
lastNewDOF = newDOF; lastNewDOF = newDOF;
last_edge[0] = edge[0]; last_edge[0] = edge[0];
...@@ -114,19 +116,21 @@ namespace AMDiS { ...@@ -114,19 +116,21 @@ namespace AMDiS {
} }
if (lastNewDOF != firstNewDOF) { if (lastNewDOF != firstNewDOF) {
for (std::map<int, VertexVector*>::iterator it = mesh->getPeriodicAssociations().begin(); for (std::map<int, std::vector<VertexVector*> >::iterator it = mesh->getPeriodicAssociations().begin();
it != mesh->getPeriodicAssociations().end(); ++it) { it != mesh->getPeriodicAssociations().end(); ++it) {
if (it->second) { if (!it->second.empty()) {
if (((*(it->second))[first_edge[0][0]] == last_edge[0][0] && for (size_t iadmin = 0; iadmin < mesh->getNumberOfDOFAdmin(); iadmin++) {
(*(it->second))[first_edge[1][0]] == last_edge[1][0]) || if (((*(it->second)[iadmin])[first_edge[0][iadmin]] == last_edge[0][iadmin] &&
((*(it->second))[first_edge[0][0]] == last_edge[1][0] && (*(it->second)[iadmin])[first_edge[1][iadmin]] == last_edge[1][iadmin]) ||
(*(it->second))[first_edge[1][0]] == last_edge[0][0])) { ((*(it->second)[iadmin])[first_edge[0][iadmin]] == last_edge[1][iadmin] &&
(*(it->second))[lastNewDOF] = firstNewDOF; (*(it->second)[iadmin])[first_edge[1][iadmin]] == last_edge[0][iadmin])) {
(*(it->second))[firstNewDOF] = lastNewDOF; (*(it->second)[iadmin])[lastNewDOF[iadmin]] = firstNewDOF[iadmin];
} (*(it->second)[iadmin])[firstNewDOF[iadmin]] = lastNewDOF[iadmin];
} }
} } // for
} } // if
} // for
} // if !=
return elInfo; return elInfo;
} }
...@@ -175,9 +179,9 @@ namespace AMDiS { ...@@ -175,9 +179,9 @@ namespace AMDiS {
} }
DegreeOfFreedom RefinementManager2d::refinePatch(DegreeOfFreedom *edge[2], DegreeOfFreedom* RefinementManager2d::refinePatch(DegreeOfFreedom *edge[2],
RCNeighbourList &refineList, RCNeighbourList &refineList,
int n_neigh, bool bound) int n_neigh, bool bound)
{ {
DegreeOfFreedom *dof[3] = {NULL, NULL, NULL}; DegreeOfFreedom *dof[3] = {NULL, NULL, NULL};
Triangle *el = Triangle *el =
...@@ -222,8 +226,8 @@ namespace AMDiS { ...@@ -222,8 +226,8 @@ namespace AMDiS {
DOFAdmin* admin = const_cast<DOFAdmin*>(&mesh->getDofAdmin(iadmin)); DOFAdmin* admin = const_cast<DOFAdmin*>(&mesh->getDofAdmin(iadmin));
std::list<DOFIndexedBase*>::iterator end = admin->endDOFIndexed(); std::list<DOFIndexedBase*>::iterator end = admin->endDOFIndexed();
for (std::list<DOFIndexedBase*>::iterator it = admin->beginDOFIndexed(); for (std::list<DOFIndexedBase*>::iterator it = admin->beginDOFIndexed();
it != end; it++) it != end; it++)
(*it)->refineInterpol(refineList, n_neigh); (*it)->refineInterpol(refineList, n_neigh);
} }