Geometry.hpp
Go to the documentation of this file.
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.
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
57
58#include <opm/common/ErrorMacros.hpp>
59
60namespace Dune
61{
62 namespace cpgrid
63 {
64
73 template <int mydim, int cdim>
75 {
76 };
77
78
79
80
82 template <int cdim> // GridImp arg never used
83 class Geometry<0, cdim>
84 {
85 static_assert(cdim == 3, "");
86 public:
88 enum { dimension = 3 };
90 enum { mydimension = 0};
92 enum { coorddimension = cdim };
94 enum { dimensionworld = 3 };
95
97 typedef double ctype;
98
100 typedef FieldVector<ctype, mydimension> LocalCoordinate;
102 typedef FieldVector<ctype, coorddimension> GlobalCoordinate;
103
105 typedef FieldMatrix< ctype, coorddimension, mydimension > Jacobian;
107 typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse;
109 typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed;
111 typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed;
112
113
117 : pos_(pos)
118 {
119 }
120
123 : pos_(0.0)
124 {
125 }
126
129 {
130 return pos_;
131 }
132
135 {
136 // return 0 to make the geometry check happy.
137 return LocalCoordinate(0.0);
138 }
139
142 {
143 return volume();
144 }
145
147 GeometryType type() const
148 {
149 return Dune::GeometryTypes::cube(mydimension);
150 }
151
153 int corners() const
154 {
155 return 1;
156 }
157
160 {
161 static_cast<void>(cor);
162 assert(cor == 0);
163 return pos_;
164 }
165
167 ctype volume() const
168 {
169 return 1.0;
170 }
171
174 {
175 return pos_;
176 }
177
179 JacobianTransposed
180 jacobianTransposed(const LocalCoordinate& /* local */) const
181 {
182
183 // Meaningless to call jacobianTransposed() on singular geometries. But we need to make DUNE happy.
184 return {};
185 }
186
188 JacobianInverseTransposed
190 {
191 // Meaningless to call jacobianInverseTransposed() on singular geometries. But we need to make DUNE happy.
192 return {};
193 }
194
196 Jacobian
197 jacobian(const LocalCoordinate& /*local*/) const
198 {
199 return {};
200 }
201
203 JacobianInverse
204 jacobianInverse(const LocalCoordinate& /*local*/) const
205 {
206 return {};
207 }
208
210 bool affine() const
211 {
212 return true;
213 }
214
215 private:
216 GlobalCoordinate pos_;
217 }; // class Geometry<0,cdim>
218
219
220
221
224 template <int cdim> // GridImp arg never used
225 class Geometry<2, cdim>
226 {
227 static_assert(cdim == 3, "");
228 public:
230 enum { dimension = 3 };
232 enum { mydimension = 2 };
234 enum { coorddimension = cdim };
236 enum { dimensionworld = 3 };
237
239 typedef double ctype;
240
242 typedef FieldVector<ctype, mydimension> LocalCoordinate;
244 typedef FieldVector<ctype, coorddimension> GlobalCoordinate;
245
247 typedef FieldMatrix< ctype, coorddimension, mydimension > Jacobian;
249 typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse;
251 typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed;
253 typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed;
254
259 ctype vol)
260 : pos_(pos), vol_(vol)
261 {
262 }
263
266 : pos_(0.0), vol_(0.0)
267 {
268 }
269
272 {
273 OPM_THROW(std::runtime_error, "Geometry::global() meaningless on singular geometry.");
274 }
275
278 {
279 OPM_THROW(std::runtime_error, "Geometry::local() meaningless on singular geometry.");
280 }
281
285 {
286 return vol_;
287 }
288
290 GeometryType type() const
291 {
292 return Dune::GeometryTypes::none(mydimension);
293 }
294
297 int corners() const
298 {
299 return 0;
300 }
301
303 GlobalCoordinate corner(int /* cor */) const
304 {
305 // Meaningless call to cpgrid::Geometry::corner(int):
306 //"singular geometry has no corners.
307 // But the DUNE tests assume at least one corner.
308 return GlobalCoordinate( 0.0 );
309 }
310
312 ctype volume() const
313 {
314 return vol_;
315 }
316
319 {
320 return pos_;
321 }
322
324 const FieldMatrix<ctype, mydimension, coorddimension>&
325 jacobianTransposed(const LocalCoordinate& /* local */) const
326 {
327 OPM_THROW(std::runtime_error, "Meaningless to call jacobianTransposed() on singular geometries.");
328 }
329
331 const FieldMatrix<ctype, coorddimension, mydimension>&
333 {
334 OPM_THROW(std::runtime_error, "Meaningless to call jacobianInverseTransposed() on singular geometries.");
335 }
336
338 Jacobian
339 jacobian(const LocalCoordinate& /*local*/) const
340 {
341 return jacobianTransposed({}).transposed();
342 }
343
345 JacobianInverse
346 jacobianInverse(const LocalCoordinate& /*local*/) const
347 {
348 return jacobianInverseTransposed({}).transposed();
349 }
350
352 bool affine() const
353 {
354 return true;
355 }
356
357 private:
358 GlobalCoordinate pos_;
359 ctype vol_;
360 };
361
362
363
364
365
367 template <int cdim>
368 class Geometry<3, cdim>
369 {
370 static_assert(cdim == 3, "");
371 public:
373 enum { dimension = 3 };
375 enum { mydimension = 3 };
377 enum { coorddimension = cdim };
379 enum { dimensionworld = 3 };
380
382 typedef double ctype;
383
385 typedef FieldVector<ctype, mydimension> LocalCoordinate;
387 typedef FieldVector<ctype, coorddimension> GlobalCoordinate;
388
390 typedef FieldMatrix< ctype, coorddimension, mydimension > Jacobian;
392 typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse;
394 typedef FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed;
396 typedef FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed;
397
398 typedef Dune::Impl::FieldMatrixHelper< double > MatrixHelperType;
399
409 ctype vol,
410 std::shared_ptr<const EntityVariable<cpgrid::Geometry<0, 3>, 3>> allcorners_ptr,
411 const int* corner_indices)
412 : pos_(pos), vol_(vol),
413 allcorners_(allcorners_ptr), cor_idx_(corner_indices)
414 {
415 assert(allcorners_ && corner_indices);
416 }
417
428 ctype vol)
429 : pos_(pos), vol_(vol)
430 {
431 }
432
435 : pos_(0.0), vol_(0.0), allcorners_(0), cor_idx_(0)
436 {
437 }
438
444 GlobalCoordinate global(const LocalCoordinate& local_coord) const
445 {
446 static_assert(mydimension == 3, "");
447 static_assert(coorddimension == 3, "");
448 // uvw = { (1-u, 1-v, 1-w), (u, v, w) }
449 LocalCoordinate uvw[2] = { LocalCoordinate(1.0), local_coord };
450 uvw[0] -= local_coord;
451 // Access pattern for uvw matching ordering of corners.
452 const int pat[8][3] = { { 0, 0, 0 },
453 { 1, 0, 0 },
454 { 0, 1, 0 },
455 { 1, 1, 0 },
456 { 0, 0, 1 },
457 { 1, 0, 1 },
458 { 0, 1, 1 },
459 { 1, 1, 1 } };
460 GlobalCoordinate xyz(0.0);
461 for (int i = 0; i < 8; ++i) {
462 GlobalCoordinate corner_contrib = corner(i);
463 double factor = 1.0;
464 for (int j = 0; j < 3; ++j) {
465 factor *= uvw[pat[i][j]][j];
466 }
467 corner_contrib *= factor;
468 xyz += corner_contrib;
469 }
470 return xyz;
471 }
472
476 {
477 static_assert(mydimension == 3, "");
478 static_assert(coorddimension == 3, "");
479 // This code is modified from dune/grid/genericgeometry/mapping.hh
480 // \todo: Implement direct computation.
481 const ctype epsilon = 1e-12;
482 auto refElement = Dune::ReferenceElements<ctype, 3>::cube();
483 LocalCoordinate x = refElement.position(0,0);
485 do {
486 // DF^n dx^n = F^n, x^{n+1} -= dx^n
487 JacobianTransposed JT = jacobianTransposed(x);
488 GlobalCoordinate z = global(x);
489 z -= y;
490 MatrixHelperType::template xTRightInvA<3, 3>(JT, z, dx );
491 x -= dx;
492 } while (dx.two_norm2() > epsilon*epsilon);
493 return x;
494 }
495
500 double integrationElement(const LocalCoordinate& local_coord) const
501 {
502 JacobianTransposed Jt = jacobianTransposed(local_coord);
503 return MatrixHelperType::template sqrtDetAAT<3, 3>(Jt);
504 }
505
508 GeometryType type() const
509 {
510 return Dune::GeometryTypes::cube(mydimension);
511 }
512
515 int corners() const
516 {
517 return 8;
518 }
519
522 {
523 assert(allcorners_ && cor_idx_);
524 return (allcorners_->data())[cor_idx_[cor]].center();
525 }
526
528 ctype volume() const
529 {
530 return vol_;
531 }
532
534 vol_ = volume;
535 }
536
539 {
540 return pos_;
541 }
542
549 const JacobianTransposed
550 jacobianTransposed(const LocalCoordinate& local_coord) const
551 {
552 static_assert(mydimension == 3, "");
553 static_assert(coorddimension == 3, "");
554
555 // uvw = { (1-u, 1-v, 1-w), (u, v, w) }
556 LocalCoordinate uvw[2] = { LocalCoordinate(1.0), local_coord };
557 uvw[0] -= local_coord;
558 // Access pattern for uvw matching ordering of corners.
559 const int pat[8][3] = { { 0, 0, 0 },
560 { 1, 0, 0 },
561 { 0, 1, 0 },
562 { 1, 1, 0 },
563 { 0, 0, 1 },
564 { 1, 0, 1 },
565 { 0, 1, 1 },
566 { 1, 1, 1 } };
567 JacobianTransposed Jt(0.0);
568 for (int i = 0; i < 8; ++i) {
569 for (int deriv = 0; deriv < 3; ++deriv) {
570 // This part contributing to dg/du_{deriv}
571 double factor = 1.0;
572 for (int j = 0; j < 3; ++j) {
573 factor *= (j != deriv) ? uvw[pat[i][j]][j]
574 : (pat[i][j] == 0 ? -1.0 : 1.0);
575 }
576 GlobalCoordinate corner_contrib = corner(i);
577 corner_contrib *= factor;
578 Jt[deriv] += corner_contrib; // using FieldMatrix row access.
579 }
580 }
581 return Jt;
582 }
583
585 const JacobianInverseTransposed
587 {
588 JacobianInverseTransposed Jti = jacobianTransposed(local_coord);
589 Jti.invert();
590 return Jti;
591 }
592
594 Jacobian
595 jacobian(const LocalCoordinate& local_coord) const
596 {
597 return jacobianTransposed(local_coord).transposed();
598 }
599
601 JacobianInverse
602 jacobianInverse(const LocalCoordinate& local_coord) const
603 {
604 return jacobianInverseTransposed(local_coord).transposed();
605 }
606
608 bool affine() const
609 {
610 return false;
611 }
612
631 typedef Dune::FieldVector<double,3> PointType;
632 void refineCellifiedPatch(const std::array<int,3>& cells_per_dim,
633 DefaultGeometryPolicy& all_geom,
634 std::vector<std::array<int,8>>& refined_cell_to_point,
635 cpgrid::OrientedEntityTable<0,1>& refined_cell_to_face,
636 Opm::SparseTable<int>& refined_face_to_point,
637 cpgrid::OrientedEntityTable<1,0>& refined_face_to_cell,
639 cpgrid::SignedEntityVariable<PointType, 1>& refined_face_normals,
640 const std::array<int,3>& patch_dim,
641 const std::vector<double>& widthsX,
642 const std::vector<double>& lengthsY,
643 const std::vector<double>& heightsZ) const
644 {
646 *(all_geom.geomVector(std::integral_constant<int,3>()));
648 *(all_geom.geomVector(std::integral_constant<int,1>()));
650 *(all_geom.geomVector(std::integral_constant<int,0>()));
651 EntityVariableBase<enum face_tag>& mutable_face_tags = refined_face_tags;
652 EntityVariableBase<PointType>& mutable_face_normals = refined_face_normals;
653
655 // The strategy is to compute the local refined corners
656 // of the unit/reference cube, and then apply the map global().
657 // Determine the size of the vector containing all the corners
658 // of all the global refined cells (children cells).
659 // For easier notation:
660 const std::array<int,3>& refined_dim = { cells_per_dim[0]*patch_dim[0],
661 cells_per_dim[1]*patch_dim[1],
662 cells_per_dim[2]*patch_dim[2]};
663 refined_corners.resize((refined_dim[0] + 1)*(refined_dim[1] + 1)*(refined_dim[2] + 1));
664 // The nummbering starts at the botton, so k=0 (z-axis), and j=0 (y-axis), i=0 (x-axis).
665 // Then, increasing k ('going up'), followed by increasing i ('going right->'),
666 // and finally, increasing j ('going back'). This order criteria for corners
667 // 'Up [increasing k]- Right [incresing i]- Back [increasing j]'
668 // is consistant with cpgrid numbering.
669 //
670 assert(static_cast<int>(widthsX.size()) == patch_dim[0]);
671 assert(static_cast<int>(lengthsY.size()) == patch_dim[1]);
672 assert(static_cast<int>(heightsZ.size()) == patch_dim[2]);
673 const auto localCoordNumerator = []( const std::vector<double>& vec, int sumLimit, double multiplier) {
674 double lcn = 0;
675 assert(!vec.empty());
676 assert(sumLimit < static_cast<int>(vec.size()));
677 lcn += multiplier*vec[sumLimit];
678 for (int m = 0; m < sumLimit; ++m) {
679 lcn += vec[m];
680 }
681 return lcn;
682 };
683 // E.g. localCoordNumerator( dx, 3, 0.25) = x0 + x1 + x2 + 0.25.x3
684 //
685 const double sumWidths = std::accumulate(widthsX.begin(), widthsX.end(), double(0));
686 // x0 + x1 + ... + xL, if dx = {x0, x1, ..., xL}
687 const double sumLengths = std::accumulate(lengthsY.begin(), lengthsY.end(), double(0));
688 // y0 + y1 + ... + yM, if dy = {y0, y1, ..., yM}
689 const double sumHeights = std::accumulate(heightsZ.begin(), heightsZ.end(), double(0));
690 // z0 + z1 + ... + zN, if dz = {z0, z1, ..., zN}
691
692 for (int j = 0; j < refined_dim[1] +1; ++j) {
693 double local_y = 0;
694 for (int i = 0; i < refined_dim[0] +1; ++i) {
695 double local_x = 0.;
696 for (int k = 0; k < refined_dim[2] +1; ++k) {
697 double local_z = 0.;
698
699 // Compute the index of each global refined corner associated with 'jik'.
700 int refined_corner_idx =
701 (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) + k;
702
703 // Compute the local refined corner of the unit/reference cube associated with 'jik'.
704 if ( i == refined_dim[0]) { // last corner in the x-direction
705 local_x = sumWidths;
706 } else {
707 local_x = localCoordNumerator(widthsX, i/cells_per_dim[0], double((i % cells_per_dim[0])) / cells_per_dim[0]);
708 }
709 if ( j == refined_dim[1]) { // last corner in the y-direction
710 local_y = sumLengths;
711 } else {
712 local_y = localCoordNumerator(lengthsY, j/cells_per_dim[1], double((j % cells_per_dim[1])) / cells_per_dim[1]);
713 }
714 if ( k == refined_dim[2]) { // last corner in the z-direction
715 local_z = sumHeights;
716 } else {
717 local_z = localCoordNumerator(heightsZ, k/cells_per_dim[2], double((k % cells_per_dim[2])) /cells_per_dim[2]);
718 }
719
720 const LocalCoordinate& local_refined_corner = { local_x/sumWidths, local_y/sumLengths, local_z/sumHeights };
721 assert(local_x/sumWidths <= 1.);
722 assert(local_y/sumLengths <= 1.);
723 assert(local_z/sumHeights <= 1.);
724
725 // Compute the global refined corner 'jik' and add it in its corresponfing entry in "refined_corners".
726 refined_corners[refined_corner_idx] = Geometry<0, 3>(this->global(local_refined_corner));
727 } // end k-for-loop
728 } // end i-for-loop
729 } // end j-for-loop
731 //
733 // We want to populate "refined_faces". The size of "refined_faces" is
734 const int refined_faces_size =
735 (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1)) // 'bottom/top faces'
736 + ((refined_dim[0]+1)*refined_dim[1]*refined_dim[2]) // 'left/right faces'
737 + (refined_dim[0]*(refined_dim[1]+1)*refined_dim[2]); // 'front/back faces'
738 refined_faces.resize(refined_faces_size);
739 refined_face_tags.resize(refined_faces_size);
740 refined_face_normals.resize(refined_faces_size);
741 //
742 // To create a face as a Geometry<2,3> type object we need its CENTROID and its VOLUME(area).
743 // We store the centroids/areas in the following order:
744 // - Bottom-top faces -> 3rd coordinate constant in each face.
745 // - Left-right faces -> 1st coordinate constant in each face.
746 // - Front-back faces -> 2nd coordinate constant in each face.
747 //
748 // REFINED FACE AREAS
749 // To compute the area of each face, we divide it in 4 triangles,
750 // compute the area of those with "area()", where the arguments
751 // are the 3 corners of each triangle. Then, sum them up to get the area
752 // of the global refined face.
753 // For each face, we construct 4 triangles with
754 // (1) centroid of the face,
755 // (2) one of the edges of the face.
756 //
757 // A triangle has 3 edges. Once we choose a face to base a triangle on,
758 // we choose an edge of that face as one of the edges of the triangle.
759 // The other 2 edges are fixed, since the centroid of the face the triangle
760 // is based on is one of its corners. That's why to identify
761 // a triangle we only need two things:
762 // (1) the face it's based on and
763 // (2) one of the four edges of that face.
764 //
765 // For each face, we need
766 // 1. index of the refined face
767 // [needed to access indices of the 4 edges of the face in "refined_face_to_edges"]
768 // 2. centroid of the face (common corner of the 4 triangles based on that face).
769 // [available via "['face'].center()"
770 // 3. container of 4 entries (the 4 edges of the face).
771 // Each entry consists in the 2 indices defining each edge of the face.
772 // [available in "refined_face_to_edges"].
773 //
774 // Populate "mutable_face_tags/normals", "refined_face_to_point/cell",
775 // "refined_faces".
776 //
777 for (int constant_direction = 0; constant_direction < 3; ++constant_direction){
778 // adding %3 and constant_direction, we go through the 3 type of faces.
779 // 0 -> 3rd coordinate constant: l('k') < cells_per_dim[2]+1, m('j') < cells_per_dim[1], n('i') < cells_per_dim[0]
780 // 1 -> 1rt coordinate constant: l('i') < cells_per_dim[0]+1, m('k') < cells_per_dim[2], n('j') < cells_per_dim[1]
781 // 2 -> 2nd coordinate constant: l('j') < cells_per_dim[1]+1, m('i') < cells_per_dim[0], n('k') < cells_per_dim[2]
782 std::array<int,3> refined_dim_mixed = {
783 refined_dim[(2+constant_direction)%3],
784 refined_dim[(1+constant_direction)%3],
785 refined_dim[constant_direction % 3] };
786 for (int l = 0; l < refined_dim_mixed[0] + 1; ++l) {
787 for (int m = 0; m < refined_dim_mixed[1]; ++m) {
788 for (int n = 0; n < refined_dim_mixed[2]; ++n) {
789 // Compute the face data.
790 auto [face_tag, idx, face_to_point, face_to_cell, wrong_local_centroid] =
791 getIndicesFace(l, m, n, constant_direction, refined_dim);
792 // Add the tag to "refined_face_tags".
793 mutable_face_tags[idx]= face_tag;
794 // Add the 4 corners of the face to "refined_face_to_point".
795 refined_face_to_point.appendRow(face_to_point.begin(), face_to_point.end());
796 // Add the neighboring cells of the face to "refined_face_to_cell".
797 refined_face_to_cell.appendRow(face_to_cell.begin(), face_to_cell.end());
798 // Compute the centroid as the average of the 4 corners of the face
799 GlobalCoordinate face_center = { 0., 0., 0.};
800 for (int corn = 0; corn < 4; ++corn){
801 face_center += refined_corners[face_to_point[corn]].center();
802 }
803 face_center /= 4.;
804 // Construct global face normal(s) (only one 'needed') and add it to "mutable_face_normals"
805 // Construct two vectors in the face, e.g. difference of two conners with the centroid,
806 // then obtain an orthogonal vector to both of them. Finally, normalize.
807 // Auxuliary vectors on the face:
808 GlobalCoordinate face_vector0 = refined_corners[face_to_point[0]].center() - face_center;
809 GlobalCoordinate face_vector1 = refined_corners[face_to_point[1]].center() - face_center;
810 mutable_face_normals[idx] = {
811 (face_vector0[1]*face_vector1[2]) - (face_vector0[2]*face_vector1[1]),
812 (face_vector0[2]*face_vector1[0]) - (face_vector0[0]*face_vector1[2]),
813 (face_vector0[0]*face_vector1[1]) - (face_vector0[1]*face_vector1[0])};
814 mutable_face_normals[idx] /= mutable_face_normals[idx].two_norm();
815 if (face_tag == J_FACE) {
816 mutable_face_normals[idx] *= -1;
817 }
818 // Construct "refined_face_to_edges"
819 // with the {edge_indix[0], edge_index[1]} for each edge of the refined face.
820 std::vector<std::array<int,2>> refined_face_to_edges = {
821 { face_to_point[0], face_to_point[1] },
822 { face_to_point[0], face_to_point[2] },
823 { face_to_point[1], face_to_point[3] },
824 { face_to_point[2], face_to_point[3] }
825 };
826 // Calculate the AREA of each face of a global refined face,
827 // by adding the 4 areas of the triangles partitioning each face.
828 double refined_face_area = 0.0;
829 for (int edge = 0; edge < 4; ++edge) {
830 // Construction of each triangle on the current face with one
831 // of its edges equal to "edge".
832 Geometry<0,3>::GlobalCoordinate trian_corners[3] = {
833 refined_corners[refined_face_to_edges[edge][0]].center(),
834 refined_corners[refined_face_to_edges[edge][1]].center(),
835 face_center };
836 refined_face_area += std::fabs(area(trian_corners));
837 } // end edge-for-loop
838 //
839 //
840 // Construct the Geometry<2,3> of the global refined face.
841 refined_faces[idx] = Geometry<2,cdim>(face_center, refined_face_area);
842 } // end n-for-loop
843 } // end m-for-loop
844 } // end l-for-loop
845 } // end r-for-loop
847 //
849 // We need to populate "refined_cells"
850 // "refined_cells"'s size is cells_per_dim[0] * cells_per_dim[1] * cells_per_dim[2].
851 // To build each global refined cell, we need
852 // 1. its global refined CENTER
853 // 2. its VOLUME
854 // 3. all global refined corners [available in "refined_corners"]
855 // 4. indices of its 8 corners.
856 //
857 refined_cells.resize(refined_dim[0] * refined_dim[1] * refined_dim[2]);
858 // Vector to store, in each entry, the 8 indices of the 8 corners
859 // of each global refined cell. Determine its size.
860 refined_cell_to_point.resize(refined_dim[0] * refined_dim[1] * refined_dim[2]);
861 // The numembering starts with index 0 for the refined cell with corners
862 // {0,0,0}, ...,{1/cells_per_dim[0], 1/cells_per_dim[1], 1/cells_per_dim[2]},
863 // then the indices grow first picking the cells in the x-axis (Right, i), then y-axis (Back, j), and
864 // finally, z-axis (Up, k).
865 //
866 // CENTERS
867 // REFINED CELL CENTERS
868 // The strategy is to compute the centers of the refined local
869 // unit/reference cube, and then apply the map global().
870 //
871 // VOLUMES OF THE REFINED CELLS
872 // REMARK: Each global refined 'cell' is a hexahedron since it may not be cube-shaped
873 // since its a 'deformation' of unit/reference cube. We may use 'hexahedron' to refer
874 // to the global refined cell in the computation of its volume.
875 //
876 // The strategy is to construct 24 tetrahedra in each hexahedron.
877 // Each tetrahedron is built with
878 // (1) the center of the hexahedron,
879 // (2) the middle point of the face the tetrahedron is based on, and
880 // (3) one of the edges of the face mentioned in 2.
881 // Each face 'supports' 4 tetrahedra, and we have 6 faces per hexahedron, which
882 // gives us the 24 tetrahedra per 'cell' (hexahedron).
883 //
884 // To compute the volume of each tetrahedron, we use "simplex_volume()" with
885 // the 6 corners of the tetrahedron as arguments. Summing up the 24 volumes,
886 // we get the volumne of the hexahedorn (global refined 'cell').
887 //
888 // Sum of all the volumes of all the (children) global refined cells.
889 double sum_all_refined_cell_volumes = 0.0;
890 //
891 // For each (global refined 'cell') hexahedron, to create 24 tetrahedra and their volumes,
892 // we introduce
893 // Vol1. "hexa_to_face" (needed to access face centroids).
894 // Vol2. "hexa_face_centroids" (one of the 6 corners of all 4 tetrahedra based on that face).
895 // Vol3. the center of the global refined 'cell' (hexahedron)
896 // (common corner of the 24 tetrahedra).
897 // Vol4. "tetra_edge_indices" indices of the 4x6 tetrahedra per 'cell',
898 // grouped by the face they are based on.
899 // Then we construct and compute the volume of the 24 tetrahedra with mainly
900 // "hexa_face_centroids" (Vol2.), global refined cell center (Vol3.), and "tetra_edge_indices" (Vol4.).
901 //
902 for (int k = 0; k < refined_dim[2]; ++k) {
903 for (int j = 0; j < refined_dim[1]; ++j) {
904 for (int i = 0; i < refined_dim[0]; ++i) {
905 // INDEX of the global refined cell associated with 'kji'.
906 int refined_cell_idx = (k*refined_dim[0]*refined_dim[1]) + (j*refined_dim[0]) +i;
907 // Obtain the global refined center with 'this->global(local_refined_cell_center)'.
908 // 2. VOLUME of the global refined 'kji' cell
909 double refined_cell_volume = 0.0; // (computed below!)
910 // 3. All Global refined corners ("refined_corners")
911 // 4. Indices of the 8 corners of the global refined cell associated with 'kji'.
912 std::array<int,8> cell_to_point = { //
913 (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k, // fake '0' {0,0,0}
914 (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k, // fake '1' {1,0,0}
915 ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k, // fake '2' {0,1,0}
916 ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k, // fake '3' {1,1,0}
917 (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k+1, // fake '4' {0,0,1}
918 (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k+1, // fake '5' {1,0,1}
919 ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k+1, // fake '6' {0,1,1}
920 ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k+1 // fake '7' {1,1,1}
921 };
922 // Add this 8 corners to the corresponding entry of "refined_cell_to_point".
923 refined_cell_to_point[refined_cell_idx] = cell_to_point;
924 // 1. CENTER of the global refined cell associated with 'kji' (Vol3.)
925 // Compute the center of the local refined unit/reference cube associated with 'kji'.
926 GlobalCoordinate refined_cell_center = {0., 0., 0.};
927 for (int corn = 0; corn < 8; ++corn) {
928 refined_cell_center += refined_corners[cell_to_point[corn]].center();
929 }
930 refined_cell_center /= 8.;
931 //
932 // VOLUME HEXAHEDRON (GLOBAL REFINED 'CELL')
933 // Vol1. INDICES ('from 0 to 5') of the faces of the hexahedron (needed to access face centroids).
934 std::vector<int> hexa_to_face = { //hexa_face_0to5_indices = {
935 // index face '0' bottom
936 (k*refined_dim[0]*refined_dim[1]) + (j*refined_dim[0]) + i,
937 // index face '1' front
938 (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1))
939 + ((refined_dim[0]+1)*refined_dim[1]*refined_dim[2])
940 + (j*refined_dim[0]*refined_dim[2]) + (i*refined_dim[2]) + k,
941 // index face '2' left
942 (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1))
943 + (i*refined_dim[1]*refined_dim[2]) + (k*refined_dim[1]) + j,
944 // index face '3' right
945 (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1))
946 + ((i+1)*refined_dim[1]*refined_dim[2]) + (k*refined_dim[1]) + j,
947 // index face '4' back
948 (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1)) +
949 ((refined_dim[0]+1)*refined_dim[1]*refined_dim[2])
950 + ((j+1)*refined_dim[0]*refined_dim[2]) + (i*refined_dim[2]) + k,
951 // index face '5' top
952 ((k+1)*refined_dim[0]*refined_dim[1]) + (j*refined_dim[0]) + i};
953 //
954 // We add the 6 faces of the cell into "refined_cell_to_face".
955 using cpgrid::EntityRep;
956 // First value is index, Second is orientation.
957 // Still have to find out what the orientation should be.
958 // right face ('3') outer normal points 'from left to right' -> orientation true
959 // back face ('4') outer normal points 'from front to back' -> orientation true
960 // top face ('5') outer normal points 'from bottom to top' -> orientation true
961 // (the other cases are false)
962 std::vector<cpgrid::EntityRep<1>> cell_to_face = {
963 { hexa_to_face[0], false}, {hexa_to_face[1], false},
964 { hexa_to_face[2], false}, {hexa_to_face[3], true},
965 { hexa_to_face[4], true}, {hexa_to_face[5], true} };
966 refined_cell_to_face.appendRow(cell_to_face.begin(), cell_to_face.end());
967 //
968 // Vol2. CENTROIDS of the faces of the hexahedron.
969 // (one of the 6 corners of all 4 tetrahedra based on that face).
970 std::vector<Geometry<0,3>::GlobalCoordinate> hexa_face_centroids;
971 for (auto& idx : hexa_to_face) {
972 hexa_face_centroids.push_back(refined_faces[idx].center());
973 }
974 // Indices of the 4 edges of each face of the hexahedron.
975 // A tetrahedron has six edges. Once we choose a face to base a
976 // tetrahedron on, we choose an edge of that face as one of the
977 // edges of the tetrahedron. The other five edges are fixed, since
978 // the center of the hexahedron and the center of the face are
979 // the reminder 2 corners of the tetrahedron. That's why to identify
980 // a tetrahedron we only need two things:
981 // (1) the face it's based on and
982 // (2) one of the four edges of that face.
983 //
984 // Container with 6 entries, one per face. Each entry has the
985 // 4 indices of the 4 corners of each face.
986 std::vector<std::array<int,4>> cell_face4corners;
987 cell_face4corners.reserve(6);
988 for (int face = 0; face < 6; ++face) {
989 cell_face4corners.push_back({
990 refined_face_to_point[hexa_to_face[face]][0],
991 refined_face_to_point[hexa_to_face[face]][1],
992 refined_face_to_point[hexa_to_face[face]][2],
993 refined_face_to_point[hexa_to_face[face]][3] });
994 }
995 // Vol4. Container with indices of the edges of the 4 tetrahedra per face
996 // [according to description above]
997 std::vector<std::vector<std::array<int,2>>> tetra_edge_indices;
998 tetra_edge_indices.reserve(6);
999 for (auto& face_indices : cell_face4corners)
1000 {
1001 std::vector<std::array<int,2>> face4edges_indices = {
1002 { face_indices[0], face_indices[1]}, // fake '{0,1}'/'{4,5}'
1003 { face_indices[0], face_indices[2]}, // fake '{0,2}'/'{4,6}'
1004 { face_indices[1], face_indices[3]}, // fake '{1,3}'/'{5,7}'
1005 { face_indices[2], face_indices[3]} }; // fake '{2,3}'/'{6,7}'
1006 tetra_edge_indices.push_back(face4edges_indices);
1007 }
1008 // Sum of the 24 volumes to get the volume of the hexahedron,
1009 // stored in "refined_cell_volume".
1010 // Calculate the volume of each hexahedron, by adding
1011 // the 4 tetrahedra at each face (4x6 = 24 tetrahedra).
1012 for (int face = 0; face < 6; ++face) {
1013 for (int edge = 0; edge < 4; ++edge) {
1014 // Construction of each tetrahedron based on "face" with one
1015 // of its edges equal to "edge".
1016 const Geometry<0, 3>::GlobalCoordinate tetra_corners[4] = {
1017 refined_corners[tetra_edge_indices[face][edge][0]].center(), // (see Vol4.)
1018 refined_corners[tetra_edge_indices[face][edge][1]].center(), // (see Vol4.)
1019 hexa_face_centroids[face], // (see Vol2.)
1020 refined_cell_center }; // (see Vol3.)
1021 refined_cell_volume += std::fabs(simplex_volume(tetra_corners));
1022 } // end edge-for-loop
1023 } // end face-for-loop
1024 // Add the volume of the hexahedron (global refined 'cell')
1025 // to the container with of all volumes of all the refined cells.
1026 sum_all_refined_cell_volumes += refined_cell_volume;
1027 // Create a pointer to the first element of "refined_cell_to_point"
1028 // (required as the fourth argement to construct a Geometry<3,3> type object).
1029 int* indices_storage_ptr = refined_cell_to_point[refined_cell_idx].data();
1030 // Construct the Geometry of the refined cell associated with 'kji'.
1031 refined_cells[refined_cell_idx] =
1032 Geometry<3,cdim>(refined_cell_center,
1033 refined_cell_volume,
1034 all_geom.geomVector(std::integral_constant<int,3>()),
1035 indices_storage_ptr);
1036 } // end i-for-loop
1037 } // end j-for-loop
1038 } // end k-for-loop
1039 // Rescale all volumes if the sum of volume of all the global refined 'cells' does not match the
1040 // volume of the 'parent cell'.
1041 // Compare the sum of all the volumes of all refined cells with 'parent cell' volume.
1042 if (std::fabs(sum_all_refined_cell_volumes - this->volume())
1043 > std::numeric_limits<Geometry<3, cdim>::ctype>::epsilon()) {
1044 Geometry<3, cdim>::ctype correction = this->volume() / sum_all_refined_cell_volumes;
1045 for(auto& cell: refined_cells){
1046 cell.vol_ *= correction;
1047 }
1048 } // end if-statement
1050 }
1051
1052 private:
1053 GlobalCoordinate pos_;
1054 double vol_;
1055 std::shared_ptr<const EntityVariable<Geometry<0, 3>,3>> allcorners_; // For dimension 3 only
1056 const int* cor_idx_; // For dimension 3 only
1057
1071 const std::tuple< enum face_tag, int,
1072 std::array<int, 4>, std::vector<cpgrid::EntityRep<0>>,
1073 LocalCoordinate>
1074 getIndicesFace(int l, int m, int n, int constant_direction, const std::array<int, 3>& cells_per_dim) const
1075 {
1076 using cpgrid::EntityRep;
1077 std::vector<cpgrid::EntityRep<0>> neighboring_cells_of_one_face; // {index, orientation}
1078 switch(constant_direction) {
1079 case 0: // {l,m,n} = {k,j,i}, constant in z-direction
1080 // Orientation true when outer normal points 'from bottom to top'
1081 // Orientation false when outer normal points 'from top to bottom'
1082 if (l != 0) {
1083 neighboring_cells_of_one_face.push_back({((l-1)*cells_per_dim[0]*cells_per_dim[1])
1084 + (m*cells_per_dim[0]) + n, true});
1085 }
1086 if (l != cells_per_dim[2]) {
1087 neighboring_cells_of_one_face.push_back({ (l*cells_per_dim[0]*cells_per_dim[1])
1088 + (m*cells_per_dim[0]) + n, false});
1089 }
1090 return { face_tag::K_FACE, (l*cells_per_dim[0]*cells_per_dim[1]) + (m*cells_per_dim[0]) + n,
1091 {(m*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (n*(cells_per_dim[2]+1)) +l,
1092 (m*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((n+1)*(cells_per_dim[2]+1)) +l,
1093 ((m+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (n*(cells_per_dim[2]+1)) +l,
1094 ((m+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((n+1)*(cells_per_dim[2]+1)) +l},
1095 neighboring_cells_of_one_face,
1096 {(.5 + n)/cells_per_dim[0], (.5 + m)/cells_per_dim[1], double(l)/cells_per_dim[2]}};
1097 case 1: // {l,m,n} = {i,k,j}, constant in the x-direction
1098 // Orientation true when outer normal points 'from left to right'
1099 // Orientation false when outer normal points 'from right to left'
1100 if (l != 0) {
1101 neighboring_cells_of_one_face.push_back({(m*cells_per_dim[0]*cells_per_dim[1])
1102 + (n*cells_per_dim[0]) +l-1, true});
1103 }
1104 if (l != cells_per_dim[0]) {
1105 neighboring_cells_of_one_face.push_back({ (m*cells_per_dim[0]*cells_per_dim[1])
1106 + (n*cells_per_dim[0]) + l, false});
1107 }
1108 return { face_tag::I_FACE, (cells_per_dim[0]*cells_per_dim[1]*(cells_per_dim[2]+1))
1109 + (l*cells_per_dim[1]*cells_per_dim[2]) + (m*cells_per_dim[1]) + n,
1110 {(n*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m,
1111 ((n+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m,
1112 (n*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m+1,
1113 ((n+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m+1},
1114 neighboring_cells_of_one_face,
1115 { double(l)/cells_per_dim[0], (.5 + n)/cells_per_dim[1], (.5 + m)/cells_per_dim[2]}};
1116 case 2: // {l,m,n} = {j,i,k}, constant in the y-direction
1117 // Orientation true when outer normal points 'from front to back'
1118 // Orientation false when outer normal points 'from back to front'
1119 if (l != 0) {
1120 neighboring_cells_of_one_face.push_back({(n*cells_per_dim[0]*cells_per_dim[1])
1121 + ((l-1)*cells_per_dim[0]) +m, true});
1122 }
1123 if (l != cells_per_dim[1]) {
1124 neighboring_cells_of_one_face.push_back({(n*cells_per_dim[0]*cells_per_dim[1])
1125 + (l*cells_per_dim[0]) + m, false});
1126 }
1127 return { face_tag::J_FACE, (cells_per_dim[0]*cells_per_dim[1]*(cells_per_dim[2] +1))
1128 + ((cells_per_dim[0]+1)*cells_per_dim[1]*cells_per_dim[2])
1129 + (l*cells_per_dim[0]*cells_per_dim[2]) + (m*cells_per_dim[2]) + n,
1130 {(l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (m*(cells_per_dim[2]+1)) +n,
1131 (l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((m+1)*(cells_per_dim[2]+1)) +n,
1132 (l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (m*(cells_per_dim[2]+1)) +n+1,
1133 (l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((m+1)*(cells_per_dim[2]+1)) +n+1},
1134 neighboring_cells_of_one_face,
1135 {(.5 + m)/cells_per_dim[0], double(l)/cells_per_dim[1], (.5 + n)/cells_per_dim[2]}};
1136 default:
1137 // Should never be reached, but prevents compiler warning
1138 OPM_THROW(std::logic_error, "Unhandled dimension. This should never happen!");
1139 }
1140 }
1141 };
1142 } // namespace cpgrid
1143
1144 template< int mydim, int cdim >
1145 auto referenceElement(const cpgrid::Geometry<mydim,cdim>& geo) -> decltype(referenceElement<double,mydim>(geo.type()))
1146 {
1147 return referenceElement<double,mydim>(geo.type());
1148 }
1149
1150} // namespace Dune
1151
1152#endif // OPM_GEOMETRY_HEADER
Definition: DefaultGeometryPolicy.hpp:53
const EntityVariable< cpgrid::Geometry< 3 - codim, 3 >, codim > & geomVector() const
Definition: DefaultGeometryPolicy.hpp:86
Represents an entity of a given codim, with positive or negative orientation.
Definition: EntityRep.hpp:99
Base class for EntityVariable and SignedEntityVariable. Forwards a restricted subset of the std::vect...
Definition: EntityRep.hpp:219
A class design to hold a variable with a value for each entity of the given codimension,...
Definition: EntityRep.hpp:267
FieldVector< ctype, coorddimension > GlobalCoordinate
Range type of.
Definition: Geometry.hpp:102
bool affine() const
The mapping implemented by this geometry is constant, therefore affine.
Definition: Geometry.hpp:210
FieldMatrix< ctype, coorddimension, mydimension > Jacobian
Type of Jacobian matrix.
Definition: Geometry.hpp:105
JacobianInverse jacobianInverse(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:204
FieldVector< ctype, mydimension > LocalCoordinate
Domain type of.
Definition: Geometry.hpp:100
Jacobian jacobian(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:197
double integrationElement(const LocalCoordinate &) const
Returns 1 for the vertex geometry.
Definition: Geometry.hpp:141
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed
Type of the inverse of the transposed Jacobian matrix.
Definition: Geometry.hpp:111
Geometry(const GlobalCoordinate &pos)
Construct from vertex position.
Definition: Geometry.hpp:116
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse
Type of inverse of Jacobian matrix.
Definition: Geometry.hpp:107
JacobianTransposed jacobianTransposed(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:180
GeometryType type() const
Using the cube type for vertices.
Definition: Geometry.hpp:147
ctype volume() const
Volume of vertex is arbitrarily set to 1.
Definition: Geometry.hpp:167
FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed
Type of transposed Jacobian matrix.
Definition: Geometry.hpp:109
GlobalCoordinate corner(int cor) const
Returns the single corner: the vertex itself.
Definition: Geometry.hpp:159
int corners() const
A vertex is defined by a single corner.
Definition: Geometry.hpp:153
const GlobalCoordinate & center() const
Returns the centroid of the geometry.
Definition: Geometry.hpp:173
Geometry()
Default constructor, giving a non-valid geometry.
Definition: Geometry.hpp:122
const GlobalCoordinate & global(const LocalCoordinate &) const
Returns the position of the vertex.
Definition: Geometry.hpp:128
JacobianInverseTransposed jacobianInverseTransposed(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:189
LocalCoordinate local(const GlobalCoordinate &) const
Meaningless for the vertex geometry.
Definition: Geometry.hpp:134
double ctype
Coordinate element type.
Definition: Geometry.hpp:97
Definition: Geometry.hpp:226
JacobianInverse jacobianInverse(const LocalCoordinate &) const
The inverse of the jacobian.
Definition: Geometry.hpp:346
const FieldMatrix< ctype, mydimension, coorddimension > & jacobianTransposed(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:325
const GlobalCoordinate & center() const
Returns the centroid of the geometry.
Definition: Geometry.hpp:318
int corners() const
Definition: Geometry.hpp:297
LocalCoordinate local(const GlobalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:277
FieldMatrix< ctype, coorddimension, mydimension > Jacobian
Type of Jacobian matrix.
Definition: Geometry.hpp:247
bool affine() const
Since integrationElement() is constant, returns true.
Definition: Geometry.hpp:352
FieldVector< ctype, mydimension > LocalCoordinate
Domain type of.
Definition: Geometry.hpp:242
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed
Type of the inverse of the transposed Jacobian matrix.
Definition: Geometry.hpp:253
ctype volume() const
Volume (area, actually) of intersection.
Definition: Geometry.hpp:312
const FieldMatrix< ctype, coorddimension, mydimension > & jacobianInverseTransposed(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:332
GeometryType type() const
We use the singular type (None) for intersections.
Definition: Geometry.hpp:290
FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed
Type of transposed Jacobian matrix.
Definition: Geometry.hpp:251
double integrationElement(const LocalCoordinate &) const
Definition: Geometry.hpp:284
Geometry()
Default constructor, giving a non-valid geometry.
Definition: Geometry.hpp:265
const GlobalCoordinate & global(const LocalCoordinate &) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:271
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse
Type of inverse of Jacobian matrix.
Definition: Geometry.hpp:249
Geometry(const GlobalCoordinate &pos, ctype vol)
Construct from centroid and volume (1- and 0-moments).
Definition: Geometry.hpp:258
double ctype
Coordinate element type.
Definition: Geometry.hpp:239
Jacobian jacobian(const LocalCoordinate &) const
The jacobian.
Definition: Geometry.hpp:339
FieldVector< ctype, coorddimension > GlobalCoordinate
Range type of.
Definition: Geometry.hpp:244
GlobalCoordinate corner(int) const
This method is meaningless for singular geometries.
Definition: Geometry.hpp:303
Specialization for 3-dimensional geometries, i.e. cells.
Definition: Geometry.hpp:369
const JacobianInverseTransposed jacobianInverseTransposed(const LocalCoordinate &local_coord) const
Inverse of Jacobian transposed.
Definition: Geometry.hpp:586
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverseTransposed
Type of the inverse of the transposed Jacobian matrix.
Definition: Geometry.hpp:396
bool affine() const
The mapping implemented by this geometry is not generally affine.
Definition: Geometry.hpp:608
double ctype
Coordinate element type.
Definition: Geometry.hpp:382
void set_volume(ctype volume)
Definition: Geometry.hpp:533
FieldVector< ctype, coorddimension > GlobalCoordinate
Range type of.
Definition: Geometry.hpp:387
GlobalCoordinate corner(int cor) const
Get the cor-th of 8 corners of the hexahedral base cell.
Definition: Geometry.hpp:521
FieldMatrix< ctype, mydimension, coorddimension > JacobianTransposed
Type of transposed Jacobian matrix.
Definition: Geometry.hpp:394
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:408
GeometryType type() const
Definition: Geometry.hpp:508
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:632
double integrationElement(const LocalCoordinate &local_coord) const
Definition: Geometry.hpp:500
const JacobianTransposed jacobianTransposed(const LocalCoordinate &local_coord) const
Jacobian transposed. J^T_{ij} = (dg_j/du_i) where g is the mapping from the reference domain,...
Definition: Geometry.hpp:550
GlobalCoordinate global(const LocalCoordinate &local_coord) const
Definition: Geometry.hpp:444
Geometry()
Default constructor, giving a non-valid geometry.
Definition: Geometry.hpp:434
FieldMatrix< ctype, coorddimension, mydimension > JacobianInverse
Type of inverse of Jacobian matrix.
Definition: Geometry.hpp:392
LocalCoordinate local(const GlobalCoordinate &y) const
Definition: Geometry.hpp:475
int corners() const
Definition: Geometry.hpp:515
ctype volume() const
Cell volume.
Definition: Geometry.hpp:528
const GlobalCoordinate & center() const
Returns the centroid of the geometry.
Definition: Geometry.hpp:538
Jacobian jacobian(const LocalCoordinate &local_coord) const
The jacobian.
Definition: Geometry.hpp:595
Geometry(const GlobalCoordinate &pos, ctype vol)
Construct from centroid and volume (1- and 0-moments). Note that since corners are not given,...
Definition: Geometry.hpp:427
Dune::FieldVector< double, 3 > PointType
Refine a single cell considering different widths, lengths, and heights.
Definition: Geometry.hpp:631
FieldVector< ctype, mydimension > LocalCoordinate
Domain type of.
Definition: Geometry.hpp:385
Dune::Impl::FieldMatrixHelper< double > MatrixHelperType
Definition: Geometry.hpp:398
JacobianInverse jacobianInverse(const LocalCoordinate &local_coord) const
The inverse of the jacobian.
Definition: Geometry.hpp:602
FieldMatrix< ctype, coorddimension, mydimension > Jacobian
Type of Jacobian matrix.
Definition: Geometry.hpp:390
Definition: Geometry.hpp:75
void appendRow(DataIter row_beg, DataIter row_end)
Appends a row to the table.
Definition: SparseTable.hpp:108
void appendRow(DataIter row_beg, DataIter row_end)
Appends a row to the table.
Definition: SparseTable.hpp:108
The namespace Dune is the main namespace for all Dune code.
Definition: common/CartesianIndexMapper.hpp:10
T area(const Point< T, 2 > *c)
Definition: Volumes.hpp:118
T volume(const Point< T, 3 > *c)
Computes the volume of a 3D simplex (embedded i 3D space).
Definition: Volumes.hpp:137
T simplex_volume(const Point< T, Dim > *a)
Definition: Volumes.hpp:104
auto referenceElement(const cpgrid::Geometry< mydim, cdim > &geo) -> decltype(referenceElement< double, mydim >(geo.type()))
Definition: Geometry.hpp:1145
face_tag
Definition: preprocess.h:66
@ K_FACE
Definition: preprocess.h:69
@ J_FACE
Definition: preprocess.h:68
@ I_FACE
Definition: preprocess.h:67