Skip to content
Snippets Groups Projects
supportpatchfactory.hh 7.78 KiB
Newer Older
podlesny's avatar
podlesny committed
#ifndef SUPPORT_PATCH_FACTORY_HH
#define SUPPORT_PATCH_FACTORY_HH

podlesny's avatar
.  
podlesny committed
#include <queue>
#include <set>
podlesny's avatar
podlesny committed

#include <dune/common/bitsetvector.hh>
#include <dune/common/fvector.hh>

#include <dune/fufem/referenceelementhelper.hh>
#include <dune/grid/common/mcmgmapper.hh>

#include <dune/faultnetworks/hierarchicleveliterator.hh>

template <class BasisType>
class SupportPatchFactory
{
    protected:
        typedef typename BasisType::GridView GV;
        typedef typename BasisType::LocalFiniteElement LFE;
	
	typedef typename GV::Grid GridType;
	typedef typename GridType::ctype ctype;
	static const int dim = GridType::dimension;
	typedef typename GridType::template Codim<0>::Entity Element;
	typedef typename GridType::template Codim<dim>::Entity Vertex;

	typedef HierarchicLevelIterator<GridType> HierarchicLevelIteratorType;
	typedef typename Dune::LevelMultipleCodimMultipleGeomTypeMapper<GridType,  Dune::MCMGElementLayout > ElementMapper;
	
    private:
	const BasisType& coarseBasis_;
	const BasisType& fineBasis_;
	
	const int coarseLevel_;
	const int fineLevel_;
	
 	const std::vector< std::vector <Element>>& vertexInElements_;
	const int centerVertexIdx_;
	const int patchDepth_;

  
	const GridType& grid;
	const GV& coarseGridView;
	const GV& fineGridView;
	
	std::vector<int> localToGlobal;
	Dune::BitSetVector<1> boundaryDofs;
	std::vector<Element> fineRegionElements;
	
	ElementMapper coarseMapper;

    public:
        //setup 
    SupportPatchFactory(const BasisType& coarseBasis, const BasisType& fineBasis, const int coarseLevel, const int fineLevel, const std::vector< std::vector <Element>>& vertexInElements, const int centerVertexIdx, const int patchDepth) :
            coarseBasis_(coarseBasis),
            fineBasis_(fineBasis),
            coarseLevel_(coarseLevel),
            fineLevel_(fineLevel),
            vertexInElements_(vertexInElements),
            centerVertexIdx_(centerVertexIdx),
            patchDepth_(patchDepth),
            grid(coarseBasis_.getGridView().grid()),
	    coarseGridView(coarseBasis_.getGridView()),
	    fineGridView(fineBasis_.getGridView()),
	    coarseMapper(grid, coarseLevel_)
        {   
	    fineRegionElements.resize(0);
	  
            std::vector<Element> coarseElements;
	    Dune::BitSetVector<1> visited(coarseMapper.size());
	    Dune::BitSetVector<1> vertexVisited(vertexInElements_.size());
            visited.unsetAll();
	    vertexVisited.unsetAll();
	    
	    std::set<int> localDofs;
	    std::set<int> localBoundaryDofs;

	    addVertexSupport(centerVertexIdx_, coarseElements, visited, vertexVisited);
	    
	    // construct coarse patch
	    for (int depth=1; depth<patchDepth_; depth++) {
		std::vector<Element> coarseElementNeighbors;
		
		for (size_t i=0; i<coarseElements.size(); ++i) {
		    const Element& elem = coarseElements[i];     
		    const LFE& coarseLFE = coarseBasis_.getLocalFiniteElement(elem);
	      
		    for (size_t j=0; j<coarseLFE.localBasis().size(); ++j) {
            int dofIndex = coarseBasis_.indexInGridView(elem, j);
			
			if (!vertexVisited[dofIndex][0]) {
			    addVertexSupport(dofIndex, coarseElementNeighbors, visited, vertexVisited);
			}
		    }
		}	        
		    
		coarseElements.insert(coarseElements.begin(), coarseElementNeighbors.begin(), coarseElementNeighbors.end());
	    }
	    

	    // construct fine patch
	    for (size_t i=0; i<coarseElements.size(); ++i) {
		const Element& elem = coarseElements[i];
		addFinePatchElements(elem, visited, localDofs, localBoundaryDofs);
	    }

	 
	 
        localToGlobal.resize(localDofs.size());
	    boundaryDofs.resize(localDofs.size());
	    boundaryDofs.unsetAll();
	    
	    std::set<int>::iterator dofIt = localDofs.begin();
	    std::set<int>::iterator dofEndIt = localDofs.end();
	    size_t i=0;
	    for (; dofIt != dofEndIt; ++dofIt) {
		int localDof = *dofIt;
		localToGlobal[i] = localDof;
		
		if (localBoundaryDofs.count(localDof)) {
		    boundaryDofs[i][0] = true;
		}
		i++;
	    }
	}

