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