25 #ifndef TPSA_FACE_PROPERTIES_IMPL_HPP 26 #define TPSA_FACE_PROPERTIES_IMPL_HPP 28 #ifndef TPSA_FACE_PROPERTIES_HPP 30 #include <opm/simulators/flow/FacePropertiesTPSA.hpp> 33 #include <dune/grid/common/mcmgmapper.hh> 35 #include <opm/common/utility/ThreadSafeMapBuilder.hpp> 37 #include <opm/grid/utility/ElementChunks.hpp> 39 #include <opm/input/eclipse/EclipseState/EclipseState.hpp> 52 constexpr
unsigned elemIdxShift = 32;
54 std::uint64_t isIdTPSA(std::uint32_t elemIdx1, std::uint32_t elemIdx2)
56 const std::uint32_t elemAIdx = std::min(elemIdx1, elemIdx2);
57 const std::uint64_t elemBIdx = std::max(elemIdx1, elemIdx2);
59 return (elemBIdx << elemIdxShift) + elemAIdx;
75 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
78 const GridView& gridView,
79 const CartesianIndexMapper& cartMapper,
81 std::function<std::array<double,dimWorld>(
int)> centroids)
84 , cartMapper_(cartMapper)
86 , centroids_(centroids)
87 , lookUpData_(gridView)
88 , lookUpCartesianData_(gridView, cartMapper)
94 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
104 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
109 ElementMapper elemMapper(gridView_, Dune::mcmgElementLayout());
110 unsigned numElements = elemMapper.size();
121 weightsProd_.clear();
124 if (num_threads == 1) {
125 weightsAvg_.reserve(numElements * 3 * 1.05);
126 weightsProd_.reserve(numElements * 3 * 1.05);
127 distance_.reserve(numElements * 3 * 1.05);
128 faceNormal_.reserve(numElements * 3 * 1.05);
130 weightsAvgBoundary_.clear();
131 weightsProdBoundary_.clear();
132 distanceBoundary_.clear();
133 faceNormalBoundary_.clear();
136 centroids_cache_.resize(gridView_.size(0));
137 for (
const auto& elem : elements(gridView_)) {
138 const unsigned elemIdx = elemMapper.index(elem);
139 centroids_cache_[elemIdx] = centroids_(elemIdx);
143 ThreadSafeMapBuilder weightsAvgMap(weightsAvg_, num_threads, MapBuilderInsertionMode::Insert_Or_Assign);
144 ThreadSafeMapBuilder weightsProdMap(weightsProd_, num_threads, MapBuilderInsertionMode::Insert_Or_Assign);
145 ThreadSafeMapBuilder distanceMap(distance_, num_threads, MapBuilderInsertionMode::Insert_Or_Assign);
146 ThreadSafeMapBuilder faceNormalMap(faceNormal_, num_threads, MapBuilderInsertionMode::Insert_Or_Assign);
148 ThreadSafeMapBuilder weightsAvgBoundaryMap(weightsAvgBoundary_, num_threads, MapBuilderInsertionMode::Insert_Or_Assign);
149 ThreadSafeMapBuilder weightsProdBoundaryMap(weightsProdBoundary_, num_threads, MapBuilderInsertionMode::Insert_Or_Assign);
150 ThreadSafeMapBuilder distanceBoundaryMap(distanceBoundary_, num_threads, MapBuilderInsertionMode::Insert_Or_Assign);
151 ThreadSafeMapBuilder faceNormalBoundaryMap(faceNormalBoundary_, num_threads, MapBuilderInsertionMode::Insert_Or_Assign);
154 #pragma omp parallel for 157 for (
const auto& chunk : ElementChunks(gridView_, Dune::Partitions::all, num_threads)) {
158 for (
const auto& elem : chunk) {
162 DimVector faceNormal;
165 inside.elemIdx = elemMapper.index(elem);
166 inside.cartElemIdx = lookUpCartesianData_.
167 template getFieldPropCartesianIdx<Grid>(inside.elemIdx);
170 unsigned boundaryIsIdx = 0;
171 for (
const auto& intersection : intersections(gridView_, elem)) {
173 if (intersection.boundary()) {
175 const auto& geometry = intersection.geometry();
176 inside.faceCenter = geometry.center();
177 faceNormal = intersection.centerUnitOuterNormal();
180 const auto index_pair = std::make_pair(inside.elemIdx, boundaryIsIdx);
181 Scalar distBound = computeDistance_(distanceVector_(inside.faceCenter, inside.elemIdx), faceNormal);
182 distanceBoundaryMap.insert_or_assign(index_pair, distBound);
184 Scalar weightsAvgBound = 1.0;
185 Scalar weightsProdBound = 0.0;
186 weightsAvgBoundaryMap.insert_or_assign(index_pair, weightsAvgBound);
187 weightsProdBoundaryMap.insert_or_assign(index_pair, weightsProdBound);
189 faceNormalBoundaryMap.insert_or_assign(index_pair, faceNormal);
196 if (!intersection.neighbor()) {
202 const auto& outsideElem = intersection.outside();
203 outside.elemIdx = elemMapper.index(outsideElem);
204 outside.cartElemIdx = lookUpCartesianData_.
205 template getFieldPropCartesianIdx<Grid>(outside.elemIdx);
208 if (std::tie(inside.cartElemIdx, inside.elemIdx) > std::tie(outside.cartElemIdx, outside.elemIdx)) {
213 inside.faceIdx = intersection.indexInInside();
214 outside.faceIdx = intersection.indexInOutside();
217 if (inside.faceIdx == -1) {
218 const auto id = details::isIdTPSA(inside.elemIdx, outside.elemIdx);
219 weightsAvgMap.insert_or_assign(
id, 0.0);
220 distanceMap.insert_or_assign(
id, 0.0);
221 faceNormalMap.insert_or_assign(
id, DimVector{0.0, 0.0, 0.0});
227 typename std::is_same<Grid, Dune::CpGrid>::type isCpGrid;
228 computeCellProperties(intersection,
235 const auto id = details::isIdTPSA(inside.elemIdx, outside.elemIdx);
236 Scalar dist_in = computeDistance_(distanceVector_(inside.faceCenter, inside.elemIdx), faceNormal);
237 Scalar dist_out = computeDistance_(distanceVector_(outside.faceCenter, outside.elemIdx), faceNormal);
238 distanceMap.insert_or_assign(
id, dist_in + dist_out);
240 Scalar weight_in = computeWeight_(dist_in, sModulus_[inside.elemIdx]);
241 Scalar weight_out = computeWeight_(dist_out, sModulus_[outside.elemIdx]);
242 Scalar weightsAvg = weight_in / (weight_in + weight_out);
243 Scalar weightsProd = weight_in * weight_out;
244 weightsAvgMap.insert_or_assign(
id, weightsAvg);
245 weightsProdMap.insert_or_assign(
id, weightsProd);
247 faceNormalMap.insert_or_assign(
id, faceNormal);
253 centroids_cache_.clear();
256 #pragma omp parallel sections 262 weightsAvgMap.finalize();
266 weightsProdMap.finalize();
270 distanceMap.finalize();
274 faceNormalMap.finalize();
278 weightsAvgBoundaryMap.finalize();
282 weightsProdBoundaryMap.finalize();
286 distanceBoundaryMap.finalize();
290 faceNormalBoundaryMap.finalize();
301 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
305 auto tmp_whgt = weightsAvg_.at(details::isIdTPSA(elemIdx1, elemIdx2));
307 auto cartIdx1 = lookUpCartesianData_.
308 template getFieldPropCartesianIdx<Grid>(elemIdx1);
309 auto cartIdx2 = lookUpCartesianData_.
310 template getFieldPropCartesianIdx<Grid>(elemIdx2);
311 if (cartIdx1 < cartIdx2) {
315 return 1.0 - tmp_whgt;
326 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
330 return weightsAvgBoundary_.at(std::make_pair(elemIdx, boundaryFaceIdx));
340 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
344 return weightsProd_.at(details::isIdTPSA(elemIdx1, elemIdx2));
354 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
358 return weightsProdBoundary_.at(std::make_pair(elemIdx, boundaryFaceIdx));
368 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
372 return distance_.at(details::isIdTPSA(elemIdx1, elemIdx2));
382 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
386 return distanceBoundary_.at(std::make_pair(elemIdx, boundaryFaceIdx));
398 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
399 typename FacePropertiesTPSA<Grid, GridView, ElementMapper, CartesianIndexMapper, Scalar>::DimVector
403 auto cartIdx1 = lookUpCartesianData_.
404 template getFieldPropCartesianIdx<Grid>(elemIdx1);
405 auto cartIdx2 = lookUpCartesianData_.
406 template getFieldPropCartesianIdx<Grid>(elemIdx2);
407 int sign = (cartIdx1 < cartIdx2) ? 1 : -1;
408 return sign * faceNormal_.at(details::isIdTPSA(elemIdx1, elemIdx2));
420 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
421 const typename FacePropertiesTPSA<Grid, GridView, ElementMapper, CartesianIndexMapper, Scalar>::DimVector&
425 return faceNormalBoundary_.at(std::make_pair(elemIdx, boundaryFaceIdx));
438 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
442 return std::abs(Dune::dot(faceNormal, distVec));
455 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
456 template<
class Intersection>
461 [[maybe_unused]] DimVector& faceNormal,
462 std::false_type)
const 464 throw std::runtime_error(
"TPSA not implemented for DUNE grid types other than CpGrid!");
477 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
478 template<
class Intersection>
483 DimVector& faceNormal,
484 std::true_type)
const 486 int faceIdx = intersection.id();
487 if (grid_.maxLevel() == 0) {
489 inside.faceCenter = grid_.faceCenterEcl(inside.elemIdx, inside.faceIdx, intersection);
490 outside.faceCenter = grid_.faceCenterEcl(outside.elemIdx, outside.faceIdx, intersection);
493 faceNormal = grid_.faceNormal(faceIdx);
494 auto cartFaceCell0 = lookUpCartesianData_.
495 template getFieldPropCartesianIdx<Grid>(grid_.faceCell(faceIdx, 0));
496 auto cartFaceCell1 = lookUpCartesianData_.
497 template getFieldPropCartesianIdx<Grid>(grid_.faceCell(faceIdx, 1));
498 if (cartFaceCell0 > cartFaceCell1) {
503 throw std::runtime_error(
"TPSA not implemented with LGR");
515 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
519 return distance / smod;
529 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
530 typename FacePropertiesTPSA<Grid, GridView, ElementMapper, CartesianIndexMapper, Scalar>::DimVector
534 const auto& cellCenter = centroids_cache_.empty() ? centroids_(cellIdx)
535 : centroids_cache_[cellIdx];
536 DimVector x = faceCenter;
537 for (
unsigned dimIdx = 0; dimIdx < dimWorld; ++dimIdx) {
538 x[dimIdx] -= cellCenter[dimIdx];
551 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
555 unsigned numElem = gridView_.size(0);
556 sModulus_.resize(numElem);
558 const auto& fp = eclState_.fieldProps();
559 std::vector<double> sModulusData;
560 if (fp.has_double(
"SMODULUS")) {
561 sModulusData = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"SMODULUS");
563 else if (fp.has_double(
"YMODULE") && fp.has_double(
"LAME")) {
565 const std::vector<double>& ymodulus = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"YMODULE");
566 const std::vector<double>& lameParam = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"LAME");
567 sModulusData.resize(numElem);
568 for (std::size_t i = 0; i < sModulusData.size(); ++i) {
569 const double r = std::sqrt(ymodulus[i] * ymodulus[i] + 9 * lameParam[i] * lameParam[i]
570 + 2 * ymodulus[i] * lameParam[i]);
571 sModulusData[i] = (ymodulus[i] - 3 * lameParam[i] + r) / 4.0;
574 else if (fp.has_double(
"YMODULE") && fp.has_double(
"PRATIO")) {
575 const std::vector<double>& ymodulus = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"YMODULE");
576 const std::vector<double>& pratio = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"PRATIO");
577 sModulusData.resize(numElem);
578 for (std::size_t i = 0; i < sModulusData.size(); ++i) {
579 sModulusData[i] = ymodulus[i] / (2 * (1 + pratio[i]));
582 else if (fp.has_double(
"LAME") && fp.has_double(
"PRATIO")) {
583 const std::vector<double>& lameParam = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"LAME");
584 const std::vector<double>& pratio = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"PRATIO");
585 sModulusData.resize(numElem);
586 for (std::size_t i = 0; i < sModulusData.size(); ++i) {
587 sModulusData[i] = lameParam[i] * (1 - 2 * pratio[i]) / (2 * pratio[i]);
591 throw std::logic_error(
"Cannot read shear modulus data from ecl state, SMODULUS keyword missing, " 592 "and one of the following keyword pairs are missing for conversion: " 593 "(YMODULE, LAME), (YMODULE, PRATIO) and (LAME, PRATIO)!");
597 for (std::size_t dofIdx = 0; dofIdx < numElem; ++ dofIdx) {
598 sModulus_[dofIdx] = sModulusData[dofIdx];
Scalar weightProduct(unsigned elemIdx1, unsigned elemIdx2) const
Product of weights at interface between two elements.
Definition: FacePropertiesTPSA_impl.hpp:342
static unsigned maxThreads()
Return the maximum number of threads of the current process.
Definition: threadmanager.hpp:66
Cell face properties needed in TPSA equation calculations.
Definition: FacePropertiesTPSA.hpp:48
Scalar weightAverageBoundary(unsigned elemIdx1, unsigned boundaryFaceIdx) const
Average (half-)weight at boundary interface.
Definition: FacePropertiesTPSA_impl.hpp:328
This file contains a set of helper functions used by VFPProd / VFPInj.
Definition: blackoilbioeffectsmodules.hh:45
DimVector cellFaceNormal(unsigned elemIdx1, unsigned elemIdx2)
Cell face normal at interface between two elements.
Definition: FacePropertiesTPSA_impl.hpp:401
void update()
Compute TPSA face properties.
Definition: FacePropertiesTPSA_impl.hpp:106
Scalar computeDistance_(const DimVector &distVec, const DimVector &faceNormal)
Compute normal distance from cell center to face center.
Definition: FacePropertiesTPSA_impl.hpp:440
FacePropertiesTPSA(const EclipseState &eclState, const GridView &gridView, const CartesianIndexMapper &cartMapper, const Grid &grid, std::function< std::array< double, dimWorld >(int)> centroids)
Constructor.
Definition: FacePropertiesTPSA_impl.hpp:77
Scalar weightAverage(unsigned elemIdx1, unsigned elemIdx2) const
Average (half-)weight at interface between two elements.
Definition: FacePropertiesTPSA_impl.hpp:303
Definition: FacePropertiesTPSA.hpp:82
void extractSModulus_()
Extract shear modulus from eclState.
Definition: FacePropertiesTPSA_impl.hpp:553
Simplifies multi-threaded capabilities.
Scalar normalDistanceBoundary(unsigned elemIdx1, unsigned boundaryFaceIdx) const
Distance to boundary interface.
Definition: FacePropertiesTPSA_impl.hpp:384
DimVector distanceVector_(const DimVector &faceCenter, const unsigned &cellIdx) const
Distance vector from cell center to face center.
Definition: FacePropertiesTPSA_impl.hpp:532
Scalar weightProductBoundary(unsigned elemIdx1, unsigned boundaryFaceIdx) const
Product of weights at boundary interface.
Definition: FacePropertiesTPSA_impl.hpp:356
Scalar computeWeight_(const Scalar distance, const Scalar smod)
Compute weight ratio between distance and shear modulus.
Definition: FacePropertiesTPSA_impl.hpp:517
Scalar normalDistance(unsigned elemIdx1, unsigned elemIdx2) const
Distance between two elements.
Definition: FacePropertiesTPSA_impl.hpp:370
void finishInit()
Compute TPSA face properties.
Definition: FacePropertiesTPSA_impl.hpp:96
const DimVector & cellFaceNormalBoundary(unsigned elemIdx1, unsigned boundaryFaceIdx) const
Cell face normal of boundary interface.
Definition: FacePropertiesTPSA_impl.hpp:423