Skip to content

Commit

Permalink
use unique_ptr to forward declaration of MultigridState
Browse files Browse the repository at this point in the history
Co-authored-by: Terry Cojean <terry.cojean@kit.edu>
  • Loading branch information
yhmtsai and tcojean committed Nov 7, 2022
1 parent b609166 commit 3a2d29c
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 89 deletions.
97 changes: 89 additions & 8 deletions core/solver/multigrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,78 @@ void clear_and_reserve(Vec& vec, size_type size)


namespace multigrid {
namespace experimental {
/**
* MultigridState is to store the necessary cache and run the operation of all
* levels.
*
* @note it should only be used internally
*/
struct MultigridState {
MultigridState() : nrhs{0} {}

/**
* Generate the cache for later usage.
*
* @param system_matrix_in the system matrix
* @param multigrid_in the multigrid information
* @param nrhs_in the number of right hand side
*/
void generate(const LinOp* system_matrix_in, const Multigrid* multigrid_in,
const size_type nrhs_in);

/**
* allocate_memory is a helper function to allocate the memory of one level
*
* @tparam VT the value type of memory
*
* @param level the current level index
* @param cycle the multigrid cycle
* @param current_nrows the number of rows of current fine matrix
* @param next_nrows the number of rows of next coarse matrix
*/
template <typename VT>
void allocate_memory(int level, multigrid::cycle cycle,
size_type current_nrows, size_type next_nrows);

/**
* run the cycle of the level
*
* @param cycle the multigrid cycle
* @param level the current level index
* @param matrix the system matrix of current level
* @param b the right hand side
* @param x the input vectors
*/
void run_cycle(multigrid::cycle cycle, size_type level,
const std::shared_ptr<const LinOp>& matrix, const LinOp* b,
LinOp* x, bool x_is_zero = false, bool is_first = true,
bool is_end = true);

/**
* @copydoc run_cycle
*
* @tparam VT the value type
*
* @note it is the version with known ValueType
*/
template <typename VT>
void run_cycle(multigrid::cycle cycle, size_type level,
const std::shared_ptr<const LinOp>& matrix, const LinOp* b,
LinOp* x, bool x_is_zero, bool is_first, bool is_end);

// current level's nrows x nrhs
std::vector<std::shared_ptr<LinOp>> r_list;
// next level's nrows x nrhs
std::vector<std::shared_ptr<LinOp>> g_list;
std::vector<std::shared_ptr<LinOp>> e_list;
// constant 1 x 1
std::vector<std::shared_ptr<const LinOp>> one_list;
std::vector<std::shared_ptr<const LinOp>> next_one_list;
std::vector<std::shared_ptr<const LinOp>> neg_one_list;
const LinOp* system_matrix;
const Multigrid* multigrid;
size_type nrhs;
};


void MultigridState::generate(const LinOp* system_matrix_in,
Expand Down Expand Up @@ -368,7 +439,7 @@ void MultigridState::run_cycle(multigrid::cycle cycle, size_type level,
}
}

} // namespace experimental

} // namespace multigrid


