37#ifndef OPM_GEOMETRY_REFINEMENT_HEADER
38#define OPM_GEOMETRY_REFINEMENT_HEADER
50std::vector<std::array<int,8>>& refined_cell_to_point,
52Opm::SparseTable<int>& refined_face_to_point,
56const std::array<int,3>& patch_dim,
57const std::vector<double>& widthsX,
58const std::vector<double>& lengthsY,
59const std::vector<double>& heightsZ)
const
62 all_geom.
geomVector(std::integral_constant<int,3>());
64 all_geom.
geomVector(std::integral_constant<int,1>());
66 all_geom.
geomVector(std::integral_constant<int,0>());
76 const std::array<int,3>& refined_dim = { cells_per_dim[0]*patch_dim[0],
77 cells_per_dim[1]*patch_dim[1],
78 cells_per_dim[2]*patch_dim[2]};
79 refined_corners.resize((refined_dim[0] + 1)*(refined_dim[1] + 1)*(refined_dim[2] + 1));
86 assert(
static_cast<int>(widthsX.size()) == patch_dim[0]);
87 assert(
static_cast<int>(lengthsY.size()) == patch_dim[1]);
88 assert(
static_cast<int>(heightsZ.size()) == patch_dim[2]);
89 const auto localCoordNumerator = [](
const std::vector<double>& vec,
int sumLimit,
double multiplier) {
92 assert(sumLimit <
static_cast<int>(vec.size()));
93 lcn += multiplier*vec[sumLimit];
94 for (
int m = 0; m < sumLimit; ++m) {
101 const double sumWidths = std::accumulate(widthsX.begin(), widthsX.end(),
double(0));
103 const double sumLengths = std::accumulate(lengthsY.begin(), lengthsY.end(),
double(0));
105 const double sumHeights = std::accumulate(heightsZ.begin(), heightsZ.end(),
double(0));
108 for (
int j = 0; j < refined_dim[1] +1; ++j) {
110 for (
int i = 0; i < refined_dim[0] +1; ++i) {
112 for (
int k = 0; k < refined_dim[2] +1; ++k) {
116 int refined_corner_idx =
117 (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) + k;
120 if ( i == refined_dim[0]) {
123 local_x = localCoordNumerator(widthsX, i/cells_per_dim[0],
double((i % cells_per_dim[0])) / cells_per_dim[0]);
125 if ( j == refined_dim[1]) {
126 local_y = sumLengths;
128 local_y = localCoordNumerator(lengthsY, j/cells_per_dim[1],
double((j % cells_per_dim[1])) / cells_per_dim[1]);
130 if ( k == refined_dim[2]) {
131 local_z = sumHeights;
133 local_z = localCoordNumerator(heightsZ, k/cells_per_dim[2],
double((k % cells_per_dim[2])) /cells_per_dim[2]);
136 const LocalCoordinate& local_refined_corner = { local_x/sumWidths, local_y/sumLengths, local_z/sumHeights };
137 assert(local_x/sumWidths <= 1.);
138 assert(local_y/sumLengths <= 1.);
139 assert(local_z/sumHeights <= 1.);
142 refined_corners[refined_corner_idx] =
Geometry<0, 3>(this->global(local_refined_corner));
150 const int refined_faces_size =
151 (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1))
152 + ((refined_dim[0]+1)*refined_dim[1]*refined_dim[2])
153 + (refined_dim[0]*(refined_dim[1]+1)*refined_dim[2]);
154 refined_faces.resize(refined_faces_size);
155 refined_face_tags.resize(refined_faces_size);
156 refined_face_normals.resize(refined_faces_size);
193 for (
int constant_direction = 0; constant_direction < 3; ++constant_direction){
198 std::array<int,3> refined_dim_mixed = {
199 refined_dim[(2+constant_direction)%3],
200 refined_dim[(1+constant_direction)%3],
201 refined_dim[constant_direction % 3] };
202 for (
int l = 0; l < refined_dim_mixed[0] + 1; ++l) {
203 for (
int m = 0; m < refined_dim_mixed[1]; ++m) {
204 for (
int n = 0; n < refined_dim_mixed[2]; ++n) {
206 auto [
face_tag, idx, face_to_point, face_to_cell, wrong_local_centroid] =
207 getIndicesFace(l, m, n, constant_direction, refined_dim);
211 refined_face_to_point.appendRow(face_to_point.begin(), face_to_point.end());
213 refined_face_to_cell.appendRow(face_to_cell.begin(), face_to_cell.end());
216 for (
int corn = 0; corn < 4; ++corn){
217 face_center += refined_corners[face_to_point[corn]].center();
224 GlobalCoordinate face_vector0 = refined_corners[face_to_point[0]].center() - face_center;
225 GlobalCoordinate face_vector1 = refined_corners[face_to_point[1]].center() - face_center;
226 mutable_face_normals[idx] = {
227 (face_vector0[1]*face_vector1[2]) - (face_vector0[2]*face_vector1[1]),
228 (face_vector0[2]*face_vector1[0]) - (face_vector0[0]*face_vector1[2]),
229 (face_vector0[0]*face_vector1[1]) - (face_vector0[1]*face_vector1[0])};
230 mutable_face_normals[idx] /= mutable_face_normals[idx].two_norm();
232 mutable_face_normals[idx] *= -1;
236 std::vector<std::array<int,2>> refined_face_to_edges = {
237 { face_to_point[0], face_to_point[1] },
238 { face_to_point[1], face_to_point[2] },
239 { face_to_point[2], face_to_point[3] },
240 { face_to_point[3], face_to_point[0] }
244 double refined_face_area = 0.0;
245 for (
int edge = 0; edge < 4; ++edge) {
249 refined_corners[refined_face_to_edges[edge][0]].center(),
250 refined_corners[refined_face_to_edges[edge][1]].center(),
252 refined_face_area += std::fabs(
area(trian_corners));
273 refined_cells.resize(refined_dim[0] * refined_dim[1] * refined_dim[2]);
276 refined_cell_to_point.resize(refined_dim[0] * refined_dim[1] * refined_dim[2]);
305 double sum_all_refined_cell_volumes = 0.0;
318 for (
int k = 0; k < refined_dim[2]; ++k) {
319 for (
int j = 0; j < refined_dim[1]; ++j) {
320 for (
int i = 0; i < refined_dim[0]; ++i) {
322 int refined_cell_idx = (k*refined_dim[0]*refined_dim[1]) + (j*refined_dim[0]) +i;
325 double refined_cell_volume = 0.0;
328 std::array<int,8> cell_to_point = {
329 (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k,
330 (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k,
331 ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k,
332 ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k,
333 (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k+1,
334 (j*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k+1,
335 ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + (i*(refined_dim[2]+1)) +k+1,
336 ((j+1)*(refined_dim[0]+1)*(refined_dim[2]+1)) + ((i+1)*(refined_dim[2]+1)) +k+1
339 refined_cell_to_point[refined_cell_idx] = cell_to_point;
343 for (
int corn = 0; corn < 8; ++corn) {
344 refined_cell_center += refined_corners[cell_to_point[corn]].center();
346 refined_cell_center /= 8.;
350 std::vector<int> hexa_to_face = {
352 (k*refined_dim[0]*refined_dim[1]) + (j*refined_dim[0]) + i,
354 (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1))
355 + ((refined_dim[0]+1)*refined_dim[1]*refined_dim[2])
356 + (j*refined_dim[0]*refined_dim[2]) + (i*refined_dim[2]) + k,
358 (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1))
359 + (i*refined_dim[1]*refined_dim[2]) + (k*refined_dim[1]) + j,
361 (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1))
362 + ((i+1)*refined_dim[1]*refined_dim[2]) + (k*refined_dim[1]) + j,
364 (refined_dim[0]*refined_dim[1]*(refined_dim[2]+1)) +
365 ((refined_dim[0]+1)*refined_dim[1]*refined_dim[2])
366 + ((j+1)*refined_dim[0]*refined_dim[2]) + (i*refined_dim[2]) + k,
368 ((k+1)*refined_dim[0]*refined_dim[1]) + (j*refined_dim[0]) + i};
378 std::vector<cpgrid::EntityRep<1>> cell_to_face = {
379 { hexa_to_face[0],
false}, {hexa_to_face[1],
false},
380 { hexa_to_face[2],
false}, {hexa_to_face[3],
true},
381 { hexa_to_face[4],
true}, {hexa_to_face[5],
true} };
382 refined_cell_to_face.appendRow(cell_to_face.begin(), cell_to_face.end());
386 std::vector<Geometry<0,3>::GlobalCoordinate> hexa_face_centroids;
387 for (
auto& idx : hexa_to_face) {
388 hexa_face_centroids.push_back(refined_faces[idx].center());
402 std::vector<std::array<int,4>> cell_face4corners;
403 cell_face4corners.reserve(6);
404 for (
int face = 0; face < 6; ++face) {
405 cell_face4corners.push_back({
406 refined_face_to_point[hexa_to_face[face]][0],
407 refined_face_to_point[hexa_to_face[face]][1],
408 refined_face_to_point[hexa_to_face[face]][2],
409 refined_face_to_point[hexa_to_face[face]][3] });
413 std::vector<std::vector<std::array<int,2>>> tetra_edge_indices;
414 tetra_edge_indices.reserve(6);
415 for (
auto& face_indices : cell_face4corners)
417 std::vector<std::array<int,2>> face4edges_indices = {
418 { face_indices[0], face_indices[1]},
419 { face_indices[0], face_indices[2]},
420 { face_indices[1], face_indices[3]},
421 { face_indices[2], face_indices[3]} };
422 tetra_edge_indices.push_back(face4edges_indices);
428 for (
int face = 0; face < 6; ++face) {
429 for (
int edge = 0; edge < 4; ++edge) {
433 refined_corners[tetra_edge_indices[face][edge][0]].center(),
434 refined_corners[tetra_edge_indices[face][edge][1]].center(),
435 hexa_face_centroids[face],
436 refined_cell_center };
442 sum_all_refined_cell_volumes += refined_cell_volume;
445 int* indices_storage_ptr = refined_cell_to_point[refined_cell_idx].data();
447 refined_cells[refined_cell_idx] =
451 indices_storage_ptr);
458 if (std::fabs(sum_all_refined_cell_volumes - this->
volume())
461 for(
auto& cell: refined_cells){
462 cell.vol_ *= correction;
469const std::tuple<
enum face_tag, int,
470std::array<int, 4>, std::vector<cpgrid::EntityRep<0>>,
475 std::vector<cpgrid::EntityRep<0>> neighboring_cells_of_one_face;
476 switch(constant_direction) {
481 neighboring_cells_of_one_face.push_back({((l-1)*cells_per_dim[0]*cells_per_dim[1])
482 + (m*cells_per_dim[0]) + n,
true});
484 if (l != cells_per_dim[2]) {
485 neighboring_cells_of_one_face.push_back({ (l*cells_per_dim[0]*cells_per_dim[1])
486 + (m*cells_per_dim[0]) + n,
false});
489 (l*cells_per_dim[0]*cells_per_dim[1]) + (m*cells_per_dim[0]) + n,
490 {(m*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (n*(cells_per_dim[2]+1)) +l,
491 (m*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((n+1)*(cells_per_dim[2]+1)) +l,
492 ((m+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((n+1)*(cells_per_dim[2]+1)) +l,
493 ((m+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (n*(cells_per_dim[2]+1)) +l},
494 neighboring_cells_of_one_face,
495 {(.5 + n)/cells_per_dim[0], (.5 + m)/cells_per_dim[1], double(l)/cells_per_dim[2]}};
500 neighboring_cells_of_one_face.push_back({(m*cells_per_dim[0]*cells_per_dim[1])
501 + (n*cells_per_dim[0]) +l-1,
true});
503 if (l != cells_per_dim[0]) {
504 neighboring_cells_of_one_face.push_back({ (m*cells_per_dim[0]*cells_per_dim[1])
505 + (n*cells_per_dim[0]) + l,
false});
508 (cells_per_dim[0]*cells_per_dim[1]*(cells_per_dim[2]+1))
509 + (l*cells_per_dim[1]*cells_per_dim[2]) + (m*cells_per_dim[1]) + n,
510 {(n*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m,
511 ((n+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m,
512 ((n+1)*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m+1,
513 (n*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (l*(cells_per_dim[2]+1)) +m+1},
514 neighboring_cells_of_one_face,
515 { double(l)/cells_per_dim[0], (.5 + n)/cells_per_dim[1], (.5 + m)/cells_per_dim[2]}};
520 neighboring_cells_of_one_face.push_back({(n*cells_per_dim[0]*cells_per_dim[1])
521 + ((l-1)*cells_per_dim[0]) +m,
true});
523 if (l != cells_per_dim[1]) {
524 neighboring_cells_of_one_face.push_back({(n*cells_per_dim[0]*cells_per_dim[1])
525 + (l*cells_per_dim[0]) + m,
false});
528 (cells_per_dim[0]*cells_per_dim[1]*(cells_per_dim[2] +1))
529 + ((cells_per_dim[0]+1)*cells_per_dim[1]*cells_per_dim[2])
530 + (l*cells_per_dim[0]*cells_per_dim[2]) + (m*cells_per_dim[2]) + n,
531 {(l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (m*(cells_per_dim[2]+1)) +n,
532 (l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((m+1)*(cells_per_dim[2]+1)) +n,
533 (l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + ((m+1)*(cells_per_dim[2]+1)) +n+1,
534 (l*(cells_per_dim[0]+1)*(cells_per_dim[2]+1)) + (m*(cells_per_dim[2]+1)) +n+1},
535 neighboring_cells_of_one_face,
536 {(.5 + m)/cells_per_dim[0],
double(l)/cells_per_dim[1], (.5 + n)/cells_per_dim[2]}};
539 OPM_THROW(std::logic_error,
"Unhandled dimension. This should never happen!");
Definition: DefaultGeometryPolicy.hpp:53
const EntityVariable< cpgrid::Geometry< 3 - codim, 3 >, codim > & geomVector() const
Definition: DefaultGeometryPolicy.hpp:86
std::shared_ptr< const EntityVariable< cpgrid::Geometry< 0, 3 >, 3 > > pointGeometryPtr() const
Keep the corner geometries alive when constructing cell geometries.
Definition: DefaultGeometryPolicy.hpp:129
Represents an entity of a given codim, with positive or negative orientation.
Definition: EntityRep.hpp:98
Base class for EntityVariable and SignedEntityVariable. Forwards a restricted subset of the std::vect...
Definition: EntityRep.hpp:218
Definition: Geometry.hpp:229
Specialization for 3-dimensional geometries, i.e. cells.
Definition: Geometry.hpp:374
FieldVector< ctype, coorddimension > GlobalCoordinate
Range type of.
Definition: Geometry.hpp:394
FieldVector< ctype, mydimension > LocalCoordinate
Domain type of.
Definition: Geometry.hpp:392
Definition: Geometry.hpp:76
A class design to hold a variable with a value for each entity of the given codimension,...
Definition: EntityRep.hpp:306
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