	std::vector<int>& getLocalToGlobal() {
	    return localToGlobal;
	}
	
	std::vector<Element>& getRegionElements() {
	    return fineRegionElements;
	}
	
	Dune::BitSetVector<1>& getBoundaryDofs() {
	    return boundaryDofs;
	}
	
	
private:


    void print(const Dune::BitSetVector<1>& x, std::string message){
       std::cout << message << std::endl;
       for (size_t i=0; i<x.size(); i++) {
           std::cout << x[i][0] << " ";
       }
       std::cout << std::endl << std::endl;
   }

	void addVertexSupport(const int vertexIdx, std::vector<Element>& coarseElements, Dune::BitSetVector<1>& visited, Dune::BitSetVector<1>& vertexVisited) {
	    const std::vector<Element>& vertexInElement = vertexInElements_[vertexIdx];
	    
	    for (size_t i=0; i<vertexInElement.size(); i++) {
		const Element& elem = vertexInElement[i];
		const int elemIdx = coarseMapper.index(elem);
		
		if (!visited[elemIdx][0]) {
		    coarseElements.push_back(elem);
		    visited[elemIdx][0] = true;
		}
	    }
	    vertexVisited[vertexIdx][0] = true;
	}
      
	bool containsInsideSubentity(const Element& elem, const typename GridType::LevelIntersection& intersection, int subEntity, int codim) {
	    return ReferenceElementHelper<double, dim>::subEntityContainsSubEntity(elem.type(), intersection.indexInInside(), 1, subEntity, codim);
	}
      
      
	void addFinePatchElements(const Element& coarseElem, const Dune::BitSetVector<1>& inCoarsePatch, std::set<int>& localDofs, std::set<int>& localBoundaryDofs) {
	    HierarchicLevelIteratorType endHierIt(grid, coarseElem, HierarchicLevelIteratorType::PositionFlag::end, fineLevel_);
	    for (HierarchicLevelIteratorType hierIt(grid, coarseElem, HierarchicLevelIteratorType::PositionFlag::begin, fineLevel_); hierIt!=endHierIt; ++hierIt) {

		const Element& fineElem = *hierIt;
		fineRegionElements.push_back(fineElem);

		addLocalDofs(coarseElem, fineElem, inCoarsePatch, localDofs, localBoundaryDofs);
	    }
	}	  
	
	void addLocalDofs(const Element& coarseElem, const Element& fineElem, const Dune::BitSetVector<1>& inCoarsePatch, std::set<int>& localDofs, std::set<int>& localBoundaryDofs) {
	    const LFE& fineLFE = fineBasis_.getLocalFiniteElement(fineElem);
	    
        /*
	    const auto& fineGeometry = fineElem.geometry();
	    const auto& coarseGeometry = coarseElem.geometry();
		
        const auto& ref = Dune::ReferenceElements<ctype, dim>::general(fineElem.type()); */
	    
	    // insert local dofs
	    for (size_t i=0; i<fineLFE.localBasis().size(); ++i) {
		int dofIndex = fineBasis_.index(fineElem, i);
		localDofs.insert(dofIndex);
	    }

	    
	    // search for parts of the global and inner boundary 
	    typename GridType::LevelIntersectionIterator neighborIt = fineGridView.ibegin(fineElem);
	    typename GridType::LevelIntersectionIterator neighborItEnd = fineGridView.iend(fineElem);
	    for (; neighborIt!=neighborItEnd; ++neighborIt) {
		const typename GridType::LevelIntersection& intersection = *neighborIt;

		bool isInnerBoundary = false;
		if (intersection.neighbor()) {
		    Element outsideFather = intersection.outside();
		    
		    while (outsideFather.level()>coarseLevel_) {
			outsideFather = outsideFather.father();
		    }
		    
		    if (!inCoarsePatch[coarseMapper.index(outsideFather)][0]) {
			isInnerBoundary = true;
		    }
		}
		
		if (intersection.boundary() or isInnerBoundary) {
		    typedef typename LFE::Traits::LocalCoefficientsType LocalCoefficients;
		    const LocalCoefficients* localCoefficients = &fineBasis_.getLocalFiniteElement(intersection.inside()).localCoefficients();

		    for (size_t i=0; i<localCoefficients->size(); i++) {
			unsigned int entity = localCoefficients->localKey(i).subEntity();
			unsigned int codim  = localCoefficients->localKey(i).codim();

			if (containsInsideSubentity(fineElem, intersection, entity, codim))
			    localBoundaryDofs.insert(fineBasis_.index(intersection.inside(), i));
		    } 
		}
	    }	
	}
};
#endif