opm-grid
gridfactory.hh
1 // -*- mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 // vi: set et ts=2 sw=2 sts=2:
3 #ifndef DUNE_POLYHEDRALGRID_GRIDFACTORY_HH
4 #define DUNE_POLYHEDRALGRID_GRIDFACTORY_HH
5 
6 #include <algorithm>
7 #include <numeric>
8 
9 #include <dune/common/typetraits.hh>
10 #include <dune/common/version.hh>
11 
12 #include <dune/grid/common/gridfactory.hh>
13 #include <opm/grid/polyhedralgrid/grid.hh>
14 
15 namespace Dune
16 {
17 
18 
19  // GridFactory for PolyhedralGrid
20  // ---------------------------------
21 
22  template< int dim, int dimworld, class coord_t >
23  class GridFactory< PolyhedralGrid< dim, dimworld, coord_t > >
24  : public GridFactoryInterface< PolyhedralGrid< dim, dimworld, coord_t > >
25  {
26  public:
28 
29  const static int dimension = Grid::dimension;
30  const static int dimensionworld = Grid::dimensionworld;
31  typedef typename Grid::ctype ctype;
32 
33  typedef MPIHelper::MPICommunicator MPICommunicatorType;
34  typedef typename Grid::template Codim<0>::Entity Element;
35  typedef typename Grid::template Codim<dimension>::Entity Vertex;
36 
37  typedef Dune::FieldVector<ctype,dimensionworld> CoordinateType;
38  typedef CoordinateType Coordinate;
39 
40  using UniquePtrType = std::unique_ptr<Grid>;
41 
43  explicit GridFactory ( const MPICommunicatorType& = MPIHelper::getCommunicator() )
44  : nodes_(),
45  faces_(),
46  cells_()
47  {}
48 
49  virtual void insertVertex(const CoordinateType& pos)
50  {
51  nodes_.push_back( pos );
52  }
53 
63  virtual void insertElement(const GeometryType& type,
64  const std::vector<unsigned int>& items)
65  {
66  if( type.isNone() )
67  {
68  // copy into vector of integers
69  std::vector< int > numbers( items.size() );
70  std::copy( items.begin(), items.end(), numbers.begin() );
71 
72  if( type.dim() == dimension-1 )
73  {
74  faces_.push_back( numbers );
75  }
76  else if( type.dim() == dimension )
77  {
78  // note vertices holds the face
79  // numbers in this case
80  cells_.push_back( numbers );
81  }
82  else
83  {
84  DUNE_THROW(Dune::NotImplemented,"insertElement not implemented for type " << type );
85  }
86  }
87  else // use ReferenceElement to insert faces
88  {
89 
90 
91  }
92  }
93 
94  void insertBoundarySegment(const std::vector<unsigned int>&)
95  {
96  DUNE_THROW(NotImplemented,"yet");
97  }
98 
99  UniquePtrType createGrid()
100  {
101  std::vector< CoordinateType >& nodes = nodes_;
102  std::vector< std::vector< int > >& faces = faces_;
103  std::vector< std::vector< int > >& cells = cells_;
104 
105  if( cells.empty() )
106  {
107  DUNE_THROW( GridError, "No cells found for PolyhedralGrid" );
108  }
109 
110  const auto sumSize = [] ( std::size_t s, const std::vector< int > &v ) { return s + v.size(); };
111  const std::size_t numFaceNodes = std::accumulate( faces.begin(), faces.end(), std::size_t( 0 ), sumSize );
112  const std::size_t numCellFaces = std::accumulate( cells.begin(), cells.end(), std::size_t( 0 ), sumSize );
113 
114  typename Grid::UnstructuredGridPtr ug =
115  Grid::allocateGrid( cells.size(), faces.size(), numFaceNodes, numCellFaces, nodes.size() );
116 
117  // copy faces
118  {
119 #ifndef NDEBUG
120  std::map< std::vector< int >, std::vector< int > > faceMap;
121 #endif
122 
123  const int nFaces = faces.size();
124  // set all face_cells values to -2 as default
125  std::fill( ug->face_cells, ug->face_cells + 2*nFaces, -1 );
126 
127  int facepos = 0;
128  std::vector< int > faceVertices;
129  faceVertices.reserve( 30 );
130  for( int face = 0; face < nFaces; ++face )
131  {
132  //std::cout << "face " << face << ": ";
133  faceVertices.clear();
134  ug->face_nodepos[ face ] = facepos;
135  const int nVertices = faces[ face ].size();
136  for( int vx = 0; vx < nVertices; ++vx, ++facepos )
137  {
138  //std::cout << " " << faces[ face ][ vx ];
139  ug->face_nodes[ facepos ] = faces[ face ][ vx ];
140  faceVertices.push_back( faces[ face ][ vx ] );
141  }
142  //std::cout << std::endl;
143 
144 #ifndef NDEBUG
145  // sort vertices
146  std::sort( faceVertices.begin(), faceVertices.end() );
147  // make sure each face only exists once
148  faceMap[ faceVertices ].push_back( face );
149  assert( faceMap[ faceVertices ].size() == 1 );
150 #endif
151  }
152  ug->face_nodepos[ nFaces ] = facepos ;
153  }
154 
155  // copy cells
156  {
157  const int nCells = cells.size();
158  int cellpos = 0;
159  for( int cell = 0; cell < nCells; ++cell )
160  {
161  //std::cout << "Cell " << cell << ": ";
162  ug->cell_facepos[ cell ] = cellpos;
163  const int nFaces = cells[ cell ].size();
164  for( int f = 0; f < nFaces; ++f, ++cellpos )
165  {
166  const int face = cells[ cell ][ f ];
167  // std::cout << " " << face ;
168  ug->cell_faces[ cellpos ] = face;
169 
170  // TODO find cells for each face
171  if( ug->face_cells[ 2*face ] == -1 )
172  {
173  ug->face_cells[ 2*face ] = cell;
174  }
175  else // if ( ug->face_cells[ 2*face+1 ] == -1 )
176  {
177  //assert( ug->face_cells[ 2*face+1 ] == -1 );
178  ug->face_cells[ 2*face+1 ] = cell;
179  }
180  }
181  //std::cout << std::endl;
182  }
183  ug->cell_facepos[ nCells ] = cellpos ;
184  }
185 
186  // copy node coordinates
187  {
188  const int nNodes = nodes.size();
189  int nodepos = 0;
190  for( int vx = 0 ; vx < nNodes; ++vx )
191  {
192  for( int d=0; d<dim; ++d, ++nodepos )
193  ug->node_coordinates[ nodepos ] = nodes[ vx ][ d ];
194  }
195  }
196 
197  /*
198  for( int i=0; i<int(faces.size() ); ++i)
199  {
200  std::cout << "face "<< i<< " connects to " << ug->face_cells[ 2*i ] << " " <<
201  ug->face_cells[ 2*i+1] << std::endl;
202  }
203  */
204 
205  // free cell face tag since it's not a cartesian grid
206  if( ug->cell_facetag )
207  {
208  std::free( ug->cell_facetag );
209  ug->cell_facetag = nullptr ;
210  for( int i=0; i<3; ++i ) ug->cartdims[ i ] = 0;
211  }
212 
213  // compute geometric quantities like cell volume and face normals
214  Grid::computeGeometry( ug );
215 
216  // check normal direction
217  {
218  for( int face = 0 ; face < ug->number_of_faces; ++face )
219  {
220  const int a = ug->face_cells[ 2*face ];
221  const int b = ug->face_cells[ 2*face + 1 ];
222  if( a < 0 || b < 0 )
223  continue ;
224 
225  Coordinate centerDiff( 0 );
226  Coordinate normal( 0 );
227  //std::cout << "Cell center " << a << " " << b << std::endl;
228  for( int d=0; d<dim; ++d )
229  {
230  //std::cout << ug->cell_centroids[ a*dim + d ] << " " << ug->cell_centroids[ b*dim + d ] << std::endl;
231  centerDiff[ d ] = ug->cell_centroids[ b*dim + d ] - ug->cell_centroids[ a*dim + d ];
232  normal[ d ] = ug->face_normals[ face*dim + d ];
233  }
234 
235  // if diff and normal point in different direction, flip faces
236  if( centerDiff * normal > 0 )
237  {
238  ug->face_cells[ 2*face ] = b;
239  ug->face_cells[ 2*face + 1 ] = a;
240  }
241  }
242  }
243 
244  return UniquePtrType( new Grid( std::move( ug ) ));
245  }
246 
247  protected:
248  std::vector< CoordinateType > nodes_;
249  std::vector< std::vector< int > > faces_;
250  std::vector< std::vector< int > > cells_;
251  };
252 
253 } // namespace Dune
254 
255 #endif // #ifndef DUNE_POLYHEDRALGRID_DGFPARSER_HH
The namespace Dune is the main namespace for all Dune code.
Definition: CartesianIndexMapper.hpp:9
identical grid wrapper
Definition: declaration.hh:10
Traits::ctype ctype
type of vector coordinates (e.g., double)
Definition: grid.hh:308
GridFactory(const MPICommunicatorType &=MPIHelper::getCommunicator())
Default constructor.
Definition: gridfactory.hh:43
virtual void insertElement(const GeometryType &type, const std::vector< unsigned int > &items)
Insert an element into the coarse grid.
Definition: gridfactory.hh:63