diff --git a/opm/simulators/flow/GenericCpGridVanguard.cpp b/opm/simulators/flow/GenericCpGridVanguard.cpp index 39f523fb9..de6b967b4 100644 --- a/opm/simulators/flow/GenericCpGridVanguard.cpp +++ b/opm/simulators/flow/GenericCpGridVanguard.cpp @@ -440,12 +440,27 @@ void GenericCpGridVanguard::doCreateGrids_(Eclips // when there is numerical aquifers, new NNC are generated during // grid processing we need to pass the NNC from root process to // other processes - if (has_numerical_aquifer && mpiSize > 1) { - auto nnc_input = eclState.getInputNNC(); - Parallel::MpiSerializer ser(grid_->comm()); - ser.broadcast(nnc_input); - if (mpiRank > 0) { - eclState.setInputNNC(nnc_input); + if ( mpiSize > 1) + { + if (has_numerical_aquifer) { + auto nnc_input = eclState.getInputNNC(); + Parallel::MpiSerializer ser(grid_->comm()); + ser.broadcast(nnc_input); + if (mpiRank > 0) { + eclState.setInputNNC(nnc_input); + } + } + bool hasPinchNnc = eclState.hasPinchNNC(); + grid_->comm().broadcast(&hasPinchNnc, 1, 0); + + if(hasPinchNnc) + { + auto pinch_nnc = eclState.getPinchNNC(); + Parallel::MpiSerializer ser(grid_->comm()); + ser.broadcast(pinch_nnc); + if (mpiRank > 0) { + eclState.setPinchNNC(std::move(pinch_nnc)); + } } } } diff --git a/opm/simulators/flow/Transmissibility.hpp b/opm/simulators/flow/Transmissibility.hpp index dab92cae2..18bc1b191 100644 --- a/opm/simulators/flow/Transmissibility.hpp +++ b/opm/simulators/flow/Transmissibility.hpp @@ -172,8 +172,7 @@ protected: unsigned insideCartElemIdx, unsigned outsideCartElemIdx, const TransMult& transMult, - const std::array& cartDims, - bool pinchTop); + const std::array& cartDims); /// \brief Creates TRANS{XYZ} arrays for modification by FieldProps data /// @@ -225,6 +224,12 @@ protected: */ void applyNncToGridTrans_(const std::unordered_map& cartesianToCompressed); + /// \brief Applies the previous calculate transmissibilities to the NNCs created via PINCH + /// + /// \param cartesianToCompressed Vector containing the compressed index (or -1 for inactive + /// cells) as the element at the cartesian index. + void applyPinchNncToGridTrans_(const std::unordered_map& cartesianToCompressed); + /// \brief Multiplies the grid transmissibilities according to EDITNNC. void applyEditNncToGridTrans_(const std::unordered_map& globalToLocal); diff --git a/opm/simulators/flow/Transmissibility_impl.hpp b/opm/simulators/flow/Transmissibility_impl.hpp index ad753d875..63cd04923 100644 --- a/opm/simulators/flow/Transmissibility_impl.hpp +++ b/opm/simulators/flow/Transmissibility_impl.hpp @@ -217,14 +217,22 @@ update(bool global, const TransUpdateQuantities update_quantities, // Then the smallest multiplier is applied. // Default is to apply the top and bottom multiplier bool useSmallestMultiplier; + bool pinchOption4ALL; bool pinchActive; if (comm.rank() == 0) { const auto& eclGrid = eclState_.getInputGrid(); pinchActive = eclGrid.isPinchActive(); + auto pinchTransCalcMode = eclGrid.getPinchOption(); useSmallestMultiplier = eclGrid.getMultzOption() == PinchMode::ALL; + pinchOption4ALL = (pinchTransCalcMode == PinchMode::ALL); + if (pinchOption4ALL) + { + useSmallestMultiplier = false; + } } if (global && comm.size() > 1) { comm.broadcast(&useSmallestMultiplier, 1, 0); + comm.broadcast(&pinchOption4ALL, 1, 0); comm.broadcast(&pinchActive, 1, 0); } @@ -393,11 +401,11 @@ update(bool global, const TransUpdateQuantities update_quantities, if (useSmallestMultiplier) { - // Currently PINCH(4) is never queries and hence PINCH(4) == TOPBOT is assumed - // and in this branch PINCH(5) == ALL holds + // PINCH(4) == TOPBOT is assumed here as we set useSmallestMultipliers + // to false if PINCH(4) == ALL holds + // In contrast to the name this will also apply applyAllZMultipliers_(trans, insideFaceIdx, outsideFaceIdx, insideCartElemIdx, - outsideCartElemIdx, transMult, cartDims, - /* pinchTop= */ false); + outsideCartElemIdx, transMult, cartDims); } else { @@ -541,6 +549,7 @@ update(bool global, const TransUpdateQuantities update_quantities, // be seen in a parallel. Unfortunately, when we do not use transmissibilities // we will only see warnings for the partition of process 0 and also false positives. this->applyEditNncToGridTrans_(globalToLocal); + this->applyPinchNncToGridTrans_(globalToLocal); this->applyNncToGridTrans_(globalToLocal); this->applyEditNncrToGridTrans_(globalToLocal); if (applyNncMultregT) { @@ -712,8 +721,7 @@ applyAllZMultipliers_(Scalar& trans, unsigned insideCartElemIdx, unsigned outsideCartElemIdx, const TransMult& transMult, - const std::array& cartDims, - bool pinchTop) + const std::array& cartDims) { if(grid_.maxLevel()> 0) { OPM_THROW(std::invalid_argument, "MULTZ not support with LGRS, yet."); @@ -733,17 +741,14 @@ applyAllZMultipliers_(Scalar& trans, Scalar mult = transMult.getMultiplier(lastCartElemIdx , FaceDir::ZPlus) * transMult.getMultiplier(outsideCartElemIdx , FaceDir::ZMinus); - if ( !pinchTop ) + // pick the smallest multiplier using (Z+)*(Z-) while looking down + // the pillar until reaching the other end of the connection + for(auto cartElemIdx = insideCartElemIdx; cartElemIdx < lastCartElemIdx;) { - // pick the smallest multiplier using (Z+)*(Z-) while looking down - // the pillar until reaching the other end of the connection - for(auto cartElemIdx = insideCartElemIdx; cartElemIdx < lastCartElemIdx;) - { - auto multiplier = transMult.getMultiplier(cartElemIdx, FaceDir::ZPlus); - cartElemIdx += cartDims[0]*cartDims[1]; - multiplier *= transMult.getMultiplier(cartElemIdx, FaceDir::ZMinus); - mult = std::min(mult, static_cast(multiplier)); - } + auto multiplier = transMult.getMultiplier(cartElemIdx, FaceDir::ZPlus); + cartElemIdx += cartDims[0]*cartDims[1]; + multiplier *= transMult.getMultiplier(cartElemIdx, FaceDir::ZMinus); + mult = std::min(mult, static_cast(multiplier)); } trans *= mult; @@ -1019,6 +1024,46 @@ computeFaceProperties(const Intersection& intersection, } } } +template +void +Transmissibility:: +applyPinchNncToGridTrans_(const std::unordered_map& cartesianToCompressed) +{ + // First scale NNCs with EDITNNC. + const auto& nnc_input = eclState_.getPinchNNC(); + + for (const auto& nncEntry : nnc_input) { + auto c1 = nncEntry.cell1; + auto c2 = nncEntry.cell2; + auto lowIt = cartesianToCompressed.find(c1); + auto highIt = cartesianToCompressed.find(c2); + int low = (lowIt == cartesianToCompressed.end())? -1 : lowIt->second; + int high = (highIt == cartesianToCompressed.end())? -1 : highIt->second; + + if (low > high) + std::swap(low, high); + + if (low == -1 && high == -1) + // Silently discard as it is not between active cells + continue; + + if (low == -1 || high == -1) { + // We can end up here if one of the cells is overlap/ghost, because those + // are lacking connections to other cells in the ghost/overlap. + // Hence discard the NNC if it is between active cell and inactive cell + continue; + } + + { + auto candidate = trans_.find(details::isId(low, high)); + if (candidate != trans_.end()) { + // the correctly calculated transmissibility is stored in + // the NNC. Overwrite previous value with it. + candidate->second = nncEntry.trans; + } + } + } +} template void