diff --git a/core/reorder/nested_dissection.cpp b/core/reorder/nested_dissection.cpp index 2703f47d3b7..ff7bb06dc93 100644 --- a/core/reorder/nested_dissection.cpp +++ b/core/reorder/nested_dissection.cpp @@ -69,7 +69,7 @@ std::string metis_error_message(idx_t metis_error) case METIS_OK: return "METIS_OK"; default: - return ""; + return "<" + std::to_string(metis_error) + ">"; } } @@ -87,7 +87,12 @@ std::array build_metis_options( result[pair.first] = pair.second; } // make sure users don't accidentally switch on 1-based indexing - result[METIS_OPTION_NUMBERING] = 0; + if (options.find(METIS_OPTION_NUMBERING) != options.end() && + options.at(METIS_OPTION_NUMBERING) != 0) { + throw MetisError( + __FILE__, __LINE__, "build_metis_options", + "METIS_OPTION_NUMBERING: Only 0-based indexing is supported"); + } return result; } @@ -151,7 +156,7 @@ NestedDissection::NestedDissection( template std::unique_ptr> NestedDissection::generate( - std::shared_ptr system_matrix) const + std::shared_ptr system_matrix) const { auto product = std::unique_ptr(static_cast( diff --git a/core/test/reorder/CMakeLists.txt b/core/test/reorder/CMakeLists.txt index d654c5d78fc..383eb171b8b 100644 --- a/core/test/reorder/CMakeLists.txt +++ b/core/test/reorder/CMakeLists.txt @@ -1,2 +1,5 @@ +if(GINKGO_HAVE_METIS) + ginkgo_create_test(nested_dissection) +endif() ginkgo_create_test(rcm) ginkgo_create_test(scaled_reordered) diff --git a/core/test/reorder/nested_dissection.cpp b/core/test/reorder/nested_dissection.cpp new file mode 100644 index 00000000000..e738883d977 --- /dev/null +++ b/core/test/reorder/nested_dissection.cpp @@ -0,0 +1,71 @@ +/************************************************************* +Copyright (c) 2017-2023, the Ginkgo authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*************************************************************/ + +#include + + +#include + + +#include + + +#include + + +#include "core/test/utils.hpp" + + +namespace { + +class NestedDissection : public ::testing::Test { +protected: + using value_type = double; + using index_type = int; + using reorder_type = + gko::experimental::reorder::NestedDissection; + + NestedDissection() + : exec(gko::ReferenceExecutor::create()), + nd_factory(reorder_type::build().on(exec)) + {} + + std::shared_ptr exec; + std::unique_ptr nd_factory; +}; + +TEST_F(NestedDissection, KnowsItsExecutor) +{ + ASSERT_EQ(this->nd_factory->get_executor(), this->exec); +} + +} // namespace diff --git a/include/ginkgo/core/reorder/nested_dissection.hpp b/include/ginkgo/core/reorder/nested_dissection.hpp index d5e7967eb69..738dd6d8a0e 100644 --- a/include/ginkgo/core/reorder/nested_dissection.hpp +++ b/include/ginkgo/core/reorder/nested_dissection.hpp @@ -112,6 +112,11 @@ class NestedDissection } }; + /** + * Returns the parameters used to construct the factory. + */ + const parameters_type& get_parameters() { return parameters_; } + /** * @copydoc LinOpFactory::generate * @note This function overrides the default LinOpFactory::generate to @@ -120,7 +125,7 @@ class NestedDissection * It is only necessary because smart pointers aren't covariant. */ std::unique_ptr generate( - std::shared_ptr system_matrix) const; + std::shared_ptr system_matrix) const; /** Creates a new parameter_type to set up the factory. */ static parameters_type build() { return {}; } diff --git a/reference/test/reorder/CMakeLists.txt b/reference/test/reorder/CMakeLists.txt index 77017df1604..766decfb749 100644 --- a/reference/test/reorder/CMakeLists.txt +++ b/reference/test/reorder/CMakeLists.txt @@ -1,3 +1,6 @@ +if(GINKGO_HAVE_METIS) + ginkgo_create_test(nested_dissection) +endif() ginkgo_create_test(rcm) ginkgo_create_test(rcm_kernels) ginkgo_create_test(scaled_reordered) diff --git a/reference/test/reorder/nested_dissection.cpp b/reference/test/reorder/nested_dissection.cpp new file mode 100644 index 00000000000..ab1cd073f5a --- /dev/null +++ b/reference/test/reorder/nested_dissection.cpp @@ -0,0 +1,135 @@ +/************************************************************* +Copyright (c) 2017-2023, the Ginkgo authors +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: + +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS +IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED +TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*************************************************************/ + +#include + + +#include + + +#include +#include GKO_METIS_HEADER + + +#include +#include +#include +#include + + +#include "core/test/utils.hpp" +#include "core/test/utils/assertions.hpp" +#include "ginkgo/core/base/exception.hpp" + + +namespace { + + +template +class NestedDissection : public ::testing::Test { +protected: + using value_type = double; + using index_type = IndexType; + using reorder_type = + gko::experimental::reorder::NestedDissection; + using Mtx = gko::matrix::Dense; + NestedDissection() + : exec(gko::ReferenceExecutor::create()), + nd_factory(reorder_type::build().on(exec)), + star_mtx{gko::initialize({{1.0, 1.0, 1.0, 1.0}, + {1.0, 1.0, 0.0, 0.0}, + {1.0, 0.0, 1.0, 0.0}, + {1.0, 0.0, 0.0, 1.0}}, + exec)} + {} + + std::shared_ptr exec; + std::shared_ptr star_mtx; + std::unique_ptr nd_factory; +}; + +TYPED_TEST_SUITE(NestedDissection, gko::test::IndexTypes, + TypenameNameGenerator); + + +TYPED_TEST(NestedDissection, HasSensibleDefaults) +{ + using reorder_type = typename TestFixture::reorder_type; + + auto factory = reorder_type::build().on(this->exec); + + ASSERT_TRUE(factory->get_parameters().options.empty()); +} + + +TYPED_TEST(NestedDissection, FailsWithInvalidOption) +{ + using value_type = typename TestFixture::value_type; + using reorder_type = typename TestFixture::reorder_type; + auto factory = reorder_type::build() + .with_options({{METIS_NOPTIONS, 0}}) + .on(this->exec); + + ASSERT_THROW(factory->generate(this->star_mtx), gko::MetisError); +} + + +TYPED_TEST(NestedDissection, FailsWithOneBasedIndexing) +{ + using value_type = typename TestFixture::value_type; + using reorder_type = typename TestFixture::reorder_type; + auto factory = reorder_type::build() + .with_options({{METIS_OPTION_NUMBERING, 1}}) + .on(this->exec); + + ASSERT_THROW(factory->generate(this->star_mtx), gko::MetisError); +} + + +TYPED_TEST(NestedDissection, ComputesSensiblePermutation) +{ + auto perm = this->nd_factory->generate(this->star_mtx); + + auto perm_array = gko::make_array_view(this->exec, perm->get_size()[0], + perm->get_permutation()); + auto permuted = gko::as( + this->star_mtx->permute(&perm_array)); + GKO_ASSERT_MTX_NEAR(permuted, + I>({{1.0, 0.0, 0.0, 1.0}, + {0.0, 1.0, 0.0, 1.0}, + {0.0, 0.0, 1.0, 1.0}, + {1.0, 1.0, 1.0, 1.0}}), + 0.0); +} + + +} // namespace