#include #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" namespace AMDiS { const int DOFAdmin::sizeIncrement = 10; void DOFAdmin::init() { firstHole = size = usedCount = holeCount = sizeUsed = 0; dofFree.clear(); } 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::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 < 4; 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&) {} 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::iterator di; std::list::iterator end = dofIndexedList.end(); for (di = dofIndexedList.begin(); di != end; ++di) { (*di)->freeDOFContent(dof); } std::list::iterator dc; std::list::iterator dcend = dofContainerList.end(); for (dc = dofContainerList.begin(); dc != dcend; ++dc) { (*dc)->freeDOFIndex(dof); } dofFree[dof] = true; if (static_cast(firstHole) > dof) firstHole = dof; usedCount--; holeCount++; } /****************************************************************************/ int DOFAdmin::getDOFIndex() { FUNCNAME("DOFAdmin::getDOFIndex()"); int dof = 0; // if there is a hole if (firstHole < static_cast(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(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(0); TEST_EXIT_DBG(firstHole < static_cast(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((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 don't have to be changed std::list::iterator di; std::list::iterator end = dofIndexedList.end(); for (di = dofIndexedList.begin(); di != end; ++di) { if ((*di)->getSize() < newval) { (*di)->resize(newval); } } } void DOFAdmin::addDOFIndexed(DOFIndexedBase* dofIndexed) { FUNCNAME("DOFAdmin::addDOFIndexed()"); TEST_EXIT_DBG(dofIndexed)("no dofIndexed\n"); if (dofIndexed->getSize() < size) { dofIndexed->resize(size); } dofIndexedList.push_back(dofIndexed); } void DOFAdmin::removeDOFIndexed(DOFIndexedBase* dofIndexed) { FUNCNAME("DOFAdmin::removeDOFIndexed()"); std::list::iterator it; std::list::iterator end = dofIndexedList.end(); for (it = dofIndexedList.begin(); it != end; ++it) { if (*it == dofIndexed) { dofIndexedList.erase(it); return; } } ERROR("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::iterator it; std::list::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 &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= 0)) { first = i; break; } } std::list::iterator di; std::list::iterator end = dofIndexedList.end(); for (di = dofIndexedList.begin(); di != end; ++di) { (*di)->compressDOFIndexed(first, last, new_dof); }; std::list::iterator dc; std::list::iterator endc = dofContainerList.end(); for (dc = dofContainerList.begin(); dc != endc; dc++) { (*dc)->compressDOFContainer(n, new_dof); }; return; } void DOFAdmin::setNumberOfDOFs(int i,int v) { TEST_EXIT_DBG((0 <= i) && (4 > i))(""); nrDOF[i] = v; } void DOFAdmin::setNumberOfPreDOFs(int i, int v) { TEST_EXIT_DBG((0 <= i) && (4 > i))(""); nr0DOF[i] = v; } DOFAdmin::~DOFAdmin() {} void DOFAdmin::serialize(std::ostream &out) { // write name out << name << "\n"; // write dofFree int s = static_cast(dofFree.size()); out.write(reinterpret_cast(&s), sizeof(int)); for (int i = 0; i < s; i++) { bool free = dofFree[i]; out.write(reinterpret_cast(&free), sizeof(bool)); } // write firstHole out.write(reinterpret_cast(&firstHole), sizeof(unsigned int)); // write size out.write(reinterpret_cast(&size), sizeof(int)); // write usedCount out.write(reinterpret_cast(&usedCount), sizeof(int)); // write holeCount out.write(reinterpret_cast(&holeCount), sizeof(int)); // write sizeUsed out.write(reinterpret_cast(&sizeUsed), sizeof(int)); // write nrDOF nrDOF.serialize(out); // write nr0DOF nr0DOF.serialize(out); } void DOFAdmin::deserialize(std::istream &in) { // read name in >> name; in.get(); // read dofFree int s; in.read(reinterpret_cast(&s), sizeof(int)); dofFree.resize(s); for (int i = 0; i < s; i++) { bool free; in.read(reinterpret_cast(&free), sizeof(bool)); dofFree[i] = free; } // read firstHole in.read(reinterpret_cast(&firstHole), sizeof(unsigned int)); // read size in.read(reinterpret_cast(&size), sizeof(int)); // read usedCount in.read(reinterpret_cast(&usedCount), sizeof(int)); // read holeCount in.read(reinterpret_cast(&holeCount), sizeof(int)); // read sizeUsed in.read(reinterpret_cast(&sizeUsed), sizeof(int)); // read nrDOF nrDOF.deserialize(in); // read nr0DOF nr0DOF.deserialize(in); std::list::iterator di; std::list::iterator end = dofIndexedList.end(); for (di = dofIndexedList.begin(); di != end; ++di) { (*di)->resize(size); } } }