Rheolef  7.1
an efficient C++ finite element environment
mpi_assembly_end.h
Go to the documentation of this file.
1 #ifndef _RHEO_MPI_ASSEMBLY_END_H
2 #define _RHEO_MPI_ASSEMBLY_END_H
3 
24 #include "rheolef/msg_util.h"
25 #include <boost/functional.hpp>
26 #include <boost/iterator/transform_iterator.hpp>
27 
28 namespace rheolef {
29 
30 /*F:
31 NAME: msg_assembly_end -- array or matrix assembly (@PACKAGE@ @VERSION@)
32 DESCRIPTION:
33  Finish a dense array or sparse matrix assembly.
34 COMPLEXITY:
35  **TO DO**
36 AUTHORS:
37  LMC-IMAG, 38041 Grenoble cedex 9, France
38  | Pierre.Saramito@imag.fr
39 DATE: 23 march 1999
40 END:
41 */
42 
43 //<mpi_assembly_end:
44 template <
45  class Container,
46  class Message,
47  class Size>
48 Size
50 // input:
51  Message& receive,
52  Message& send,
53  Size receive_max_size,
54 // output:
55  Container x)
56 {
57  typedef Size size_type;
58  typedef typename Container::data_type data_type;
59  // -----------------------------------------------------------------
60  // 1) receive data and store it in container
61  // -----------------------------------------------------------------
62 
63  // note: for wait_any, build an iterator adapter that scan the pair.second in [index,request]
64  // and then get an iterator in the pair using iter.base(): retrive the corresponding index
65  // for computing the position in the receive.data buffer
66  typedef boost::transform_iterator<select2nd<size_type,mpi::request>,
67  typename std::list<std::pair<size_type,mpi::request> >::iterator>
68  request_iterator;
69 
70 #define _RHEOLEF_BUG_FOR_NON_MPI_DATA_TYPE
71 #ifdef _RHEOLEF_BUG_FOR_NON_MPI_DATA_TYPE
72  while (receive.waits.size() != 0) {
73  request_iterator iter_r_waits (receive.waits.begin(), select2nd<size_type,mpi::request>()),
74  last_r_waits (receive.waits.end(), select2nd<size_type,mpi::request>());
75  // waits on any receive...
76  std::pair<mpi::status,request_iterator> pair_status = mpi::wait_any (iter_r_waits, last_r_waits);
77  // check status
78  boost::optional<int> i_msg_size_opt = pair_status.first.template count<data_type>();
79  check_macro (i_msg_size_opt, "receive wait failed");
80  int iproc = pair_status.first.source();
81  check_macro (iproc >= 0, "receive: source iproc = "<<iproc<<" < 0 !");
82  // get size of receive and number in data
83  size_type i_msg_size = (size_type)i_msg_size_opt.get();
84  typename std::list<std::pair<size_type,mpi::request> >::iterator i_pair_ptr = pair_status.second.base();
85  size_type i_receive = (*i_pair_ptr).first;
86  size_type i_start = i_receive*receive_max_size;
87  for (size_type j = i_start; j < i_start + i_msg_size; j++) {
88  x (receive.data[j]);
89  }
90  receive.waits.erase (i_pair_ptr);
91  }
92 #else // _RHEOLEF_BUG_FOR_NON_MPI_DATA_TYPE
93  // wait_all works better when using an array of non mpi_data_type, as an array of set<size_t>
94  request_iterator iter_r_waits (receive.waits.begin(), select2nd<size_type,mpi::request>()),
95  last_r_waits (receive.waits.end(), select2nd<size_type,mpi::request>());
96  std::vector<mpi::status> recv_status (receive.waits.size());
97  mpi::wait_all (iter_r_waits, last_r_waits, recv_status.begin());
98  for (size_type i_recv = 0, n_recv = recv_status.size(); i_recv < n_recv; i_recv++) {
99  boost::optional<int> i_msg_size_opt = recv_status[i_recv].template count<data_type>();
100  check_macro (i_msg_size_opt, "receive wait failed");
101  int iproc = recv_status[i_recv].source();
102  check_macro (iproc >= 0, "receive: source iproc = "<<iproc<<" < 0 !");
103  // get size of receive and number in data
104  size_type i_msg_size = (size_type)i_msg_size_opt.get();
105  size_type i_start = i_recv*receive_max_size;
106  for (size_type j = i_start; j < i_start + i_msg_size; j++) {
107  x (receive.data[j]);
108  }
109  }
110 #endif // _RHEOLEF_BUG_FOR_NON_MPI_DATA_TYPE
111  // -----------------------------------------------------------------
112  // 2) wait on sends
113  // -----------------------------------------------------------------
114  request_iterator iter_s_waits (send.waits.begin(), select2nd<size_type,mpi::request>()),
115  last_s_waits (send.waits.end(), select2nd<size_type,mpi::request>());
116  Size send_nproc = send.waits.size();
117  std::vector<mpi::status> send_status(send_nproc);
118  mpi::wait_all (iter_s_waits, last_s_waits, send_status.begin());
119  // -----------------------------------------------------------------
120  // 3) clear send & receive messages [waits,data]
121  // -----------------------------------------------------------------
122  send.waits.clear();
123  send.data.clear();
124  receive.waits.clear();
125  receive.data.clear();
126  return x.n_new_entry();
127 }
128 //>mpi_assembly_end:
129 } // namespace rheolef
130 #endif //_RHEO_MPI_ASSEMBLY_END_H
check_macro
check_macro(expr1.have_homogeneous_space(Xh1), "dual(expr1,expr2); expr1 should have homogeneous space. HINT: use dual(interpolate(Xh, expr1),expr2)")
rheolef::size_type
size_t size_type
Definition: basis_get.cc:76
rheolef::select2nd
Definition: msg_util.h:45
rheolef
This file is part of Rheolef.
Definition: compiler_eigen.h:37
size_type
field::size_type size_type
Definition: branch.cc:425
rheolef::mpi_assembly_end
Size mpi_assembly_end(Message &receive, Message &send, Size receive_max_size, Container x)
Definition: mpi_assembly_end.h:49