Code owners
Assign users and groups as approvers for specific file changes. Learn more.
grid_imp.cc 20.16 KiB
#ifndef DUNE_ALUGRID_GRID_IMP_CC
#define DUNE_ALUGRID_GRID_IMP_CC
#if COMPILE_ALUGRID_INLINE == 0
#include <config.h>
#endif
// Dune includes
#include <dune/common/stdstreams.hh>
// Local includes
#include "entity.hh"
#include "iterator.hh"
#include "datahandle.hh"
#include "grid.hh"
#if COMPILE_ALUGRID_INLINE
#define alu_inline inline
#else
#define alu_inline
#endif
namespace Dune
{
template< class Comm >
template< class GridType >
alu_inline
void ALU3dGridVertexList< Comm >::
setupVxList(const GridType & grid, int level)
{
// iterates over grid elements of given level and adds all vertices to
// given list
enum { codim = 3 };
VertexListType & vxList = vertexList_;
//we need Codim 3 instead of Codim dim because the ALUGrid IndexManager is called
unsigned int vxsize = grid.hierarchicIndexSet().size(codim);
if( vxList.size() < vxsize ) vxList.reserve(vxsize);
std::vector<int> visited_(vxsize);
for(unsigned int i=0; i<vxsize; i++)
{
visited_[i] = 0;
}
vxList.resize(0);
const ALU3dGridElementType elType = GridType:: elementType;
typedef ALU3DSPACE ALU3dGridLevelIteratorWrapper< 0, Dune::All_Partition, Comm > ElementLevelIteratorType;
typedef typename ElementLevelIteratorType :: val_t val_t;
typedef ALU3dImplTraits< elType, Comm > ImplTraits;
typedef typename ImplTraits::IMPLElementType IMPLElementType;
typedef typename ImplTraits::VertexType VertexType;
enum { nVx = ElementTopologyMapping < elType > :: numVertices };
ElementLevelIteratorType it ( grid, level, grid.nlinks() );
int count = 0;
for( it.first(); !it.done() ; it.next())
{
val_t & item = it.item();
IMPLElementType * elem = 0;
if( item.first )
elem = static_cast<IMPLElementType *> (item.first);
else if( item.second )
elem = static_cast<IMPLElementType *> (item.second->getGhost().first);
alugrid_assert ( elem );
for(int i=0; i<nVx; ++i)
{
VertexType * vx = elem->myvertex(i);
alugrid_assert ( vx );
// insert only interior and border vertices
if( vx->isGhost() ) continue;
const int idx = vx->getIndex();
if(visited_[idx] == 0)
{
vxList.push_back(vx);
++count;
}
visited_[idx] = 1;
}
}
alugrid_assert ( count == (int) vxList.size());;
up2Date_ = true;
}
template< class Comm >
template< class GridType >
alu_inline
void ALU3dGridLeafVertexList< Comm >::
setupVxList(const GridType & grid)
{
// iterates over grid elements of given level and adds all vertices to
// given list
enum { codim = 3 };
VertexListType & vxList = vertexList_;
//we need Codim 3 instead of Codim dim because the ALUGrid IndexManager is called
size_t vxsize = grid.hierarchicIndexSet().size(codim);
if( vxList.capacity() < vxsize) vxList.reserve(vxsize);
vxList.resize(vxsize);
for(size_t i=0; i<vxsize; ++i)
{
ItemType & vx = vxList[i];
vx.first = 0;
vx.second = -1;
}
const ALU3dGridElementType elType = GridType:: elementType;
typedef ALU3DSPACE ALU3dGridLeafIteratorWrapper< 0, Dune::All_Partition, Comm > ElementIteratorType;
typedef typename ElementIteratorType :: val_t val_t;
typedef ALU3dImplTraits< elType, Comm > ImplTraits;
typedef typename ImplTraits::IMPLElementType IMPLElementType;
typedef typename ImplTraits::VertexType VertexType;
enum { nVx = ElementTopologyMapping < elType > :: numVertices };
ElementIteratorType it ( grid, grid.maxLevel() , grid.nlinks() );
#ifdef ALUGRIDDEBUG
int count = 0;
#endif
for( it.first(); !it.done() ; it.next())
{
val_t & item = it.item();
IMPLElementType * elem = 0;
if( item.first )
elem = static_cast<IMPLElementType *> (item.first);
else if( item.second )
elem = static_cast<IMPLElementType *> (item.second->getGhost().first);
alugrid_assert ( elem );
int level = elem->level();
for(int i=0; i<nVx; ++i)
{
VertexType * vx = elem->myvertex(i);
alugrid_assert ( vx );
// insert only interior and border vertices
if( vx->isGhost() ) continue;
const int idx = vx->getIndex();
ItemType & vxpair = vxList[idx];
if( vxpair.first == 0 )
{
vxpair.first = vx;
vxpair.second = level;
#ifdef ALUGRIDDEBUG
++ count;
#endif
}
// always store max level of vertex as grdi definition says
else
{
// set the max level for each vertex, see Grid definition
if (vxpair.second < level) vxpair.second = level;
}
}
}
//std::cout << count << "c | s " << vxList.size() << "\n";
// make sure that the found number of vertices equals to stored ones
//alugrid_assert ( count == (int)vxList.size() );
up2Date_ = true;
}
// ALU3dGrid
// ---------
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
const ALU3dGrid< dim, dimworld, elType, Comm > &
ALU3dGrid< dim, dimworld, elType, Comm >::operator= ( const ALU3dGrid< dim, dimworld, elType, Comm > &other )
{
DUNE_THROW(GridError,"Do not use assignment operator of ALU3dGrid! \n");
return (*this);
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
ALU3dGrid< dim, dimworld, elType, Comm >::~ALU3dGrid ()
{
delete communications_;
delete vertexProjection_;
//delete bndPrj_;
if( bndVec_ )
{
const size_t bndSize = bndVec_->size();
for(size_t i=0; i<bndSize; ++i)
{
delete (*bndVec_)[i];
}
delete bndVec_; bndVec_ = 0;
}
for(unsigned int i=0; i<levelIndexVec_.size(); i++) delete levelIndexVec_[i];
delete globalIdSet_; globalIdSet_ = 0;
delete leafIndexSet_; leafIndexSet_ = 0;
delete sizeCache_; sizeCache_ = 0;
/*
if(myGrid().container().iterators_attached())
{
dwarn << "WRANING: There still exists instances of iterators giving access to this grid which is about to be removed! in: " << __FILE__ << " line: " << __LINE__ << std::endl;
}
*/
delete mygrid_; mygrid_ = 0;
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
int ALU3dGrid< dim, dimworld, elType, Comm >::size ( int level, int codim ) const
{
// if we dont have this level return 0
if( (level > maxlevel_) || (level < 0) ) return 0;
alugrid_assert ( codim >= 0);
alugrid_assert ( codim < dimension+1 );
alugrid_assert ( sizeCache_ );
return sizeCache_->size(level,codim);
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
size_t ALU3dGrid< dim, dimworld, elType, Comm >::numBoundarySegments () const
{
if (dim == 3)
return myGrid().numMacroBndSegments();
else if(elType == tetra)
return myGrid().numMacroBndSegments() - size(0);
else if (elType == hexa)
return myGrid().numMacroBndSegments() - 2*size(0);
}
// --size
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
int ALU3dGrid< dim, dimworld, elType, Comm >::size ( int level, GeometryType type ) const
{
if(elType == tetra && !type.isSimplex()) return 0;
if(elType == hexa && !type.isCube ()) return 0;
return size( level, dimension - type.dim() );
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
int ALU3dGrid< dim, dimworld, elType, Comm >::size ( int codim ) const
{
alugrid_assert ( codim >= 0 );
alugrid_assert ( codim <= dimension );
alugrid_assert ( sizeCache_ );
return sizeCache_->size(codim);
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
int ALU3dGrid< dim, dimworld, elType, Comm >::size ( GeometryType type ) const
{
if(elType == tetra && !type.isSimplex()) return 0;
if(elType == hexa && !type.isCube ()) return 0;
return size( dimension - type.dim() );
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
int ALU3dGrid< dim, dimworld, elType, Comm >::ghostSize ( int codim ) const
{
return ( ghostCellsEnabled() && codim == 0 ) ? 1 : 0 ;
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
int ALU3dGrid< dim, dimworld, elType, Comm >::ghostSize ( int level, int codim ) const
{
return ghostSize( codim );
}
// calc all necessary things that might have changed
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
void ALU3dGrid< dim, dimworld, elType, Comm >::updateStatus()
{
calcMaxLevel();
calcExtras();
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
void ALU3dGrid< dim, dimworld, elType, Comm >::calcMaxLevel ()
{
// old fashioned way
int testMaxLevel = 0;
typedef ALU3DSPACE ALU3dGridLeafIteratorWrapper< 0, All_Partition, Comm > IteratorType;
IteratorType w (*this, maxLevel(), nlinks() );
typedef typename IteratorType :: val_t val_t ;
typedef typename ALU3dImplTraits< elType, Comm >::IMPLElementType IMPLElementType;
for (w.first () ; ! w.done () ; w.next ())
{
val_t & item = w.item();
IMPLElementType * elem = 0;
if( item.first )
elem = static_cast<IMPLElementType *> (item.first);
else if( item.second )
elem = static_cast<IMPLElementType *> (item.second->getGhost().first);
alugrid_assert ( elem );
int level = elem->level();
if(level > testMaxLevel) testMaxLevel = level;
}
maxlevel_ = comm().max( testMaxLevel );
alugrid_assert ( maxlevel_ == comm().max( maxlevel_ ));
}
// --calcExtras
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
void ALU3dGrid< dim, dimworld, elType, Comm >::calcExtras ()
{
// make sure maxLevel is the same on all processes ????
//alugrid_assert ( maxlevel_ == comm().max( maxlevel_ ));
if(sizeCache_) delete sizeCache_;
sizeCache_ = new SizeCacheType (*this);
// unset up2date before recalculating the index sets,
// becasue they will use this feature
leafVertexList_.unsetUp2Date();
for(size_t i=0; i<MAXL; ++i)
{
vertexList_[i].unsetUp2Date();
levelEdgeList_[i].unsetUp2Date();
}
if( comm().size() > 1 )
{
//here dimension has to be 3, as this is used ALU internally
// was for( int i = 0; i < dimension; ++i )
for( int i = 0; i < 3; ++i )
{
ghostLeafList_[i].unsetUp2Date();
for(size_t l=0; l<MAXL; ++l) ghostLevelList_[i][l].unsetUp2Date();
}
}
// update all index set that are already in use
for(size_t i=0; i<levelIndexVec_.size(); ++i)
{
if(levelIndexVec_[i])
(*(levelIndexVec_[i])).calcNewIndex( this->template lbegin<0>( i ),
this->template lend<0>( i ) );
}
if(leafIndexSet_)
leafIndexSet_->calcNewIndex( this->template leafbegin<0>(), this->template leafend<0>() );
// build global ID set new (to be revised)
if( globalIdSet_ ) globalIdSet_->updateIdSet();
coarsenMarked_ = 0;
refineMarked_ = 0;
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
const typename ALU3dGrid< dim, dimworld, elType, Comm >::Traits::LeafIndexSet &
ALU3dGrid< dim, dimworld, elType, Comm >::leafIndexSet () const
{
if(!leafIndexSet_) leafIndexSet_ = new LeafIndexSetImp ( *this,
this->template leafbegin<0>(),
this->template leafend<0>() );
return *leafIndexSet_;
}
// global refine
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
void ALU3dGrid< dim, dimworld, elType, Comm >::globalRefine ( int refCount )
{
alugrid_assert ( (refCount + maxLevel()) < MAXL );
for( int count = refCount; count > 0; --count )
{
const LeafIteratorType end = leafend();
for( LeafIteratorType it = leafbegin(); it != end; ++it )
mark( 1, *it );
const bool refined = adapt();
if( refined )
postAdapt();
}
}
// preprocess grid
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
bool ALU3dGrid< dim, dimworld, elType, Comm >::preAdapt()
{
return (coarsenMarked_ > 0);
}
// adapt grid
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
bool ALU3dGrid< dim, dimworld, elType, Comm >::adapt ()
{
bool ref = false;
if( lockPostAdapt_ == true )
{
DUNE_THROW(InvalidStateException,"Make sure that postAdapt is called after adapt was called and returned true!");
}
bool mightCoarse = preAdapt();
// if prallel run, then adapt also global id set
if(globalIdSet_)
{
//std::cout << "Start adapt with globalIdSet prolong \n";
int defaultChunk = newElementsChunk_;
int actChunk = refineEstimate_ * refineMarked_;
// guess how many new elements we get
int newElements = std::max( actChunk , defaultChunk );
globalIdSet_->setChunkSize( newElements );
ref = myGrid().duneAdapt(*globalIdSet_); // adapt grid
}
else
{
ref = myGrid().adaptWithoutLoadBalancing();
}
// in parallel this is different
if( this->comm().size() == 1 )
{
ref = ref && refineMarked_ > 0;
}
if(ref || mightCoarse)
{
// calcs maxlevel and other extras
updateStatus();
// notify that postAdapt must be called
lockPostAdapt_ = true;
}
return ref;
}
// post process grid
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
void ALU3dGrid< dim, dimworld, elType, Comm >::clearIsNewMarkers ()
{
// old fashioned way
typedef ALU3DSPACE ALU3dGridLeafIteratorWrapper< 0, All_Partition, Comm > IteratorType;
IteratorType w (*this, maxLevel(), nlinks() );
typedef typename IteratorType::val_t val_t;
typedef typename ALU3dImplTraits< elType, Comm >::IMPLElementType IMPLElementType;
for (w.first () ; ! w.done () ; w.next ())
{
val_t & item = w.item();
alugrid_assert ( item.first || item.second );
IMPLElementType * elem = 0;
if( item.first )
elem = static_cast<IMPLElementType *> (item.first);
else if( item.second )
{
elem = static_cast<IMPLElementType *>( item.second->getGhost().first );
alugrid_assert ( elem );
}
if (elem->hasBeenRefined())
{
elem->resetRefinedTag();
// on bisected grids its possible that not only leaf elements where added so
// we have to move up the hierarchy to make sure that the refined tag on parents are also removed
while (elem->up())
{
elem = static_cast<IMPLElementType *>(elem->up());
elem->resetRefinedTag();
}
}
}
}
// post process grid
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
void ALU3dGrid< dim, dimworld, elType, Comm >::postAdapt ()
{
if( lockPostAdapt_ )
{
// clear all isNew markers on entities
clearIsNewMarkers();
// make that postAdapt has been called
lockPostAdapt_ = false;
}
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
inline bool ALU3dGrid< dim, dimworld, elType, Comm >
::writeMacroGrid ( const std::string path, const std::string name,
const ALU3DSPACE MacroFileHeader::Format format ) const
{
std::stringstream filename;
filename << path << "/" << name << "." << comm().rank();
std::ofstream macro( filename.str().c_str() );
if( macro )
{
// dump distributed macro grid as ascii files
myGrid().container().dumpMacroGrid( macro, format );
}
else
std::cerr << "WARNING: couldn't open file `" << filename.str() << "' for writing!" << std::endl;
return true;
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
void ALU3dGrid< dim, dimworld, elType, Comm >::
backup( std::ostream& stream, const ALU3DSPACE MacroFileHeader::Format format ) const
{
// backup grid to given stream
myGrid().backup( stream, format );
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
void ALU3dGrid< dim, dimworld, elType, Comm >::restore( std::istream& stream )
{
// if grid exists delete first
if( mygrid_ ) delete mygrid_;
// create new grid from stream
mygrid_ = createALUGrid( stream );
// check for grid
if( ! mygrid_ )
{
DUNE_THROW(InvalidStateException,"ALUGrid::restore failed");
}
// check for element type
this->checkMacroGrid ();
// restore hierarchy from given stream
myGrid().restore( stream );
// calculate new maxlevel
// calculate indices
updateStatus();
// reset refinement markers
clearIsNewMarkers();
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
void ALU3dGrid< dim, dimworld, elType, Comm >::checkMacroGridFile ( const std::string filename )
{
if(filename == "") return;
std::ifstream file(filename.c_str());
if(!file)
{
std::cerr << "Couldn't open file '" << filename <<"' !" << std::endl;
DUNE_THROW(IOError,"Couldn't open file '" << filename <<"' !");
}
const std::string aluid((elType == tetra) ? "!Tetrahedra" : "!Hexahedra");
const std::string oldAluId((elType == tetra) ? "!Tetraeder" : "!Hexaeder");
std::string idline;
std::getline(file,idline);
std::stringstream idstream(idline);
std::string id;
idstream >> id;
if(id == aluid )
{
return;
}
else if ( id == oldAluId )
{
derr << "\nKeyword '" << oldAluId << "' is deprecated! Change it to '" << aluid << "' in file '" << filename<<"'! \n";
return ;
}
else
{
std::cerr << "Delivered file '"<<filename<<"' does not contain keyword '"
<< aluid << "'. Found id '" <<id<< "'. Check the macro grid file! Bye." << std::endl;
DUNE_THROW(IOError,"Wrong file format! ");
}
}
template< int dim, int dimworld, ALU3dGridElementType elType, class Comm >
alu_inline
void ALU3dGrid< dim, dimworld, elType, Comm >::checkMacroGrid ()
{
typedef typename ALU3dImplTraits< elType, Comm >::HElementType HElementType;
typedef ALU3DSPACE PureElementLeafIterator< HElementType > IteratorType;
IteratorType w( this->myGrid() );
for (w->first () ; ! w->done () ; w->next ())
{
ALU3dGridElementType type = (ALU3dGridElementType) w->item().type();
if( type != elType )
{
derr << "\nERROR: " << elType2Name(elType) << " Grid tries to read a ";
derr << elType2Name(type) << " macro grid file! \n\n";
alugrid_assert (type == elType);
DUNE_THROW(GridError,"\nERROR: " << elType2Name(elType) << " Grid tries to read a " << elType2Name(type) << " macro grid file! ");
}
}
}
alu_inline
const char * elType2Name( ALU3dGridElementType elType )
{
switch( elType )
{
case tetra : return "Tetrahedra";
case hexa : return "Hexahedra";
case mixed : return "Mixed";
default : return "Error";
}
}
#if COMPILE_ALUGRID_LIB
// Instantiation
template class ALU3dGrid< 2, 2, hexa, ALUGridNoComm >;
template class ALU3dGrid< 2, 2, tetra, ALUGridNoComm >;
template class ALU3dGrid< 2, 2, hexa, ALUGridMPIComm >;
template class ALU3dGrid< 2, 2, tetra, ALUGridMPIComm >;
//2-3
template class ALU3dGrid< 2, 3, hexa, ALUGridNoComm >;
template class ALU3dGrid< 2, 3, tetra, ALUGridNoComm >;
template class ALU3dGrid< 2, 3, hexa, ALUGridMPIComm >;
template class ALU3dGrid< 2, 3, tetra, ALUGridMPIComm >;
//3-3
template class ALU3dGrid< 3, 3, hexa, ALUGridNoComm >;
template class ALU3dGrid< 3, 3, tetra, ALUGridNoComm >;
template class ALU3dGrid< 3, 3, hexa, ALUGridMPIComm >;
template class ALU3dGrid< 3, 3, tetra, ALUGridMPIComm >;
#endif // #if COMPILE_ALUGRID_LIB
} // end namespace Dune
#endif // end DUNE_ALUGRID_GRID_IMP_CC