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