diff --git a/misc/examples/sizes.cc b/misc/examples/sizes.cc index 04b32ddb370f1c91db69e98dbccde6922ec8a1f5..cec4fe604c3ff0069775aecbd33a4dddc0120dc8 100644 --- a/misc/examples/sizes.cc +++ b/misc/examples/sizes.cc @@ -12,7 +12,7 @@ using namespace std; -#define PARALLEL +// #define PARALLEL #define COUNT_FLOPS @@ -83,7 +83,7 @@ void checkRefinements( GitterType& grid ) // refine grid globally, i.e. mark all elements and then call adapt template <class GitterType> -void globalRefine(GitterType& grid, bool global) +void globalRefine(GitterType& grid, bool global,int step) { { if (global) @@ -109,10 +109,16 @@ void globalRefine(GitterType& grid, bool global) } // adapt grid grid.adapt (); + grid.printsize () ; } else { + double t = double(step)/10.; double center[3] = {0.2,0.2,0.2}; + double dir[3] = {1.0,0.0,0.0}; + center[0] += dir[0]*t; + center[1] += dir[1]*t; + center[2] += dir[2]*t; double rad=0.6; grid.refineBall(center,rad,10); } @@ -171,16 +177,19 @@ int main (int argc, char ** argv, const char ** envp) { MPI_Init(&argc,&argv); - int mxl = 0; + int mxl = 0, glb = 0; const char* filename = 0 ; if (argc < 2) { filename = "../macrogrids/reference.tetra"; mxl = 1; - cout << "usage: "<< argv[0] << " <macro grid> <opt: level> \n"; + glb = 1; + cout << "usage: "<< argv[0] << " <macro grid> <opt: level global> \n"; } else + { filename = argv[ 1 ]; + } { int rank = 0; @@ -196,6 +205,13 @@ int main (int argc, char ** argv, const char ** envp) } else mxl = atoi(argv[2]); + if (argc < 4) + { + if( rank == 0 ) + cout << "Default global refinement = "<< glb << " choosen! \n"; + } + else + glb = atoi(argv[3]); std::string macroname( filename ); @@ -218,84 +234,31 @@ int main (int argc, char ** argv, const char ** envp) //cout << "P[ " << rank << " ] : Grid generated! \n"; grid.printsize(); cout << "---------------------------------------------\n"; - /* + grid.printMemUsage(); - for (int i = 0; i < 6; ++i) - globalRefine(grid, true); - */ - - //int bla; - // cin >> bla; - for( int i = 0; i <= mxl; ++i ) + for (int i = 0; i < glb; ++i) + globalRefine(grid, true,-1); + for (int i = 0; i < glb; ++i) + globalRefine(grid, false,0); + for( int i = 0; i < mxl; ++i ) { std::ostringstream ss; ss << "out-" << ZeroPadNumber(i) << ".vtu"; grid.tovtk( ss.str().c_str() ); - if( i < mxl ) - globalRefine(grid, false); + globalRefine(grid, false,i); } - -#if 0 - checkRefinements( grid ); - - std::ofstream file( "file.out" ); - grid.duneBackup( file ); - file.close(); - - /* { - ObjectStream os ; - grid.duneBackup( os ); - - char* buffer = ObjectStream ::allocateBuffer( os.size() ); - os.read( buffer, os.size() ); - - std::ofstream obj( "obj.out" ); - const size_t size = os.size(); - obj.write( (const char *) &size, sizeof( size_t ) ); - obj.write( buffer, size ); - ObjectStream :: freeBuffer( buffer ); + std::ostringstream ss; + ss << "out-" << ZeroPadNumber(mxl) << ".vtu"; + grid.tovtk( ss.str().c_str() ); } - - globalRefine(grid, mxl); - - { - size_t size = 0; - - std::ifstream obj( "obj.out" ); - obj.read( (char *) &size, sizeof( size_t ) ); - char * buffer = ObjectStream ::allocateBuffer( size ); - obj.read( buffer, size ); - //ObjectStream :: freeBuffer( buffer ); - - ObjectStream is; - is.clear(); - is.write( buffer, size ); - - { - ObjectStream copy( is ); - std::ofstream obj( "check.out" ); - const size_t size = copy.size(); - obj.write( buffer, size ); - //ObjectStream :: freeBuffer( buffer ); - } - }*/ - + globalCoarsening(grid,3*glb); { - std::ifstream file( "file.out" ); -#ifdef PARALLEL - MpAccessMPI a (MPI_COMM_WORLD); - GitterDunePll grid2( file, a); -#else - GitterDuneImpl grid2( file ); -#endif - grid2.printsize(); + std::ostringstream ss; + ss << "out-" << ZeroPadNumber(mxl+1) << ".vtu"; + grid.tovtk( ss.str().c_str() ); } - //levelwalk(grid, mxl); - // globalCoarsening(grid, mxl); - //grid.printMemUsage(); - //cin.get(); -#endif + return 1; } } diff --git a/src/duneinterface/gitter_dune_pll_impl.cc b/src/duneinterface/gitter_dune_pll_impl.cc index 05876facfdebfceffaabde48ec35b785a5fe8ca8..cc6daaae635fd530c1b33486e790a25e99803c6b 100644 --- a/src/duneinterface/gitter_dune_pll_impl.cc +++ b/src/duneinterface/gitter_dune_pll_impl.cc @@ -1395,8 +1395,6 @@ void GitterDunePll :: duneRestore(const char *fileName) } void GitterDunePll :: tovtk( const std::string &fn ) { - const bool showbnd = false; - const bool showface = true; const int myrank = mpAccess ().myrank () ; const int nProc = mpAccess ().psize () ; @@ -1405,6 +1403,8 @@ void GitterDunePll :: tovtk( const std::string &fn ) // openfile std::ofstream vtuFile; + Gitter :: tovtk( ss.str() ); +#if 0 vtuFile.open( ss.str().c_str() ); // header info @@ -1642,6 +1642,7 @@ void GitterDunePll :: tovtk( const std::string &fn ) vtuFile << "</VTKFile>" << std::endl; vtuFile.close(); +#endif if( myrank == 0 ) { diff --git a/src/serial/gitter_geo.cc b/src/serial/gitter_geo.cc index 5cf293f7f3958ca6aea895d65dd0e943a879186d..7127383ab27ebb6146707a1009c31c5394d3044b 100644 --- a/src/serial/gitter_geo.cc +++ b/src/serial/gitter_geo.cc @@ -549,9 +549,9 @@ int Gitter :: Geometric :: Tetra :: tagForBallRefinement (const alucoord_t (&cen } } #endif - return hit ? (request (myrule_t :: bisect), 1) : (request (myrule_t :: nosplit), 0); - // (level () < limit ? (request (myrule_t :: iso8), 1) - // : (request (myrule_t :: nosplit), 0)) : (request (myrule_t :: crs), 1) ; + if (!hit) return (request (myrule_t :: crs), 1) ; + if (level()>limit) return (request (myrule_t :: nosplit), 0); + return (request (myrule_t :: bisect), 1); } // ###### ##### diff --git a/src/serial/gitter_sti.cc b/src/serial/gitter_sti.cc index 732416b7a9938c0fe9d89cf8ee31f27bb2e9bb92..94124c2cc9771b4f8e43bb47a7dd7586ec468d21 100644 --- a/src/serial/gitter_sti.cc +++ b/src/serial/gitter_sti.cc @@ -312,13 +312,22 @@ bool Gitter :: markNonConform() { bool x = true ; leaf_element__macro_element__iterator i (container ()) ; - // std::cout << "check non conform refinement" << std::endl; for( i.first(); ! i.done() ; i.next()) { x &= i.item ().markNonConform () ; } return x; } +void Gitter :: markEdgeCoarsening () +{ + edgeCoarseningFlags_.assign( indexManagerStorage().get(2).getMaxIndex(), true ); + leaf_element__macro_element__iterator i (container ()) ; + for( i.first(); ! i.done() ; i.next() ) + { + i.item().markEdgeCoarsening(); + } +} void Gitter :: coarse() { + markEdgeCoarsening(); assert (debugOption (20) ? (cout << "**INFO Gitter :: coarse ()" << endl, 1) : 1) ; { AccessIterator < helement_STI > :: Handle i (container ()) ; @@ -327,10 +336,18 @@ void Gitter :: coarse() i.item ().coarse () ; } } + std::ostringstream ss; + int filenr = adaptstep*100+nr; + ss << "crs-" << ZeroPadNumber(filenr) << ".vtu"; + tovtk( ss.str() ); + ++nr; } void Gitter :: tovtk( const std::string &fn ) { + const bool showbnd = false; + const bool showface = true; + // openfile std::ofstream vtuFile; vtuFile.open( fn.c_str() ); @@ -346,30 +363,54 @@ void Gitter :: tovtk( const std::string &fn ) VertexList vertexList; int nCells = 0; - - typedef Gitter :: Geometric :: tetra_GEO tetra_GEO ; + int nBnd = 0; + int nFaces = 0; +#if 1 typedef LeafIterator < Gitter::helement_STI > Iterator; - // typedef LevelIterator < Gitter::helement_STI > Iterator; Iterator w (*this) ; - + typedef LeafIterator < Gitter::hbndseg_STI > BndIterator; + BndIterator wbnd (*this) ; + typedef LeafIterator < Gitter::hface_STI > FaceIterator; + FaceIterator wface (*this) ; +#else + typedef LevelIterator < Gitter::helement_STI > Iterator; + Iterator w (*this,0) ; + typedef LevelIterator < Gitter::hbndseg_STI > BndIterator; + BndIterator wbnd (*this,0) ; + typedef LevelIterator < Gitter::hface_STI > FaceIterator; + FaceIterator wface (*this,0) ; +#endif + typedef Geometric :: tetra_GEO tetra ; + typedef Geometric :: hbndseg3_GEO bndseg ; + typedef Geometric :: hface3_GEO face; // loop to find vertexList and count cells { for (w->first () ; ! w->done () ; w->next ()) { - tetra_GEO* item = ((tetra_GEO *) &w->item ()); - for (int i=0;i<4;++i) - { - Vertex v(3); - for (int k=0;k<3;++k) - v[k] = item->myvertex(i)->Point()[k]; - vertexList[ item->myvertex(i)->getIndex() ] = make_pair(-1,v); - } - ++nCells; + tetra* item = ((tetra *) &w->item ()); + for (int i=0;i<4;++i) + { + Vertex v(3); + for (int k=0;k<3;++k) + v[k] = item->myvertex(i)->Point()[k]; + vertexList[ item->myvertex(i)->getIndex() ] = make_pair(-1,v); + } + ++nCells; + } + if (showbnd) + { + for (wbnd->first () ; ! wbnd->done () ; wbnd->next ()) + ++nBnd; + } + if (showface) + { + for (wface->first () ; ! wface->done () ; wface->next ()) + ++nFaces; } } vtuFile << " <Piece NumberOfPoints=\"" << vertexList.size() << "\" " - << "NumberOfCells=\"" << nCells << "\">" << std::endl; + << "NumberOfCells=\"" << nCells+nBnd+nFaces << "\">" << std::endl; // cell data { @@ -379,9 +420,69 @@ void Gitter :: tovtk( const std::string &fn ) for (w->first () ; ! w->done () ; w->next ()) { - vtuFile << w->item ().getIndex() << " "; + tetra* item = ((tetra *) &w->item ()); + // vtuFile << item->getIndex() << " "; + bool ok = true; + for (int k=0;k<4;++k) + ok &= item->myneighbour( k ).first->isRealObject(); + if (!ok) + { + std::cout << "Problem: " << item << std::endl; + for (int k=0;k<4;++k) + if (!item->myneighbour( k ).first->isRealObject()) + { + std::cout << item->myhface3(k) << std::endl; + if ( item->myhface3(k)->nb.front().first->isRealObject() ) + { + std::cout << item->myhface3(k)->nb.front().first << std::endl; + std::cout << ((bndseg *) item->myhface3(k)->nb.front().first)->myhface3(0) << std::endl; + } + if ( item->myhface3(k)->nb.rear().first->isRealObject() ) + { + std::cout << item->myhface3(k)->nb.rear().first << std::endl; + std::cout << ((bndseg *) item->myhface3(k)->nb.rear().first)->myhface3(0) << std::endl; + } + std::cout << std::endl; + } + std::cout << std::endl; + } + + vtuFile << ((ok)?1:-1) << " "; } + vtuFile << std::endl; + if (showbnd) + for (wbnd->first () ; ! wbnd->done () ; wbnd->next ()) + { + bndseg* item = ((bndseg *) &wbnd->item ()); + bool ok = true; + ok &= item->myhface3(0)->nb.front().first->isRealObject(); + ok &= item->myhface3(0)->nb.rear().first->isRealObject(); + if (!ok) + { + if ( item->myhface3(0)->nb.front().first->isRealObject() ) + assert( item->myhface3(0)->nb.front().first == item ); + if ( item->myhface3(0)->nb.rear().first->isRealObject() ) + assert( item->myhface3(0)->nb.rear().first == item ); + std::cout << "Problem: " << item << std::endl; + std::cout << item->myhface3(0) << std::endl; + std::cout << item->myhface3(0)->nb.front().first << std::endl; + std::cout << item->myhface3(0)->nb.rear().first << std::endl; + std::cout << std::endl; + } + vtuFile << ((ok)?1:-1)*item->myhface3(0)->ref << " "; + } + if (showface) + for (wface->first () ; ! wface->done () ; wface->next ()) + { + face* item = ((face *) &wface->item ()); + bool ok = true; + ok &= item->nb.front().first->isRealObject(); + ok &= item->nb.rear().first->isRealObject(); + assert(item->ref>0); + vtuFile << ((ok)?1:-1)*item->ref << " "; + } + vtuFile << std::endl; vtuFile << " </DataArray>" << std::endl; vtuFile << " </CellData>" << std::endl; @@ -413,12 +514,30 @@ void Gitter :: tovtk( const std::string &fn ) for (w->first () ; ! w->done () ; w->next ()) { - tetra_GEO* item = ((tetra_GEO *) &w->item ()); - for (int i=0;i<4;++i) + tetra* item = ((tetra *) &w->item ()); + for (int i=0;i<4;++i) + { + vtuFile << " " << vertexList[item->myvertex(i)->getIndex()].first; + } + } + if (showbnd) + for (wbnd->first () ; ! wbnd->done () ; wbnd->next ()) { - vtuFile << " " << vertexList[item->myvertex(i)->getIndex()].first; + bndseg* item = ((bndseg *) &wbnd->item ()); + for (int i=0;i<3;++i) + { + vtuFile << " " << vertexList[item->myvertex(0,i)->getIndex()].first; + } + } + if (showface) + for (wface->first () ; ! wface->done () ; wface->next ()) + { + face* item = ((face *) &wface->item ()); + for (int i=0;i<3;++i) + { + vtuFile << " " << vertexList[item->myvertex(i)->getIndex()].first; + } } - } vtuFile << std::endl; vtuFile << " </DataArray>" << std::endl; @@ -428,7 +547,15 @@ void Gitter :: tovtk( const std::string &fn ) for( int i = 0; i < nCells; ++i ) { - vtuFile << " " << (i+1)*4; + vtuFile << " " << (i+1)*4; + } + for( int i = 0; i < nBnd; ++i ) + { + vtuFile << " " << nCells*4 + (i+1)*3; + } + for( int i = 0; i < nFaces; ++i ) + { + vtuFile << " " << nCells*4 + nBnd*3 + (i+1)*3; } vtuFile << std::endl; @@ -440,13 +567,20 @@ void Gitter :: tovtk( const std::string &fn ) for( int i = 0; i < nCells; ++i ) { - vtuFile << " " << 10; // 10 for tetrahedra + vtuFile << " " << 10; // 10 for tetrahedra + } + for( int i = 0; i < nBnd; ++i ) + { + vtuFile << " " << 5; // 5 for triangle + } + for( int i = 0; i < nFaces; ++i ) + { + vtuFile << " " << 5; // 5 for trianglea } vtuFile << std::endl; vtuFile << " </DataArray>" << std::endl; } - vtuFile << " </Cells>" << std::endl; vtuFile << " </Piece>" << std::endl; vtuFile << " </UnstructuredGrid>" << std::endl; @@ -467,11 +601,9 @@ bool Gitter :: adapt () do { refined &= refine (); // check for conformity - // if noconform break; - std::cout << "check non conform refinement" << std::endl; x = markNonConform(); } - while (!x); // need something here on required conformity + while (!x); if (!refined) { cerr << "**WARNUNG (IGNORIERT) Verfeinerung nicht vollst\"andig (warum auch immer)\n" ; @@ -480,6 +612,7 @@ bool Gitter :: adapt () } int lap = clock () ; coarse () ; + assert ( markNonConform() ); int end = clock () ; if (debugOption (1)) { float u1 = (float)(lap - start)/(float)(CLOCKS_PER_SEC) ; diff --git a/src/serial/gitter_sti.h b/src/serial/gitter_sti.h index 96a5056526dbe0efe75e9efe6502091bbeaddaab..2e33217854e998a5f007bbf1c17855efcc7630f7 100644 --- a/src/serial/gitter_sti.h +++ b/src/serial/gitter_sti.h @@ -573,6 +573,8 @@ public : virtual void backupIndex (ObjectStream& os ) const { backupIndexErr(); } virtual void restoreIndex (ObjectStream& is, RestoreInfo& ) { restoreIndexErr(); } + + virtual bool canCoarsen( std::vector<bool> &edgeCoarseningFlags ) const; } ; class hface : public FacePllXDefault, @@ -687,6 +689,7 @@ public : virtual int segmentIndex (const int) const { return -1; } virtual bool markNonConform () = 0; + virtual void markEdgeCoarsening () = 0; // mark element for using iso8 rule virtual int tagForGlobalRefinement () = 0 ; // mark element for coarsening @@ -1564,6 +1567,7 @@ public : virtual myrule_t getrule () const = 0 ; virtual void request (myrule_t) = 0 ; virtual bool markNonConform () { return true; } + virtual void markEdgeCoarsening () { } int tagForGlobalRefinement () ; int tagForGlobalCoarsening () ; int resetRefinementRequest () ; @@ -1655,6 +1659,7 @@ public : virtual myrule_t requestrule () const = 0; virtual void request (myrule_t) = 0 ; virtual bool markNonConform () { return true; } + virtual void markEdgeCoarsening () { } int tagForGlobalRefinement () ; int tagForGlobalCoarsening () ; int resetRefinementRequest () ; @@ -1728,6 +1733,7 @@ public : virtual myrule_t getrule () const = 0 ; virtual void request (myrule_t) = 0 ; virtual bool markNonConform () { return true; } + virtual void markEdgeCoarsening () { } int tagForGlobalRefinement () ; int tagForGlobalCoarsening () ; int resetRefinementRequest () ; @@ -1778,6 +1784,7 @@ public : virtual bool isperiodic() const { return false; } virtual bool markNonConform () { return true; } + virtual void markEdgeCoarsening () { } virtual int nChild () const; // just returns level virtual int nbLevel() const { return level(); } @@ -1827,6 +1834,7 @@ public : inline hface4_GEO * subface4 (int,int) const ; virtual bool markNonConform () { return true; } + virtual void markEdgeCoarsening () { } virtual bool isboundary() const { return true; } virtual bool isperiodic() const { return false; } virtual int nChild () const; @@ -2026,6 +2034,7 @@ protected : // methods for refining and coarsening virtual bool refine () ; virtual bool markNonConform () ; + virtual void markEdgeCoarsening () ; virtual void coarse () ; virtual Makrogitter & container () = 0 ; @@ -2096,6 +2105,10 @@ protected: friend class LevelIterator < hbndseg_STI > ; friend class LevelIterator < hedge_STI > ; friend class LevelIterator < hface_STI > ; + + public: + // flags to say if an edge can be coarsened during conform bisection + mutable std::vector<bool> edgeCoarseningFlags_; } ; // --endGitter @@ -2820,6 +2833,18 @@ inline const Gitter :: Geometric :: hedge1 :: myvertex_t * Gitter :: Geometric : return i == 1 ? v1 : v0 ; } + + +inline bool Gitter :: hedge :: canCoarsen( std::vector<bool> &edgeCoarseningFlags ) const +{ + int idx = this->getIndex(); + if ( !edgeCoarseningFlags[ idx ] ) return false; + if ( this->down() ) return this->down()->canCoarsen( edgeCoarseningFlags ); + if ( this->next() ) return this->next()->canCoarsen( edgeCoarseningFlags ); + return true; +} + + // # # ##### ###### // # # ###### ## #### ###### # # # # # # # ###### // # # # # # # # # # # # # # # # @@ -3031,8 +3056,8 @@ Gitter :: Geometric :: hface3 :: face3Neighbour :: setPrevRear ( ) inline void Gitter :: Geometric :: hface3 :: face3Neighbour :: operator = (const face3Neighbour & n) { - frontList_ = n.frontList_; - rearList_ = n.rearList_; + frontList_.clear(); + rearList_.clear(); _faceFront = n._faceFront; _faceRear = n._faceRear; _numFront = n._numFront; @@ -3043,6 +3068,7 @@ inline void Gitter :: Geometric :: hface3 :: face3Neighbour :: operator = (const inline int Gitter :: Geometric :: hface3 :: face3Neighbour :: complete (const face3Neighbour & n) { int ret = 0; + // assert(0); if( front() == null ) { @@ -3109,7 +3135,6 @@ inline void Gitter :: Geometric :: hface3 :: attachElement (const pair < myconne ref ++ ; if (t>=0 && nb.frontList_.size()==0) ref ++ ; - if( t < 0 ) nb.setRear( p ); else diff --git a/src/serial/gitter_tetra_top.cc b/src/serial/gitter_tetra_top.cc index 34a97cd5e28bd4c5e43a696b9d0f772c2a046961..40475c5757da3e88b1d0bf66b4d41fc3dff2e633 100644 --- a/src/serial/gitter_tetra_top.cc +++ b/src/serial/gitter_tetra_top.cc @@ -422,7 +422,6 @@ template < class A > bool Hface3Top < A > :: coarse () // vollst"andigt, die eventuell durch Elementvergr"oberung // durcheinander gekommen war. Die Vergr"oberung geht dann // auf das n"achste Level "uber. - if (f->ref) { if (f->ref == 1) f->nb.complete (this->nb) ; f->coarse () ; @@ -2103,6 +2102,7 @@ template < class A > bool TetraTop < A > :: coarse () { if (this->leaf ()) { + if (!up()) return false; assert (_req == myrule_t :: nosplit || _req == myrule_t :: crs) ; myrule_t w = _req ; _req = myrule_t :: nosplit ; @@ -2132,12 +2132,34 @@ template < class A > bool TetraTop < A > :: coarse () // not faces that are not leaf if (x) { + // test marking on refinement edge + assert( this->nEdges() == 6 ); + // int e = getrule()-2; // did not work.... + for (int e=0;e<6;++e) + { + myhedge1_t *edge = this->myhedge1(e); + if ( edge->down() ) + { + int idx = edge->getIndex(); + if ( !this->myGrid()->edgeCoarseningFlags_[ idx ] ) + return false; + // we need to make sure that none of the children of this + // refinement edge should not be removed + // (we could not go up on edges during marking so we go down here) + if (! edge->down()->canCoarsen( this->myGrid()->edgeCoarseningFlags_ ) ) + { + return false; + } + } + } + this->preCoarsening () ; this->attachleafs(); delete _inner ; _inner = 0 ; +#if 0 // for bisection refinement we have to again // set the face neighbours, since they have been overwritten // by the refined element @@ -2158,6 +2180,7 @@ template < class A > bool TetraTop < A > :: coarse () } } } +#endif // reset refinement rule _rule = myrule_t :: nosplit ; diff --git a/src/serial/gitter_tetra_top.h b/src/serial/gitter_tetra_top.h index 3496dd23c581d12c6780641ba651aced1c3a77b3..e423a744ed011fa225c5087f2451ac7d659486b6 100644 --- a/src/serial/gitter_tetra_top.h +++ b/src/serial/gitter_tetra_top.h @@ -403,7 +403,6 @@ template < class A > class TetraTop : public A assert( this->nEdges() == 6 ); for (int e=0; e < 6; ++e) { - // std::cout << this->myhedge1(e) << std::endl; if( this->myhedge1(e)->down() ) { this->request ( myrule_t :: bisect ); @@ -412,6 +411,24 @@ template < class A > class TetraTop : public A } return true; } + virtual void markEdgeCoarsening () + { + assert( this->nEdges() == 6 ); + if (!this->up()) return; + for (int e=0; e<6; ++e) + { + myhedge1_t *edge = this->up()->myhedge1(e); + // if (e == (int)(this->up()->getrule())-2) // does not seem to // work... + if (_req == myrule_t :: crs && edge->down()) // the father of a leaf element can only have one non leaf edge + { // we leave thing as they are + } + else + { + int idx = edge->getIndex(); + this->myGrid()->edgeCoarseningFlags_[ idx ] = false; + } + } + } void refineImmediate (myrule_t) ; inline void append (innertetra_t * h) ;