Expand Down Expand Up @@ -533,8 +604,10 @@ void Multigrid::apply_dense_impl(const VectorType* b, VectorType* x,
{
using ws = workspace_traits<Multigrid>;
this->setup_workspace();
if (state.nrhs != b->get_size()[1]) {
state.generate(this->get_system_matrix().get(), this, b->get_size()[1]);
this->create_state();
if (cache_.state->nrhs != b->get_size()[1]) {
cache_.state->generate(this->get_system_matrix().get(), this,
b->get_size()[1]);
}
auto lambda = [&, this](auto mg_level, auto b, auto x) {
using value_type = typename std::decay_t<
Expand All @@ -551,7 +624,7 @@ void Multigrid::apply_dense_impl(const VectorType* b, VectorType* x,
bool one_changed{};
exec->run(multigrid::make_initialize(&stop_status));
// compute the residual at the r_list(0);
// auto r = state.r_list.at(0);
// auto r = state->r_list.at(0);
// r->copy_from(b)
// system_matrix->apply(lend(neg_one_op), x, lend(one_op), r.get());
auto stop_criterion = this->get_stop_criterion_factory()->generate(
Expand All @@ -572,9 +645,9 @@ void Multigrid::apply_dense_impl(const VectorType* b, VectorType* x,
break;
}

state.run_cycle(this->get_parameters().cycle, 0,
this->get_system_matrix(), b, x,
guess == initial_guess_mode::zero);
cache_.state->run_cycle(this->get_parameters().cycle, 0,
this->get_system_matrix(), b, x,
guess == initial_guess_mode::zero);
// r->copy_from(b);
// system_matrix->apply(lend(neg_one_op), x, lend(one_op),
// r.get());
Expand All @@ -589,6 +662,14 @@ void Multigrid::apply_dense_impl(const VectorType* b, VectorType* x,
}


void Multigrid::create_state() const
{
if (cache_.state == nullptr) {
cache_.state = std::make_unique<multigrid::MultigridState>();
}
}


int workspace_traits<Multigrid>::num_arrays(const Solver&) { return 1; }


Expand Down
106 changes: 29 additions & 77 deletions include/ginkgo/core/solver/multigrid.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,82 +98,7 @@ enum class cycle { v, f, w };
enum class mid_smooth_type { both, post_smoother, pre_smoother, standalone };


namespace experimental {


/**
* MultigridState is to store the necessary cache and run the operation of all
* levels.
*
* @note it should only be used internally
*/
struct MultigridState {
MultigridState() : nrhs{0} {}

/**
* Generate the cache for later usage.
*
* @param system_matrix_in the system matrix
* @param multigrid_in the multigrid information
* @param nrhs_in the number of right hand side
*/
void generate(const LinOp* system_matrix_in, const Multigrid* multigrid_in,
const size_type nrhs_in);

/**
* allocate_memory is a helper function to allocate the memory of one level
*
* @tparam VT the value type of memory
*
* @param level the current level index
* @param cycle the multigrid cycle
* @param current_nrows the number of rows of current fine matrix
* @param next_nrows the number of rows of next coarse matrix
*/
template <typename VT>
void allocate_memory(int level, multigrid::cycle cycle,
size_type current_nrows, size_type next_nrows);

/**
* run the cycle of the level
*
* @param cycle the multigrid cycle
* @param level the current level index
* @param matrix the system matrix of current level
* @param b the right hand side
* @param x the input vectors
*/
void run_cycle(multigrid::cycle cycle, size_type level,
const std::shared_ptr<const LinOp>& matrix, const LinOp* b,
LinOp* x, bool x_is_zero = false, bool is_first = true,
bool is_end = true);

/**
* @copydoc run_cycle
*
* @tparam VT the value type
*
* @note it is the version with known ValueType
*/
template <typename VT>
void run_cycle(multigrid::cycle cycle, size_type level,
const std::shared_ptr<const LinOp>& matrix, const LinOp* b,
LinOp* x, bool x_is_zero, bool is_first, bool is_end);

// current level's nrows x nrhs
std::vector<std::shared_ptr<LinOp>> r_list;
// next level's nrows x nrhs
std::vector<std::shared_ptr<LinOp>> g_list;
std::vector<std::shared_ptr<LinOp>> e_list;
// constant 1 x 1
std::vector<std::shared_ptr<const LinOp>> one_list;
std::vector<std::shared_ptr<const LinOp>> next_one_list;
std::vector<std::shared_ptr<const LinOp>> neg_one_list;
const LinOp* system_matrix;
const Multigrid* multigrid;
size_type nrhs;
};
} // namespace experimental
class MultigridState;


} // namespace multigrid
Expand Down Expand Up @@ -591,6 +516,8 @@ class Multigrid : public EnableLinOp<Multigrid>,
}
}

void create_state() const;

private:
std::vector<std::shared_ptr<const gko::multigrid::MultigridLevel>>
mg_level_list_{};
Expand All @@ -600,7 +527,32 @@ class Multigrid : public EnableLinOp<Multigrid>,
std::shared_ptr<const LinOp> coarsest_solver_{};
std::function<size_type(const size_type, const LinOp*)> level_selector_;
std::function<size_type(const size_type, const LinOp*)> solver_selector_;
mutable multigrid::experimental::MultigridState state;

/**
* Manages three vectors as a cache, so there is no need to allocate them
* every time an intermediate vector is required. Copying an instance
* will only yield an empty object since copying the cached vector would
* not make sense.
*
* @internal The struct is present so the whole class can be copyable
* (could also be done with writing `operator=` and copy
* constructor of the enclosing class by hand)
*/
mutable struct cache_struct {
cache_struct() = default;

~cache_struct() = default;

cache_struct(const cache_struct&) {}

cache_struct(cache_struct&&) {}

cache_struct& operator=(const cache_struct&) { return *this; }

cache_struct& operator=(cache_struct&&) { return *this; }

std::shared_ptr<multigrid::MultigridState> state;
} cache_;
};

template <>
Expand Down
6 changes: 2 additions & 4 deletions include/ginkgo/core/solver/solver_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,13 +71,11 @@ enum class initial_guess_mode {


namespace multigrid {
namespace experimental {


class MultigridState;


} // namespace experimental
} // namespace multigrid


Expand All @@ -88,7 +86,7 @@ class MultigridState;
*/
class ApplyWithInitialGuess {
protected:
friend class multigrid::experimental::MultigridState;
friend class multigrid::MultigridState;

/**
* Applies a linear operator to a vector (or a sequence of vectors) with
Expand Down Expand Up @@ -167,7 +165,7 @@ class ApplyWithInitialGuess {
template <typename DerivedType>
class EnableApplyWithInitialGuess : public ApplyWithInitialGuess {
protected:
friend class multigrid::experimental::MultigridState;
friend class multigrid::MultigridState;

explicit EnableApplyWithInitialGuess(
initial_guess_mode guess = initial_guess_mode::provided)
Expand Down

0 comments on commit 3a2d29c

Please sign in to comment.