#include <algorithm> #include "QPsiPhi.h" #include "BasisFunction.h" #include "Boundary.h" #include "DOFAdmin.h" #include "ElInfo.h" #include "Error.h" #include "FiniteElemSpace.h" #include "Mesh.h" #include "DOFVector.h" #include "DOFIterator.h" #include "Serializer.h" namespace AMDiS { const int DOFAdmin::sizeIncrement = 10; DOFAdmin::DOFAdmin(Mesh* m) : mesh(m), nrDOF(mesh->getDim(), NO_INIT), nr0DOF(mesh->getDim(), NO_INIT) { init(); } DOFAdmin::DOFAdmin(Mesh* m, std::string aName) : name(aName), mesh(m), nrDOF(mesh->getDim(), NO_INIT), nr0DOF(mesh->getDim(), NO_INIT) { init(); } DOFAdmin::~DOFAdmin() {} void DOFAdmin::init() { firstHole = 0; size = 0; usedCount = 0; holeCount = 0; sizeUsed = 0; dofFree.clear(); } DOFAdmin& DOFAdmin::operator=(const DOFAdmin& src) { if (this != &src) { mesh = src.mesh; name = src.name; dofFree = src.dofFree; firstHole = src.firstHole; size = src.size; usedCount = src.usedCount; holeCount = src.holeCount; sizeUsed = src.sizeUsed; for (int i = 0; i <= mesh->getDim(); i++) { nrDOF[i] = src.nrDOF[i]; nr0DOF[i] = src.nr0DOF[i]; } dofIndexedList = src.dofIndexedList; dofContainerList = src.dofContainerList; } return *this; } /****************************************************************************/ /* use a bit vector to indicate used/unused dofs */ /* storage needed: one bit per dof */ /****************************************************************************/ bool DOFAdmin::operator==(const DOFAdmin& ad) const { if (name != ad.name) return false; if (mesh != ad.mesh) return false; return true; } DOFAdmin::DOFAdmin(const DOFAdmin&) { FUNCNAME("DOFAdmin::DOFAdmin()"); ERROR_EXIT("TODO\n"); } void DOFAdmin::freeDOFIndex(int dof) { FUNCNAME("DOFAdmin::freeDOFIndex()"); TEST_EXIT_DBG(usedCount > 0)("no dofs in use\n"); TEST_EXIT_DBG((dof >= 0) && (dof < size))("invalid dof index %d\n",dof); std::list<DOFIndexedBase*>::iterator di; std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end(); for (di = dofIndexedList.begin(); di != end; ++di) (*di)->freeDOFContent(dof); std::list<DOFContainer*>::iterator dc; std::list<DOFContainer*>::iterator dcend = dofContainerList.end(); for (dc = dofContainerList.begin(); dc != dcend; ++dc) (*dc)->freeDOFIndex(dof); dofFree[dof] = true; if (static_cast<int>(firstHole) > dof) firstHole = dof; usedCount--; holeCount++; } int DOFAdmin::getDOFIndex() { FUNCNAME("DOFAdmin::getDOFIndex()"); int dof = 0; // if there is a hole if (firstHole < static_cast<int>(dofFree.size())) { TEST_EXIT_DBG(dofFree[firstHole])("no hole at firstHole!\n"); // its no longer a hole dofFree[firstHole] = false; dof = firstHole; // search new hole int dfsize = static_cast<int>(dofFree.size()); int i = firstHole + 1; for (; i < dfsize; i++) if (dofFree[i]) break; firstHole = i; } else { // if there is no hole // enlarge dof-list enlargeDOFLists(); TEST_EXIT_DBG(firstHole < static_cast<int>(dofFree.size())) ("no free entry after enlargeDOFLists\n"); TEST_EXIT_DBG(dofFree[firstHole])("no free bit at firstHole\n"); dofFree[firstHole] = false; dof = firstHole; firstHole++; } usedCount++; if (holeCount > 0) holeCount--; sizeUsed = max(sizeUsed, dof + 1); return dof; } void DOFAdmin::enlargeDOFLists(int minsize) { FUNCNAME("DOFAdmin::enlargeDOFLists()"); int old = size; if (minsize > 0) if (old > minsize) return; int newval = max(minsize, static_cast<int>((dofFree.size() + sizeIncrement))); size = newval; // stl resizes dofFree to at least newval and sets all new values true dofFree.resize(newval, true); firstHole = old; // enlarge all vectors and matrices // but DOFVectors<int> don't have to be changed std::list<DOFIndexedBase*>::iterator di; for (di = dofIndexedList.begin(); di != dofIndexedList.end(); ++di) if ((*di)->getSize() < newval) (*di)->resize(newval); } void DOFAdmin::addDOFIndexed(DOFIndexedBase* dofIndexed) { FUNCNAME("DOFAdmin::addDOFIndexed()"); TEST_EXIT(dofIndexed)("no dofIndexed\n"); #ifdef _OPENMP #pragma omp critical (dofIndexAccess) #endif { if (dofIndexed->getSize() < size) dofIndexed->resize(size); dofIndexedList.push_back(dofIndexed); } } void DOFAdmin::removeDOFIndexed(DOFIndexedBase* dofIndexed) { FUNCNAME("DOFAdmin::removeDOFIndexed()"); bool removed = false; #ifdef _OPENMP #pragma omp critical (dofIndexAccess) #endif { std::list<DOFIndexedBase*>::iterator it; std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end(); for (it = dofIndexedList.begin(); it != end; ++it) { if (*it == dofIndexed) { dofIndexedList.erase(it); removed = true; break; } } } TEST_EXIT(removed)("DOFIndexed not in list\n"); } void DOFAdmin::addDOFContainer(DOFContainer* cont) { FUNCNAME("DOFAdmin::addDOFContainer()"); TEST_EXIT_DBG(cont)("no container\n"); dofContainerList.push_back(cont); } void DOFAdmin::removeDOFContainer(DOFContainer* cont) { FUNCNAME("DOFAdmin::removeDOFContainer()"); std::list<DOFContainer*>::iterator it; std::list<DOFContainer*>::iterator end = dofContainerList.end(); for (it = dofContainerList.begin(); it != end; ++it) { if (*it == cont) { dofContainerList.erase(it); return; } } ERROR("container not in list\n"); } void DOFAdmin::compress(std::vector<DegreeOfFreedom> &new_dof) { FUNCNAME("DOFAdmin::compress()"); // nothing to do ? if (size < 1) return; if (usedCount < 1) return; if (holeCount < 1) return; // vector to mark used dofs for (int i = 0; i < size; i++) new_dof[i] = -1; // mark used dofs DOFIteratorBase it(this, USED_DOFS); for (it.reset(); !it.end(); ++it) new_dof[it.getDOFIndex()] = 1; int n = 0, last = 0; for (int i = 0; i < size; i++) { /* create a MONOTONE compress */ if (new_dof[i] == 1) { new_dof[i] = n++; last = i; } } TEST_EXIT_DBG(n == usedCount)("count %d != usedCount %d\n", n, usedCount); // mark used dofs in compressed dofFree for (int i = 0; i < n; i++) dofFree[i] = false; // mark unused dofs in compressed dofFree for (int i = n; i < size; i++) dofFree[i] = true; firstHole = n; holeCount = 0; sizeUsed = n; // get index of first changed dof int first = last; for (int i = 0; i<size; i++) { if ((new_dof[i] < i) && (new_dof[i] >= 0)) { first = i; break; } } std::list<DOFIndexedBase*>::iterator di; std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end(); for (di = dofIndexedList.begin(); di != end; ++di) (*di)->compressDOFIndexed(first, last, new_dof); std::list<DOFContainer*>::iterator dc; std::list<DOFContainer*>::iterator endc = dofContainerList.end(); for (dc = dofContainerList.begin(); dc != endc; dc++) (*dc)->compressDOFContainer(n, new_dof); } void DOFAdmin::setNumberOfDOFs(int i, int v) { FUNCNAME("DOFAdmin::setNumberOfDOFs()"); TEST_EXIT_DBG(0 <= i && 4 > i)("Should not happen!\n"); nrDOF[i] = v; } void DOFAdmin::setNumberOfPreDOFs(int i, int v) { FUNCNAME("DOFAdmin::setNumberOfPreDOFs()"); TEST_EXIT_DBG(0 <= i && 4 > i)("Should not happen!\n"); nr0DOF[i] = v; } int DOFAdmin::calcMemoryUsage() { return sizeof(DOFAdmin); } void DOFAdmin::serialize(std::ostream &out) { // write name out << name << "\n"; // write dofFree int s = static_cast<int>(dofFree.size()); SerUtil::serialize(out, s); for (int i = 0; i < s; i++) { bool free = dofFree[i]; SerUtil::serialize(out, free); } SerUtil::serialize(out, firstHole); SerUtil::serialize(out, size); SerUtil::serialize(out, usedCount); SerUtil::serialize(out, holeCount); SerUtil::serialize(out, sizeUsed); nrDOF.serialize(out); nr0DOF.serialize(out); } void DOFAdmin::deserialize(std::istream &in) { // read name in >> name; in.get(); // read dofFree int s; SerUtil::deserialize(in, s); dofFree.resize(s); for (int i = 0; i < s; i++) { bool free; SerUtil::deserialize(in, free); dofFree[i] = free; } SerUtil::deserialize(in, firstHole); SerUtil::deserialize(in, size); SerUtil::deserialize(in, usedCount); SerUtil::deserialize(in, holeCount); SerUtil::deserialize(in, sizeUsed); nrDOF.deserialize(in); nr0DOF.deserialize(in); std::list<DOFIndexedBase*>::iterator di; std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end(); for (di = dofIndexedList.begin(); di != end; ++di) (*di)->resize(size); } }