From 5a3373f93f9a180ab59f2c857b3962ec3028130a Mon Sep 17 00:00:00 2001 From: Arne Morten Kvarving Date: Tue, 4 Feb 2025 17:05:25 +0100 Subject: [PATCH] added: voigt array this is a container for vector data stored using voigt notation --- CMakeLists_files.cmake | 3 + opm/simulators/utils/VoigtArray.cpp | 85 +++++++++++++++++++++ opm/simulators/utils/VoigtArray.hpp | 112 ++++++++++++++++++++++++++++ tests/test_VoigtArray.cpp | 87 +++++++++++++++++++++ 4 files changed, 287 insertions(+) create mode 100644 opm/simulators/utils/VoigtArray.cpp create mode 100644 opm/simulators/utils/VoigtArray.hpp create mode 100644 tests/test_VoigtArray.cpp diff --git a/CMakeLists_files.cmake b/CMakeLists_files.cmake index f366b92b1..3b7779d59 100644 --- a/CMakeLists_files.cmake +++ b/CMakeLists_files.cmake @@ -160,6 +160,7 @@ list (APPEND MAIN_SOURCE_FILES opm/simulators/utils/PressureAverage.cpp opm/simulators/utils/SerializationPackers.cpp opm/simulators/utils/UnsupportedFlowKeywords.cpp + opm/simulators/utils/VoigtArray.cpp opm/simulators/utils/compressPartition.cpp opm/simulators/utils/gatherDeferredLogger.cpp opm/simulators/utils/phaseUsageFromDeck.cpp @@ -419,6 +420,7 @@ list (APPEND TEST_SOURCE_FILES tests/test_stoppedwells.cpp tests/test_timer.cpp tests/test_vfpproperties.cpp + tests/test_VoigtArray.cpp tests/test_wellmodel.cpp tests/test_wellprodindexcalculator.cpp tests/test_wellstate.cpp @@ -985,6 +987,7 @@ list (APPEND PUBLIC_HEADER_FILES opm/simulators/utils/ParallelSerialization.hpp opm/simulators/utils/readDeck.hpp opm/simulators/utils/satfunc/RelpermDiagnostics.hpp + opm/simulators/utils/VoigtArray.hpp opm/simulators/wells/ALQState.hpp opm/simulators/wells/BlackoilWellModel.hpp opm/simulators/wells/BlackoilWellModel_impl.hpp diff --git a/opm/simulators/utils/VoigtArray.cpp b/opm/simulators/utils/VoigtArray.cpp new file mode 100644 index 000000000..d930c555f --- /dev/null +++ b/opm/simulators/utils/VoigtArray.cpp @@ -0,0 +1,85 @@ +/* + Copyright 2025 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 + +#include + +namespace Opm { + +template +template +VoigtContainer:: +VoigtContainer(const Array& array) +{ + std::copy(array.begin(), array.end(), data_.begin()); +} + +template +VoigtArray:: +VoigtArray(const std::size_t size) +{ + this->resize(size); +} + +template +void VoigtArray:: +resize(const std::size_t size) +{ + std::for_each(this->data_.begin(), this->data_.end(), + [size](auto& d) { d.resize(size); }); +} + +template +void VoigtArray:: +assign(const std::size_t i, const VoigtContainer& array) +{ + for (const auto idx : this->unique_indices) { + (*this)[idx][i] = array[idx]; + } +} + +template +Scalar VoigtArray:: +operator()(const VoigtIndex idx, const std::size_t i) const +{ + return (*this)[idx].at(i); +} + +template +Scalar& VoigtArray:: +operator()(const VoigtIndex idx, const std::size_t i) +{ + return (*this)[idx].at(i); +} + +#define INSTANTIATE_TYPE(T) \ + template class VoigtArray; \ + template VoigtContainer::VoigtContainer(const std::array&); \ + template VoigtContainer::VoigtContainer(const Dune::FieldVector&); + +INSTANTIATE_TYPE(double) + +#if FLOW_INSTANTIATE_FLOAT +INSTANTIATE_TYPE(float) +#endif + +} // namespace Opm diff --git a/opm/simulators/utils/VoigtArray.hpp b/opm/simulators/utils/VoigtArray.hpp new file mode 100644 index 000000000..b25912c76 --- /dev/null +++ b/opm/simulators/utils/VoigtArray.hpp @@ -0,0 +1,112 @@ +/* + Copyright 2025 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_UTIL_VOIGT_ARRAY_HPP +#define OPM_UTIL_VOIGT_ARRAY_HPP + +#include +#include +#include +#include +#include +#include + +namespace Opm { + +enum class VoigtIndex { + XX = 0, XY = 5, XZ = 4, + YX = XY, YY = 1, YZ = 3, + ZX = XZ, ZY = YZ, ZZ = 2, +}; + +template +class VoigtContainer +{ +public: + static constexpr auto indices = std::array{ + Opm::VoigtIndex::XX, + Opm::VoigtIndex::XY, + Opm::VoigtIndex::XZ, + Opm::VoigtIndex::YX, + Opm::VoigtIndex::YY, + Opm::VoigtIndex::YZ, + Opm::VoigtIndex::ZX, + Opm::VoigtIndex::ZY, + Opm::VoigtIndex::ZZ, + }; + + static constexpr auto unique_indices = std::array{ + Opm::VoigtIndex::XX, + Opm::VoigtIndex::YY, + Opm::VoigtIndex::ZZ, + Opm::VoigtIndex::YZ, + Opm::VoigtIndex::XZ, + Opm::VoigtIndex::XY + }; + + static constexpr auto diag_indices = std::array{ + Opm::VoigtIndex::XX, + Opm::VoigtIndex::YY, + Opm::VoigtIndex::ZZ, + }; + + VoigtContainer() = default; + + template + VoigtContainer(const Array& array); + + VoigtContainer(std::initializer_list value) + { + std::copy_n(value.begin(), + std::min(data_.size(), value.size()), + data_.begin()); + } + + const T& operator[](const VoigtIndex idx) const + { return data_[static_cast>(idx)]; } + + T& operator [](const VoigtIndex idx) + { return data_[static_cast>(idx)]; } + + constexpr std::size_t size() const { return data_.size(); } + +protected: + std::array data_{}; +}; + +template using SymmTensor = VoigtContainer; + +template +class VoigtArray : public VoigtContainer> +{ +public: + VoigtArray() = default; + explicit VoigtArray(const std::size_t size); + + void resize(const std::size_t size); + + Scalar operator()(const VoigtIndex idx, const std::size_t i) const; + Scalar& operator()(const VoigtIndex idx, const std::size_t i); + + void assign(const std::size_t i, const VoigtContainer& array); +}; + +} // namespace Opm + +#endif // OPM_UTIL_VOIGT_ARRAY_HPP diff --git a/tests/test_VoigtArray.cpp b/tests/test_VoigtArray.cpp new file mode 100644 index 000000000..de524f9a0 --- /dev/null +++ b/tests/test_VoigtArray.cpp @@ -0,0 +1,87 @@ +/* + Copyright 2025 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 + +#define BOOST_TEST_MODULE VoigArrayTest +#include +#include + +#include + +namespace { + #if FLOW_INSTANTIATE_FLOAT + using Types = boost::mpl::list; + #else + using Types = boost::mpl::list; + #endif +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(DefaultConstructed, Scalar, Types) +{ + Opm::VoigtArray array; + static constexpr auto& indices = Opm::VoigtArray::indices; + BOOST_CHECK_EQUAL(array.size(), 6); + for (const auto i : indices) { + BOOST_CHECK(array[i].empty()); + } + + for (const auto i : indices) { + BOOST_CHECK(array[i].empty()); + BOOST_CHECK_THROW(array(i, 1), std::out_of_range); + } + + array.resize(5); + for (const auto i : indices) { + BOOST_CHECK(!array[i].empty()); + BOOST_CHECK_NO_THROW(array(i, 1)); + } +} + +BOOST_AUTO_TEST_CASE_TEMPLATE(SizeConstructed, Scalar, Types) +{ + Opm::VoigtArray array(4); + BOOST_CHECK_EQUAL(array.size(), 6); + static constexpr auto& indices = Opm::VoigtArray::indices; + static constexpr auto& uindices = Opm::VoigtArray::unique_indices; + for (const auto i : indices) { + BOOST_CHECK_EQUAL(array[i].size(), 4); + } + + for (const auto i : uindices) { + std::fill(array[i].begin(), array[i].end(), static_cast(i)); + } + + for (const auto i: indices) { + BOOST_CHECK_EQUAL(array[i].size(), 4); + BOOST_CHECK_EQUAL(array[i][1], static_cast(i)); + BOOST_CHECK_EQUAL(array(i,1), static_cast(i)); + } + + BOOST_CHECK_EQUAL(array(Opm::VoigtIndex::XY, 1), + array(Opm::VoigtIndex::YX, 1)); + + BOOST_CHECK_EQUAL(array(Opm::VoigtIndex::XZ, 2), + array(Opm::VoigtIndex::ZX, 2)); + + BOOST_CHECK_EQUAL(array(Opm::VoigtIndex::YZ, 3), + array(Opm::VoigtIndex::ZY, 3)); +}