/* Copyright 2014 SINTEF ICT, Applied Mathematics. This file is part of the Open Porous Media project (OPM). OPM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OPM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OPM. If not, see . */ #ifndef OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED #define OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED #include #include #include #include #include #include namespace Opm { /// The state of a set of wells, tailored for use by the fully /// implicit blackoil simulator. class WellStateFullyImplicitBlackoil { public: /// Allocate and initialize if wells is non-null. Also tries /// to give useful initial values to the bhp(), wellRates() /// and perfPhaseRates() fields, depending on controls template void init(const Wells* wells, const State& state) { if (wells == 0) { return; } // We use the WellState::init() function to do bhp and well rates init. // The alternative would be to copy that function wholesale. basic_well_state_.init(wells, state); // Initialize perfphaserates_, which must be done here. const int nw = wells->number_of_wells; const int np = wells->number_of_phases; const int nperf = wells->well_connpos[nw]; perfphaserates_.resize(nperf * np, 0.0); for (int w = 0; w < nw; ++w) { assert((wells->type[w] == INJECTOR) || (wells->type[w] == PRODUCER)); const WellControls* ctrl = wells->ctrls[w]; if (well_controls_well_is_shut(ctrl)) { // Shut well: perfphaserates_ are all zero. } else { // Open well: Initialize perfphaserates_ to well // rates divided by the number of perforations. const int num_perf_this_well = wells->well_connpos[w + 1] - wells->well_connpos[w]; for (int perf = wells->well_connpos[w]; perf < wells->well_connpos[w + 1]; ++perf) { for (int p = 0; p < np; ++p) { perfphaserates_[np*perf + p] = wellRates()[np*w + p] / double(num_perf_this_well); } } } } // Initialize current_controls_. // The controls set in the Wells object are treated as defaults, // and also used for initial values. current_controls_.resize(nw); for (int w = 0; w < nw; ++w) { current_controls_[w] = well_controls_get_current(wells->ctrls[w]); } } /// One bhp pressure per well. std::vector& bhp() { return basic_well_state_.bhp(); } const std::vector& bhp() const { return basic_well_state_.bhp(); } /// One rate per well and phase. std::vector& wellRates() { return basic_well_state_.wellRates(); } const std::vector& wellRates() const { return basic_well_state_.wellRates(); } /// One rate per phase and well connection. std::vector& perfPhaseRates() { return perfphaserates_; } const std::vector& perfPhaseRates() const { return perfphaserates_; } /// One current control per well. std::vector& currentControls() { return current_controls_; } const std::vector& currentControls() const { return current_controls_; } /// For interfacing with functions that take a WellState. const WellState& basicWellState() const { return basic_well_state_; } /// The number of wells present. int numWells() const { return bhp().size(); } /// The number of phases present. int numPhases() const { return wellRates().size() / numWells(); } /// Copy data for the first num_wells_to_copy from source, /// overwriting any data in this object associated with those /// wells. Assumes that the number of phases are the same, /// that the number of perforations associated with the wells /// is unchanging, and that both objects contain at least /// num_wells_to_copy wells. void partialCopy(const WellStateFullyImplicitBlackoil& source, const Wells& wells, const int num_wells_to_copy) { if (numPhases() != source.numPhases()) { OPM_THROW(std::logic_error, "partialCopy(): source and destination have different number of phases."); } if (num_wells_to_copy > numWells() || num_wells_to_copy > source.numWells()) { OPM_THROW(std::logic_error, "partialCopy(): trying to copy too many wells."); } // bhp std::copy(source.bhp().begin(), source.bhp().begin() + num_wells_to_copy, bhp().begin()); // wellRates std::copy(source.wellRates().begin(), source.wellRates().begin() + numPhases()*num_wells_to_copy, wellRates().begin()); // perfPhaseRates const int num_perfs_to_copy = wells.well_connpos[num_wells_to_copy]; std::copy(source.perfPhaseRates().begin(), source.perfPhaseRates().begin() + numPhases()*num_perfs_to_copy, perfPhaseRates().begin()); // currentControls std::copy(source.currentControls().begin(), source.currentControls().begin() + num_wells_to_copy, currentControls().begin()); } private: WellState basic_well_state_; std::vector perfphaserates_; std::vector current_controls_; }; } // namespace Opm #endif // OPM_WELLSTATEFULLYIMPLICITBLACKOIL_HEADER_INCLUDED