Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-06-30 08:21:41

0001 /*
0002  [auto_generated]
0003  boost/numeric/odeint/external/openmp/openmp_state.hpp
0004 
0005  [begin_description]
0006  Wrappers for OpenMP.
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_OPENMP_OPENMP_STATE_HPP_INCLUDED
0020 #define BOOST_NUMERIC_ODEINT_EXTERNAL_OPENMP_OPENMP_STATE_HPP_INCLUDED
0021 
0022 #include <omp.h>
0023 #include <vector>
0024 #include <algorithm>
0025 #include <type_traits>
0026 #include <boost/range/adaptor/sliced.hpp>
0027 #include <boost/numeric/odeint/util/copy.hpp>
0028 #include <boost/numeric/odeint/util/split.hpp>
0029 #include <boost/numeric/odeint/util/resize.hpp>
0030 #include <boost/numeric/odeint/external/openmp/openmp_nested_algebra.hpp>
0031 
0032 namespace boost {
0033 namespace numeric {
0034 namespace odeint {
0035 
0036 /** \brief A container that is split into distinct parts, for threading.
0037  * Just a wrapper for vector<vector<T>>, use `copy` for splitting/joining.
0038  */
0039 template< class T >
0040 struct openmp_state : public std::vector< std::vector< T > >
0041 {
0042     openmp_state() {}
0043 
0044     openmp_state(size_t n, const std::vector<T>& val = std::vector<T>())
0045     : std::vector< std::vector< T > >(n, val) {}
0046 
0047     template<class InputIterator>
0048     openmp_state(InputIterator first, InputIterator last)
0049     : std::vector< std::vector< T > >(first, last) {}
0050 
0051     openmp_state(const std::vector< std::vector< T > > &orig)
0052     : std::vector< std::vector< T > >(orig) {}
0053 
0054 };
0055 
0056 
0057 
0058 
0059 template< class T >
0060 struct is_resizeable< openmp_state< T > > : std::true_type { };
0061 
0062 
0063 template< class T >
0064 struct same_size_impl< openmp_state< T > , openmp_state< T > >
0065 {
0066     static bool same_size( const openmp_state< T > &x , const openmp_state< T > &y )
0067     {
0068         if( x.size() != y.size() ) return false;
0069         for( size_t i = 0 ; i != x.size() ; i++ )
0070             if( x[i].size() != y[i].size() ) return false;
0071         return true;
0072     }
0073 };
0074 
0075 
0076 template< class T >
0077 struct resize_impl< openmp_state< T > , openmp_state< T > >
0078 {
0079     static void resize( openmp_state< T > &x , const openmp_state< T > &y )
0080     {
0081         x.resize( y.size() );
0082 #       pragma omp parallel for schedule(dynamic)
0083         for(size_t i = 0 ; i < x.size() ; i++)
0084             x[i].resize( y[i].size() );
0085     }
0086 };
0087 
0088 
0089 /** \brief Copy data between openmp_states of same size. */
0090 template< class T >
0091 struct copy_impl< openmp_state< T >, openmp_state< T > >
0092 {
0093     static void copy( const openmp_state< T > &from, openmp_state< T > &to )
0094     {
0095 #       pragma omp parallel for schedule(dynamic)
0096         for(size_t i = 0 ; i < from.size() ; i++)
0097             std::copy( from[i].begin() , from[i].end() , to.begin() );
0098     }
0099 };
0100 
0101 
0102 
0103 /** \brief Copy data from some container to an openmp_state and resize it.
0104  * Target container size will determine number of blocks to split into.
0105  * If it is empty, it will be resized to the maximum number of OpenMP threads.
0106  * SourceContainer must support `s::value_type`, `s::const_iterator`, `s.begin()`, `s.end()` and `s.size()`,
0107  * with Random Access Iterators; i.e. it must be a Random Access Container. */
0108 template< class SourceContainer >
0109 struct split_impl< SourceContainer, openmp_state< typename SourceContainer::value_type > >
0110 {
0111     static void split( const SourceContainer &from, openmp_state< typename SourceContainer::value_type > &to )
0112     {
0113         if(to.size() == 0) to.resize( omp_get_max_threads() );
0114         const size_t part = from.size() / to.size();
0115 #       pragma omp parallel for schedule(dynamic)
0116         for(size_t i = 0 ; i < to.size() ; i++) {
0117             typedef typename SourceContainer::const_iterator it_t;
0118             const it_t begin = from.begin() + i * part;
0119             it_t end = begin + part;
0120             // for cases where from.size() % to.size() > 0
0121             if(i + 1 == to.size() || end > from.end()) end = from.end();
0122             to[i].resize(end - begin);
0123             std::copy(begin, end, to[i].begin());
0124         }
0125     }
0126 };
0127 
0128 /** \brief Copy data from an openmp_state to some container and resize it.
0129  * TargetContainer must support `s::value_type`, `s::iterator`, `s.begin()` and `s.resize(n)`,
0130  * i.e. it must be a `std::vector`. */
0131 template< class TargetContainer >
0132 struct unsplit_impl< openmp_state< typename TargetContainer::value_type >, TargetContainer >
0133 {
0134     static void unsplit( const openmp_state< typename TargetContainer::value_type > &from , TargetContainer &to )
0135     {
0136         // resize target
0137         size_t total_size = 0;
0138         for(size_t i = 0 ; i < from.size() ; i++)
0139             total_size += from[i].size();
0140         to.resize( total_size );
0141         // copy parts
0142         typename TargetContainer::iterator out = to.begin();
0143         for(size_t i = 0 ; i < from.size() ; i++)
0144             out = std::copy(from[i].begin(), from[i].end(), out);
0145     }
0146 };
0147 
0148 
0149 
0150 
0151 /** \brief OpenMP-parallelized algebra.
0152  * For use with openmp_state.
0153  */
0154 typedef openmp_nested_algebra< range_algebra > openmp_algebra;
0155 
0156 
0157 
0158 /** \brief Use `openmp_algebra` for `openmp_state`. */
0159 template< class T >
0160 struct algebra_dispatcher< openmp_state< T > >
0161 {
0162     typedef openmp_algebra algebra_type;
0163 };
0164 
0165 
0166 }
0167 }
0168 }
0169 
0170 
0171 #endif
0172