Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:42:51

0001 /*
0002  [auto_generated]
0003  boost/numeric/odeint/external/mpi/mpi_vector_state.hpp
0004 
0005  [begin_description]
0006  Copying a container from/to an mpi_state splits/joins it.
0007  [end_description]
0008 
0009  Copyright 2013 Karsten Ahnert
0010  Copyright 2013 Mario Mulansky
0011  Copyright 2013 Pascal Germroth
0012 
0013  Distributed under the Boost Software License, Version 1.0.
0014  (See accompanying file LICENSE_1_0.txt or
0015  copy at http://www.boost.org/LICENSE_1_0.txt)
0016  */
0017 
0018 
0019 #ifndef BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_VECTOR_STATE_HPP_INCLUDED
0020 #define BOOST_NUMERIC_ODEINT_EXTERNAL_MPI_MPI_VECTOR_STATE_HPP_INCLUDED
0021 
0022 #include <vector>
0023 #include <algorithm>
0024 #include <boost/mpi.hpp>
0025 #include <boost/numeric/odeint/util/copy.hpp>
0026 #include <boost/numeric/odeint/util/split_adaptor.hpp>
0027 #include <boost/numeric/odeint/algebra/algebra_dispatcher.hpp>
0028 #include <boost/numeric/odeint/external/mpi/mpi_state.hpp>
0029 
0030 namespace boost {
0031 namespace numeric {
0032 namespace odeint {
0033 
0034 
0035 /** \brief Split data from some container on node 0 to the slaves.
0036  * Source must be a model of Random Access Range. */
0037 template< class Source , class InnerState >
0038 struct split_impl< Source, mpi_state< InnerState >,
0039     typename boost::enable_if< boost::has_range_const_iterator<Source> >::type >
0040 {
0041     typedef typename boost::range_iterator<const Source>::type iterator;
0042 
0043     static void split( const Source &from, mpi_state< InnerState > &to )
0044     {
0045         std::vector< InnerState > pieces;
0046         if(to.world.rank() == 0) {
0047             const size_t num = static_cast<size_t>(to.world.size());
0048             pieces.resize(num);
0049             for(size_t i = 0 ; i < num ; i++) {
0050                 iterator_range<iterator> part = detail::make_split_range(from, i, num);
0051                 boost::numeric::odeint::resize(pieces[i], part);
0052                 boost::numeric::odeint::copy(part, pieces[i]);
0053             }
0054         }
0055         // send to nodes
0056         boost::mpi::scatter(to.world, pieces, to(), 0);
0057     }
0058 };
0059 
0060 /** \brief Merge data from an mpi_state to some container on node 0.
0061  * Target must be a model Single Pass Range. */
0062 template< class Target, class InnerState >
0063 struct unsplit_impl< mpi_state< InnerState >, Target,
0064     typename boost::enable_if< boost::has_range_iterator<Target> >::type >
0065 {
0066     typedef typename boost::range_iterator<Target>::type iterator;
0067 
0068     static void unsplit( const mpi_state< InnerState > &from , Target &to )
0069     {
0070         std::vector< InnerState > pieces;
0071         // send data to root
0072         boost::mpi::gather(from.world, from(), pieces, 0);
0073         if(from.world.rank() == 0) {
0074             // check target size
0075             size_t total_size = 0;
0076             for(size_t i = 0 ; i < pieces.size() ; i++)
0077                 total_size += boost::size(pieces[i]);
0078             BOOST_ASSERT( total_size <= boost::size(to) );
0079             // copy parts
0080             iterator out = boost::begin(to);
0081             for(size_t i = 0 ; i < pieces.size() ; i++)
0082                 out = boost::copy(pieces[i], out);
0083         }
0084     }
0085 };
0086 
0087 
0088 }
0089 }
0090 }
0091 
0092 
0093 #endif
0094