Skip to content

Commit

Permalink
Add Bicg typed tests for reference kernels.
Browse files Browse the repository at this point in the history
  • Loading branch information
pratikvn committed May 8, 2020
1 parent 984f631 commit 6b45684
Showing 1 changed file with 126 additions and 81 deletions.
207 changes: 126 additions & 81 deletions reference/test/solver/bicg_kernels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,28 +45,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <ginkgo/core/stop/time.hpp>


#include "core/test/utils/assertions.hpp"
#include "core/test/utils.hpp"


namespace {


template <typename T>
class Bicg : public ::testing::Test {
protected:
using Mtx = gko::matrix::Dense<>;
using value_type = T;
using Mtx = gko::matrix::Dense<value_type>;
using Solver = gko::solver::Bicg<value_type>;
Bicg()
: exec(gko::ReferenceExecutor::create()),
mtx(gko::initialize<Mtx>(
{{2, -1.0, 0.0}, {-1.0, 2, -1.0}, {0.0, -1.0, 2}}, exec)),
bicg_factory(
gko::solver::Bicg<>::build()
Solver::build()
.with_criteria(
gko::stop::Iteration::build().with_max_iters(4u).on(exec),
gko::stop::Time::build()
.with_time_limit(std::chrono::seconds(6))
.on(exec),
gko::stop::ResidualNormReduction<>::build()
.with_reduction_factor(1e-15)
gko::stop::ResidualNormReduction<value_type>::build()
.with_reduction_factor(r<value_type>::value)
.on(exec))
.on(exec)),
mtx_big(gko::initialize<Mtx>(
Expand All @@ -78,12 +81,12 @@ class Bicg : public ::testing::Test {
{5856.0, 3919.5, 3836.5, -132.0, 4373.5, 5678.0}},
exec)),
bicg_factory_big(
gko::solver::Bicg<>::build()
Solver::build()
.with_criteria(
gko::stop::Iteration::build().with_max_iters(100u).on(
exec),
gko::stop::ResidualNormReduction<>::build()
.with_reduction_factor(1e-15)
gko::stop::ResidualNormReduction<value_type>::build()
.with_reduction_factor(r<value_type>::value)
.on(exec))
.on(exec)),
mtx_non_symmetric(gko::initialize<Mtx>(
Expand All @@ -96,167 +99,209 @@ class Bicg : public ::testing::Test {
std::shared_ptr<Mtx> mtx;
std::shared_ptr<Mtx> mtx_big;
std::shared_ptr<Mtx> mtx_non_symmetric;
std::unique_ptr<gko::solver::Bicg<>::Factory> bicg_factory;
std::unique_ptr<gko::solver::Bicg<>::Factory> bicg_factory_big;
std::unique_ptr<gko::solver::Bicg<>::Factory> bicg_factory_non_symmetric;
std::unique_ptr<typename Solver::Factory> bicg_factory;
std::unique_ptr<typename Solver::Factory> bicg_factory_big;
std::unique_ptr<typename Solver::Factory> bicg_factory_non_symmetric;
};

TYPED_TEST_CASE(Bicg, gko::test::ValueTypes);

TEST_F(Bicg, SolvesStencilSystem)

TYPED_TEST(Bicg, SolvesStencilSystem)
{
auto solver = bicg_factory->generate(mtx);
auto b = gko::initialize<Mtx>({-1.0, 3.0, 1.0}, exec);
auto x = gko::initialize<Mtx>({0.0, 0.0, 0.0}, exec);
using Mtx = typename TestFixture::Mtx;
using value_type = typename TestFixture::value_type;
auto solver = this->bicg_factory->generate(this->mtx);
auto b = gko::initialize<Mtx>({-1.0, 3.0, 1.0}, this->exec);
auto x = gko::initialize<Mtx>({0.0, 0.0, 0.0}, this->exec);

solver->apply(b.get(), x.get());

GKO_ASSERT_MTX_NEAR(x, l({1.0, 3.0, 2.0}), 1e-14);
GKO_ASSERT_MTX_NEAR(x, l({1.0, 3.0, 2.0}), r<value_type>::value);
}


TEST_F(Bicg, SolvesMultipleStencilSystems)
TYPED_TEST(Bicg, SolvesMultipleStencilSystems)
{
auto solver = bicg_factory->generate(mtx);
auto b = gko::initialize<Mtx>({{-1.0, 1.0}, {3.0, 0.0}, {1.0, 1.0}}, exec);
auto x = gko::initialize<Mtx>({{0.0, 0.0}, {0.0, 0.0}, {0.0, 0.0}}, exec);
using Mtx = typename TestFixture::Mtx;
using value_type = typename TestFixture::value_type;
using T = value_type;
auto solver = this->bicg_factory->generate(this->mtx);
auto b = gko::initialize<Mtx>(
{I<T>{-1.0, 1.0}, I<T>{3.0, 0.0}, I<T>{1.0, 1.0}}, this->exec);
auto x = gko::initialize<Mtx>(
{I<T>{0.0, 0.0}, I<T>{0.0, 0.0}, I<T>{0.0, 0.0}}, this->exec);

solver->apply(b.get(), x.get());

GKO_ASSERT_MTX_NEAR(x, l({{1.0, 1.0}, {3.0, 1.0}, {2.0, 1.0}}), 1e-14);
GKO_ASSERT_MTX_NEAR(x, l({{1.0, 1.0}, {3.0, 1.0}, {2.0, 1.0}}),
r<value_type>::value);
}


TEST_F(Bicg, SolvesStencilSystemUsingAdvancedApply)
TYPED_TEST(Bicg, SolvesStencilSystemUsingAdvancedApply)
{
auto solver = bicg_factory->generate(mtx);
auto alpha = gko::initialize<Mtx>({2.0}, exec);
auto beta = gko::initialize<Mtx>({-1.0}, exec);
auto b = gko::initialize<Mtx>({-1.0, 3.0, 1.0}, exec);
auto x = gko::initialize<Mtx>({0.5, 1.0, 2.0}, exec);
using Mtx = typename TestFixture::Mtx;
using value_type = typename TestFixture::value_type;
auto solver = this->bicg_factory->generate(this->mtx);
auto alpha = gko::initialize<Mtx>({2.0}, this->exec);
auto beta = gko::initialize<Mtx>({-1.0}, this->exec);
auto b = gko::initialize<Mtx>({-1.0, 3.0, 1.0}, this->exec);
auto x = gko::initialize<Mtx>({0.5, 1.0, 2.0}, this->exec);

solver->apply(alpha.get(), b.get(), beta.get(), x.get());

GKO_ASSERT_MTX_NEAR(x, l({1.5, 5.0, 2.0}), 1e-14);
GKO_ASSERT_MTX_NEAR(x, l({1.5, 5.0, 2.0}), r<value_type>::value);
}


TEST_F(Bicg, SolvesMultipleStencilSystemsUsingAdvancedApply)
TYPED_TEST(Bicg, SolvesMultipleStencilSystemsUsingAdvancedApply)
{
auto solver = bicg_factory->generate(mtx);
auto alpha = gko::initialize<Mtx>({2.0}, exec);
auto beta = gko::initialize<Mtx>({-1.0}, exec);
auto b = gko::initialize<Mtx>({{-1.0, 1.0}, {3.0, 0.0}, {1.0, 1.0}}, exec);
auto x = gko::initialize<Mtx>({{0.5, 1.0}, {1.0, 2.0}, {2.0, 3.0}}, exec);
using Mtx = typename TestFixture::Mtx;
using value_type = typename TestFixture::value_type;
using T = value_type;
auto solver = this->bicg_factory->generate(this->mtx);
auto alpha = gko::initialize<Mtx>({2.0}, this->exec);
auto beta = gko::initialize<Mtx>({-1.0}, this->exec);
auto b = gko::initialize<Mtx>(
{I<T>{-1.0, 1.0}, I<T>{3.0, 0.0}, I<T>{1.0, 1.0}}, this->exec);
auto x = gko::initialize<Mtx>(
{I<T>{0.5, 1.0}, I<T>{1.0, 2.0}, I<T>{2.0, 3.0}}, this->exec);

solver->apply(alpha.get(), b.get(), beta.get(), x.get());

GKO_ASSERT_MTX_NEAR(x, l({{1.5, 1.0}, {5.0, 0.0}, {2.0, -1.0}}), 1e-14);
GKO_ASSERT_MTX_NEAR(x, l({{1.5, 1.0}, {5.0, 0.0}, {2.0, -1.0}}),
r<value_type>::value * 1e1);
}


TEST_F(Bicg, SolvesBigDenseSystem1)
TYPED_TEST(Bicg, SolvesBigDenseSystem1)
{
auto solver = bicg_factory_big->generate(mtx_big);
using Mtx = typename TestFixture::Mtx;
using value_type = typename TestFixture::value_type;
auto solver = this->bicg_factory_big->generate(this->mtx_big);
auto b = gko::initialize<Mtx>(
{1300083.0, 1018120.5, 906410.0, -42679.5, 846779.5, 1176858.5}, exec);
auto x = gko::initialize<Mtx>({0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, exec);
{1300083.0, 1018120.5, 906410.0, -42679.5, 846779.5, 1176858.5},
this->exec);
auto x = gko::initialize<Mtx>({0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, this->exec);

solver->apply(b.get(), x.get());

GKO_ASSERT_MTX_NEAR(x, l({81.0, 55.0, 45.0, 5.0, 85.0, -10.0}), 1e-10);
GKO_ASSERT_MTX_NEAR(x, l({81.0, 55.0, 45.0, 5.0, 85.0, -10.0}),
r<value_type>::value * 1e2);
}


TEST_F(Bicg, SolvesBigDenseSystem2)
TYPED_TEST(Bicg, SolvesBigDenseSystem2)
{
auto solver = bicg_factory_big->generate(mtx_big);
using Mtx = typename TestFixture::Mtx;
using value_type = typename TestFixture::value_type;
auto solver = this->bicg_factory_big->generate(this->mtx_big);
auto b = gko::initialize<Mtx>(
{886630.5, -172578.0, 684522.0, -65310.5, 455487.5, 607436.0}, exec);
auto x = gko::initialize<Mtx>({0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, exec);
{886630.5, -172578.0, 684522.0, -65310.5, 455487.5, 607436.0},
this->exec);
auto x = gko::initialize<Mtx>({0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, this->exec);

solver->apply(b.get(), x.get());

GKO_ASSERT_MTX_NEAR(x, l({33.0, -56.0, 81.0, -30.0, 21.0, 40.0}), 1e-10);
GKO_ASSERT_MTX_NEAR(x, l({33.0, -56.0, 81.0, -30.0, 21.0, 40.0}),
r<value_type>::value * 1e2);
}


TEST_F(Bicg, SolvesNonSymmetricStencilSystem)
TYPED_TEST(Bicg, SolvesNonSymmetricStencilSystem)
{
auto solver = bicg_factory->generate(mtx_non_symmetric);
auto b = gko::initialize<Mtx>({13.0, 7.0, 1.0}, exec);
auto x = gko::initialize<Mtx>({0.0, 0.0, 0.0}, exec);
using Mtx = typename TestFixture::Mtx;
using value_type = typename TestFixture::value_type;
auto solver = this->bicg_factory->generate(this->mtx_non_symmetric);
auto b = gko::initialize<Mtx>({13.0, 7.0, 1.0}, this->exec);
auto x = gko::initialize<Mtx>({0.0, 0.0, 0.0}, this->exec);

solver->apply(b.get(), x.get());

GKO_ASSERT_MTX_NEAR(x, l({1.0, 3.0, 2.0}), 1e-14);
GKO_ASSERT_MTX_NEAR(x, l({1.0, 3.0, 2.0}), r<value_type>::value);
}


double infNorm(gko::matrix::Dense<> *mat, size_t col = 0)
template <typename T>
gko::remove_complex<T> infNorm(gko::matrix::Dense<T> *mat, size_t col = 0)
{
using std::abs;
double norm = 0.0;
using no_cpx_t = gko::remove_complex<T>;
no_cpx_t norm = 0.0;
for (size_t i = 0; i < mat->get_size()[0]; ++i) {
double absEntry = abs(mat->at(i, col));
no_cpx_t absEntry = abs(mat->at(i, col));
if (norm < absEntry) norm = absEntry;
}
return norm;
}


TEST_F(Bicg, SolvesMultipleDenseSystemForDivergenceCheck)
TYPED_TEST(Bicg, SolvesMultipleDenseSystemForDivergenceCheck)
{
auto solver = bicg_factory_big->generate(mtx_big);
using Mtx = typename TestFixture::Mtx;
using value_type = typename TestFixture::value_type;
auto solver = this->bicg_factory_big->generate(this->mtx_big);
auto b1 = gko::initialize<Mtx>(
{1300083.0, 1018120.5, 906410.0, -42679.5, 846779.5, 1176858.5}, exec);
{1300083.0, 1018120.5, 906410.0, -42679.5, 846779.5, 1176858.5},
this->exec);
auto b2 = gko::initialize<Mtx>(
{886630.5, -172578.0, 684522.0, -65310.5, 455487.5, 607436.0}, exec);
auto x1 = gko::initialize<Mtx>({0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, exec);
auto x2 = gko::initialize<Mtx>({0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, exec);
auto bc = Mtx::create(exec, gko::dim<2>{mtx_big->get_size()[0], 2});
auto xc = Mtx::create(exec, gko::dim<2>{mtx_big->get_size()[1], 2});
{886630.5, -172578.0, 684522.0, -65310.5, 455487.5, 607436.0},
this->exec);

auto x1 = gko::initialize<Mtx>({0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, this->exec);
auto x2 = gko::initialize<Mtx>({0.0, 0.0, 0.0, 0.0, 0.0, 0.0}, this->exec);

auto bc =
Mtx::create(this->exec, gko::dim<2>{this->mtx_big->get_size()[0], 2});
auto xc =
Mtx::create(this->exec, gko::dim<2>{this->mtx_big->get_size()[1], 2});
for (size_t i = 0; i < bc->get_size()[0]; ++i) {
bc->at(i, 0) = b1->at(i);
bc->at(i, 1) = b2->at(i);

xc->at(i, 0) = x1->at(i);
xc->at(i, 1) = x2->at(i);
}

solver->apply(b1.get(), x1.get());
solver->apply(b2.get(), x2.get());
solver->apply(bc.get(), xc.get());
auto mergedRes = Mtx::create(exec, gko::dim<2>{b1->get_size()[0], 2});
auto mergedRes = Mtx::create(this->exec, gko::dim<2>{b1->get_size()[0], 2});
for (size_t i = 0; i < mergedRes->get_size()[0]; ++i) {
mergedRes->at(i, 0) = x1->at(i);
mergedRes->at(i, 1) = x2->at(i);
}

auto alpha = gko::initialize<Mtx>({1.0}, exec);
auto beta = gko::initialize<Mtx>({-1.0}, exec);
auto residual1 = Mtx::create(exec, b1->get_size());
auto alpha = gko::initialize<Mtx>({1.0}, this->exec);
auto beta = gko::initialize<Mtx>({-1.0}, this->exec);

auto residual1 = Mtx::create(this->exec, b1->get_size());
residual1->copy_from(b1.get());
auto residual2 = Mtx::create(exec, b2->get_size());
auto residual2 = Mtx::create(this->exec, b2->get_size());
residual2->copy_from(b2.get());
auto residualC = Mtx::create(exec, bc->get_size());
auto residualC = Mtx::create(this->exec, bc->get_size());
residualC->copy_from(bc.get());

mtx_big->apply(alpha.get(), x1.get(), beta.get(), residual1.get());
mtx_big->apply(alpha.get(), x2.get(), beta.get(), residual2.get());
mtx_big->apply(alpha.get(), xc.get(), beta.get(), residualC.get());
this->mtx_big->apply(alpha.get(), x1.get(), beta.get(), residual1.get());
this->mtx_big->apply(alpha.get(), x2.get(), beta.get(), residual2.get());
this->mtx_big->apply(alpha.get(), xc.get(), beta.get(), residualC.get());

auto normS1 = infNorm(residual1.get());
auto normS2 = infNorm(residual2.get());
auto normC1 = infNorm(residualC.get(), 0);
auto normC2 = infNorm(residualC.get(), 1);
auto normB1 = infNorm(b1.get());
auto normB2 = infNorm(b2.get());

double normS1 = infNorm(residual1.get());
double normS2 = infNorm(residual2.get());
double normC1 = infNorm(residualC.get(), 0);
double normC2 = infNorm(residualC.get(), 1);
double normB1 = infNorm(b1.get());
double normB2 = infNorm(b2.get());
// make sure that all combined solutions are as good or better than the
// single solutions
ASSERT_LE(normC1 / normB1, normS1 / normB1 + 1e-14);
ASSERT_LE(normC2 / normB2, normS2 / normB2 + 1e-14);
// Not sure if this is necessary, the assertions above should cover what
// is needed.
GKO_ASSERT_MTX_NEAR(xc, mergedRes, 1e-14);
ASSERT_LE(normC1 / normB1, normS1 / normB1 + r<value_type>::value);
ASSERT_LE(normC2 / normB2, normS2 / normB2 + r<value_type>::value);

// Not sure if this is necessary, the assertions above should cover what is
// needed.
GKO_ASSERT_MTX_NEAR(xc, mergedRes, r<value_type>::value);
}


Expand Down

0 comments on commit 6b45684

Please sign in to comment.