mpi_vector_state.hpp 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  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. #include <boost/numeric/odeint/tools/assert.hpp>
  24. namespace boost {
  25. namespace numeric {
  26. namespace odeint {
  27. /** \brief Split data from some container on node 0 to the slaves.
  28. * Source must be a model of Random Access Range. */
  29. template< class Source , class InnerState >
  30. struct split_impl< Source, mpi_state< InnerState >,
  31. typename boost::enable_if< boost::has_range_const_iterator<Source> >::type >
  32. {
  33. typedef typename boost::range_iterator<const Source>::type iterator;
  34. static void split( const Source &from, mpi_state< InnerState > &to )
  35. {
  36. std::vector< InnerState > pieces;
  37. if(to.world.rank() == 0) {
  38. const size_t num = static_cast<size_t>(to.world.size());
  39. pieces.resize(num);
  40. for(size_t i = 0 ; i < num ; i++) {
  41. iterator_range<iterator> part = detail::make_split_range(from, i, num);
  42. boost::numeric::odeint::resize(pieces[i], part);
  43. boost::numeric::odeint::copy(part, pieces[i]);
  44. }
  45. }
  46. // send to nodes
  47. boost::mpi::scatter(to.world, pieces, to(), 0);
  48. }
  49. };
  50. /** \brief Merge data from an mpi_state to some container on node 0.
  51. * Target must be a model Single Pass Range. */
  52. template< class Target, class InnerState >
  53. struct unsplit_impl< mpi_state< InnerState >, Target,
  54. typename boost::enable_if< boost::has_range_iterator<Target> >::type >
  55. {
  56. typedef typename boost::range_iterator<Target>::type iterator;
  57. static void unsplit( const mpi_state< InnerState > &from , Target &to )
  58. {
  59. std::vector< InnerState > pieces;
  60. // send data to root
  61. boost::mpi::gather(from.world, from(), pieces, 0);
  62. if(from.world.rank() == 0) {
  63. // check target size
  64. size_t total_size = 0;
  65. for(size_t i = 0 ; i < pieces.size() ; i++)
  66. total_size += boost::size(pieces[i]);
  67. BOOST_NUMERIC_ODEINT_ASSERT( total_size <= boost::size(to) );
  68. // copy parts
  69. iterator out = boost::begin(to);
  70. for(size_t i = 0 ; i < pieces.size() ; i++)
  71. out = boost::copy(pieces[i], out);
  72. }
  73. }
  74. };
  75. }
  76. }
  77. }
  78. #endif