Skip to content

Commit

Permalink
Improved Documentation and code coverage
Browse files Browse the repository at this point in the history
- Added used LaTeX packages into `Doxyfile-usr.in`
- Improved code coverage by adding tests for
  + `IteratorFactory` (specifically for the `operator<` in Reference)
  + `ParIlu` (Added additional test with sorted CSR matrix)
- re-added the overview description for `ParIlu`
  • Loading branch information
Thomas Grützmacher committed Jun 6, 2019
1 parent 0486f1c commit e8108e8
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 17 deletions.
4 changes: 4 additions & 0 deletions core/base/iterator_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ class IteratorFactory {
// An empty reference makes no sense, so is is disabled
Reference() = delete;

~Reference() {}

Reference(IteratorFactory &parent, array_index_type array_index)
: parent_(parent), arr_index_(array_index)
{}
Expand Down Expand Up @@ -200,6 +202,8 @@ class IteratorFactory {
using reference = Reference;
using iterator_category = std::random_access_iterator_tag;

~Iterator() {}

Iterator(IteratorFactory &parent, difference_type array_index)
: parent_(parent), arr_index_(array_index)
{}
Expand Down
44 changes: 37 additions & 7 deletions core/test/base/iterator_factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,22 @@ class IteratorFactory : public ::testing::Test {
}
}

template <typename Iterator>
// Require that Iterator has a `value_type` specified
template <typename Iterator, typename = typename Iterator::value_type>
bool is_sorted_iterator(Iterator begin, Iterator end)
{
while (begin + 1 < end) {
if (*(begin + 1) < *begin) {
using value_type = typename Iterator::value_type;
for (; begin + 1 < end; ++begin) {
auto curr_ref = *begin;
auto curr_val = static_cast<value_type>(curr_ref);
auto next_ref = *(begin + 1);
auto next_val = static_cast<value_type>(next_ref);

// Test all combinations of the `<` operator
if (*(begin + 1) < *begin || next_ref < curr_ref ||
next_ref < curr_val || next_val < curr_ref) {
return false;
}
++begin;
}
return true;
}
Expand Down Expand Up @@ -105,11 +113,9 @@ TEST_F(IteratorFactory, SortingReversedWithIterator)
auto test_iter = gko::detail::IteratorFactory<int_type, double_type>(
vec1.data(), vec2.data(), vec1.size());
std::sort(test_iter.begin(), test_iter.end());
auto is_sorted = is_sorted_iterator(test_iter.begin(), test_iter.end());

check_vector_equal(vec1, ordered_int);
check_vector_equal(vec2, reversed_double);
ASSERT_TRUE(is_sorted);
}


Expand All @@ -121,10 +127,34 @@ TEST_F(IteratorFactory, SortingAlreadySortedWithIterator)
auto test_iter = gko::detail::IteratorFactory<int_type, double_type>(
vec1.data(), vec2.data(), vec1.size());
std::sort(test_iter.begin(), test_iter.end());
auto is_sorted = is_sorted_iterator(test_iter.begin(), test_iter.end());

check_vector_equal(vec1, ordered_int);
check_vector_equal(vec2, ordered_double);
}


TEST_F(IteratorFactory, IteratorReferenceOperatorSmaller)
{
std::vector<int_type> vec1{reversed_int};
std::vector<double_type> vec2{ordered_double};

auto test_iter = gko::detail::IteratorFactory<int_type, double_type>(
vec1.data(), vec2.data(), vec1.size());
bool is_sorted = is_sorted_iterator(test_iter.begin(), test_iter.end());

ASSERT_FALSE(is_sorted);
}


TEST_F(IteratorFactory, IteratorReferenceOperatorSmaller2)
{
std::vector<int_type> vec1{ordered_int};
std::vector<double_type> vec2{ordered_double};

auto test_iter = gko::detail::IteratorFactory<int_type, double_type>(
vec1.data(), vec2.data(), vec1.size());
bool is_sorted = is_sorted_iterator(test_iter.begin(), test_iter.end());

ASSERT_TRUE(is_sorted);
}

Expand Down
2 changes: 2 additions & 0 deletions doc/conf/Doxyfile-usr.in
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ CALL_GRAPH = NO
CALLER_GRAPH = NO
EXCLUDE_SYMBOLS = *detail::* std::*
WARN_LOGFILE = @out@.log
# These are the LaTeX packages we use
EXTRA_PACKAGES = amsmath amsfonts mathtools
18 changes: 14 additions & 4 deletions include/ginkgo/core/factorization/par_ilu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,16 +55,26 @@ namespace factorization {
/**
* ParILU is an incomplete LU factorization which is computed in parallel.
*
* $L$ is a lower unitriangular, while $U$ is an upper triangular matrix, which
* approximate a given matrix $A$ with $A \approx LU$. Here, $L$ and $U$ have
* the same sparsity pattern as $A$, which is also called ILU(0).
*
* The ParILU algorithm generates the incomplete factors iteratively, using a
* fixed-point iteration of the form
* $F(L, U) = \begin{cases}\frac{1}{u_{jj}}\left(a_{ij}-\sum_{k=1}^{j-1}
* l_{ik}u_{kj}\right), \quad &i>j\\
* a_{ij}-\sum_{k=1}^{i-1} l_{ik}u_{kj},\quad &i\leq j \end{cases}*$
*
* $
* F(L, U) =
* \begin{cases}
* \frac{1}{u_{jj}}
* \left(a_{ij}-\sum_{k=1}^{j-1}l_{ik}u_{kj}\right), \quad & i>j \\
* a_{ij}-\sum_{k=1}^{i-1}l_{ik}u_{kj}, \quad & i\leq j
* \end{cases}
* $
*
* In general, the entries of $L$ and $U$ can be iterated in parallel and in
* asynchronous fashion, the algorithm asymptotically converges to the
* incomplete factors $L$ and $U$ fulfilling $\left(R = A - L \cdot
* U\right)\vert_\mathcal{S} = 0\vert_\mathcal{S}$ where $\mathcal{S}$ is the
* U\right)\vert_\mathcal{S} = 0$ where $\mathcal{S}$ is the
* pre-defined sparsity pattern (in case of ILU(0) the sparsity pattern of the
* system matrix $A$). The number of ParILU sweeps needed for convergence
* depends on the parallelism level: For sequential execution, a single sweep
Expand Down
34 changes: 28 additions & 6 deletions reference/test/factorization/par_ilu_kernels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,10 +238,10 @@ TEST_F(ParIlu, LUFactorFunctionsSetProperly)

TEST_F(ParIlu, GenerateForCooIdentity)
{
auto coo_mtx = Coo::create(exec);
auto coo_mtx = gko::share(Coo::create(exec));
identity->convert_to(coo_mtx.get());

auto factors = ilu_factory_skip->generate(identity);
auto factors = ilu_factory_skip->generate(coo_mtx);
auto l_factor = factors->get_l_factor();
auto u_factor = factors->get_u_factor();

Expand All @@ -252,10 +252,10 @@ TEST_F(ParIlu, GenerateForCooIdentity)

TEST_F(ParIlu, GenerateForCsrIdentity)
{
auto csr_mtx = Csr::create(exec);
auto csr_mtx = gko::share(Csr::create(exec));
identity->convert_to(csr_mtx.get());

auto factors = ilu_factory_skip->generate(identity);
auto factors = ilu_factory_skip->generate(csr_mtx);
auto l_factor = factors->get_l_factor();
auto u_factor = factors->get_u_factor();

Expand Down Expand Up @@ -322,6 +322,17 @@ TEST_F(ParIlu, GenerateForDenseSmall)
}


TEST_F(ParIlu, GenerateForCsrSmall)
{
auto factors = ilu_factory_skip->generate(mtx_csr_small);
auto l_factor = factors->get_l_factor();
auto u_factor = factors->get_u_factor();

GKO_ASSERT_MTX_NEAR(l_factor, small_l_expected, 1e-14);
GKO_ASSERT_MTX_NEAR(u_factor, small_u_expected, 1e-14);
}


TEST_F(ParIlu, GenerateForDenseSmallWithMultipleIterations)
{
auto multiple_iter_factory = gko::factorization::ParIlu<>::build()
Expand All @@ -348,11 +359,22 @@ TEST_F(ParIlu, GenerateForDenseBig)
}


TEST_F(ParIlu, GenerateForDenseBigSort)
{
auto factors = ilu_factory_skip->generate(mtx_big);
auto l_factor = factors->get_l_factor();
auto u_factor = factors->get_u_factor();

GKO_ASSERT_MTX_NEAR(l_factor, big_l_expected, 1e-14);
GKO_ASSERT_MTX_NEAR(u_factor, big_u_expected, 1e-14);
}


TEST_F(ParIlu, GenerateForReverseCooSmall)
{
const auto size = mtx_small->get_size();
const auto nnz = size[0] * size[1];
std::shared_ptr<Coo> reverse_coo = Coo::create(exec, size, nnz);
auto reverse_coo = gko::share(Coo::create(exec, size, nnz));
// Fill the Coo matrix in reversed row order (right to left)
for (size_t i = 0; i < size[0]; ++i) {
for (size_t j = 0; j < size[1]; ++j) {
Expand All @@ -377,7 +399,7 @@ TEST_F(ParIlu, GenerateForReverseCsrSmall)
{
const auto size = mtx_csr_small->get_size();
const auto nnz = size[0] * size[1];
std::shared_ptr<Csr> reverse_csr = Csr::create(exec);
auto reverse_csr = gko::share(Csr::create(exec));
reverse_csr->copy_from(mtx_csr_small.get());
// Fill the Csr matrix rows in reverse order
for (size_t i = 0; i < size[0]; ++i) {
Expand Down

0 comments on commit e8108e8

Please sign in to comment.