diff --git a/opm/models/blackoil/blackoilintensivequantities.hh b/opm/models/blackoil/blackoilintensivequantities.hh index 1cdb6c9e1..5ad66322a 100644 --- a/opm/models/blackoil/blackoilintensivequantities.hh +++ b/opm/models/blackoil/blackoilintensivequantities.hh @@ -122,7 +122,9 @@ class BlackOilIntensiveQuantities struct DirectionalMobility { using array_type = std::array; - DirectionalMobility(const array_type& mX, const array_type& mY, const array_type& mZ) + DirectionalMobility(const DirectionalMobility& other) + : mobilityX_{other.mobilityX_}, mobilityY_{other.mobilityY_}, mobilityZ_{other.mobilityZ_} {} + DirectionalMobility(const array_type& mX, const array_type& mY, const array_type& mZ) : mobilityX_{mX}, mobilityY_{mY}, mobilityZ_{mZ} {} DirectionalMobility() : mobilityX_{}, mobilityY_{}, mobilityZ_{} {} array_type& getArray(int index) { @@ -142,6 +144,59 @@ class BlackOilIntensiveQuantities array_type mobilityZ_; }; + // Instead of writing a custom copy constructor and a custom assignment operator just to handle + // the dirMob_ unique ptr member variable when copying BlackOilIntensiveQuantites (see for example + // updateIntensitiveQuantities_() in fvbaseelementcontext.hh for a copy example) we write the below + // custom wrapper class CopyablePtr which wraps the unique ptr and makes it copyable. + // + // The advantage of this approach is that we avoid having to call all the base class copy constructors and + // assignment operators explicitly (which is needed when writing the custom copy constructor and assignment + // operators) which could become maintenance burden. For example, when adding a new base class (if that should + // be needed sometime in the future) to BlackOilIntensiveQuantites we could forget to update the copy + // constructor and assignment operators. + // + // We want each copy of the BlackOilIntensiveQuantites to be unique, (TODO: why?) so we have to make a copy + // of the unique_ptr each time we copy construct or assign to it from another BlackOilIntensiveQuantites. + // (On the other hand, if a copy could share the ptr with the original, a shared_ptr could be used instead and the + // wrapper would not be needed) + template + class CopyablePtr { + public: + CopyablePtr() : ptr_(nullptr) {} + CopyablePtr(const CopyablePtr& other) { + if (other) { // other does not contain a nullptr + ptr_ = std::make_unique(other.get()); + } + // else {ptr_ = nullptr;} // this is the default construction value + } + // assignment operator + CopyablePtr& operator=(const CopyablePtr& other) { + if (other) { + ptr_ = std::make_unique(other.get()); + } + else { + ptr_ = nullptr; + } + return *this; + } + // assign directly from a unique_ptr + CopyablePtr& operator=(std::unique_ptr&& uptr) { + ptr_ = std::move(uptr); + return *this; + } + // member access operator + T* operator->() const {return ptr_.get(); } + // boolean context operator + explicit operator bool() const noexcept { + return ptr_ ? true : false; + } + // get a reference to the stored value + T& get() const {return *ptr_;} + T* release() const {return ptr_.release();} + private: + std::unique_ptr ptr_; + }; + public: using FluidState = BlackOilFluidState( - other.dirMob_->mobilityX_, - other.dirMob_->mobilityY_, - other.dirMob_->mobilityY_ - ); - } - }; - - BlackOilIntensiveQuantities& operator=(const BlackOilIntensiveQuantities& other) { - fluidState_ = other.fluidState_; - referencePorosity_ = other.referencePorosity_; - porosity_ = other.porosity_; - rockCompTransMultiplier_ = other.rockCompTransMultiplier_; - mobility_ = other.mobility_; - if (other.dirMob_) { - dirMob_ = std::make_unique( - other.dirMob_->mobilityX_, - other.dirMob_->mobilityY_, - other.dirMob_->mobilityY_ - ); - } - else { - dirMob_.release(); // release any memory, and assign nullptr - } - // call assignment operators in the parent classes - GetPropType::operator=(other); - GetPropType::FluxIntensiveQuantities::operator=(other); - BlackOilDiffusionIntensiveQuantities() >::operator=(other); - BlackOilSolventIntensiveQuantities::operator=(other); - BlackOilExtboIntensiveQuantities::operator=(other); - BlackOilPolymerIntensiveQuantities::operator=(other); - BlackOilFoamIntensiveQuantities::operator=(other); - BlackOilBrineIntensiveQuantities::operator=(other); - BlackOilEnergyIntensiveQuantities::operator=(other); - BlackOilMICPIntensiveQuantities::operator=(other); - - return *this; - }; + BlackOilIntensiveQuantities& operator=(const BlackOilIntensiveQuantities& other) = default; /*! * \copydoc IntensiveQuantities::update @@ -685,7 +702,7 @@ private: static void updateRelperms( std::array &mobility, - std::unique_ptr &dirMob, + CopyablePtr &dirMob, FluidState &fluidState, const Problem& problem, const MaterialLawParams& materialParams, @@ -731,7 +748,7 @@ private: Evaluation porosity_; Evaluation rockCompTransMultiplier_; std::array mobility_; - std::unique_ptr dirMob_; + CopyablePtr dirMob_; }; } // namespace Opm