From: Denis Davydov Date: Thu, 7 Mar 2019 08:33:00 +0000 (+0100) Subject: streamline treatment of block and non-block vectors in MatrixFree using updated Vecto... X-Git-Tag: v9.1.0-rc1~296^2 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F7787%2Fhead;p=dealii.git streamline treatment of block and non-block vectors in MatrixFree using updated VectorDataExchange --- diff --git a/include/deal.II/matrix_free/matrix_free.h b/include/deal.II/matrix_free/matrix_free.h index 19edab9683..4877be670b 100644 --- a/include/deal.II/matrix_free/matrix_free.h +++ b/include/deal.II/matrix_free/matrix_free.h @@ -3405,166 +3405,17 @@ namespace internal return components; } - template - void - update_ghost_values_start_block(const VectorStruct &vec, - const unsigned int channel, - std::integral_constant, - VectorDataExchange &exchanger); - template - void - reset_ghost_values_block(const VectorStruct &vec, - std::integral_constant, - VectorDataExchange &exchanger); - template - void - update_ghost_values_finish_block(const VectorStruct &vec, - const unsigned int channel, - std::integral_constant, - VectorDataExchange &exchanger); - template - void - compress_start_block(const VectorStruct &vec, - const unsigned int channel, - std::integral_constant, - VectorDataExchange &exchanger); - template - void - compress_finish_block(const VectorStruct &vec, - const unsigned int channel, - std::integral_constant, - VectorDataExchange &exchanger); - template - void - zero_vector_region_block(const unsigned int range_index, - VectorStruct &, - std::integral_constant, - VectorDataExchange &); - - template - void - update_ghost_values_start_block(const VectorStruct &, - const unsigned int, - std::integral_constant, - VectorDataExchange &) - {} - template - void - reset_ghost_values_block(const VectorStruct &, - std::integral_constant, - VectorDataExchange &) - {} - template - void - update_ghost_values_finish_block(const VectorStruct &, - const unsigned int, - std::integral_constant, - VectorDataExchange &) - {} - template - void - compress_start_block(const VectorStruct &, - const unsigned int, - std::integral_constant, - VectorDataExchange &) - {} - template - void - compress_finish_block(const VectorStruct &, - const unsigned int, - std::integral_constant, - VectorDataExchange &) - {} - template - void - zero_vector_region_block(const unsigned int range_index, - VectorStruct & vec, - std::integral_constant, - VectorDataExchange &) - { - if (range_index == 0 || range_index == numbers::invalid_unsigned_int) - vec = 0; - } - - - - // if the input vector did not have ghosts imported, clear them here again - // in order to avoid subsequent operations e.g. in linear solvers to work - // with ghosts all the time - template - inline void - reset_ghost_values(const VectorStruct & vec, - VectorDataExchange &exchanger) - { - reset_ghost_values_block( - vec, - std::integral_constant::value>(), - exchanger); - } - - - - template - inline void - reset_ghost_values(const LinearAlgebra::distributed::Vector &vec, - VectorDataExchange &exchanger) - { - exchanger.reset_ghost_values(vec); - } - - - - template - inline void - reset_ghost_values(const std::vector &vec, - VectorDataExchange &exchanger) - { - // return immediately if there is nothing to do. - if (exchanger.ghosts_were_set == true) - return; - - for (unsigned int comp = 0; comp < vec.size(); comp++) - reset_ghost_values(vec[comp], exchanger); - } - - - - template - inline void - reset_ghost_values(const std::vector &vec, - VectorDataExchange & exchanger) - { - // return immediately if there is nothing to do. - if (exchanger.ghosts_were_set == true) - return; - - for (unsigned int comp = 0; comp < vec.size(); comp++) - reset_ghost_values(*vec[comp], exchanger); - } - - - - template - inline void - reset_ghost_values_block(const VectorStruct &vec, - std::integral_constant, - VectorDataExchange &exchanger) - { - // return immediately if there is nothing to do. - if (exchanger.ghosts_were_set == true) - return; - - for (unsigned int i = 0; i < vec.n_blocks(); ++i) - reset_ghost_values(vec.block(i), exchanger); - } - // A helper function to identify block vectors with many components where we // should not try to overlap computations and communication because there - // would be too many outstanding communication requests. This is the base case - // for generic vectors - template + // would be too many outstanding communication requests. + + // default value for vectors that do not have communication_block_size + template < + typename VectorStruct, + typename std::enable_if::value, + VectorStruct>::type * = nullptr> constexpr unsigned int get_communication_block_size(const VectorStruct &) { @@ -3573,46 +3424,70 @@ namespace internal - // Specialized case for the block vector which as the additional member - // variable - template + template < + typename VectorStruct, + typename std::enable_if::value, + VectorStruct>::type * = nullptr> constexpr unsigned int - get_communication_block_size( - const LinearAlgebra::distributed::BlockVector &) + get_communication_block_size(const VectorStruct &) { - return LinearAlgebra::distributed::BlockVector< - Number>::communication_block_size; + return VectorStruct::communication_block_size; } - template - inline void + // -------------------------------------------------------------------------- + // below we have wrappers to distinguish between block and non-block vectors. + // -------------------------------------------------------------------------- + + // + // update_ghost_values_start + // + + // update_ghost_values for block vectors + template ::value, + VectorStruct>::type * = nullptr> + void update_ghost_values_start(const VectorStruct & vec, VectorDataExchange &exchanger, const unsigned int channel = 0) { - update_ghost_values_start_block( - vec, - channel, - std::integral_constant::value>(), - exchanger); + if (get_communication_block_size(vec) < vec.n_blocks()) + { + // don't forget to set ghosts_were_set, that otherwise happens + // inside VectorDataExchange::update_ghost_values_start() + exchanger.ghosts_were_set = vec.has_ghost_elements(); + vec.update_ghost_values(); + } + else + { + for (unsigned int i = 0; i < vec.n_blocks(); ++i) + update_ghost_values_start(vec.block(i), exchanger, channel + i); + } } - template - inline void - update_ghost_values_start( - const LinearAlgebra::distributed::Vector &vec, - VectorDataExchange & exchanger, - const unsigned int channel = 0) + // update_ghost_values for non-block vectors + template ::value, + VectorStruct>::type * = nullptr> + void + update_ghost_values_start(const VectorStruct & vec, + VectorDataExchange &exchanger, + const unsigned int channel = 0) { exchanger.update_ghost_values_start(channel, vec); } + // update_ghost_values_start() for vector of vectors template inline void update_ghost_values_start(const std::vector &vec, @@ -3628,6 +3503,7 @@ namespace internal + // update_ghost_values_start() for vector of pointers to vectors template inline void update_ghost_values_start(const std::vector &vec, @@ -3643,56 +3519,50 @@ namespace internal - template - inline void - update_ghost_values_start_block(const VectorStruct &vec, - const unsigned int channel, - std::integral_constant, - VectorDataExchange &exchanger) + // + // update_ghost_values_finish + // + + // for block vectors + template ::value, + VectorStruct>::type * = nullptr> + void + update_ghost_values_finish(const VectorStruct & vec, + VectorDataExchange &exchanger, + const unsigned int channel = 0) { if (get_communication_block_size(vec) < vec.n_blocks()) { - // don't forget to set ghosts_were_set, that otherwise happens - // inside VectorDataExchange::update_ghost_values_start() - exchanger.ghosts_were_set = vec.has_ghost_elements(); - vec.update_ghost_values(); + // do nothing, everything has already been completed in the _start() + // call } else - { - for (unsigned int i = 0; i < vec.n_blocks(); ++i) - update_ghost_values_start(vec.block(i), exchanger, channel + i); - } + for (unsigned int i = 0; i < vec.n_blocks(); ++i) + update_ghost_values_finish(vec.block(i), exchanger, channel + i); } - template - inline void + // for non-block vectors + template ::value, + VectorStruct>::type * = nullptr> + void update_ghost_values_finish(const VectorStruct & vec, VectorDataExchange &exchanger, const unsigned int channel = 0) - { - update_ghost_values_finish_block( - vec, - channel, - std::integral_constant::value>(), - exchanger); - } - - - - template - inline void - update_ghost_values_finish( - const LinearAlgebra::distributed::Vector &vec, - VectorDataExchange & exchanger, - const unsigned int channel = 0) { exchanger.update_ghost_values_finish(channel, vec); } + // for vector of vectors template inline void update_ghost_values_finish(const std::vector &vec, @@ -3708,6 +3578,7 @@ namespace internal + // for vector of pointers to vectors template inline void update_ghost_values_finish(const std::vector &vec, @@ -3723,51 +3594,47 @@ namespace internal - template + // + // compress_start + // + + // for block vectors + template ::value, + VectorStruct>::type * = nullptr> inline void - update_ghost_values_finish_block(const VectorStruct &vec, - const unsigned int channel, - std::integral_constant, - VectorDataExchange &exchanger) + compress_start(VectorStruct & vec, + VectorDataExchange &exchanger, + const unsigned int channel = 0) { if (get_communication_block_size(vec) < vec.n_blocks()) - { - // do nothing, everything has already been completed in the _start() - // call - } + vec.compress(dealii::VectorOperation::add); else for (unsigned int i = 0; i < vec.n_blocks(); ++i) - update_ghost_values_finish(vec.block(i), exchanger, channel + i); + compress_start(vec.block(i), exchanger, channel + i); } - template + // for non-block vectors + template ::value, + VectorStruct>::type * = nullptr> inline void compress_start(VectorStruct & vec, VectorDataExchange &exchanger, const unsigned int channel = 0) - { - compress_start_block( - vec, - channel, - std::integral_constant::value>(), - exchanger); - } - - - - template - inline void - compress_start(LinearAlgebra::distributed::Vector &vec, - VectorDataExchange & exchanger, - const unsigned int channel = 0) { exchanger.compress_start(channel, vec); } + // for std::vector of vectors template inline void compress_start(std::vector & vec, @@ -3783,6 +3650,7 @@ namespace internal + // for std::vector of pointer to vectors template inline void compress_start(std::vector & vec, @@ -3798,48 +3666,50 @@ namespace internal - template + // + // compress_finish + // + + // for block vectors + template ::value, + VectorStruct>::type * = nullptr> inline void - compress_start_block(VectorStruct & vec, - const unsigned int channel, - std::integral_constant, - VectorDataExchange &exchanger) + compress_finish(VectorStruct & vec, + VectorDataExchange &exchanger, + const unsigned int channel = 0) { if (get_communication_block_size(vec) < vec.n_blocks()) - vec.compress(dealii::VectorOperation::add); + { + // do nothing, everything has already been completed in the _start() + // call + } else for (unsigned int i = 0; i < vec.n_blocks(); ++i) - compress_start(vec.block(i), exchanger, channel + i); + compress_finish(vec.block(i), exchanger, channel + i); } - template + // for non-block vectors + template ::value, + VectorStruct>::type * = nullptr> inline void compress_finish(VectorStruct & vec, VectorDataExchange &exchanger, const unsigned int channel = 0) - { - compress_finish_block( - vec, - channel, - std::integral_constant::value>(), - exchanger); - } - - - - template - inline void - compress_finish(LinearAlgebra::distributed::Vector &vec, - VectorDataExchange & exchanger, - const unsigned int channel = 0) { exchanger.compress_finish(channel, vec); } + // for std::vector of vectors template inline void compress_finish(std::vector & vec, @@ -3855,6 +3725,7 @@ namespace internal + // for std::vector of pointer to vectors template inline void compress_finish(std::vector & vec, @@ -3870,51 +3741,119 @@ namespace internal + // + // reset_ghost_values: + // + // if the input vector did not have ghosts imported, clear them here again + // in order to avoid subsequent operations e.g. in linear solvers to work + // with ghosts all the time + // + + // for block vectors + template ::value, + VectorStruct>::type * = nullptr> + inline void + reset_ghost_values(const VectorStruct & vec, + VectorDataExchange &exchanger) + { + // return immediately if there is nothing to do. + if (exchanger.ghosts_were_set == true) + return; + + for (unsigned int i = 0; i < vec.n_blocks(); ++i) + reset_ghost_values(vec.block(i), exchanger); + } + + + + // for non-block vectors + template ::value, + VectorStruct>::type * = nullptr> + inline void + reset_ghost_values(const VectorStruct & vec, + VectorDataExchange &exchanger) + { + exchanger.reset_ghost_values(vec); + } + + + + // for std::vector of vectors template inline void - compress_finish_block(VectorStruct & vec, - const unsigned int channel, - std::integral_constant, - VectorDataExchange &exchanger) + reset_ghost_values(const std::vector &vec, + VectorDataExchange &exchanger) { - if (get_communication_block_size(vec) < vec.n_blocks()) - { - // do nothing, everything has already been completed in the _start() - // call - } - else - for (unsigned int i = 0; i < vec.n_blocks(); ++i) - compress_finish(vec.block(i), exchanger, channel + i); + // return immediately if there is nothing to do. + if (exchanger.ghosts_were_set == true) + return; + + for (unsigned int comp = 0; comp < vec.size(); comp++) + reset_ghost_values(vec[comp], exchanger); } + // for std::vector of pointer to vectors template inline void + reset_ghost_values(const std::vector &vec, + VectorDataExchange & exchanger) + { + // return immediately if there is nothing to do. + if (exchanger.ghosts_were_set == true) + return; + + for (unsigned int comp = 0; comp < vec.size(); comp++) + reset_ghost_values(*vec[comp], exchanger); + } + + + + // + // zero_vector_region + // + + // for block vectors + template ::value, + VectorStruct>::type * = nullptr> + inline void zero_vector_region(const unsigned int range_index, VectorStruct & vec, VectorDataExchange &exchanger) { - zero_vector_region_block( - range_index, - vec, - std::integral_constant::value>(), - exchanger); + for (unsigned int i = 0; i < vec.n_blocks(); ++i) + exchanger.zero_vector_region(range_index, vec.block(i)); } - template + // for non-block vectors + template ::value, + VectorStruct>::type * = nullptr> inline void - zero_vector_region(const unsigned int range_index, - LinearAlgebra::distributed::Vector &vec, - VectorDataExchange & exchanger) + zero_vector_region(const unsigned int range_index, + VectorStruct & vec, + VectorDataExchange &exchanger) { exchanger.zero_vector_region(range_index, vec); } + // for std::vector of vectors template inline void zero_vector_region(const unsigned int range_index, @@ -3927,6 +3866,7 @@ namespace internal + // for std::vector of pointers to vectors template inline void zero_vector_region(const unsigned int range_index, @@ -3939,19 +3879,6 @@ namespace internal - template - inline void - zero_vector_region_block(const unsigned int range_index, - VectorStruct & vec, - std::integral_constant, - VectorDataExchange &exchanger) - { - for (unsigned int i = 0; i < vec.n_blocks(); ++i) - zero_vector_region(range_index, vec.block(i), exchanger); - } - - - namespace MatrixFreeFunctions { // struct to select between a const interface and a non-const interface