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 weightsProdMap.insert_or_assign(
id, 0.0);
221 distanceMap.insert_or_assign(
id, 1.0);
222 faceNormalMap.insert_or_assign(
id, DimVector{0.0, 0.0, 0.0});
228 typename std::is_same<Grid, Dune::CpGrid>::type isCpGrid;
229 computeCellProperties(intersection,
236 const auto id = details::isIdTPSA(inside.elemIdx, outside.elemIdx);
237 Scalar dist_in = computeDistance_(distanceVector_(inside.faceCenter, inside.elemIdx), faceNormal);
238 Scalar dist_out = computeDistance_(distanceVector_(outside.faceCenter, outside.elemIdx), faceNormal);
239 distanceMap.insert_or_assign(
id, dist_in + dist_out);
241 Scalar weight_in = computeWeight_(dist_in, sModulus_[inside.elemIdx]);
242 Scalar weight_out = computeWeight_(dist_out, sModulus_[outside.elemIdx]);
243 Scalar weightsAvg = weight_in / (weight_in + weight_out);
244 Scalar weightsProd = weight_in * weight_out;
245 weightsAvgMap.insert_or_assign(
id, weightsAvg);
246 weightsProdMap.insert_or_assign(
id, weightsProd);
248 faceNormalMap.insert_or_assign(
id, faceNormal);
254 centroids_cache_.clear();
257 #pragma omp parallel sections 263 weightsAvgMap.finalize();
267 weightsProdMap.finalize();
271 distanceMap.finalize();
275 faceNormalMap.finalize();
279 weightsAvgBoundaryMap.finalize();
283 weightsProdBoundaryMap.finalize();
287 distanceBoundaryMap.finalize();
291 faceNormalBoundaryMap.finalize();
302 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
306 auto tmp_whgt = weightsAvg_.at(details::isIdTPSA(elemIdx1, elemIdx2));
308 auto cartIdx1 = lookUpCartesianData_.
309 template getFieldPropCartesianIdx<Grid>(elemIdx1);
310 auto cartIdx2 = lookUpCartesianData_.
311 template getFieldPropCartesianIdx<Grid>(elemIdx2);
312 if (cartIdx1 < cartIdx2) {
316 return 1.0 - tmp_whgt;
327 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
331 return weightsAvgBoundary_.at(std::make_pair(elemIdx, boundaryFaceIdx));
341 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
345 return weightsProd_.at(details::isIdTPSA(elemIdx1, elemIdx2));
355 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
359 return weightsProdBoundary_.at(std::make_pair(elemIdx, boundaryFaceIdx));
369 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
373 return distance_.at(details::isIdTPSA(elemIdx1, elemIdx2));
383 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
387 return distanceBoundary_.at(std::make_pair(elemIdx, boundaryFaceIdx));
399 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
400 typename FacePropertiesTPSA<Grid, GridView, ElementMapper, CartesianIndexMapper, Scalar>::DimVector
404 auto cartIdx1 = lookUpCartesianData_.
405 template getFieldPropCartesianIdx<Grid>(elemIdx1);
406 auto cartIdx2 = lookUpCartesianData_.
407 template getFieldPropCartesianIdx<Grid>(elemIdx2);
408 int sign = (cartIdx1 < cartIdx2) ? 1 : -1;
409 return sign * faceNormal_.at(details::isIdTPSA(elemIdx1, elemIdx2));
421 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
422 const typename FacePropertiesTPSA<Grid, GridView, ElementMapper, CartesianIndexMapper, Scalar>::DimVector&
426 return faceNormalBoundary_.at(std::make_pair(elemIdx, boundaryFaceIdx));
439 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
443 return std::abs(Dune::dot(faceNormal, distVec));
456 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
457 template<
class Intersection>
462 [[maybe_unused]] DimVector& faceNormal,
463 std::false_type)
const 465 throw std::runtime_error(
"TPSA not implemented for DUNE grid types other than CpGrid!");
478 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
479 template<
class Intersection>
484 DimVector& faceNormal,
485 std::true_type)
const 487 int faceIdx = intersection.id();
488 if (grid_.maxLevel() == 0) {
490 inside.faceCenter = grid_.faceCenterEcl(inside.elemIdx, inside.faceIdx, intersection);
491 outside.faceCenter = grid_.faceCenterEcl(outside.elemIdx, outside.faceIdx, intersection);
494 faceNormal = grid_.faceNormal(faceIdx);
495 auto cartFaceCell0 = lookUpCartesianData_.
496 template getFieldPropCartesianIdx<Grid>(grid_.faceCell(faceIdx, 0));
497 auto cartFaceCell1 = lookUpCartesianData_.
498 template getFieldPropCartesianIdx<Grid>(grid_.faceCell(faceIdx, 1));
499 if (cartFaceCell0 > cartFaceCell1) {
504 throw std::runtime_error(
"TPSA not implemented with LGR");
516 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
520 return distance / smod;
530 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
531 typename FacePropertiesTPSA<Grid, GridView, ElementMapper, CartesianIndexMapper, Scalar>::DimVector
535 const auto& cellCenter = centroids_cache_.empty() ? centroids_(cellIdx)
536 : centroids_cache_[cellIdx];
537 DimVector x = faceCenter;
538 for (
unsigned dimIdx = 0; dimIdx < dimWorld; ++dimIdx) {
539 x[dimIdx] -= cellCenter[dimIdx];
552 template<
class Gr
id,
class Gr
idView,
class ElementMapper,
class CartesianIndexMapper,
class Scalar>
556 unsigned numElem = gridView_.size(0);
557 sModulus_.resize(numElem);
559 const auto& fp = eclState_.fieldProps();
560 std::vector<double> sModulusData;
561 if (fp.has_double(
"SMODULUS")) {
562 sModulusData = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"SMODULUS");
564 else if (fp.has_double(
"YMODULE") && fp.has_double(
"LAME")) {
566 const std::vector<double>& ymodulus = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"YMODULE");
567 const std::vector<double>& lameParam = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"LAME");
568 sModulusData.resize(numElem);
569 for (std::size_t i = 0; i < sModulusData.size(); ++i) {
570 const double r = std::sqrt(ymodulus[i] * ymodulus[i] + 9 * lameParam[i] * lameParam[i]
571 + 2 * ymodulus[i] * lameParam[i]);
572 sModulusData[i] = (ymodulus[i] - 3 * lameParam[i] + r) / 4.0;
575 else if (fp.has_double(
"YMODULE") && fp.has_double(
"PRATIO")) {
576 const std::vector<double>& ymodulus = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"YMODULE");
577 const std::vector<double>& pratio = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"PRATIO");
578 sModulusData.resize(numElem);
579 for (std::size_t i = 0; i < sModulusData.size(); ++i) {
580 sModulusData[i] = ymodulus[i] / (2 * (1 + pratio[i]));
583 else if (fp.has_double(
"LAME") && fp.has_double(
"PRATIO")) {
584 const std::vector<double>& lameParam = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"LAME");
585 const std::vector<double>& pratio = this->lookUpData_.assignFieldPropsDoubleOnLeaf(fp,
"PRATIO");
586 sModulusData.resize(numElem);
587 for (std::size_t i = 0; i < sModulusData.size(); ++i) {
588 sModulusData[i] = lameParam[i] * (1 - 2 * pratio[i]) / (2 * pratio[i]);
592 throw std::logic_error(
"Cannot read shear modulus data from ecl state, SMODULUS keyword missing, " 593 "and one of the following keyword pairs are missing for conversion: " 594 "(YMODULE, LAME), (YMODULE, PRATIO) and (LAME, PRATIO)!");
598 for (std::size_t dofIdx = 0; dofIdx < numElem; ++ dofIdx) {
599 sModulus_[dofIdx] = sModulusData[dofIdx];
Scalar weightProduct(unsigned elemIdx1, unsigned elemIdx2) const
Product of weights at interface between two elements.
Definition: FacePropertiesTPSA_impl.hpp:343
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:329
Structs needed for tpfalinearizer and its gpuparams struct extracted to be defined in one place that ...
Definition: blackoilbioeffectsmodules.hh:45
DimVector cellFaceNormal(unsigned elemIdx1, unsigned elemIdx2)
Cell face normal at interface between two elements.
Definition: FacePropertiesTPSA_impl.hpp:402
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:441
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:304
Definition: FacePropertiesTPSA.hpp:82
void extractSModulus_()
Extract shear modulus from eclState.
Definition: FacePropertiesTPSA_impl.hpp:554
Simplifies multi-threaded capabilities.
Scalar normalDistanceBoundary(unsigned elemIdx1, unsigned boundaryFaceIdx) const
Distance to boundary interface.
Definition: FacePropertiesTPSA_impl.hpp:385
DimVector distanceVector_(const DimVector &faceCenter, const unsigned &cellIdx) const
Distance vector from cell center to face center.
Definition: FacePropertiesTPSA_impl.hpp:533
Scalar weightProductBoundary(unsigned elemIdx1, unsigned boundaryFaceIdx) const
Product of weights at boundary interface.
Definition: FacePropertiesTPSA_impl.hpp:357
Scalar computeWeight_(const Scalar distance, const Scalar smod)
Compute weight ratio between distance and shear modulus.
Definition: FacePropertiesTPSA_impl.hpp:518
Scalar normalDistance(unsigned elemIdx1, unsigned elemIdx2) const
Distance between two elements.
Definition: FacePropertiesTPSA_impl.hpp:371
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:424