mpi_vector_state.hpp 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. [auto_generated]
  3. boost/numeric/odeint/external/mpi/mpi_vector_state.hpp
  4. [begin_description]
  5. Copying a container from/to an mpi_state splits/joins it.
  6. [end_description]
  7. Copyright 2013 Karsten Ahnert
  8. Copyright 2013 Mario Mulansky
  9. Copyright 2013 Pascal Germroth
  10. Distributed under the Boost Software License, Version 1.0.
  11. (See accompanying file LICENSE_1_0.txt or
  12. copy at http://www.boost.org/LICENSE_1_0.txt)
  13. */
  14. #ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_VECTOR_STATE_HPP_INCLUDED
  15. #define BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_VECTOR_STATE_HPP_INCLUDED
  16. #include <vector>
  17. #include <algorithm>
  18. #include <boost/mpi.hpp>
  19. #include <boost/numeric/odeint/util/copy.hpp>
  20. #include <boost/numeric/odeint/util/split_adaptor.hpp>
  21. #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp>
  22. #include <boost/numeric/odeint/external/mpi/mpi_state.hpp>
  23. namespace boost {
  24. namespace numeric {
  25. namespace odeint {
  26. /** \brief Split data from some container on node 0 to the slaves.
  27. * Source must be a model of Random Access Range. */
  28. template< class Source , class InnerState >
  29. struct split_impl< Source, mpi_state< InnerState >,
  30. typename boost::enable_if< boost::has_range_const_iterator<Source> >::type >
  31. {
  32. typedef typename boost::range_iterator<const Source>::type iterator;
  33. static void split( const Source &from, mpi_state< InnerState > &to )
  34. {
  35. std::vector< InnerState > pieces;
  36. if(to.world.rank() == 0) {
  37. const size_t num = static_cast<size_t>(to.world.size());
  38. pieces.resize(num);
  39. for(size_t i = 0 ; i < num ; i++) {
  40. iterator_range<iterator> part = detail::make_split_range(from, i, num);
  41. boost::numeric::odeint::resize(pieces[i], part);
  42. boost::numeric::odeint::copy(part, pieces[i]);
  43. }
  44. }
  45. // send to nodes
  46. boost::mpi::scatter(to.world, pieces, to(), 0);
  47. }
  48. };
  49. /** \brief Merge data from an mpi_state to some container on node 0.
  50. * Target must be a model Single Pass Range. */
  51. template< class Target, class InnerState >
  52. struct unsplit_impl< mpi_state< InnerState >, Target,
  53. typename boost::enable_if< boost::has_range_iterator<Target> >::type >
  54. {
  55. typedef typename boost::range_iterator<Target>::type iterator;
  56. static void unsplit( const mpi_state< InnerState > &from , Target &to )
  57. {
  58. std::vector< InnerState > pieces;
  59. // send data to root
  60. boost::mpi::gather(from.world, from(), pieces, 0);
  61. if(from.world.rank() == 0) {
  62. // check target size
  63. size_t total_size = 0;
  64. for(size_t i = 0 ; i < pieces.size() ; i++)
  65. total_size += boost::size(pieces[i]);
  66. BOOST_ASSERT( total_size <= boost::size(to) );
  67. // copy parts
  68. iterator out = boost::begin(to);
  69. for(size_t i = 0 ; i < pieces.size() ; i++)
  70. out = boost::copy(pieces[i], out);
  71. }
  72. }
  73. };
  74. }
  75. }
  76. }
  77. #endif