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

Fixed one billon bugs, and added even more features.

parent 2f1b3b77
...@@ -238,10 +238,10 @@ namespace AMDiS { ...@@ -238,10 +238,10 @@ namespace AMDiS {
if (condition->applyBoundaryCondition()) { if (condition->applyBoundaryCondition()) {
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS #ifdef HAVE_PARALLEL_DOMAIN_AMDIS
// if (dofMap->isRankDof(rowIndices[i])) { if (dofMap->isRankDof(rowIndices[i])) {
applyDBCs.insert(row); applyDBCs.insert(row);
// dirichletDofs.push_back(row); // dirichletDofs.push_back(row);
// } }
#else #else
applyDBCs.insert(row); applyDBCs.insert(row);
#endif #endif
...@@ -496,13 +496,13 @@ namespace AMDiS { ...@@ -496,13 +496,13 @@ namespace AMDiS {
// Do the following only in sequential code. In parallel mode, the specific // Do the following only in sequential code. In parallel mode, the specific
// solver method must care about dirichlet boundary conditions. // solver method must care about dirichlet boundary conditions.
#ifndef HAVE_PARALLEL_DOMAIN_AMDIS //#ifndef HAVE_PARALLEL_DOMAIN_AMDIS
inserter_type &ins = *inserter; inserter_type &ins = *inserter;
for (std::set<int>::iterator it = rows->begin(); it != rows->end(); ++it) for (std::set<int>::iterator it = rows->begin(); it != rows->end(); ++it)
ins[*it][*it] = 1.0; ins[*it][*it] = 1.0;
rows->clear(); rows->clear();
#endif //#endif
} }
......
...@@ -664,13 +664,13 @@ namespace AMDiS { ...@@ -664,13 +664,13 @@ namespace AMDiS {
std::vector<Operator*>::iterator it; std::vector<Operator*>::iterator it;
std::vector<double*>::iterator factorIt; std::vector<double*>::iterator factorIt;
for (it = this->operators.begin(), factorIt = this->operatorFactor.begin(); for (it = this->operators.begin(), factorIt = this->operatorFactor.begin();
it != this->operators.end(); it != this->operators.end();
++it, ++factorIt) ++it, ++factorIt)
if ((*it)->getNeedDualTraverse() == false) { if ((*it)->getNeedDualTraverse() == false) {
(*it)->getElementVector(elInfo, this->elementVector, (*it)->getElementVector(elInfo, this->elementVector,
*factorIt ? **factorIt : 1.0); *factorIt ? **factorIt : 1.0);
addVector = true; addVector = true;
} }
} }
......
...@@ -194,12 +194,10 @@ namespace AMDiS { ...@@ -194,12 +194,10 @@ namespace AMDiS {
Flag getAssembleFlag(); Flag getAssembleFlag();
/** \brief /// Evaluates \f[ u_h(x(\lambda)) = \sum_{i=0}^{m-1} vec[ind[i]] *
* Evaluates \f[ u_h(x(\lambda)) = \sum_{i=0}^{m-1} vec[ind[i]] * /// \varphi^i(\lambda) \f] where \f$ \varphi^i \f$ is the i-th basis
* \varphi^i(\lambda) \f] where \f$ \varphi^i \f$ is the i-th basis function, /// function, \f$ x(\lambda) \f$ are the world coordinates of lambda
* \f$ x(\lambda) \f$ are the world coordinates of lambda and /// and \f$ m \f$ is the number of basis functions
* \f$ m \f$ is the number of basis functions
*/
T evalUh(const DimVec<double>& lambda, DegreeOfFreedom* ind); T evalUh(const DimVec<double>& lambda, DegreeOfFreedom* ind);
inline vector<Operator*>& getOperators() inline vector<Operator*>& getOperators()
......
...@@ -142,7 +142,8 @@ namespace AMDiS { ...@@ -142,7 +142,8 @@ namespace AMDiS {
FUNCNAME("DOFVector::addElementVector()"); FUNCNAME("DOFVector::addElementVector()");
std::vector<DegreeOfFreedom> indices(nBasFcts); std::vector<DegreeOfFreedom> indices(nBasFcts);
feSpace->getBasisFcts()->getLocalIndices(elInfo->getElement(), feSpace->getAdmin(), feSpace->getBasisFcts()->getLocalIndices(elInfo->getElement(),
feSpace->getAdmin(),
indices); indices);
for (DegreeOfFreedom i = 0; i < nBasFcts; i++) { for (DegreeOfFreedom i = 0; i < nBasFcts; i++) {
...@@ -155,7 +156,7 @@ namespace AMDiS { ...@@ -155,7 +156,7 @@ namespace AMDiS {
if (add) if (add)
(*this)[irow] += factor * elVec[i]; (*this)[irow] += factor * elVec[i];
else else
(*this)[irow] = factor * elVec[i]; (*this)[irow] = factor * elVec[i];
} }
} }
} }
...@@ -1205,10 +1206,36 @@ namespace AMDiS { ...@@ -1205,10 +1206,36 @@ namespace AMDiS {
x.getFeSpace()->getAdmin(), result.getFeSpace()->getAdmin()); x.getFeSpace()->getAdmin(), result.getFeSpace()->getAdmin());
if (transpose == NoTranspose) if (transpose == NoTranspose) {
mult(a.getBaseMatrix(), x, result); mtl::dense_vector<T> tmp_x(x.getUsedSize());
else if (transpose == Transpose) mtl::dense_vector<T> tmp_result(result.getUsedSize());
mult(trans(const_cast<DOFMatrix::base_matrix_type&>(a.getBaseMatrix())), x, result);
{
int counter = 0;
typename DOFVector<T>::Iterator it(const_cast<DOFVector<T>*>(&x), USED_DOFS);
for (it.reset(); !it.end(); ++it)
tmp_x[counter++] = *it;
}
mult(a.getBaseMatrix(), tmp_x, tmp_result);
{
int counter = 0;
typename DOFVector<T>::Iterator it(&result, USED_DOFS);
for (it.reset(); !it.end(); ++it)
if (add)
*it += tmp_result[counter++];
else
*it = tmp_result[counter++];
}
} else if (transpose == Transpose) {
ERROR_EXIT("Not yet implemented!\n");
// mult(trans(const_cast<DOFMatrix::base_matrix_type&>(a.getBaseMatrix())),
// x, result);
}
else else
ERROR_EXIT("transpose = %d\n", transpose); ERROR_EXIT("transpose = %d\n", transpose);
} }
......
...@@ -78,15 +78,18 @@ namespace AMDiS { ...@@ -78,15 +78,18 @@ namespace AMDiS {
std::string filename); std::string filename);
/** \brief /** \brief
* Creates a vtu file where all elements in the mesh are colored by the global * Creates a vtu file where all elements in the mesh are colored by the
* element indices. * global element indices.
* *
* \param[in] feSpace The FE space to be used. * \param[in] feSpace The FE space to be used.
* \param[in] filename Name of the file. * \param[in] filename Name of the file.
* \param[in] level If level is -1, all leaf elements will be put to the * \param[in] level If level is -1, all leaf elements will be put to
* output file, otherwise the elements with the given level. * the output file, otherwise the elements with the
* given level.
*/ */
void writeElementIndexMesh(Mesh *mesh, std::string filename, int level = -1); void writeElementIndexMesh(Mesh *mesh,
std::string filename,
int level = -1);
void highlightElementIndexMesh(Mesh *mesh, int idx, std::string filename); void highlightElementIndexMesh(Mesh *mesh, int idx, std::string filename);
......
...@@ -65,7 +65,7 @@ namespace AMDiS { ...@@ -65,7 +65,7 @@ namespace AMDiS {
for (int i = 0; i < nBasFcts; i++) { for (int i = 0; i < nBasFcts; i++) {
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS #ifdef HAVE_PARALLEL_DOMAIN_AMDIS
// if (vector->isRankDof(dofIndices[i])) if (vector->isRankDof(dofIndices[i]))
#endif #endif
if (localBound[i] == boundaryType) { if (localBound[i] == boundaryType) {
double value = 0.0; double value = 0.0;
...@@ -76,11 +76,11 @@ namespace AMDiS { ...@@ -76,11 +76,11 @@ namespace AMDiS {
if (dofVec) if (dofVec)
value = (*dofVec)[dofIndices[i]]; value = (*dofVec)[dofIndices[i]];
#ifdef HAVE_PARALLEL_DOMAIN_AMDIS // #ifdef HAVE_PARALLEL_DOMAIN_AMDIS
vector->setDirichletDofValue(dofIndices[i], value); // vector->setDirichletDofValue(dofIndices[i], value);
#else // #else
(*vector)[dofIndices[i]] = value; (*vector)[dofIndices[i]] = value;
#endif //#endif
} }
} }
} }
......
...@@ -37,13 +37,11 @@ namespace AMDiS { ...@@ -37,13 +37,11 @@ namespace AMDiS {
class FirstOrderAssembler : public SubAssembler class FirstOrderAssembler : public SubAssembler
{ {
public: public:
/** \brief /// Creates and returns the FirstOrderAssembler for Operator op and
* Creates and returns the FirstOrderAssembler for Operator op and /// the given assembler. If all terms are piecewise constant precalculated
* the given assembler. If all terms are piecewise constant precalculated /// integrals can be used while assembling and the returned
* integrals can be used while assembling and the returned /// ZeroOrderAssembler is of type Pre0. Otherwise a Quad0 object will
* ZeroOrderAssembler is of type Pre0. Otherwise a Quad0 object will /// be returned.
* be returned.
*/
static FirstOrderAssembler* getSubAssembler(Operator *op, static FirstOrderAssembler* getSubAssembler(Operator *op,
Assembler *assembler, Assembler *assembler,
Quadrature *quadrat, Quadrature *quadrat,
......
...@@ -76,10 +76,8 @@ namespace AMDiS { ...@@ -76,10 +76,8 @@ namespace AMDiS {
} }
protected: protected:
/** \brief /// Evaluation of \f$ \Lambda \cdot b\f$ if b contains the value 1.0
* Evaluation of \f$ \Lambda \cdot b\f$ if b contains the value 1.0 in /// in each component.
* each component.
*/
inline void l1(const DimVec<WorldVector<double> >& Lambda, inline void l1(const DimVec<WorldVector<double> >& Lambda,
mtl::dense_vector<double>& Lb, mtl::dense_vector<double>& Lb,
double factor) const double factor) const
......
...@@ -100,10 +100,8 @@ namespace AMDiS { ...@@ -100,10 +100,8 @@ namespace AMDiS {
/// Adds a SecondOrderTerm to the Operator /// Adds a SecondOrderTerm to the Operator
void addTerm(SecondOrderTerm *term); void addTerm(SecondOrderTerm *term);
/** \brief /// Calculates the element matrix for this ElInfo and adds it multiplied by
* Calculates the element matrix for this ElInfo and adds it multiplied by /// factor to userMat.
* factor to userMat.
*/
virtual void getElementMatrix(const ElInfo *elInfo, virtual void getElementMatrix(const ElInfo *elInfo,
ElementMatrix& userMat, ElementMatrix& userMat,
double factor = 1.0); double factor = 1.0);
...@@ -116,10 +114,8 @@ namespace AMDiS { ...@@ -116,10 +114,8 @@ namespace AMDiS {
ElementMatrix& userMat, ElementMatrix& userMat,
double factor = 1.0); double factor = 1.0);
/** \brief /// Calculates the element vector for this ElInfo and adds it multiplied by
* Calculates the element vector for this ElInfo and adds it multiplied by /// factor to userVec.
* factor to userVec.
*/
virtual void getElementVector(const ElInfo *elInfo, virtual void getElementVector(const ElInfo *elInfo,
ElementVector& userVec, ElementVector& userVec,
double factor = 1.0); double factor = 1.0);
......
...@@ -107,10 +107,8 @@ namespace AMDiS { ...@@ -107,10 +107,8 @@ namespace AMDiS {
mtl::dense_vector<double>& result, mtl::dense_vector<double>& result,
double factor) = 0; double factor) = 0;
/** \brief /// Determines the value of a dof vector at the quadrature points of a given
* Determines the value of a dof vector at the quadrature points of a given /// element. It is used by all VecAtQP like operator terms.
* element. It is used by all VecAtQP like operator terms.
*/
template<typename T> template<typename T>
void getVectorAtQPs(DOFVectorBase<T>* vec, void getVectorAtQPs(DOFVectorBase<T>* vec,
const ElInfo* elInfo, const ElInfo* elInfo,
...@@ -118,12 +116,11 @@ namespace AMDiS { ...@@ -118,12 +116,11 @@ namespace AMDiS {
Quadrature *quad, Quadrature *quad,
mtl::dense_vector<T>& vecAtQPs); mtl::dense_vector<T>& vecAtQPs);
/** \brief /// Determines the value of a dof vector at the quadrature points of a given
* Determines the value of a dof vector at the quadrature points of a given /// element. This function is used, if an operator is assembled on two
* element. This function is used, if an operator is assembled on two different /// different meshes using the dual traverse. The element, i.e. the small or
* meshes using the dual traverse. The element, i.e. the small or the large one, /// the large one, is choosen, which corresponds to the mesh the dof vector
* is choosen, which corresponds to the mesh the dof vector is defined on. /// is defined on.
*/
template<typename T> template<typename T>
void getVectorAtQPs(DOFVectorBase<T>* vec, void getVectorAtQPs(DOFVectorBase<T>* vec,
const ElInfo* smallElInfo, const ElInfo* smallElInfo,
...@@ -165,13 +162,11 @@ namespace AMDiS { ...@@ -165,13 +162,11 @@ namespace AMDiS {
/// Pointer to the Operator this OperatorTerm belongs to. /// Pointer to the Operator this OperatorTerm belongs to.
Operator* operat; Operator* operat;
/** \brief /// In many cases, the vector b in the evaluation \f$ \Lambda \cdot b\f$ has
* In many cases, the vector b in the evaluation \f$ \Lambda \cdot b\f$ has zeros /// zeros in all components expect one that is set to one. Using the function
* in all components expect one that is set to one. Using the function \ref lb is /// \ref lb is then unnecessary time consuming. Instead, this variable
* then unnecessary time consuming. Instead, this variable defines the component /// defines the component of the vector b to be one. The function \ref lb_one
* of the vector b to be one. The function \ref lb_one is used if this variable is /// is used if this variable is not -1.
* not -1.
*/
int bOne; int bOne;
/// Flag for piecewise constant terms /// Flag for piecewise constant terms
......
...@@ -1674,7 +1674,13 @@ namespace AMDiS { ...@@ -1674,7 +1674,13 @@ namespace AMDiS {
// == private matrix and vector to the global one. == // == private matrix and vector to the global one. ==
if (matrix) if (matrix)
matrix->removeRowsWithDBC(matrix->getApplyDBCs()); matrix->removeRowsWithDBC(matrix->getApplyDBCs());
if (matrix)
matrix->finishAssembling();
if (vector)
vector->finishAssembling();
if (useGetBound) if (useGetBound)
delete [] bound; delete [] bound;
......
...@@ -74,7 +74,6 @@ namespace AMDiS { ...@@ -74,7 +74,6 @@ namespace AMDiS {
cachedValuesAtQPs[vec]->valid = true; cachedValuesAtQPs[vec]->valid = true;
cachedValuesAtQPs[vec]->quad = localQuad; cachedValuesAtQPs[vec]->quad = localQuad;
vecAtQPs = values; vecAtQPs = values;
} }
......
...@@ -367,8 +367,7 @@ namespace AMDiS { ...@@ -367,8 +367,7 @@ namespace AMDiS {
bool add = false) bool add = false)
{ {
FUNCNAME("mv()"); FUNCNAME("mv()");
TEST_EXIT(false)("This function is not supported any more.\n");
#if 0
int size = x.getNumVectors(); int size = x.getNumVectors();
int i; int i;
...@@ -388,7 +387,6 @@ namespace AMDiS { ...@@ -388,7 +387,6 @@ namespace AMDiS {
*(result.getDOFVector(i)), *(result.getDOFVector(i)),
true); true);
} }
#endif
} }
/// y = a*x + y; /// y = a*x + y;
......
...@@ -45,10 +45,12 @@ namespace AMDiS { ...@@ -45,10 +45,12 @@ namespace AMDiS {
} }
} else { } else {
degree = uh_->getFeSpace()->getBasisFcts()->getDegree() + 1; degree = uh_->getFeSpace()->getBasisFcts()->getDegree() + 1;
feSpace = FiniteElemSpace::provideFeSpace(NULL, feSpace =
Lagrange::getLagrange(uh_->getFeSpace()->getMesh()->getDim(), degree), FiniteElemSpace::provideFeSpace(NULL,
uh_->getFeSpace()->getMesh(), Lagrange::getLagrange(uh_->getFeSpace()->getMesh()->getDim(),
name + "->feSpace"); degree),
uh_->getFeSpace()->getMesh(),
name + "->feSpace");
if (method == 2) { if (method == 2) {
ERROR("Simple averaging only for the H1_NORM; using SPR instead\n"); ERROR("Simple averaging only for the H1_NORM; using SPR instead\n");
......
...@@ -340,7 +340,7 @@ namespace AMDiS { ...@@ -340,7 +340,7 @@ namespace AMDiS {
int method = 1; int method = 1;
double tol = 1.e-6; double tol = 1.e-6;
int maxit = 10; int maxit = 1000;
int ndecrmax = 30; int ndecrmax = 30;
int num_iter = 0; int num_iter = 0;
int converged_reason = 0; int converged_reason = 0;
......
...@@ -222,7 +222,7 @@ namespace AMDiS { ...@@ -222,7 +222,7 @@ namespace AMDiS {
bound.neighObj.ithObj = perEdgeEl1.ithObject; bound.neighObj.ithObj = perEdgeEl1.ithObject;
bound.type = it->second; bound.type = it->second;
AtomicBoundary& b = getNewPeriodic(otherElementRank); AtomicBoundary& b = getNewPeriodic(otherElementRank);
b = bound; b = bound;
......
...@@ -1209,11 +1209,14 @@ namespace AMDiS { ...@@ -1209,11 +1209,14 @@ namespace AMDiS {
void MeshDistributor::repartitionMesh() void MeshDistributor::repartitionMesh()
{ {
FUNCNAME("MeshDistributor::repartitionMesh()"); FUNCNAME("MeshDistributor::repartitionMesh()");
// === First we check if the rank with the maximum number of DOFs has at === // === First we check if the rank with the maximum number of DOFs has at ===
// === least 20% more DOFs than the rank with the minimum number of DOFs. === // === least 20% more DOFs than the rank with the minimum number of DOFs. ===
// === In this case, the mesh will be repartition. === // === In this case, the mesh will be repartition. ===
double inbalanceFactor = 1.2;
Parameters::get("parallel->repartitioning->inbalance", inbalanceFactor);
int repartitioning = 0; int repartitioning = 0;
vector<int> nDofsInRank(mpiSize); vector<int> nDofsInRank(mpiSize);
int nDofs = mesh->getDofAdmin(0).getUsedDofs(); int nDofs = mesh->getDofAdmin(0).getUsedDofs();
...@@ -1232,7 +1235,8 @@ namespace AMDiS { ...@@ -1232,7 +1235,8 @@ namespace AMDiS {
MSG("Overall DOFs: %d Min DOFs: %d Max DOFs: %d\n", MSG("Overall DOFs: %d Min DOFs: %d Max DOFs: %d\n",
nOverallDofs, minDofs, maxDofs); nOverallDofs, minDofs, maxDofs);
if (static_cast<double>(maxDofs) / static_cast<double>(minDofs) > 1.2) if (static_cast<double>(maxDofs) / static_cast<double>(minDofs) >
inbalanceFactor)
repartitioning = 1; repartitioning = 1;
mpiComm.Bcast(&repartitioning, 1, MPI_INT, 0); mpiComm.Bcast(&repartitioning, 1, MPI_INT, 0);
...@@ -1245,13 +1249,18 @@ namespace AMDiS { ...@@ -1245,13 +1249,18 @@ namespace AMDiS {
double timePoint = MPI::Wtime(); double timePoint = MPI::Wtime();
#if (DEBUG != 0) #if (DEBUG != 0)
ParallelDebug::testDoubleDofs(mesh); ParallelDebug::testDoubleDofs(mesh);
int writePartMesh = 1;
if (repartitioningCounter == 0) #else
int writePartMesh = 0;
#endif
Parameters::get("dbg->write part mesh", writePartMesh);
if (writePartMesh > 0 && repartitioningCounter == 0)
ParallelDebug::writePartitioningFile(debugOutputDir + "partitioning", ParallelDebug::writePartitioningFile(debugOutputDir + "partitioning",
repartitioningCounter, feSpaces[0]); repartitioningCounter, feSpaces[0]);
#endif
repartitioningCounter++; repartitioningCounter++;
// === Create new element weights. === // === Create new element weights. ===
...@@ -1696,6 +1705,10 @@ namespace AMDiS { ...@@ -1696,6 +1705,10 @@ namespace AMDiS {
ParallelDebug::testCommonDofs(*this, true); ParallelDebug::testCommonDofs(*this, true);
ParallelDebug::testGlobalIndexByCoords(*this); ParallelDebug::testGlobalIndexByCoords(*this);
#else #else
for (unsigned int i = 0; i < feSpaces.size(); i++)
MSG("FE space %d: nRankDofs = %d nOverallDofs = %d\n",
i, dofMap[feSpaces[i]].nRankDofs, dofMap[feSpaces[i]].nOverallDofs);
int tmp = 0; int tmp = 0;
Parameters::get(name + "->write parallel debug file", tmp); Parameters::get(name + "->write parallel debug file", tmp);
if (tmp) if (tmp)
...@@ -1816,7 +1829,7 @@ namespace AMDiS { ...@@ -1816,7 +1829,7 @@ namespace AMDiS {
for (unsigned int i = 0; i < (dofs.size() - nDofs); i++) for (unsigned int i = 0; i < (dofs.size() - nDofs); i++)
rankToDofType[it->first].push_back(boundIt->type); rankToDofType[it->first].push_back(boundIt->type);
} }
// Send the global indices to the rank on the other side. // Send the global indices to the rank on the other side.
stdMpi.getSendData(it->first).reserve(dofs.size()); stdMpi.getSendData(it->first).reserve(dofs.size());
for (unsigned int i = 0; i < dofs.size(); i++) for (unsigned int i = 0; i < dofs.size(); i++)
......
...@@ -17,6 +17,26 @@ namespace AMDiS { ...@@ -17,6 +17,26 @@ namespace AMDiS {
using namespace std; using namespace std;
void DofToMatIndex::getReverse(int rowIndex, int &component, int &dofIndex)
{
FUNCNAME("DofToMatIndex::getReverse()");
for (map<int, map<DegreeOfFreedom, int> >::iterator it0 = data.begin();
it0 != data.end(); ++it0)
for (map<DegreeOfFreedom, int>::iterator it1 = it0->second.begin();
it1 != it0->second.end(); ++it1)
if (it1->second == rowIndex) {
component = it0->first;
dofIndex = it1->first;
return;
}
component = -1;