156 :
public GridDefaultImplementation
157 < dim, dimworld, coord_t, PolyhedralGridFamily< dim, dimworld, coord_t > >
162 typedef GridDefaultImplementation
171 inline void operator () ( UnstructuredGridType* grdPtr )
173 destroy_grid( grdPtr );
178 typedef std::unique_ptr< UnstructuredGridType, UnstructuredGridDeleter > UnstructuredGridPtr;
180 static UnstructuredGridPtr
181 allocateGrid ( std::size_t nCells, std::size_t nFaces, std::size_t nFaceNodes, std::size_t nCellFaces, std::size_t nNodes )
184 UnstructuredGridType *grid = allocate_grid( dimworld, nCells, nFaces, nFaceNodes, nCellFaces, nNodes );
186 DUNE_THROW( GridError,
"Unable to allocate grid" );
187 return UnstructuredGridPtr( grid );
191 computeGeometry ( UnstructuredGridPtr& ug )
197 compute_geometry( ugPtr );
201 typedef PolyhedralGridFamily< dim, dimworld, coord_t > GridFamily;
208 typedef typename GridFamily::Traits
Traits;
216 template<
int codim >
237 template< PartitionIteratorType pitype >
240 typedef typename GridFamily::Traits::template Partition< pitype >::LevelGridView LevelGridView;
241 typedef typename GridFamily::Traits::template Partition< pitype >::LeafGridView LeafGridView;
246 typedef typename Partition< All_Partition >::LeafGridView LeafGridView;
308 typedef typename Traits::ctype
ctype;
314 typedef typename Traits :: GlobalCoordinate GlobalCoordinate;
328 const std::vector<double>& poreVolumes = std::vector<double>{},
329 const bool edge_conformal =
false)
330 : gridPtr_ { createGrid(inputGrid, poreVolumes, static_cast<int>(edge_conformal)) }
331 , grid_ { *gridPtr_ }
332 , comm_ { MPIHelper::getCommunicator() }
333 , leafIndexSet_ { *this }
334 , globalIdSet_ { *this }
335 , localIdSet_ { *this }
336 , nBndSegments_ { 0 }
348 const std::vector< double >& dx )
349 : gridPtr_( createGrid( n, dx ) ),
351 comm_( MPIHelper::getCommunicator()),
352 leafIndexSet_( *this ),
353 globalIdSet_( *this ),
354 localIdSet_( *this ),
367 : gridPtr_( std::move( gridPtr ) ),
369 comm_( MPIHelper::getCommunicator() ),
370 leafIndexSet_( *this ),
371 globalIdSet_( *this ),
372 localIdSet_( *this ),
388 comm_( MPIHelper::getCommunicator() ),
389 leafIndexSet_( *this ),
390 globalIdSet_( *this ),
391 localIdSet_( *this ),
401 operator const UnstructuredGridType& ()
const {
return grid_; }
428 int size (
int ,
int codim )
const
430 return size( codim );
443 return grid_.number_of_cells;
445 else if ( codim == 1 )
447 return grid_.number_of_faces;
449 else if ( codim == dim )
451 return grid_.number_of_nodes;
455 std::cerr <<
"Warning: codimension " << codim <<
" not available in PolyhedralGrid" << std::endl;
468 int size (
int , GeometryType type )
const
470 return size( dim - type.dim() );
477 int size ( GeometryType type )
const
479 return size( dim - type.dim() );
490 return nBndSegments_;
494 template<
int codim >
497 return leafbegin< codim, All_Partition >();
500 template<
int codim >
503 return leafend< codim, All_Partition >();
506 template<
int codim, PartitionIteratorType pitype >
511 return Impl( extraData(),
true );
514 template<
int codim, PartitionIteratorType pitype >
519 return Impl( extraData(),
false );
522 template<
int codim >
525 return leafbegin< codim, All_Partition >();
528 template<
int codim >
531 return leafend< codim, All_Partition >();
534 template<
int codim, PartitionIteratorType pitype >
536 lbegin (
const int )
const
538 return leafbegin< codim, pitype > ();
541 template<
int codim, PartitionIteratorType pitype >
543 lend (
const int )
const
545 return leafend< codim, pitype > ();
560 return leafIndexSet();
565 return leafIndexSet_;
568 void globalRefine (
int )
598 template<
class DataHandle >
627 return (codim == 0 ) ? 1 : 0;
663 template<
class DataHandle>
666 CommunicationDirection ,
669 OPM_THROW(std::runtime_error,
"communicate not implemented for polyhedreal grid!");
684 template<
class DataHandle>
687 CommunicationDirection )
const
689 OPM_THROW(std::runtime_error,
"communicate not implemented for polyhedreal grid!");
695 OPM_THROW(std::runtime_error,
"switch to global view not implemented for polyhedreal grid!");
701 OPM_THROW(std::runtime_error,
"switch to distributed view not implemented for polyhedreal grid!");
712 const CommunicationType &
comm ()
const
748 template<
class DataHandle,
class Data >
768 template<
class DofManager >
775 template< PartitionIteratorType pitype >
778 typedef typename Partition< pitype >::LevelGridView View;
779 typedef typename View::GridViewImp ViewImp;
780 return View( ViewImp( *
this ) );
784 template< PartitionIteratorType pitype >
787 typedef typename Traits::template Partition< pitype >::LeafGridView View;
788 typedef typename View::GridViewImp ViewImp;
789 return View( ViewImp( *
this ) );
795 typedef typename LevelGridView::GridViewImp ViewImp;
802 typedef typename LeafGridView::GridViewImp ViewImp;
803 return LeafGridView( ViewImp( *
this ) );
807 template<
class EntitySeed >
812 typedef typename Traits::template Codim< EntitySeed::codimension >::EntityPointerImpl EntityPointerImpl;
813 typedef typename Traits::template Codim< EntitySeed::codimension >::EntityImpl EntityImpl;
814 return EntityPointer( EntityPointerImpl( EntityImpl( extraData(), seed ) ) );
818 template<
class EntitySeed >
822 typedef typename Traits::template Codim< EntitySeed::codimension >::EntityImpl EntityImpl;
823 return EntityImpl( extraData(), seed );
845 const std::array<int, 3>& logicalCartesianSize()
const
850 const int* globalCell()
const
856 const int* globalCellPtr()
const
858 return grid_.global_cell;
861 void getIJK(
const int c, std::array<int,3>& ijk)
const
863 int gc = globalCell()[c];
864 ijk[0] = gc % logicalCartesianSize()[0]; gc /= logicalCartesianSize()[0];
865 ijk[1] = gc % logicalCartesianSize()[1];
866 ijk[2] = gc / logicalCartesianSize()[1];
883 template<
class DataHandle>
886 OPM_THROW(std::runtime_error,
"ScatterData not implemented for polyhedral grid!");
891 UnstructuredGridType*
892 createGrid(
const Opm::EclipseGrid& inputGrid,
893 const std::vector<double>& poreVolumes,
894 const bool edge_conformal)
const
898 g.
dims[0] = inputGrid.getNX();
899 g.
dims[1] = inputGrid.getNY();
900 g.
dims[2] = inputGrid.getNZ();
902 std::vector<double> coord = inputGrid.getCOORD( );
903 std::vector<double> zcorn = inputGrid.getZCORN( );
904 std::vector<int> actnum = inputGrid.getACTNUM( );
906 g.
coord = coord.data();
907 g.
zcorn = zcorn.data();
910 const double z_tolerance = inputGrid.isPinchActive() ? inputGrid.getPinchThresholdThickness() : 0.0;
912 if (!poreVolumes.empty() && (inputGrid.getMinpvMode() != Opm::MinpvMode::Inactive))
915 const std::vector<double>& minpvv = inputGrid.getMinpvVector();
920 const size_t cartGridSize = g.
dims[0] * g.
dims[1] * g.
dims[2];
921 std::vector<double> thickness(cartGridSize);
922 for (
size_t i = 0; i < cartGridSize; ++i) {
923 thickness[i] = inputGrid.getCellThickness(i);
925 mp.process(thickness, z_tolerance, inputGrid.getPinchMaxEmptyGap() , poreVolumes,
926 minpvv, actnum, opmfil, zcorn.data());
940 UnstructuredGridType* cgrid = create_grid_cornerpoint
941 (&g, z_tolerance,
static_cast<int>(edge_conformal));
943 if (cgrid ==
nullptr) {
944 OPM_THROW(std::runtime_error,
"Failed to construct grid.");
951 UnstructuredGridType* createGrid(
const std::vector< int >& n,
const std::vector< double >& dx )
const
953 UnstructuredGridType* cgrid = nullptr ;
954 assert(
int(n.size()) == dim );
957 cgrid = create_grid_cart2d( n[ 0 ], n[ 1 ], dx[ 0 ], dx[ 1 ] );
961 cgrid = create_grid_hexa3d( n[ 0 ], n[ 1 ], n[ 2 ], dx[ 0 ], dx[ 1 ], dx[ 2 ] );
966 OPM_THROW(std::runtime_error,
"Failed to construct grid.");
972 typedef typename Traits :: ExtraData ExtraData;
973 ExtraData extraData ()
const {
return this; }
975 template <
class EntitySeed>
976 int corners(
const EntitySeed& seed )
const
978 const int codim = EntitySeed :: codimension;
979 const int index = seed.index();
981 return cellVertices_[ index ].size();
983 return grid_.face_nodepos[ index+1 ] - grid_.face_nodepos[ index ];
989 template <
class EntitySeed>
991 corner (
const EntitySeed& seed,
const int i )
const
993 const int codim = EntitySeed :: codimension;
996 const int coordIndex = GlobalCoordinate :: dimension * cellVertices_[ seed.index() ][ i ];
997 return copyToGlobalCoordinate( grid_.node_coordinates + coordIndex );
1004 const int crners = corners( seed );
1005 const int crner = (crners == 4 && EntitySeed :: dimension == 3 && i > 1 ) ? 5 - i : i;
1006 const int faceVertex = grid_.face_nodes[ grid_.face_nodepos[seed.index() ] + crner ];
1007 return copyToGlobalCoordinate( grid_.node_coordinates + GlobalCoordinate :: dimension * faceVertex );
1011 const int coordIndex = GlobalCoordinate :: dimension * seed.index();
1012 return copyToGlobalCoordinate( grid_.node_coordinates + coordIndex );
1014 return GlobalCoordinate( 0 );
1017 template <
class EntitySeed>
1018 int subEntities(
const EntitySeed& seed,
const int codim )
const
1020 const int index = seed.index();
1021 if( seed.codimension == 0 )
1026 return grid_.cell_facepos[ index+1 ] - grid_.cell_facepos[ index ];
1028 return cellVertices_[ index ].size();
1030 else if( seed.codimension == 1 )
1035 return grid_.face_nodepos[ index+1 ] - grid_.face_nodepos[ index ];
1037 else if ( seed.codimension == dim )
1045 template <
int codim,
class EntitySeedArg >
1047 subEntitySeed(
const EntitySeedArg& baseSeed,
const int i )
const
1049 assert( codim >= EntitySeedArg::codimension );
1050 assert( i>= 0 && i<subEntities( baseSeed, codim ) );
1054 if( codim == EntitySeedArg::codimension )
1056 return EntitySeed( baseSeed.index() );
1059 if( EntitySeedArg::codimension == 0 )
1063 return EntitySeed( grid_.cell_faces[ grid_.cell_facepos[ baseSeed.index() ] + i ] );
1065 else if ( codim == dim )
1067 return EntitySeed( cellVertices_[ baseSeed.index() ][ i ] );
1070 else if ( EntitySeedArg::codimension == 1 && codim == dim )
1072 return EntitySeed( grid_.face_nodes[ grid_.face_nodepos[ baseSeed.index() + i ] ]);
1075 DUNE_THROW(NotImplemented,
"codimension not available");
1076 return EntitySeed();
1079 template <
int codim>
1083 assert( i>= 0 && i<subEntities( faceSeed, codim ) );
1087 return EntitySeed( faceSeed.index() );
1089 else if ( codim == dim )
1091 return EntitySeed( grid_.face_nodes[ grid_.face_nodepos[ faceSeed.index() ] + i ] );
1095 DUNE_THROW(NotImplemented,
"codimension not available");
1101 const int faces = subEntities( seed, 1 );
1102 for(
int f=0; f<faces; ++f )
1104 const auto faceSeed = this->
template subEntitySeed<1>( seed, f );
1105 if( isBoundaryFace( faceSeed ) )
1111 bool isBoundaryFace(
const int face )
const
1113 assert( face >= 0 && face < grid_.number_of_faces );
1114 const int facePos = 2 * face;
1115 return ((grid_.face_cells[ facePos ] < 0) || (grid_.face_cells[ facePos+1 ] < 0));
1120 assert( faceSeed.isValid() );
1121 return isBoundaryFace( faceSeed.index() );
1126 const auto faceSeed = this->
template subEntitySeed<1>( seed, face );
1127 assert( faceSeed.isValid() );
1128 const int facePos = 2 * faceSeed.index();
1129 const int idx = std::min( grid_.face_cells[ facePos ], grid_.face_cells[ facePos+1 ]);
1135 const std::vector< GeometryType > &geomTypes (
const unsigned int codim )
const
1137 static std::vector< GeometryType > emptyDummy;
1138 if (codim < geomTypes_.size())
1140 return geomTypes_[codim];
1146 template <
class Seed >
1147 GeometryType geometryType(
const Seed& seed )
const
1149 if( Seed::codimension == 0 )
1151 assert(!geomTypes( Seed::codimension ).empty());
1152 return geomTypes( Seed::codimension )[ 0 ];
1157 if( dim == 3 && Seed::codimension == 1 )
1160 const int nVx = corners( seed );
1162 face = Dune::GeometryTypes::cube(2);
1164 face = Dune::GeometryTypes::simplex(2);
1166 face = Dune::GeometryTypes::none(2);
1171 assert(!geomTypes( Seed::codimension ).empty());
1172 return geomTypes( Seed::codimension )[ 0 ];
1178 return ( grid_.cell_facetag ) ? cartesianIndexInInside( seed, i ) : i;
1183 assert( i>= 0 && i<subEntities( seed, 1 ) );
1184 return grid_.cell_facetag[ grid_.cell_facepos[ seed.index() ] + i ] ;
1190 const int face = this->
template subEntitySeed<1>( seed, i ).index();
1191 int nb = grid_.face_cells[ 2 * face ];
1192 if( nb == seed.index() )
1194 nb = grid_.face_cells[ 2 * face + 1 ];
1198 return EntitySeed( nb );
1204 if( grid_.cell_facetag )
1207 const int in_inside = cartesianIndexInInside( seed, i );
1208 return in_inside + ((in_inside % 2) ? -1 : 1);
1213 EntitySeed nb = neighbor( seed, i );
1214 const int faces = subEntities( seed, 1 );
1215 for(
int face = 0; face<faces; ++ face )
1217 if( neighbor( nb, face ).equals(seed) )
1219 return indexInInside( nb, face );
1222 DUNE_THROW(InvalidStateException,
"inverse intersection not found");
1227 template <
class EntitySeed>
1229 outerNormal(
const EntitySeed& seed,
const int i )
const
1231 const int face = this->
template subEntitySeed<1>( seed, i ).index();
1232 const int normalIdx = face * GlobalCoordinate :: dimension ;
1233 GlobalCoordinate normal = copyToGlobalCoordinate( grid_.face_normals + normalIdx );
1234 const int nb = grid_.face_cells[ 2*face ];
1235 if( nb != seed.index() )
1242 template <
class EntitySeed>
1244 unitOuterNormal(
const EntitySeed& seed,
const int i )
const
1246 const int face = this->
template subEntitySeed<1>( seed, i ).index();
1247 if( seed.index() == grid_.face_cells[ 2*face ] )
1249 return unitOuterNormals_[ face ];
1253 GlobalCoordinate normal = unitOuterNormals_[ face ];
1259 template <
class EntitySeed>
1260 GlobalCoordinate centroids(
const EntitySeed& seed )
const
1262 if( ! seed.isValid() )
1263 return GlobalCoordinate( 0 );
1265 const int index = GlobalCoordinate :: dimension * seed.index();
1266 const int codim = EntitySeed::codimension;
1267 assert( index >= 0 && index <
size( codim ) * GlobalCoordinate :: dimension );
1271 return copyToGlobalCoordinate( grid_.cell_centroids + index );
1273 else if ( codim == 1 )
1275 return copyToGlobalCoordinate( grid_.face_centroids + index );
1277 else if( codim == dim )
1279 return copyToGlobalCoordinate( grid_.node_coordinates + index );
1283 DUNE_THROW(InvalidStateException,
"codimension not implemented");
1284 return GlobalCoordinate( 0 );
1288 GlobalCoordinate copyToGlobalCoordinate(
const double* coords )
const
1290 GlobalCoordinate coordinate;
1291 for(
int i=0; i<GlobalCoordinate::dimension; ++i )
1293 coordinate[ i ] = coords[ i ];
1298 template <
class EntitySeed>
1299 double volumes(
const EntitySeed& seed )
const
1301 static const int codim = EntitySeed::codimension;
1302 if( codim == dim || ! seed.isValid() )
1308 assert( seed.isValid() );
1312 return grid_.cell_volumes[ seed.index() ];
1314 else if ( codim == 1 )
1316 return grid_.face_areas[ seed.index() ];
1320 DUNE_THROW(InvalidStateException,
"codimension not implemented");
1330 for(
int i=0; i<3; ++i )
1332 cartDims_[ i ] = grid_.cartdims[ i ];
1336 const int numCells =
size( 0 );
1338 cellVertices_.resize( numCells );
1341 if( grid_.cell_facetag )
1343 typedef std::array<int, 3> KeyType;
1344 std::map< const KeyType, const int > vertexFaceTags;
1345 const int vertexFacePattern [8][3] = {
1356 for(
int i=0; i<8; ++i )
1358 KeyType key; key.fill( 4 );
1359 for(
int j=0; j<dim; ++j )
1361 key[ j ] = vertexFacePattern[ i ][ j ];
1364 vertexFaceTags.insert( std::make_pair( key, i ) );
1367 for (
int c = 0; c < numCells; ++c)
1372 int f = grid_.cell_facepos[ c ];
1373 std::swap( grid_.cell_faces[ f+1 ], grid_.cell_faces[ f+2 ] );
1374 std::swap( grid_.cell_facetag[ f+1 ], grid_.cell_facetag[ f+2 ] );
1377 typedef std::map<int,int> vertexmap_t;
1378 typedef typename vertexmap_t :: iterator iterator;
1380 std::vector< vertexmap_t > cell_pts( dim*2 );
1382 for (
unsigned hf = grid_.cell_facepos[ c ]; hf < grid_.cell_facepos[c+1]; ++hf)
1384 const int f = grid_.cell_faces[ hf ];
1385 const int faceTag = grid_.cell_facetag[ hf ];
1387 for (
unsigned nodepos = grid_.face_nodepos[f]; nodepos < grid_.face_nodepos[f+1]; ++nodepos )
1389 const int node = grid_.face_nodes[ nodepos ];
1390 iterator it = cell_pts[ faceTag ].find( node );
1391 if( it == cell_pts[ faceTag ].end() )
1393 cell_pts[ faceTag ].insert( std::make_pair( node, 1 ) );
1403 typedef std::map< int, std::set<int> > vertexlist_t;
1404 vertexlist_t vertexList;
1406 for(
int faceTag = 0; faceTag<dim*2; ++faceTag )
1408 for( iterator it = cell_pts[ faceTag ].begin(),
1409 end = cell_pts[ faceTag ].end(); it != end; ++it )
1413 if( (*it).second == 1 )
1415 vertexList[ (*it).first ].insert( faceTag );
1420 assert(
int(vertexList.size()) == ( dim == 2 ? 4 : 8) );
1422 cellVertices_[ c ].resize( vertexList.size() );
1423 for(
auto it = vertexList.begin(), end = vertexList.end(); it != end; ++it )
1425 assert( (*it).second.size() == dim );
1426 KeyType key; key.fill( 4 );
1428 std::ranges::copy(it->second, key.begin());
1429 auto vx = vertexFaceTags.find( key );
1430 assert( vx != vertexFaceTags.end() );
1431 if( vx != vertexFaceTags.end() )
1433 if( (*vx).second >=
int(cellVertices_[ c ].size()) )
1434 cellVertices_[ c ].resize( (*vx).second+1 );
1436 cellVertices_[ c ][ (*vx).second ] = (*it).first ;
1442 geomTypes_.resize(dim + 1);
1444 for (
int codim = 0; codim <= dim; ++codim)
1446 tmp = Dune::GeometryTypes::cube(dim - codim);
1447 geomTypes_[codim].push_back(tmp);
1453 int minVx = std::numeric_limits<int>::max();
1455 for (
int c = 0; c < numCells; ++c)
1457 std::set<int> cell_pts;
1458 for (
unsigned hf = grid_.cell_facepos[ c ]; hf < grid_.cell_facepos[c+1]; ++hf)
1460 int f = grid_.cell_faces[ hf ];
1461 const int* fnbeg = grid_.face_nodes + grid_.face_nodepos[f];
1462 const int* fnend = grid_.face_nodes + grid_.face_nodepos[f+1];
1463 cell_pts.insert(fnbeg, fnend);
1466 cellVertices_[ c ].resize( cell_pts.size() );
1467 std::ranges::copy(cell_pts, cellVertices_[c].begin());
1468 maxVx = std::max( maxVx,
int( cell_pts.size() ) );
1469 minVx = std::min( minVx,
int( cell_pts.size() ) );
1472 if( minVx == maxVx && maxVx == 4 )
1474 for (
int c = 0; c < numCells; ++c)
1476 assert( cellVertices_[ c ].
size() == 4 );
1477 GlobalCoordinate center( 0 );
1478 GlobalCoordinate p[ dim+1 ];
1479 for(
int i=0; i<dim+1; ++i )
1481 const int vertex = cellVertices_[ c ][ i ];
1483 for(
int d=0; d<dim; ++d )
1485 center[ d ] += grid_.node_coordinates[ vertex*dim + d ];
1486 p[ i ][ d ] = grid_.node_coordinates[ vertex*dim + d ];
1490 for(
int d=0; d<dim; ++d )
1492 grid_.cell_centroids[ c*dim + d ] = center[ d ];
1495 Dune::GeometryType simplex;
1496 simplex = Dune::GeometryTypes::simplex(dim);
1498 typedef Dune::AffineGeometry< ctype, dim, dimworld> AffineGeometryType;
1499 AffineGeometryType geometry( simplex, p );
1500 grid_.cell_volumes[ c ] = geometry.volume();
1506 const int faces = grid_.number_of_faces;
1507 for(
int face = 0 ; face < faces; ++face )
1509 const int a = grid_.face_cells[ 2*face ];
1510 const int b = grid_.face_cells[ 2*face + 1 ];
1512 assert( a >=0 || b >=0 );
1514 if( grid_.face_areas[ face ] < 0 )
1517 GlobalCoordinate centerDiff( 0 );
1520 for(
int d=0; d<dimworld; ++d )
1522 centerDiff[ d ] = grid_.cell_centroids[ b*dimworld + d ];
1527 for(
int d=0; d<dimworld; ++d )
1529 centerDiff[ d ] = grid_.face_centroids[ face*dimworld + d ];
1535 for(
int d=0; d<dimworld; ++d )
1537 centerDiff[ d ] -= grid_.cell_centroids[ a*dimworld + d ];
1542 for(
int d=0; d<dimworld; ++d )
1544 centerDiff[ d ] -= grid_.face_centroids[ face*dimworld + d ];
1548 GlobalCoordinate normal( 0 );
1549 for(
int d=0; d<dimworld; ++d )
1551 normal[ d ] = grid_.face_normals[ face*dimworld + d ];
1554 if( centerDiff.two_norm() < 1e-10 )
1558 if( centerDiff * normal < 0 )
1560 grid_.face_cells[ 2*face ] = b;
1561 grid_.face_cells[ 2*face + 1 ] = a;
1566 bool allSimplex = true ;
1567 bool allCube = true ;
1569 for (
int c = 0; c < numCells; ++c)
1571 const int nVx = cellVertices_[ c ].size();
1583 geomTypes_.resize(dim + 1);
1585 for (
int codim = 0; codim <= dim; ++codim)
1589 tmp = Dune::GeometryTypes::simplex(dim - codim);
1590 geomTypes_[ codim ].push_back( tmp );
1594 tmp = Dune::GeometryTypes::cube(dim - codim);
1595 geomTypes_[ codim ].push_back( tmp );
1599 tmp = Dune::GeometryTypes::none(dim - codim);
1600 geomTypes_[ codim ].push_back( tmp );
1607 unitOuterNormals_.resize( grid_.number_of_faces );
1608 for(
int face = 0; face < grid_.number_of_faces; ++face )
1610 const int normalIdx = face * GlobalCoordinate :: dimension ;
1611 GlobalCoordinate normal = copyToGlobalCoordinate( grid_.face_normals + normalIdx );
1612 normal /= normal.two_norm();
1613 unitOuterNormals_[ face ] = normal;
1615 if( isBoundaryFace( face ) )
1619 const int facePos = 2 * face ;
1622 if( grid_.face_cells[ facePos ] < 0 )
1624 grid_.face_cells[ facePos ] = -nBndSegments_;
1626 else if ( grid_.face_cells[ facePos+1 ] < 0 )
1628 grid_.face_cells[ facePos+1 ] = -nBndSegments_;
1634 void print( std::ostream& out,
const UnstructuredGridType& grid )
const
1636 const int numCells = grid.number_of_cells;
1637 for(
int c=0; c<numCells; ++c )
1639 out <<
"cell " << c <<
" : faces = " << std::endl;
1640 for (
int hf=grid.cell_facepos[ c ]; hf < grid.cell_facepos[c+1]; ++hf)
1642 int f = grid_.cell_faces[ hf ];
1643 const int* fnbeg = grid_.face_nodes + grid_.face_nodepos[f];
1644 const int* fnend = grid_.face_nodes + grid_.face_nodepos[f+1];
1645 out << f <<
" vx = " ;
1646 while( fnbeg != fnend )
1648 out << *fnbeg <<
" ";
1655 const auto& vx = cellVertices_[ c ];
1656 out <<
"cell " << c <<
" : vertices = ";
1657 for(
size_t i=0; i<vx.size(); ++i )
1658 out << vx[ i ] <<
" ";
1665 UnstructuredGridPtr gridPtr_;
1666 const UnstructuredGridType& grid_;
1668 CommunicationType comm_;
1669 std::array< int, 3 > cartDims_;
1670 std::vector< std::vector< GeometryType > > geomTypes_;
1671 std::vector< std::vector< int > > cellVertices_;
1673 std::vector< GlobalCoordinate > unitOuterNormals_;
1679 size_t nBndSegments_;