diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake
index 8d52a9465..ca96635a0 100644
--- a/CMakeLists_files.cmake
+++ b/CMakeLists_files.cmake
@@ -42,6 +42,7 @@ list (APPEND MAIN_SOURCE_FILES
opm/simulators/utils/ParallelRestart.cpp
opm/simulators/wells/GroupState.cpp
opm/simulators/wells/WGState.cpp
+ opm/simulators/wells/ALQState.cpp
opm/simulators/wells/ParallelWellInfo.cpp
opm/simulators/wells/VFPProdProperties.cpp
opm/simulators/wells/VFPInjProperties.cpp
@@ -109,6 +110,7 @@ list (APPEND TEST_SOURCE_FILES
tests/test_glift1.cpp
tests/test_keyword_validator.cpp
tests/test_GroupState.cpp
+ tests/test_ALQState.cpp
)
if(MPI_FOUND)
@@ -257,6 +259,7 @@ list (APPEND PUBLIC_HEADER_FILES
opm/simulators/wells/WellConnectionAuxiliaryModule.hpp
opm/simulators/wells/WellStateFullyImplicitBlackoil.hpp
opm/simulators/wells/GroupState.hpp
+ opm/simulators/wells/ALQState.hpp
opm/simulators/wells/WGState.hpp
opm/simulators/wells/VFPProperties.hpp
opm/simulators/wells/VFPHelpers.hpp
diff --git a/opm/simulators/wells/ALQState.cpp b/opm/simulators/wells/ALQState.cpp
new file mode 100644
index 000000000..2172b762e
--- /dev/null
+++ b/opm/simulators/wells/ALQState.cpp
@@ -0,0 +1,122 @@
+/*
+ Copyright 2021 Equinor ASA
+
+ 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 .
+*/
+#include
+#include
+
+
+#include
+
+namespace Opm {
+
+double ALQState::get(const std::string& wname) const {
+ auto iter = this->current_alq_.find(wname);
+ if (iter != this->current_alq_.end())
+ return iter->second;
+
+ auto default_iter = this->default_alq_.find(wname);
+ if (default_iter != this->default_alq_.end())
+ return default_iter->second;
+
+ throw std::logic_error("No ALQ value registered for well: " + wname);
+}
+
+void ALQState::update_default(const std::string& wname, double value) {
+ auto default_iter = this->default_alq_.find(wname);
+ if (default_iter == this->default_alq_.end() || default_iter->second != value) {
+ this->default_alq_.insert_or_assign(wname, value);
+ this->current_alq_.insert_or_assign(wname, value);
+ }
+}
+
+void ALQState::set(const std::string& wname, double value) {
+ this->current_alq_[wname] = value;
+}
+
+namespace {
+
+int get_counter(const std::map& count_map, const std::string& wname) {
+ auto count_iter = count_map.find(wname);
+ if (count_iter == count_map.end())
+ return 0;
+ return count_iter->second;
+}
+
+}
+
+bool ALQState::oscillation(const std::string& wname) const {
+ auto inc_count = get_counter(this->alq_increase_count_, wname);
+ if (inc_count == 0)
+ return false;
+
+ auto dec_count = get_counter(this->alq_decrease_count_, wname);
+ return dec_count >= 1;
+}
+
+
+void ALQState::update_count(const std::string& wname, bool increase) {
+ if (increase)
+ this->alq_increase_count_[wname] += 1;
+ else
+ this->alq_decrease_count_[wname] += 1;
+
+}
+
+
+void ALQState::reset_count() {
+ this->alq_decrease_count_.clear();
+ this->alq_increase_count_.clear();
+}
+
+
+int ALQState::get_increment_count(const std::string& wname) const {
+ return get_counter(this->alq_increase_count_, wname);
+}
+
+int ALQState::get_decrement_count(const std::string& wname) const {
+ return get_counter(this->alq_decrease_count_, wname);
+}
+
+std::size_t ALQState::pack_size() const {
+ return this->current_alq_.size();
+}
+
+std::size_t ALQState::pack_data(double * data) const {
+ std::size_t index = 0;
+ for (const auto& [_, value] : this->current_alq_) {
+ (void)_;
+ data[index++] = value;
+ }
+ return index;
+}
+
+std::size_t ALQState::unpack_data(const double * data) {
+ std::size_t index = 0;
+ for (auto& [_, value] : this->current_alq_) {
+ (void)_;
+ value = data[index++];
+ }
+ return index;
+}
+
+
+
+}
+
+
+
diff --git a/opm/simulators/wells/ALQState.hpp b/opm/simulators/wells/ALQState.hpp
new file mode 100644
index 000000000..d9ba27dcf
--- /dev/null
+++ b/opm/simulators/wells/ALQState.hpp
@@ -0,0 +1,59 @@
+/*
+ Copyright 2021 Equinor ASA
+
+ 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_ALQ_STATE_HEADER_INCLUDED
+#define OPM_ALQ_STATE_HEADER_INCLUDED
+
+#include