#include "DataCollector.h" #include "Traverse.h" #include "DOFVector.h" #include "SurfaceRegion_ED.h" #include "ElementRegion_ED.h" #include "Projection.h" namespace AMDiS { DataCollector::DataCollector(const FiniteElemSpace *feSpace, DOFVector<double> *values, int level, Flag traverseFlag, bool (*writeElem)(ElInfo*)) : writeElem_(writeElem) { FUNCNAME("DataCollector::DataCollector()"); TEST_EXIT(feSpace)("no feSpace\n"); TEST_EXIT(values)("no value Vector\n"); // === get mesh === mesh_ = feSpace->getMesh(); // === get admin === localAdmin_ = const_cast<DOFAdmin*>(feSpace->getAdmin()); // === create vertex info vector === vertexInfos_ = NEW DOFVector< std::list<VertexInfo> >(feSpace, "vertex infos"); interpPointInd_ = NEW DOFVector<int>(feSpace, "interpolation point indices"); interpPointCoords_ = NEW DOFVector< std::list<WorldVector<double> > >(feSpace, "interpolation point coordinates"); dofCoords_ = NEW DOFVector< std::list<WorldVector<double> > >(feSpace, "dof coords"); dim_ = mesh_->getDim(); nPreDofs_ = localAdmin_->getNumberOfPreDOFs(VERTEX); nVertices_ = 0; nElements_ = 0; nInterpPoints_ = 0; nConnections_ = 0; feSpace_ = feSpace; values_ = values; level_ = level; traverseFlag_ = traverseFlag; elementDataCollected_ = false; valueDataCollected_ = false; periodicDataCollected_ = false; vertexCoords = NEW WorldVector<double>; } DataCollector::~DataCollector() { DELETE vertexInfos_; DELETE interpPointInd_; DELETE interpPointCoords_; DELETE dofCoords_; DELETE vertexCoords; } void DataCollector::fillAllData() { if (!elementDataCollected_) { startCollectingElementData(); } if (!periodicDataCollected_) { startCollectingPeriodicData(); } if (!valueDataCollected_) { startCollectingValueData(); } } int DataCollector::startCollectingElementData() { FUNCNAME("DataCollector::startCollectingElementData()"); Flag flag = traverseFlag_; flag |= Mesh::FILL_NEIGH | Mesh::FILL_COORDS | Mesh::FILL_OPP_COORDS | Mesh::FILL_BOUND; elements_.resize(0, dim_); TraverseStack stack; // Traverse elements to create continuous element indices ElInfo *elInfo = stack.traverseFirst(mesh_, level_, flag); while (elInfo) { if (!writeElem_ || writeElem_(elInfo)) outputIndices_[elInfo->getElement()->getIndex()] = nElements_++; elInfo = stack.traverseNext(elInfo); } // Traverse elements to create element information elInfo = stack.traverseFirst(mesh_, level_, flag); while (elInfo) { if (!writeElem_ || writeElem_(elInfo)) { addElementData(elInfo); } elInfo = stack.traverseNext(elInfo); } elementDataCollected_ = true; return(0); } int DataCollector::startCollectingValueData() { FUNCNAME("DataCollector::startCollectingValueData()"); DOFVector<int>::Iterator intPointIt(interpPointInd_, USED_DOFS); for (intPointIt.reset(); !intPointIt.end(); ++intPointIt) { (*intPointIt) = -1; } interpPoints_.clear(); basisFcts_ = const_cast<BasisFunction*>(feSpace_->getBasisFcts()); nBasisFcts_ = basisFcts_->getNumber(); localDOFs_ = GET_MEMORY(DegreeOfFreedom, nBasisFcts_); TraverseStack stack; // Traverse elements to add value information and to mark // interpolation points. ElInfo *elInfo = stack.traverseFirst(mesh_, level_, traverseFlag_ | Mesh::FILL_COORDS); while (elInfo) { if (!writeElem_ || writeElem_(elInfo)) { addValueData(elInfo); } elInfo = stack.traverseNext(elInfo); } // If there are interpolation points, add them to the corresponding // data array. if (nInterpPoints_ > 0) { // Remove all interpolation marks and, instead, set to each // interpolation point its continous index starting from 0. int i = 0; for (intPointIt.reset(); !intPointIt.end(); ++intPointIt) { if (*intPointIt == -3) { *intPointIt = i++; } } // Traverse elements to create interpolation values. elInfo = stack.traverseFirst(mesh_, level_, traverseFlag_ | Mesh::FILL_COORDS); while (elInfo) { if (!writeElem_ || writeElem_(elInfo)) addInterpData(elInfo); elInfo = stack.traverseNext(elInfo); } } FREE_MEMORY(localDOFs_, DegreeOfFreedom, nBasisFcts_); valueDataCollected_ = true; return(0); } int DataCollector::startCollectingPeriodicData() { FUNCNAME("DataCollector::startCollectingPeriodicData()"); periodicConnections_.clear(); TraverseStack stack; ElInfo *elInfo = stack.traverseFirst(mesh_, level_, traverseFlag_); while (elInfo) { if (!writeElem_ || writeElem_(elInfo)) { LeafDataPeriodic *ldp = dynamic_cast<LeafDataPeriodic*> (elInfo->getElement()-> getElementData()-> getElementData(PERIODIC)); if (ldp) { nConnections_ += dynamic_cast<LeafDataPeriodic*>(ldp)->getInfoList().size(); } periodicConnections_.push_back(DimVec<bool>(dim_, DEFAULT_VALUE, false)); } elInfo = stack.traverseNext(elInfo); } nConnections_ /= 2; periodicInfos_.clear(); Flag flag = traverseFlag_; flag |= Mesh::FILL_COORDS | Mesh::FILL_OPP_COORDS| Mesh::FILL_NEIGH | Mesh::FILL_BOUND; elInfo = stack.traverseFirst(mesh_, level_, flag); while (elInfo) { if (!writeElem_ || writeElem_(elInfo)) addPeriodicData(elInfo); elInfo = stack.traverseNext(elInfo); } periodicDataCollected_ = true; return(0); } int DataCollector::addElementData(ElInfo* elInfo) { FUNCNAME("DataCollector::addElementData()"); const DegreeOfFreedom **dof = elInfo->getElement()->getDOF(); DegreeOfFreedom vertexDOF; WorldVector<double> vertexCoords; // create ElementInfo ElementInfo elementInfo(dim_); // read element region ElementData *ed = elInfo->getElement()->getElementData(ELEMENT_REGION); if (ed) { elementInfo.elementRegion = dynamic_cast<ElementRegion_ED*>(ed)->getRegion(); } else { elementInfo.elementRegion = -1; } // read surface regions to element info ed = elInfo->getElement()->getElementData(SURFACE_REGION); elementInfo.surfaceRegions.set(-1); while (ed) { SurfaceRegion_ED *sr = dynamic_cast<SurfaceRegion_ED*>(ed); elementInfo.surfaceRegions[sr->getSide()] = sr->getRegion(); ed = ed->getDecorated(SURFACE_REGION); } // for all vertices for (int i = 0; i < dim_ + 1; i++) { // get coords of this vertex vertexCoords = elInfo->getCoord(i); // get dof index of this vertex vertexDOF = dof[i][nPreDofs_]; // search for coords at this dof std::list<VertexInfo>::iterator it = find((*vertexInfos_)[vertexDOF].begin(), (*vertexInfos_)[vertexDOF].end(), vertexCoords); // coords not yet in list? if (it == (*vertexInfos_)[vertexDOF].end()) { // create new vertex info and increment number of vertices VertexInfo newVertexInfo = {vertexCoords, nVertices_}; // add new vertex info to list (*vertexInfos_)[vertexDOF].push_front(newVertexInfo); // set iterator to new vertex info it = (*vertexInfos_)[vertexDOF].begin(); nVertices_++; } // fill element info elementInfo.vertexInfo[i] = it; elementInfo.boundary[i] = elInfo->getBoundary(i); elementInfo.projection[i] = elInfo->getProjection(i); elementInfo.neighbour[i] = elInfo->getNeighbour(i) ? outputIndices_[elInfo->getNeighbour(i)->getIndex()] : -1; } if (dim_ == 3) { elementInfo.type = (dynamic_cast<ElInfo3d*>(elInfo)->getType()); } // remember element info elements_.push_back(elementInfo); return(0); } int DataCollector::addValueData(ElInfo *elInfo) { FUNCNAME("DataCollector::addValueData()"); basisFcts_->getLocalIndices(elInfo->getElement(), localAdmin_, localDOFs_); // First, traverse all DOFs at the vertices of the element, determine // their coordinates and add them to the corresponding entry in dofCoords_. for (int i = 0; i < mesh_->getGeo(VERTEX); i++) { DegreeOfFreedom dofi = localDOFs_[i]; (*interpPointInd_)[dofi] = -2; // mark as vertex // get coords of this vertex *vertexCoords = elInfo->getCoord(i); // search for coords at this dof std::list<WorldVector<double> >::iterator it = find((*dofCoords_)[dofi].begin(), (*dofCoords_)[dofi].end(), *vertexCoords); // coords not yet in list? if (it == (*dofCoords_)[dofi].end()) { // add new coords to list (*dofCoords_)[dofi].push_back(*vertexCoords); } } // Then, traverse all interpolation DOFs of the element, determine // their coordinates and add them to the corresponding entry in // interpPointCoords_. for (int i = mesh_->getGeo(VERTEX); i < nBasisFcts_; i++) { DegreeOfFreedom dofi = localDOFs_[i]; elInfo->coordToWorld(*basisFcts_->getCoords(i), *vertexCoords); if ((*interpPointInd_)[dofi] == -1) { // mark as interpolation point (*interpPointInd_)[dofi] = -3; // search for interpolation point coordinates, and insert them to the // dof-entry, if not contained in the list std::list<WorldVector<double> >::iterator it = find((*interpPointCoords_)[dofi].begin(), (*interpPointCoords_)[dofi].end(), *vertexCoords); if (it == (*interpPointCoords_)[dofi].end()) { (*interpPointCoords_)[dofi].push_back(*vertexCoords); nInterpPoints_++; } } } return(0); } int DataCollector::addInterpData(ElInfo *elInfo) { FUNCNAME("DataCollector::addInterpData()"); basisFcts_->getLocalIndices(elInfo->getElement(), localAdmin_, localDOFs_); std::vector<int> elemInterpPoints(0); for (int i = mesh_->getGeo(VERTEX); i < nBasisFcts_; i++) { elemInterpPoints.push_back((*interpPointInd_)[localDOFs_[i]]); } interpPoints_.push_back(elemInterpPoints); return(0); } int DataCollector::addPeriodicData(ElInfo *elInfo) { FUNCNAME("DataCollector::addPeriodicData"); LeafDataPeriodic *ldp = dynamic_cast<LeafDataPeriodic*> (elInfo->getElement()-> getElementData()-> getElementData(PERIODIC)); if (ldp) { std::list<LeafDataPeriodic::PeriodicInfo>::iterator it; for (it = dynamic_cast<LeafDataPeriodic*>(ldp)->getInfoList().begin(); it != dynamic_cast<LeafDataPeriodic*>(ldp)->getInfoList().end(); ++it) { int outputIndex = outputIndices_[elInfo->getElement()->getIndex()]; int neighIndex = outputIndices_[elInfo-> getNeighbour(it->elementSide)-> getIndex()]; if (!periodicConnections_[outputIndex][it->elementSide]) { PeriodicInfo periodicInfo; periodicInfo.mode = it->periodicMode; periodicInfo.type = it->type; periodicInfo.outputIndex = outputIndex; periodicInfo.neighIndex = neighIndex; periodicInfo.vertexMap.clear(); periodicConnections_[outputIndex][it->elementSide] = true; periodicConnections_ [neighIndex][elInfo->getOppVertex(it->elementSide)] = true; for (int i = 0; i < dim_; i++) { int index1 = elInfo->getElement()->getVertexOfPosition(INDEX_OF_DIM(dim_ - 1, dim_), it->elementSide, i); int dof1 = elInfo->getElement()->getDOF(index1, nPreDofs_); for (int j = 0; j < dim_; j++) { int index2 = elInfo->getElement()->getVertexOfPosition(INDEX_OF_DIM(dim_ - 1, dim_), elInfo->getOppVertex(it->elementSide), j); int dof2 = elInfo->getNeighbour(it->elementSide)->getDOF(index2, nPreDofs_); if ((dof1 == dof2) || (mesh_->associated(dof1, dof2))) { periodicInfo.vertexMap[index1] = index2; break; } } } periodicInfos_.push_back(periodicInfo); } } } return(0); } std::list<ElementInfo>* DataCollector::getElementInfos() { if (!elementDataCollected_) { startCollectingElementData(); } return &elements_; } DOFVector< std::list<VertexInfo> >* DataCollector::getVertexInfos() { if (!elementDataCollected_) { startCollectingElementData(); } return vertexInfos_; } std::list<PeriodicInfo>* DataCollector::getPeriodicInfos() { if (!periodicDataCollected_) { startCollectingPeriodicData(); } return &periodicInfos_; } int DataCollector::getNumberVertices() { if (!elementDataCollected_) { startCollectingElementData(); } return nVertices_; } int DataCollector::getNumberElements() { if (!elementDataCollected_) { startCollectingElementData(); } return nElements_; } int DataCollector::getNumberInterpPoints() { if (!valueDataCollected_) { startCollectingValueData(); } return nInterpPoints_; } int DataCollector::getNumberConnections() { if (!periodicDataCollected_) { startCollectingPeriodicData(); } return nConnections_; } const FiniteElemSpace* DataCollector::getFeSpace() { return feSpace_; } Mesh* DataCollector::getMesh() { return mesh_; } DOFVector<double>* DataCollector::getValues() { if (!valueDataCollected_) { startCollectingValueData(); } return values_; } DOFVector< std::list<WorldVector<double> > >* DataCollector::getDofCoords() { if (!valueDataCollected_) { startCollectingValueData(); } return dofCoords_; } DOFVector<int>* DataCollector::getInterpPointInd() { if (!valueDataCollected_) { startCollectingValueData(); } return interpPointInd_; } DOFVector< std::list<WorldVector<double> > >* DataCollector::getInterpPointCoords() { if (!valueDataCollected_) { startCollectingValueData(); } return interpPointCoords_; } std::vector< std::vector<int> >* DataCollector::getInterpPoints() { if (!valueDataCollected_) { startCollectingValueData(); } return &interpPoints_; } }