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