mirror of
https://github.com/OPM/opm-simulators.git
synced 2026-11-01 17:03:06 -06:00
157 lines
4.2 KiB
Plaintext
157 lines
4.2 KiB
Plaintext
/*
|
|
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 <http://www.gnu.org/licenses/>.
|
|
*/
|
|
#include <config.h>
|
|
|
|
#define BOOST_TEST_MODULE TestMiniVector
|
|
|
|
#include <boost/test/unit_test.hpp>
|
|
#include <cuda_runtime.h>
|
|
#include <opm/simulators/linalg/gpuistl/MiniVector.hpp>
|
|
#include <opm/simulators/linalg/gpuistl/detail/gpu_safe_call.hpp>
|
|
#include <opm/simulators/linalg/gpuistl/gpu_smart_pointer.hpp>
|
|
#include <utility> // for std::ignore
|
|
|
|
BOOST_AUTO_TEST_CASE(DefaultConstructor)
|
|
{
|
|
::Opm::gpuistl::MiniVector<int, 3> v; // Default constructor initializes all elements to zero
|
|
BOOST_TEST(v.size() == 3u);
|
|
for (std::size_t i = 0; i < v.size(); ++i) {
|
|
BOOST_TEST(v[i] == 0);
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(UniformValueConstructor)
|
|
{
|
|
constexpr float kVal = 2.5f;
|
|
::Opm::gpuistl::MiniVector<float, 4> v(kVal);
|
|
for (auto e : v) {
|
|
BOOST_TEST(e == kVal, boost::test_tools::tolerance(1e-6f));
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(InitializerListConstructor)
|
|
{
|
|
::Opm::gpuistl::MiniVector<double, 2> v {1.1, 2.2};
|
|
BOOST_TEST(v[0] == 1.1, boost::test_tools::tolerance(1e-12));
|
|
BOOST_TEST(v[1] == 2.2, boost::test_tools::tolerance(1e-12));
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(AtBoundsChecking)
|
|
{
|
|
::Opm::gpuistl::MiniVector<int, 2> v {5, 6};
|
|
BOOST_CHECK_THROW(v.at(2), std::out_of_range);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(IteratorTraversal)
|
|
{
|
|
::Opm::gpuistl::MiniVector<int, 3> v {1, 2, 3};
|
|
int sum = 0;
|
|
for (int e : v)
|
|
sum += e;
|
|
BOOST_TEST(sum == 6);
|
|
}
|
|
|
|
template <class VecT>
|
|
__global__ void
|
|
fillKernel(VecT* v, typename VecT::value_type val)
|
|
{
|
|
(*v)[threadIdx.x] = val;
|
|
}
|
|
|
|
template <class VecT, class IntT>
|
|
__global__ void
|
|
sumKernel(const VecT* v, IntT* out)
|
|
{
|
|
if (threadIdx.x == 0) {
|
|
IntT s = 0;
|
|
for (std::size_t i = 0; i < VecT::size(); ++i) {
|
|
s += (*v)[i];
|
|
}
|
|
*out = s;
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(GPUFill)
|
|
{
|
|
// make_gpu_shared_ptr<T>() should:
|
|
// 1. allocate device memory for a single T
|
|
// 2. return a std::shared_ptr<T> whose custom deleter frees GPU memory
|
|
// 3. optionally take a host value to copy to device (overload)
|
|
|
|
auto dvec = ::Opm::gpuistl::make_gpu_shared_ptr<::Opm::gpuistl::MiniVector<int, 3>>();
|
|
|
|
// Fill the vector from the device
|
|
fillKernel<<<1, 3>>>(dvec.get(), 7);
|
|
OPM_GPU_SAFE_CALL(cudaDeviceSynchronize());
|
|
|
|
// Copy back and verify
|
|
::Opm::gpuistl::MiniVector<int, 3> hvec = ::Opm::gpuistl::copyFromGPU(dvec);
|
|
for (int i = 0; i < 3; ++i) {
|
|
BOOST_TEST(hvec[i] == 7);
|
|
}
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(GPUSum)
|
|
{
|
|
::Opm::gpuistl::MiniVector<int, 4> hsrc(1); // [1, 1, 1, 1]
|
|
|
|
auto dsrc = ::Opm::gpuistl::make_gpu_shared_ptr<::Opm::gpuistl::MiniVector<int, 4>>(hsrc);
|
|
auto dout = ::Opm::gpuistl::make_gpu_shared_ptr<int>();
|
|
|
|
sumKernel<<<1, 1>>>(dsrc.get(), dout.get());
|
|
OPM_GPU_SAFE_CALL(cudaDeviceSynchronize());
|
|
|
|
int sum = ::Opm::gpuistl::copyFromGPU(dout);
|
|
BOOST_TEST(sum == 4);
|
|
}
|
|
|
|
BOOST_AUTO_TEST_CASE(TestArithmeticOperations)
|
|
{
|
|
::Opm::gpuistl::MiniVector<int, 3> v1 {1, 2, 3};
|
|
::Opm::gpuistl::MiniVector<int, 3> v2 {4, 5, 6};
|
|
|
|
auto v3 = v1;
|
|
v3 += v2;
|
|
BOOST_TEST(v3[0] == 5);
|
|
BOOST_TEST(v3[1] == 7);
|
|
BOOST_TEST(v3[2] == 9);
|
|
|
|
v3 = v2;
|
|
v3 -= v1;
|
|
BOOST_TEST(v3[0] == 3);
|
|
BOOST_TEST(v3[1] == 3);
|
|
BOOST_TEST(v3[2] == 3);
|
|
|
|
v3 = v1;
|
|
v3 *= 2;
|
|
BOOST_TEST(v3[0] == 2);
|
|
BOOST_TEST(v3[1] == 4);
|
|
BOOST_TEST(v3[2] == 6);
|
|
|
|
v3 = v1 + v2;
|
|
BOOST_TEST(v3[0] == 5);
|
|
BOOST_TEST(v3[1] == 7);
|
|
BOOST_TEST(v3[2] == 9);
|
|
|
|
v3 = v2 - v1;
|
|
BOOST_TEST(v3[0] == 3);
|
|
BOOST_TEST(v3[1] == 3);
|
|
BOOST_TEST(v3[2] == 3);
|
|
}
|