// // Software License for AMDiS // // Copyright (c) 2010 Dresden University of Technology // All rights reserved. // Authors: Simon Vey, Thomas Witkowski et al. // // This file is part of AMDiS // // See also license.opensource.txt in the distribution. #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), nDof(mesh->getDim(), NO_INIT), nPreDof(mesh->getDim(), NO_INIT) { init(); } DOFAdmin::DOFAdmin(Mesh* m, std::string aName) : name(aName), mesh(m), nDof(mesh->getDim(), NO_INIT), nPreDof(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++) { nDof[i] = src.nDof[i]; nPreDof[i] = src.nPreDof[i]; } dofIndexedList = src.dofIndexedList; dofContainerList = src.dofContainerList; } return *this; } 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 = std::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 = std::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"); if (dofIndexed->getSize() < size) dofIndexed->resize(size); dofIndexedList.push_back(dofIndexed); } void DOFAdmin::removeDOFIndexed(DOFIndexedBase* dofIndexed) { FUNCNAME("DOFAdmin::removeDOFIndexed()"); bool removed = false; 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> &newDofIndex) { FUNCNAME("DOFAdmin::compress()"); // nothing to do ? if (size < 1 || usedCount < 1 || holeCount < 1) return; // vector to mark used dofs for (int i = 0; i < size; i++) newDofIndex[i] = -1; // mark used dofs DOFIteratorBase it(this, USED_DOFS); for (it.reset(); !it.end(); ++it) newDofIndex[it.getDOFIndex()] = 1; // create a MONOTONE compress int n = 0, last = 0; for (int i = 0; i < size; i++) { if (newDofIndex[i] == 1) { newDofIndex[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 (newDofIndex[i] < i && newDofIndex[i] >= 0) { first = i; break; } } for (std::list<DOFIndexedBase*>::iterator di = dofIndexedList.begin(); di != dofIndexedList.end(); ++di) (*di)->compressDOFIndexed(first, last, newDofIndex); for (std::list<DOFContainer*>::iterator dc = dofContainerList.begin(); dc != dofContainerList.end(); ++dc) (*dc)->compressDofContainer(n, newDofIndex); } void DOFAdmin::setNumberOfDofs(int i, int v) { FUNCNAME("DOFAdmin::setNumberOfDOFs()"); TEST_EXIT_DBG(0 <= i && 4 > i)("Should not happen!\n"); nDof[i] = v; } void DOFAdmin::setNumberOfPreDofs(int i, int v) { FUNCNAME("DOFAdmin::setNumberOfPreDOFs()"); TEST_EXIT_DBG(0 <= i && 4 > i)("Should not happen!\n"); nPreDof[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); nDof.serialize(out); nPreDof.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); nDof.deserialize(in); nPreDof.deserialize(in); std::list<DOFIndexedBase*>::iterator di; std::list<DOFIndexedBase*>::iterator end = dofIndexedList.end(); for (di = dofIndexedList.begin(); di != end; ++di) (*di)->resize(size); } }