opm-grid
Geometry.hpp
1 //===========================================================================
2 //
3 // File: Geometry.hpp
4 //
5 // Created: Fri May 29 23:29:24 2009
6 //
7 // Author(s): Atgeirr F Rasmussen <atgeirr@sintef.no>
8 // B�rd Skaflestad <bard.skaflestad@sintef.no>
9 // Antonella Ritorto <antonella.ritorto@opm-op.com>
10 //
11 // $Date$
12 //
13 // $Revision$
14 //
15 //===========================================================================
16 
17 /*
18  Copyright 2009, 2010, 2011 SINTEF ICT, Applied Mathematics.
19  Copyright 2009, 2010, 2011, 2022 Equinor ASA.
20 
21  This file is part of the Open Porous Media project (OPM).
22 
23  OPM is free software: you can redistribute it and/or modify
24  it under the terms of the GNU General Public License as published by
25  the Free Software Foundation, either version 3 of the License, or
26  (at your option) any later version.
27 
28  OPM is distributed in the hope that it will be useful,
29  but WITHOUT ANY WARRANTY; without even the implied warranty of
30  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31  GNU General Public License for more details.
32 
33  You should have received a copy of the GNU General Public License
34  along with OPM. If not, see <http://www.gnu.org/licenses/>.
35 */
36 
37 #ifndef OPM_GEOMETRY_HEADER
38 #define OPM_GEOMETRY_HEADER
39 
40 #include <cmath>
41 
42 // Warning suppression for Dune includes.
43 #include <opm/grid/utility/platform_dependent/disable_warnings.h>
44 
45 #include <dune/common/version.hh>
46 #include <dune/geometry/referenceelements.hh>
47 #include <dune/grid/common/geometry.hh>
48 
49 #include <dune/geometry/type.hh>
50 
51 #include <opm/grid/cpgrid/EntityRep.hpp>
52 #include <opm/grid/cpgrid/DefaultGeometryPolicy.hpp>
53 #include <opm/grid/cpgrid/OrientedEntityTable.hpp>
55 #include <opm/grid/common/Volumes.hpp>
56 #include <opm/grid/utility/platform_dependent/reenable_warnings.h>
57 #include <opm/grid/utility/SparseTable.hpp>
58 
59 #include <opm/grid/utility/ErrorMacros.hpp>
60 
61 namespace Dune
62 {
63  namespace cpgrid
64  {
65 
74  template <int mydim, int cdim>
75  class Geometry
76  {
77  };
78 
79 
80 
81 
83  template <int cdim> // GridImp arg never used
84  class Geometry<0, cdim>
85  {
86  static_assert(cdim == 3, "");
87  public:
89  enum { dimension = 3 };
91  enum { mydimension = 0};
93  enum { coorddimension = cdim };
95  enum { dimensionworld = 3 };
96 
98  using ctype = double;
100  using Volume = ctype;
101 
103  typedef FieldVector<ctype, mydimension> LocalCoordinate;
105  typedef FieldVector<ctype, coorddimension> GlobalCoordinate;
106 
108  typedef FieldMatrix< ctype, coorddimension, mydimension > Jacobian;
110  typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse;
112  typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed;
114  typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed;
115 
116 
120  : pos_(pos)
121  {
122  }
123 
126  : pos_(0.0)
127  {
128  }
129 
132  {
133  return pos_;
134  }
135 
138  {
139  // return 0 to make the geometry check happy.
140  return LocalCoordinate(0.0);
141  }
142 
145  {
146  return volume();
147  }
148 
150  GeometryType type() const
151  {
152  return Dune::GeometryTypes::cube(mydimension);
153  }
154 
156  int corners() const
157  {
158  return 1;
159  }
160 
162  GlobalCoordinate corner(int cor) const
163  {
164  static_cast<void>(cor);
165  assert(cor == 0);
166  return pos_;
167  }
168 
170  Volume volume() const
171  {
172  return 1.0;
173  }
174 
176  const GlobalCoordinate& center() const
177  {
178  return pos_;
179  }
180 
182  JacobianTransposed
183  jacobianTransposed(const LocalCoordinate& /* local */) const
184  {
185 
186  // Meaningless to call jacobianTransposed() on singular geometries. But we need to make DUNE happy.
187  return {};
188  }
189 
191  JacobianInverseTransposed
193  {
194  // Meaningless to call jacobianInverseTransposed() on singular geometries. But we need to make DUNE happy.
195  return {};
196  }
197 
199  Jacobian
200  jacobian(const LocalCoordinate& /*local*/) const
201  {
202  return {};
203  }
204 
206  JacobianInverse
207  jacobianInverse(const LocalCoordinate& /*local*/) const
208  {
209  return {};
210  }
211 
213  bool affine() const
214  {
215  return true;
216  }
217 
218  private:
219  GlobalCoordinate pos_;
220  }; // class Geometry<0,cdim>
221 
222 
223 
224 
227  template <int cdim> // GridImp arg never used
228  class Geometry<2, cdim>
229  {
230  static_assert(cdim == 3, "");
231  public:
233  enum { dimension = 3 };
235  enum { mydimension = 2 };
237  enum { coorddimension = cdim };
239  enum { dimensionworld = 3 };
240 
242  using ctype = double;
244  using Volume = ctype;
245 
247  typedef FieldVector<ctype, mydimension> LocalCoordinate;
249  typedef FieldVector<ctype, coorddimension> GlobalCoordinate;
250 
252  typedef FieldMatrix< ctype, coorddimension, mydimension > Jacobian;
254  typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse;
256  typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed;
258  typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed;
259 
264  ctype vol)
265  : pos_(pos), vol_(vol)
266  {
267  }
268 
271  : pos_(0.0), vol_(0.0)
272  {
273  }
274 
277  {
278  OPM_THROW(std::runtime_error, "Geometry::global() meaningless on singular geometry.");
279  }
280 
283  {
284  OPM_THROW(std::runtime_error, "Geometry::local() meaningless on singular geometry.");
285  }
286 
290  {
291  return vol_;
292  }
293 
295  GeometryType type() const
296  {
297  return Dune::GeometryTypes::none(mydimension);
298  }
299 
302  int corners() const
303  {
304  return 0;
305  }
306 
308  GlobalCoordinate corner(int /* cor */) const
309  {
310  // Meaningless call to cpgrid::Geometry::corner(int):
311  //"singular geometry has no corners.
312  // But the DUNE tests assume at least one corner.
313  return GlobalCoordinate( 0.0 );
314  }
315 
317  Volume volume() const
318  {
319  return vol_;
320  }
321 
323  const GlobalCoordinate& center() const
324  {
325  return pos_;
326  }
327 
329  const FieldMatrix<ctype, mydimension, coorddimension>&
330  jacobianTransposed(const LocalCoordinate& /* local */) const
331  {
332  OPM_THROW(std::runtime_error, "Meaningless to call jacobianTransposed() on singular geometries.");
333  }
334 
336  const FieldMatrix<ctype, coorddimension, mydimension>&
338  {
339  OPM_THROW(std::runtime_error, "Meaningless to call jacobianInverseTransposed() on singular geometries.");
340  }
341 
343  Jacobian
344  jacobian(const LocalCoordinate& /*local*/) const
345  {
346  return jacobianTransposed({}).transposed();
347  }
348 
350  JacobianInverse
351  jacobianInverse(const LocalCoordinate& /*local*/) const
352  {
353  return jacobianInverseTransposed({}).transposed();
354  }
355 
357  bool affine() const
358  {
359  return true;
360  }
361 
362  private:
363  GlobalCoordinate pos_;
364  ctype vol_;
365  };
366 
367 
368 
369 
370 
372  template <int cdim>
373  class Geometry<3, cdim>
374  {
375  static_assert(cdim == 3, "");
376  public:
378  enum { dimension = 3 };
380  enum { mydimension = 3 };
382  enum { coorddimension = cdim };
384  enum { dimensionworld = 3 };
385 
387  using ctype = double;
389  using Volume = ctype;
390 
392  typedef FieldVector<ctype, mydimension> LocalCoordinate;
394  typedef FieldVector<ctype, coorddimension> GlobalCoordinate;
395 
397  typedef FieldMatrix< ctype, coorddimension, mydimension > Jacobian;
399  typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse;
401  typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed;
403  typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed;
404 
405  typedef Dune::Impl::FieldMatrixHelper< double > MatrixHelperType;
406 
416  ctype vol,
417  std::shared_ptr<const EntityVariable<cpgrid::Geometry<0, 3>, 3>> allcorners_ptr,
418  const int* corner_indices)
419  : pos_(pos), vol_(vol),
420  allcorners_(allcorners_ptr), cor_idx_(corner_indices)
421  {
422  assert(allcorners_ && corner_indices);
423  }
424 
427  : pos_(0.0), vol_(0.0), allcorners_(0), cor_idx_(0)
428  {
429  }
430 
436  GlobalCoordinate global(const LocalCoordinate& local_coord) const
437  {
438  static_assert(mydimension == 3, "");
439  static_assert(coorddimension == 3, "");
440  // uvw = { (1-u, 1-v, 1-w), (u, v, w) }
441  LocalCoordinate uvw[2] = { LocalCoordinate(1.0), local_coord };
442  uvw[0] -= local_coord;
443  // Access pattern for uvw matching ordering of corners.
444  const int pat[8][3] = { { 0, 0, 0 },
445  { 1, 0, 0 },
446  { 0, 1, 0 },
447  { 1, 1, 0 },
448  { 0, 0, 1 },
449  { 1, 0, 1 },
450  { 0, 1, 1 },
451  { 1, 1, 1 } };
452  GlobalCoordinate xyz(0.0);
453  for (int i = 0; i < 8; ++i) {
454  GlobalCoordinate corner_contrib = corner(i);
455  double factor = 1.0;
456  for (int j = 0; j < 3; ++j) {
457  factor *= uvw[pat[i][j]][j];
458  }
459  corner_contrib *= factor;
460  xyz += corner_contrib;
461  }
462  return xyz;
463  }
464 
468  {
469  static_assert(mydimension == 3, "");
470  static_assert(coorddimension == 3, "");
471  // This code is modified from dune/grid/genericgeometry/mapping.hh
472  // \todo: Implement direct computation.
473  const ctype epsilon = 1e-12;
474  auto refElement = Dune::ReferenceElements<ctype, 3>::cube();
475  LocalCoordinate x = refElement.position(0,0);
476  LocalCoordinate dx;
477  do {
478  // DF^n dx^n = F^n, x^{n+1} -= dx^n
479  JacobianTransposed JT = jacobianTransposed(x);
480  GlobalCoordinate z = global(x);
481  z -= y;
482  MatrixHelperType::template xTRightInvA<3, 3>(JT, z, dx );
483  x -= dx;
484  } while (dx.two_norm2() > epsilon*epsilon);
485  return x;
486  }
487 
492  Volume integrationElement(const LocalCoordinate& local_coord) const
493  {
494  JacobianTransposed Jt = jacobianTransposed(local_coord);
495  return MatrixHelperType::template sqrtDetAAT<3, 3>(Jt);
496  }
497 
500  GeometryType type() const
501  {
502  return Dune::GeometryTypes::cube(mydimension);
503  }
504 
507  int corners() const
508  {
509  return 8;
510  }
511 
513  GlobalCoordinate corner(int cor) const
514  {
515  assert(allcorners_ && cor_idx_);
516  return (allcorners_->data())[cor_idx_[cor]].center();
517  }
518 
520  Volume volume() const
521  {
522  return vol_;
523  }
524 
525  void set_volume(ctype volume) {
526  vol_ = volume;
527  }
528 
530  const GlobalCoordinate& center() const
531  {
532  return pos_;
533  }
534 
541  const JacobianTransposed
542  jacobianTransposed(const LocalCoordinate& local_coord) const
543  {
544  static_assert(mydimension == 3, "");
545  static_assert(coorddimension == 3, "");
546 
547  // uvw = { (1-u, 1-v, 1-w), (u, v, w) }
548  LocalCoordinate uvw[2] = { LocalCoordinate(1.0), local_coord };
549  uvw[0] -= local_coord;
550  // Access pattern for uvw matching ordering of corners.
551  const int pat[8][3] = { { 0, 0, 0 },
552  { 1, 0, 0 },
553  { 0, 1, 0 },
554  { 1, 1, 0 },
555  { 0, 0, 1 },
556  { 1, 0, 1 },
557  { 0, 1, 1 },
558  { 1, 1, 1 } };
559  JacobianTransposed Jt(0.0);
560  for (int i = 0; i < 8; ++i) {
561  for (int deriv = 0; deriv < 3; ++deriv) {
562  // This part contributing to dg/du_{deriv}
563  double factor = 1.0;
564  for (int j = 0; j < 3; ++j) {
565  factor *= (j != deriv) ? uvw[pat[i][j]][j]
566  : (pat[i][j] == 0 ? -1.0 : 1.0);
567  }
568  GlobalCoordinate corner_contrib = corner(i);
569  corner_contrib *= factor;
570  Jt[deriv] += corner_contrib; // using FieldMatrix row access.
571  }
572  }
573  return Jt;
574  }
575 
577  const JacobianInverseTransposed
578  jacobianInverseTransposed(const LocalCoordinate& local_coord) const
579  {
580  JacobianInverseTransposed Jti = jacobianTransposed(local_coord);
581  Jti.invert();
582  return Jti;
583  }
584 
586  Jacobian
587  jacobian(const LocalCoordinate& local_coord) const
588  {
589  return jacobianTransposed(local_coord).transposed();
590  }
591 
593  JacobianInverse
594  jacobianInverse(const LocalCoordinate& local_coord) const
595  {
596  return jacobianInverseTransposed(local_coord).transposed();
597  }
598 
600  bool affine() const
601  {
602  return false;
603  }
604 
623  typedef Dune::FieldVector<double,3> PointType;
624  void refineCellifiedPatch(const std::array<int,3>& cells_per_dim,
625  DefaultGeometryPolicy& all_geom,
626  std::vector<std::array<int,8>>& refined_cell_to_point,
627  cpgrid::OrientedEntityTable<0,1>& refined_cell_to_face,
628  Opm::SparseTable<int>& refined_face_to_point,
629  cpgrid::OrientedEntityTable<1,0>& refined_face_to_cell,
630  cpgrid::EntityVariable<enum face_tag, 1>& refined_face_tags,
631  cpgrid::SignedEntityVariable<PointType, 1>& refined_face_normals,
632  const std::array<int,3>& patch_dim,
633  const std::vector<double>& widthsX,
634  const std::vector<double>& lengthsY,
635  const std::vector<double>& heightsZ) const
636  {
637  EntityVariableBase<cpgrid::Geometry<0,3>>& refined_corners =
638  *(all_geom.geomVector(std::integral_constant<int,3>()));
640  *(all_geom.geomVector(std::integral_constant<int,1>()));
642  *(all_geom.geomVector(std::integral_constant<int,0>()));
643  EntityVariableBase<enum face_tag>& mutable_face_tags = refined_face_tags;
644  EntityVariableBase<PointType>& mutable_face_normals = refined_face_normals;
645 
647  // The strategy is to compute the local refined corners
648  // of the unit/reference cube, and then apply the map global().
649  // Determine the size of the vector containing all the corners
650  // of all the global refined cells (children cells).
651  // For easier notation:
652  const std::array<int,3>& refined_dim = { cells_per_dim[0]*patch_dim[0],
653  cells_per_dim[1]*patch_dim[1],
654  cells_per_dim[2]*patch_dim[2]};
655  refined_corners.resize((refined_dim[0] + 1)*(refined_dim[1] + 1)*(refined_dim[2] + 1));
656  // The nummbering starts at the botton, so k=0 (z-axis), and j=0 (y-axis), i=0 (x-axis).
657  // Then, increasing k ('going up'), followed by increasing i ('going right->'),
658  // and finally, increasing j ('going back'). This order criteria for corners
659  // 'Up [increasing k]- Right [incresing i]- Back [increasing j]'
660  // is consistant with cpgrid numbering.
661  //
662  assert(static_cast<int>(widthsX.size()) == patch_dim[0]);
663  assert(static_cast<int>(lengthsY.size()) == patch_dim[1]);
664  assert(static_cast<int>(heightsZ.size()) == patch_dim[2]);
665  const auto localCoordNumerator = []( const std::vector<double>& vec, int sumLimit, double multiplier) {
666  double lcn = 0;
667  assert(!vec.empty());
668  assert(sumLimit < static_cast<int>(vec.size()));
669  lcn += multiplier*vec[sumLimit];
670  for (int m = 0; m < sumLimit; ++m) {
671  lcn += vec[m];
672  }
673  return lcn;
674  };
675  // E.g. localCoordNumerator( dx, 3, 0.25) = x0 + x1 + x2 + 0.25.x3
676  //
677  const double sumWidths = std::accumulate(widthsX.begin(), widthsX.end(), double(0));
678  // x0 + x1 + ... + xL, if dx = {x0, x1, ..., xL}
679  const double sumLengths = std::accumulate(lengthsY.begin(), lengthsY.end(), double(0));
680  // y0 + y1 + ... + yM, if dy = {y0, y1, ..., yM}
681  const double sumHeights = std::accumulate(heightsZ.begin(), heightsZ.end(), double(0));
682  // z0 + z1 + ... + zN, if dz = {z0, z1, ..., zN}
683 
684  for (int j = 0; j < refined_dim[1] +1; ++j) {
685  double local_y = 0;
686  for (int i = 0; i < refined_dim[0] +1; ++i) {
687  double local_x = 0.;
688  for (int k = 0; k < refined_dim[2] +1; ++k) {
689  double local_z = 0.;
690 
691  // Compute the index of each global refined corner associated with 'jik'.
692  int refined_corner_idx =
693  (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) + k;
694 
695  // Compute the local refined corner of the unit/reference cube associated with 'jik'.
696  if ( i == refined_dim[0]) { // last corner in the x-direction
697  local_x = sumWidths;
698  } else {
699  local_x = localCoordNumerator(widthsX, i/cells_per_dim[0], double((i % cells_per_dim[0])) / cells_per_dim[0]);
700  }
701  if ( j == refined_dim[1]) { // last corner in the y-direction
702  local_y = sumLengths;
703  } else {
704  local_y = localCoordNumerator(lengthsY, j/cells_per_dim[1], double((j % cells_per_dim[1])) / cells_per_dim[1]);
705  }
706  if ( k == refined_dim[2]) { // last corner in the z-direction
707  local_z = sumHeights;
708  } else {
709  local_z = localCoordNumerator(heightsZ, k/cells_per_dim[2], double((k % cells_per_dim[2])) /cells_per_dim[2]);
710  }
711 
712  const LocalCoordinate& local_refined_corner = { local_x/sumWidths, local_y/sumLengths, local_z/sumHeights };
713  assert(local_x/sumWidths <= 1.);
714  assert(local_y/sumLengths <= 1.);
715  assert(local_z/sumHeights <= 1.);
716 
717  // Compute the global refined corner 'jik' and add it in its corresponfing entry in "refined_corners".
718  refined_corners[refined_corner_idx] = Geometry<0, 3>(this->global(local_refined_corner));
719  } // end k-for-loop
720  } // end i-for-loop
721  } // end j-for-loop
723  //
725  // We want to populate "refined_faces". The size of "refined_faces" is
726  const int refined_faces_size =
727  (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1)) // 'bottom/top faces'
728  + ((refined_dim[0]+1)*refined_dim[1]*refined_dim[2]) // 'left/right faces'
729  + (refined_dim[0]*(refined_dim[1]+1)*refined_dim[2]); // 'front/back faces'
730  refined_faces.resize(refined_faces_size);
731  refined_face_tags.resize(refined_faces_size);
732  refined_face_normals.resize(refined_faces_size);
733  //
734  // To create a face as a Geometry<2,3> type object we need its CENTROID and its VOLUME(area).
735  // We store the centroids/areas in the following order:
736  // - Bottom-top faces -> 3rd coordinate constant in each face.
737  // - Left-right faces -> 1st coordinate constant in each face.
738  // - Front-back faces -> 2nd coordinate constant in each face.
739  //
740  // REFINED FACE AREAS
741  // To compute the area of each face, we divide it in 4 triangles,
742  // compute the area of those with "area()", where the arguments
743  // are the 3 corners of each triangle. Then, sum them up to get the area
744  // of the global refined face.
745  // For each face, we construct 4 triangles with
746  // (1) centroid of the face,
747  // (2) one of the edges of the face.
748  //
749  // A triangle has 3 edges. Once we choose a face to base a triangle on,
750  // we choose an edge of that face as one of the edges of the triangle.
751  // The other 2 edges are fixed, since the centroid of the face the triangle
752  // is based on is one of its corners. That's why to identify
753  // a triangle we only need two things:
754  // (1) the face it's based on and
755  // (2) one of the four edges of that face.
756  //
757  // For each face, we need
758  // 1. index of the refined face
759  // [needed to access indices of the 4 edges of the face in "refined_face_to_edges"]
760  // 2. centroid of the face (common corner of the 4 triangles based on that face).
761  // [available via "['face'].center()"
762  // 3. container of 4 entries (the 4 edges of the face).
763  // Each entry consists in the 2 indices defining each edge of the face.
764  // [available in "refined_face_to_edges"].
765  //
766  // Populate "mutable_face_tags/normals", "refined_face_to_point/cell",
767  // "refined_faces".
768  //
769  for (int constant_direction = 0; constant_direction < 3; ++constant_direction){
770  // adding %3 and constant_direction, we go through the 3 type of faces.
771  // 0 -> 3rd coordinate constant: l('k') < cells_per_dim[2]+1, m('j') < cells_per_dim[1], n('i') < cells_per_dim[0]
772  // 1 -> 1rt coordinate constant: l('i') < cells_per_dim[0]+1, m('k') < cells_per_dim[2], n('j') < cells_per_dim[1]
773  // 2 -> 2nd coordinate constant: l('j') < cells_per_dim[1]+1, m('i') < cells_per_dim[0], n('k') < cells_per_dim[2]
774  std::array<int,3> refined_dim_mixed = {
775  refined_dim[(2+constant_direction)%3],
776  refined_dim[(1+constant_direction)%3],
777  refined_dim[constant_direction % 3] };
778  for (int l = 0; l < refined_dim_mixed[0] + 1; ++l) {
779  for (int m = 0; m < refined_dim_mixed[1]; ++m) {
780  for (int n = 0; n < refined_dim_mixed[2]; ++n) {
781  // Compute the face data.
782  auto [face_tag, idx, face_to_point, face_to_cell, wrong_local_centroid] =
783  getIndicesFace(l, m, n, constant_direction, refined_dim);
784  // Add the tag to "refined_face_tags".
785  mutable_face_tags[idx]= face_tag;
786  // Add the 4 corners of the face to "refined_face_to_point".
787  refined_face_to_point.appendRow(face_to_point.begin(), face_to_point.end());
788  // Add the neighboring cells of the face to "refined_face_to_cell".
789  refined_face_to_cell.appendRow(face_to_cell.begin(), face_to_cell.end());
790  // Compute the centroid as the average of the 4 corners of the face
791  GlobalCoordinate face_center = { 0., 0., 0.};
792  for (int corn = 0; corn < 4; ++corn){
793  face_center += refined_corners[face_to_point[corn]].center();
794  }
795  face_center /= 4.;
796  // Construct global face normal(s) (only one 'needed') and add it to "mutable_face_normals"
797  // Construct two vectors in the face, e.g. difference of two conners with the centroid,
798  // then obtain an orthogonal vector to both of them. Finally, normalize.
799  // Auxuliary vectors on the face:
800  GlobalCoordinate face_vector0 = refined_corners[face_to_point[0]].center() - face_center;
801  GlobalCoordinate face_vector1 = refined_corners[face_to_point[1]].center() - face_center;
802  mutable_face_normals[idx] = {
803  (face_vector0[1]*face_vector1[2]) - (face_vector0[2]*face_vector1[1]),
804  (face_vector0[2]*face_vector1[0]) - (face_vector0[0]*face_vector1[2]),
805  (face_vector0[0]*face_vector1[1]) - (face_vector0[1]*face_vector1[0])};
806  mutable_face_normals[idx] /= mutable_face_normals[idx].two_norm();
807  if (face_tag == J_FACE) {
808  mutable_face_normals[idx] *= -1;
809  }
810  // Construct "refined_face_to_edges"
811  // with the {edge_indix[0], edge_index[1]} for each edge of the refined face.
812  std::vector<std::array<int,2>> refined_face_to_edges = {
813  { face_to_point[0], face_to_point[1] },
814  { face_to_point[0], face_to_point[2] },
815  { face_to_point[1], face_to_point[3] },
816  { face_to_point[2], face_to_point[3] }
817  };
818  // Calculate the AREA of each face of a global refined face,
819  // by adding the 4 areas of the triangles partitioning each face.
820  double refined_face_area = 0.0;
821  for (int edge = 0; edge < 4; ++edge) {
822  // Construction of each triangle on the current face with one
823  // of its edges equal to "edge".
824  Geometry<0,3>::GlobalCoordinate trian_corners[3] = {
825  refined_corners[refined_face_to_edges[edge][0]].center(),
826  refined_corners[refined_face_to_edges[edge][1]].center(),
827  face_center };
828  refined_face_area += std::fabs(area(trian_corners));
829  } // end edge-for-loop
830  //
831  //
832  // Construct the Geometry<2,3> of the global refined face.
833  refined_faces[idx] = Geometry<2,cdim>(face_center, refined_face_area);
834  } // end n-for-loop
835  } // end m-for-loop
836  } // end l-for-loop
837  } // end r-for-loop
839  //
841  // We need to populate "refined_cells"
842  // "refined_cells"'s size is cells_per_dim[0] * cells_per_dim[1] * cells_per_dim[2].
843  // To build each global refined cell, we need
844  // 1. its global refined CENTER
845  // 2. its VOLUME
846  // 3. all global refined corners [available in "refined_corners"]
847  // 4. indices of its 8 corners.
848  //
849  refined_cells.resize(refined_dim[0] * refined_dim[1] * refined_dim[2]);
850  // Vector to store, in each entry, the 8 indices of the 8 corners
851  // of each global refined cell. Determine its size.
852  refined_cell_to_point.resize(refined_dim[0] * refined_dim[1] * refined_dim[2]);
853  // The numembering starts with index 0 for the refined cell with corners
854  // {0,0,0}, ...,{1/cells_per_dim[0], 1/cells_per_dim[1], 1/cells_per_dim[2]},
855  // then the indices grow first picking the cells in the x-axis (Right, i), then y-axis (Back, j), and
856  // finally, z-axis (Up, k).
857  //
858  // CENTERS
859  // REFINED CELL CENTERS
860  // The strategy is to compute the centers of the refined local
861  // unit/reference cube, and then apply the map global().
862  //
863  // VOLUMES OF THE REFINED CELLS
864  // REMARK: Each global refined 'cell' is a hexahedron since it may not be cube-shaped
865  // since its a 'deformation' of unit/reference cube. We may use 'hexahedron' to refer
866  // to the global refined cell in the computation of its volume.
867  //
868  // The strategy is to construct 24 tetrahedra in each hexahedron.
869  // Each tetrahedron is built with
870  // (1) the center of the hexahedron,
871  // (2) the middle point of the face the tetrahedron is based on, and
872  // (3) one of the edges of the face mentioned in 2.
873  // Each face 'supports' 4 tetrahedra, and we have 6 faces per hexahedron, which
874  // gives us the 24 tetrahedra per 'cell' (hexahedron).
875  //
876  // To compute the volume of each tetrahedron, we use "simplex_volume()" with
877  // the 6 corners of the tetrahedron as arguments. Summing up the 24 volumes,
878  // we get the volumne of the hexahedorn (global refined 'cell').
879  //
880  // Sum of all the volumes of all the (children) global refined cells.
881  double sum_all_refined_cell_volumes = 0.0;
882  //
883  // For each (global refined 'cell') hexahedron, to create 24 tetrahedra and their volumes,
884  // we introduce
885  // Vol1. "hexa_to_face" (needed to access face centroids).
886  // Vol2. "hexa_face_centroids" (one of the 6 corners of all 4 tetrahedra based on that face).
887  // Vol3. the center of the global refined 'cell' (hexahedron)
888  // (common corner of the 24 tetrahedra).
889  // Vol4. "tetra_edge_indices" indices of the 4x6 tetrahedra per 'cell',
890  // grouped by the face they are based on.
891  // Then we construct and compute the volume of the 24 tetrahedra with mainly
892  // "hexa_face_centroids" (Vol2.), global refined cell center (Vol3.), and "tetra_edge_indices" (Vol4.).
893  //
894  for (int k = 0; k < refined_dim[2]; ++k) {
895  for (int j = 0; j < refined_dim[1]; ++j) {
896  for (int i = 0; i < refined_dim[0]; ++i) {
897  // INDEX of the global refined cell associated with 'kji'.
898  int refined_cell_idx = (k*refined_dim[0]*refined_dim[1]) + (j*refined_dim[0]) +i;
899  // Obtain the global refined center with 'this->global(local_refined_cell_center)'.
900  // 2. VOLUME of the global refined 'kji' cell
901  double refined_cell_volume = 0.0; // (computed below!)
902  // 3. All Global refined corners ("refined_corners")
903  // 4. Indices of the 8 corners of the global refined cell associated with 'kji'.
904  std::array<int,8> cell_to_point = { //
905  (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k, // fake '0' {0,0,0}
906  (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k, // fake '1' {1,0,0}
907  ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k, // fake '2' {0,1,0}
908  ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k, // fake '3' {1,1,0}
909  (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k+1, // fake '4' {0,0,1}
910  (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k+1, // fake '5' {1,0,1}
911  ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k+1, // fake '6' {0,1,1}
912  ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k+1 // fake '7' {1,1,1}
913  };
914  // Add this 8 corners to the corresponding entry of "refined_cell_to_point".
915  refined_cell_to_point[refined_cell_idx] = cell_to_point;
916  // 1. CENTER of the global refined cell associated with 'kji' (Vol3.)
917  // Compute the center of the local refined unit/reference cube associated with 'kji'.
918  GlobalCoordinate refined_cell_center = {0., 0., 0.};
919  for (int corn = 0; corn < 8; ++corn) {
920  refined_cell_center += refined_corners[cell_to_point[corn]].center();
921  }
922  refined_cell_center /= 8.;
923  //
924  // VOLUME HEXAHEDRON (GLOBAL REFINED 'CELL')
925  // Vol1. INDICES ('from 0 to 5') of the faces of the hexahedron (needed to access face centroids).
926  std::vector<int> hexa_to_face = { //hexa_face_0to5_indices = {
927  // index face '0' bottom
928  (k*refined_dim[0]*refined_dim[1]) + (j*refined_dim[0]) + i,
929  // index face '1' front
930  (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1))
931  + ((refined_dim[0]+1)*refined_dim[1]*refined_dim[2])
932  + (j*refined_dim[0]*refined_dim[2]) + (i*refined_dim[2]) + k,
933  // index face '2' left
934  (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1))
935  + (i*refined_dim[1]*refined_dim[2]) + (k*refined_dim[1]) + j,
936  // index face '3' right
937  (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1))
938  + ((i+1)*refined_dim[1]*refined_dim[2]) + (k*refined_dim[1]) + j,
939  // index face '4' back
940  (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1)) +
941  ((refined_dim[0]+1)*refined_dim[1]*refined_dim[2])
942  + ((j+1)*refined_dim[0]*refined_dim[2]) + (i*refined_dim[2]) + k,
943  // index face '5' top
944  ((k+1)*refined_dim[0]*refined_dim[1]) + (j*refined_dim[0]) + i};
945  //
946  // We add the 6 faces of the cell into "refined_cell_to_face".
947  using cpgrid::EntityRep;
948  // First value is index, Second is orientation.
949  // Still have to find out what the orientation should be.
950  // right face ('3') outer normal points 'from left to right' -> orientation true
951  // back face ('4') outer normal points 'from front to back' -> orientation true
952  // top face ('5') outer normal points 'from bottom to top' -> orientation true
953  // (the other cases are false)
954  std::vector<cpgrid::EntityRep<1>> cell_to_face = {
955  { hexa_to_face[0], false}, {hexa_to_face[1], false},
956  { hexa_to_face[2], false}, {hexa_to_face[3], true},
957  { hexa_to_face[4], true}, {hexa_to_face[5], true} };
958  refined_cell_to_face.appendRow(cell_to_face.begin(), cell_to_face.end());
959  //
960  // Vol2. CENTROIDS of the faces of the hexahedron.
961  // (one of the 6 corners of all 4 tetrahedra based on that face).
962  std::vector<Geometry<0,3>::GlobalCoordinate> hexa_face_centroids;
963  for (auto& idx : hexa_to_face) {
964  hexa_face_centroids.push_back(refined_faces[idx].center());
965  }
966  // Indices of the 4 edges of each face of the hexahedron.
967  // A tetrahedron has six edges. Once we choose a face to base a
968  // tetrahedron on, we choose an edge of that face as one of the
969  // edges of the tetrahedron. The other five edges are fixed, since
970  // the center of the hexahedron and the center of the face are
971  // the reminder 2 corners of the tetrahedron. That's why to identify
972  // a tetrahedron we only need two things:
973  // (1) the face it's based on and
974  // (2) one of the four edges of that face.
975  //
976  // Container with 6 entries, one per face. Each entry has the
977  // 4 indices of the 4 corners of each face.
978  std::vector<std::array<int,4>> cell_face4corners;
979  cell_face4corners.reserve(6);
980  for (int face = 0; face < 6; ++face) {
981  cell_face4corners.push_back({
982  refined_face_to_point[hexa_to_face[face]][0],
983  refined_face_to_point[hexa_to_face[face]][1],
984  refined_face_to_point[hexa_to_face[face]][2],
985  refined_face_to_point[hexa_to_face[face]][3] });
986  }
987  // Vol4. Container with indices of the edges of the 4 tetrahedra per face
988  // [according to description above]
989  std::vector<std::vector<std::array<int,2>>> tetra_edge_indices;
990  tetra_edge_indices.reserve(6);
991  for (auto& face_indices : cell_face4corners)
992  {
993  std::vector<std::array<int,2>> face4edges_indices = {
994  { face_indices[0], face_indices[1]}, // fake '{0,1}'/'{4,5}'
995  { face_indices[0], face_indices[2]}, // fake '{0,2}'/'{4,6}'
996  { face_indices[1], face_indices[3]}, // fake '{1,3}'/'{5,7}'
997  { face_indices[2], face_indices[3]} }; // fake '{2,3}'/'{6,7}'
998  tetra_edge_indices.push_back(face4edges_indices);
999  }
1000  // Sum of the 24 volumes to get the volume of the hexahedron,
1001  // stored in "refined_cell_volume".
1002  // Calculate the volume of each hexahedron, by adding
1003  // the 4 tetrahedra at each face (4x6 = 24 tetrahedra).
1004  for (int face = 0; face < 6; ++face) {
1005  for (int edge = 0; edge < 4; ++edge) {
1006  // Construction of each tetrahedron based on "face" with one
1007  // of its edges equal to "edge".
1008  const Geometry<0, 3>::GlobalCoordinate tetra_corners[4] = {
1009  refined_corners[tetra_edge_indices[face][edge][0]].center(), // (see Vol4.)
1010  refined_corners[tetra_edge_indices[face][edge][1]].center(), // (see Vol4.)
1011  hexa_face_centroids[face], // (see Vol2.)
1012  refined_cell_center }; // (see Vol3.)
1013  refined_cell_volume += std::fabs(simplex_volume(tetra_corners));
1014  } // end edge-for-loop
1015  } // end face-for-loop
1016  // Add the volume of the hexahedron (global refined 'cell')
1017  // to the container with of all volumes of all the refined cells.
1018  sum_all_refined_cell_volumes += refined_cell_volume;
1019  // Create a pointer to the first element of "refined_cell_to_point"
1020  // (required as the fourth argement to construct a Geometry<3,3> type object).
1021  int* indices_storage_ptr = refined_cell_to_point[refined_cell_idx].data();
1022  // Construct the Geometry of the refined cell associated with 'kji'.
1023  refined_cells[refined_cell_idx] =
1024  Geometry<3,cdim>(refined_cell_center,
1025  refined_cell_volume,
1026  all_geom.geomVector(std::integral_constant<int,3>()),
1027  indices_storage_ptr);
1028  } // end i-for-loop
1029  } // end j-for-loop
1030  } // end k-for-loop
1031  // Rescale all volumes if the sum of volume of all the global refined 'cells' does not match the
1032  // volume of the 'parent cell'.
1033  // Compare the sum of all the volumes of all refined cells with 'parent cell' volume.
1034  if (std::fabs(sum_all_refined_cell_volumes - this->volume())
1035  > std::numeric_limits<Geometry<3, cdim>::ctype>::epsilon()) {
1036  Geometry<3, cdim>::ctype correction = this->volume() / sum_all_refined_cell_volumes;
1037  for(auto& cell: refined_cells){
1038  cell.vol_ *= correction;
1039  }
1040  } // end if-statement
1042  }
1043 
1044  private:
1045  GlobalCoordinate pos_;
1046  double vol_;
1047  std::shared_ptr<const EntityVariable<Geometry<0, 3>,3>> allcorners_; // For dimension 3 only
1048  const int* cor_idx_; // For dimension 3 only
1049 
1063  const std::tuple< enum face_tag, int,
1064  std::array<int, 4>, std::vector<cpgrid::EntityRep<0>>,
1065  LocalCoordinate>
1066  getIndicesFace(int l, int m, int n, int constant_direction, const std::array<int, 3>& cells_per_dim) const
1067  {
1068  using cpgrid::EntityRep;
1069  std::vector<cpgrid::EntityRep<0>> neighboring_cells_of_one_face; // {index, orientation}
1070  switch(constant_direction) {
1071  case 0: // {l,m,n} = {k,j,i}, constant in z-direction
1072  // Orientation true when outer normal points 'from bottom to top'
1073  // Orientation false when outer normal points 'from top to bottom'
1074  if (l != 0) {
1075  neighboring_cells_of_one_face.push_back({((l-1)*cells_per_dim[0]*cells_per_dim[1])
1076  + (m*cells_per_dim[0]) + n, true});
1077  }
1078  if (l != cells_per_dim[2]) {
1079  neighboring_cells_of_one_face.push_back({ (l*cells_per_dim[0]*cells_per_dim[1])
1080  + (m*cells_per_dim[0]) + n, false});
1081  }
1082  return { face_tag::K_FACE, (l*cells_per_dim[0]*cells_per_dim[1]) + (m*cells_per_dim[0]) + n,
1083  {(m*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (n*(cells_per_dim[2]+1)) +l,
1084  (m*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((n+1)*(cells_per_dim[2]+1)) +l,
1085  ((m+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (n*(cells_per_dim[2]+1)) +l,
1086  ((m+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((n+1)*(cells_per_dim[2]+1)) +l},
1087  neighboring_cells_of_one_face,
1088  {(.5 + n)/cells_per_dim[0], (.5 + m)/cells_per_dim[1], double(l)/cells_per_dim[2]}};
1089  case 1: // {l,m,n} = {i,k,j}, constant in the x-direction
1090  // Orientation true when outer normal points 'from left to right'
1091  // Orientation false when outer normal points 'from right to left'
1092  if (l != 0) {
1093  neighboring_cells_of_one_face.push_back({(m*cells_per_dim[0]*cells_per_dim[1])
1094  + (n*cells_per_dim[0]) +l-1, true});
1095  }
1096  if (l != cells_per_dim[0]) {
1097  neighboring_cells_of_one_face.push_back({ (m*cells_per_dim[0]*cells_per_dim[1])
1098  + (n*cells_per_dim[0]) + l, false});
1099  }
1100  return { face_tag::I_FACE, (cells_per_dim[0]*cells_per_dim[1]*(cells_per_dim[2]+1))
1101  + (l*cells_per_dim[1]*cells_per_dim[2]) + (m*cells_per_dim[1]) + n,
1102  {(n*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m,
1103  ((n+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m,
1104  (n*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m+1,
1105  ((n+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m+1},
1106  neighboring_cells_of_one_face,
1107  { double(l)/cells_per_dim[0], (.5 + n)/cells_per_dim[1], (.5 + m)/cells_per_dim[2]}};
1108  case 2: // {l,m,n} = {j,i,k}, constant in the y-direction
1109  // Orientation true when outer normal points 'from front to back'
1110  // Orientation false when outer normal points 'from back to front'
1111  if (l != 0) {
1112  neighboring_cells_of_one_face.push_back({(n*cells_per_dim[0]*cells_per_dim[1])
1113  + ((l-1)*cells_per_dim[0]) +m, true});
1114  }
1115  if (l != cells_per_dim[1]) {
1116  neighboring_cells_of_one_face.push_back({(n*cells_per_dim[0]*cells_per_dim[1])
1117  + (l*cells_per_dim[0]) + m, false});
1118  }
1119  return { face_tag::J_FACE, (cells_per_dim[0]*cells_per_dim[1]*(cells_per_dim[2] +1))
1120  + ((cells_per_dim[0]+1)*cells_per_dim[1]*cells_per_dim[2])
1121  + (l*cells_per_dim[0]*cells_per_dim[2]) + (m*cells_per_dim[2]) + n,
1122  {(l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (m*(cells_per_dim[2]+1)) +n,
1123  (l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((m+1)*(cells_per_dim[2]+1)) +n,
1124  (l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (m*(cells_per_dim[2]+1)) +n+1,
1125  (l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((m+1)*(cells_per_dim[2]+1)) +n+1},
1126  neighboring_cells_of_one_face,
1127  {(.5 + m)/cells_per_dim[0], double(l)/cells_per_dim[1], (.5 + n)/cells_per_dim[2]}};
1128  default:
1129  // Should never be reached, but prevents compiler warning
1130  OPM_THROW(std::logic_error, "Unhandled dimension. This should never happen!");
1131  }
1132  }
1133  };
1134 
1135  // Reference element for a given geometry
1136  template< int mydim, int cdim >
1137  auto referenceElement(const cpgrid::Geometry<mydim,cdim>& geo) -> decltype(referenceElement<double,mydim>(geo.type()))
1138  {
1139  return referenceElement<double,mydim>(geo.type());
1140  }
1141 
1142  } // namespace cpgrid
1143 } // namespace Dune
1144 
1145 #endif // OPM_GEOMETRY_HEADER
const GlobalCoordinate & global(const LocalCoordinate &) const
Returns the position of the vertex.
Definition: Geometry.hpp:131
Volume integrationElement(const LocalCoordinate &) const
For the singular geometry, we return a constant integration element equal to the volume.
Definition: Geometry.hpp:289
double ctype
Coordinate element type.
Definition: Geometry.hpp:387
FieldMatrix< ctype, coorddimension, mydimension > Jacobian
Type of Jacobian matrix.
Definition: Geometry.hpp:252
GeometryType type() const
Using the cube type for all entities now (cells and vertices), but we use the singular type for inter...
Definition: Geometry.hpp:500
Base class for EntityVariable and SignedEntityVariable.
Definition: EntityRep.hpp:217
Definition: DefaultGeometryPolicy.hpp:52
int corners() const
The number of corners of this convex polytope.
Definition: Geometry.hpp:507
JacobianInverse jacobianInverse(const LocalCoordinate &) const
The inverse of the jacobian.
Definition: Geometry.hpp:351
LocalCoordinate local(const GlobalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:282
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed
Type of the inverse of the transposed Jacobian matrix.
Definition: Geometry.hpp:258
Geometry(const GlobalCoordinate &pos, ctype vol)
Construct from centroid and volume (1- and 0-moments).
Definition: Geometry.hpp:263
Geometry()
Default constructor, giving a non-valid geometry.
Definition: Geometry.hpp:426
FieldMatrix< ctype, coorddimension, mydimension > Jacobian
Type of Jacobian matrix.
Definition: Geometry.hpp:108
const JacobianTransposed jacobianTransposed(const LocalCoordinate &local_coord) const
Jacobian transposed.
Definition: Geometry.hpp:542
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed
Type of the inverse of the transposed Jacobian matrix.
Definition: Geometry.hpp:114
void appendRow(DataIter row_beg, DataIter row_end)
Appends a row to the table.
Definition: SparseTable.hpp:182
ctype Volume
Number type used for the geometry volume.
Definition: Geometry.hpp:389
Volume integrationElement(const LocalCoordinate &local_coord) const
Equal to {{J^T J}} where J is the Jacobian.
Definition: Geometry.hpp:492
Volume volume() const
Volume (area, actually) of intersection.
Definition: Geometry.hpp:317
The namespace Dune is the main namespace for all Dune code.
Definition: CartesianIndexMapper.hpp:9
Specialization for 3-dimensional geometries, i.e. cells.
Definition: Geometry.hpp:373
Connection topologically normal to I-J plane.
Definition: preprocess.h:69
Jacobian jacobian(const LocalCoordinate &local_coord) const
The jacobian.
Definition: Geometry.hpp:587
Geometry()
Default constructor, giving a non-valid geometry.
Definition: Geometry.hpp:125
FieldVector< ctype, coorddimension > GlobalCoordinate
Range type of.
Definition: Geometry.hpp:394
double ctype
Coordinate element type.
Definition: Geometry.hpp:98
void refineCellifiedPatch(const std::array< int, 3 > &cells_per_dim, DefaultGeometryPolicy &all_geom, std::vector< std::array< int, 8 >> &refined_cell_to_point, cpgrid::OrientedEntityTable< 0, 1 > &refined_cell_to_face, Opm::SparseTable< int > &refined_face_to_point, cpgrid::OrientedEntityTable< 1, 0 > &refined_face_to_cell, cpgrid::EntityVariable< enum face_tag, 1 > &refined_face_tags, cpgrid::SignedEntityVariable< PointType, 1 > &refined_face_normals, const std::array< int, 3 > &patch_dim, const std::vector< double > &widthsX, const std::vector< double > &lengthsY, const std::vector< double > &heightsZ) const
Definition: Geometry.hpp:624
Jacobian jacobian(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:200
This class encapsulates geometry for vertices, intersections, and cells.
Definition: CpGridData.hpp:94
bool affine() const
The mapping implemented by this geometry is constant, therefore affine.
Definition: Geometry.hpp:213
GlobalCoordinate global(const LocalCoordinate &local_coord) const
Provide a trilinear mapping.
Definition: Geometry.hpp:436
int corners() const
A vertex is defined by a single corner.
Definition: Geometry.hpp:156
Jacobian jacobian(const LocalCoordinate &) const
The jacobian.
Definition: Geometry.hpp:344
const FieldMatrix< ctype, mydimension, coorddimension > & jacobianTransposed(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:330
FieldVector< ctype, mydimension > LocalCoordinate
Domain type of.
Definition: Geometry.hpp:103
const GlobalCoordinate & center() const
Returns the centroid of the geometry.
Definition: Geometry.hpp:530
Geometry()
Default constructor, giving a non-valid geometry.
Definition: Geometry.hpp:270
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse
Type of inverse of Jacobian matrix.
Definition: Geometry.hpp:399
const JacobianInverseTransposed jacobianInverseTransposed(const LocalCoordinate &local_coord) const
Inverse of Jacobian transposed.
Definition: Geometry.hpp:578
JacobianInverse jacobianInverse(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:207
int corners() const
The number of corners of this convex polytope.
Definition: Geometry.hpp:302
const FieldMatrix< ctype, coorddimension, mydimension > & jacobianInverseTransposed(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:337
Connection topologically normal to I-K plane.
Definition: preprocess.h:68
Volume volume() const
Volume of vertex is arbitrarily set to 1.
Definition: Geometry.hpp:170
Volume integrationElement(const LocalCoordinate &) const
Returns 1 for the vertex geometry.
Definition: Geometry.hpp:144
const GlobalCoordinate & center() const
Returns the centroid of the geometry.
Definition: Geometry.hpp:176
LocalCoordinate local(const GlobalCoordinate &y) const
Mapping from the cell to the reference domain.
Definition: Geometry.hpp:467
T simplex_volume(const Point< T, Dim > *a)
Computes the volume of a simplex consisting of (Dim+1) vertices embedded in Euclidean space of dimens...
Definition: Volumes.hpp:104
bool affine() const
The mapping implemented by this geometry is not generally affine.
Definition: Geometry.hpp:600
Connection topologically normal to J-K plane.
Definition: preprocess.h:67
Volume volume() const
Cell volume.
Definition: Geometry.hpp:520
JacobianInverse jacobianInverse(const LocalCoordinate &local_coord) const
The inverse of the jacobian.
Definition: Geometry.hpp:594
GeometryType type() const
Using the cube type for vertices.
Definition: Geometry.hpp:150
FieldVector< ctype, coorddimension > GlobalCoordinate
Range type of.
Definition: Geometry.hpp:105
Geometry(const GlobalCoordinate &pos, ctype vol, std::shared_ptr< const EntityVariable< cpgrid::Geometry< 0, 3 >, 3 >> allcorners_ptr, const int *corner_indices)
Construct from center, volume (1- and 0-moments) and corners.
Definition: Geometry.hpp:415
GlobalCoordinate corner(int cor) const
Returns the single corner: the vertex itself.
Definition: Geometry.hpp:162
FieldVector< ctype, mydimension > LocalCoordinate
Domain type of.
Definition: Geometry.hpp:247
LocalCoordinate local(const GlobalCoordinate &) const
Meaningless for the vertex geometry.
Definition: Geometry.hpp:137
FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed
Type of transposed Jacobian matrix.
Definition: Geometry.hpp:256
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed
Type of the inverse of the transposed Jacobian matrix.
Definition: Geometry.hpp:403
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse
Type of inverse of Jacobian matrix.
Definition: Geometry.hpp:254
const GlobalCoordinate & center() const
Returns the centroid of the geometry.
Definition: Geometry.hpp:323
ctype Volume
Number type used for the geometry volume.
Definition: Geometry.hpp:100
face_tag
Connection taxonomy.
Definition: preprocess.h:66
Geometry(const GlobalCoordinate &pos)
Construct from vertex position.
Definition: Geometry.hpp:119
T volume(const Point< T, 3 > *c)
Computes the volume of a 3D simplex (embedded i 3D space).
Definition: Volumes.hpp:138
const GlobalCoordinate & global(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:276
bool affine() const
Since integrationElement() is constant, returns true.
Definition: Geometry.hpp:357
GlobalCoordinate corner(int) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:308
FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed
Type of transposed Jacobian matrix.
Definition: Geometry.hpp:112
T area(const Point< T, 2 > *c)
Computes the area of a 2-dimensional triangle.
Definition: Volumes.hpp:119
FieldVector< ctype, mydimension > LocalCoordinate
Domain type of.
Definition: Geometry.hpp:392
ctype Volume
Number type used for the geometry volume.
Definition: Geometry.hpp:244
Low-level corner-point processing routines and supporting data structures.
A class design to hold a variable with a value for each entity of the given codimension, where the variable is not changing in sign with orientation.
Definition: EntityRep.hpp:270
Represents an entity of a given codim, with positive or negative orientation.
Definition: CpGridData.hpp:96
Specialization for 2 dimensional geometries, that is intersections (since codim 1 entities are not in...
Definition: Geometry.hpp:228
GeometryType type() const
We use the singular type (None) for intersections.
Definition: Geometry.hpp:295
void appendRow(DataIter row_beg, DataIter row_end)
Appends a row to the table.
Definition: SparseTable.hpp:182
const EntityVariable< cpgrid::Geometry< 3 - codim, 3 >, codim > & geomVector() const
Definition: DefaultGeometryPolicy.hpp:86
Dune::FieldVector< double, 3 > PointType
Refine a single cell considering different widths, lengths, and heights.
Definition: Geometry.hpp:623
FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed
Type of transposed Jacobian matrix.
Definition: Geometry.hpp:401
FieldVector< ctype, coorddimension > GlobalCoordinate
Range type of.
Definition: Geometry.hpp:249
double ctype
Coordinate element type.
Definition: Geometry.hpp:242
JacobianTransposed jacobianTransposed(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:183
FieldMatrix< ctype, coorddimension, mydimension > Jacobian
Type of Jacobian matrix.
Definition: Geometry.hpp:397
JacobianInverseTransposed jacobianInverseTransposed(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:192
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse
Type of inverse of Jacobian matrix.
Definition: Geometry.hpp:110
GlobalCoordinate corner(int cor) const
Get the cor-th of 8 corners of the hexahedral base cell.
Definition: Geometry.hpp:513