1 /*****************************************************************************
2  * Copyright (c) 2019 FrontISTR Commons
3  * This software is released under the MIT License, see LICENSE.txt
4  *****************************************************************************/
5 
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <string.h>
9 #include <assert.h>
10 #include <errno.h>
11 
12 #include "hecmw_config.h"
13 #include "hecmw_msgno.h"
14 #include "hecmw_malloc.h"
15 #include "hecmw_error.h"
16 #include "hecmw_comm.h"
17 
18 #include "hecmw_couple_define.h"
19 #include "hecmw_couple_struct.h"
20 #include "hecmw_couple_info.h"
21 #include "hecmw_couple_comm.h"
22 
HECMW_couple_inter_send_recv(int n_neighbor_pe_send,int * neighbor_pe_send,int * sendbuf_index,void * sendbuf,int n_neighbor_pe_recv,int * neighbor_pe_recv,int * recvbuf_index,void * recvbuf,HECMW_Datatype datatype,HECMW_Comm comm)23 extern int HECMW_couple_inter_send_recv(
24     int n_neighbor_pe_send, int *neighbor_pe_send, int *sendbuf_index,
25     void *sendbuf, int n_neighbor_pe_recv, int *neighbor_pe_recv,
26     int *recvbuf_index, void *recvbuf, HECMW_Datatype datatype,
27     HECMW_Comm comm) {
28   HECMW_Request *request_send = NULL, *request_recv = NULL;
29   HECMW_Status *status_send = NULL, *status_recv = NULL;
30   int rtc, i;
31 
32   if (n_neighbor_pe_send > 0) {
33     request_send = (HECMW_Request *)HECMW_calloc(n_neighbor_pe_send,
34                                                  sizeof(HECMW_Request));
35     if (request_send == NULL) {
36       HECMW_set_error(errno, "");
37       goto error;
38     }
39     status_send =
40         (HECMW_Status *)HECMW_calloc(n_neighbor_pe_send, sizeof(HECMW_Status));
41     if (status_send == NULL) {
42       HECMW_set_error(errno, "");
43       goto error;
44     }
45   }
46   if (n_neighbor_pe_recv > 0) {
47     request_recv = (HECMW_Request *)HECMW_calloc(n_neighbor_pe_recv,
48                                                  sizeof(HECMW_Request));
49     if (request_recv == NULL) {
50       HECMW_set_error(errno, "");
51       goto error;
52     }
53     status_recv =
54         (HECMW_Status *)HECMW_calloc(n_neighbor_pe_recv, sizeof(HECMW_Status));
55     if (status_recv == NULL) {
56       HECMW_set_error(errno, "");
57       goto error;
58     }
59   }
60 
61   if (datatype == HECMW_INT) {
62     int *_sendbuf = (int *)sendbuf;
63     int *_recvbuf = (int *)recvbuf;
64 
65     /* send */
66     for (i = 0; i < n_neighbor_pe_send; i++) {
67       rtc = HECMW_Isend(&_sendbuf[sendbuf_index[i]],
68                         sendbuf_index[i + 1] - sendbuf_index[i], HECMW_INT,
69                         neighbor_pe_send[i], 0, comm, &request_send[i]);
70       if (rtc != 0) goto error;
71     }
72 
73     /* receive */
74     for (i = 0; i < n_neighbor_pe_recv; i++) {
75       rtc = HECMW_Irecv(&_recvbuf[recvbuf_index[i]],
76                         recvbuf_index[i + 1] - recvbuf_index[i], HECMW_INT,
77                         neighbor_pe_recv[i], 0, comm, &request_recv[i]);
78       if (rtc != 0) goto error;
79     }
80   } else if (datatype == HECMW_DOUBLE) {
81     double *_sendbuf = (double *)sendbuf;
82     double *_recvbuf = (double *)recvbuf;
83 
84     /* send */
85     for (i = 0; i < n_neighbor_pe_send; i++) {
86       rtc = HECMW_Isend(&_sendbuf[sendbuf_index[i]],
87                         sendbuf_index[i + 1] - sendbuf_index[i], HECMW_DOUBLE,
88                         neighbor_pe_send[i], 0, comm, &request_send[i]);
89       if (rtc != 0) goto error;
90     }
91 
92     /* receive */
93     for (i = 0; i < n_neighbor_pe_recv; i++) {
94       rtc = HECMW_Irecv(&_recvbuf[recvbuf_index[i]],
95                         recvbuf_index[i + 1] - recvbuf_index[i], HECMW_DOUBLE,
96                         neighbor_pe_recv[i], 0, comm, &request_recv[i]);
97       if (rtc != 0) goto error;
98     }
99   } else if (datatype == HECMW_CHAR) {
100     char *_sendbuf = (char *)sendbuf;
101     char *_recvbuf = (char *)recvbuf;
102 
103     /* send */
104     for (i = 0; i < n_neighbor_pe_send; i++) {
105       rtc = HECMW_Isend(&_sendbuf[sendbuf_index[i]],
106                         sendbuf_index[i + 1] - sendbuf_index[i], HECMW_CHAR,
107                         neighbor_pe_send[i], 0, comm, &request_send[i]);
108       if (rtc != 0) goto error;
109     }
110 
111     /* receive */
112     for (i = 0; i < n_neighbor_pe_recv; i++) {
113       rtc = HECMW_Irecv(&_recvbuf[recvbuf_index[i]],
114                         recvbuf_index[i + 1] - recvbuf_index[i], HECMW_CHAR,
115                         neighbor_pe_recv[i], 0, comm, &request_recv[i]);
116       if (rtc != 0) goto error;
117     }
118   } else {
119     HECMW_set_error(HECMWCPL_E_MPI_DATATYPE, "");
120     goto error;
121   }
122 
123   /* wait */
124   if (n_neighbor_pe_recv > 0) {
125     rtc = HECMW_Waitall(n_neighbor_pe_recv, request_recv, status_recv);
126     if (rtc != 0) goto error;
127   }
128 
129   if (n_neighbor_pe_send > 0) {
130     rtc = HECMW_Waitall(n_neighbor_pe_send, request_send, status_send);
131     if (rtc != 0) goto error;
132   }
133 
134   HECMW_free(request_send);
135   HECMW_free(request_recv);
136   HECMW_free(status_send);
137   HECMW_free(status_recv);
138 
139   return 0;
140 
141 error:
142   HECMW_free(request_send);
143   HECMW_free(request_recv);
144   HECMW_free(status_send);
145   HECMW_free(status_recv);
146 
147   return -1;
148 }
149 
HECMW_couple_intra_send_recv(int n_neighbor_pe,int * neighbor_pe,int * sendbuf_index,void * sendbuf,int * recvbuf_index,void * recvbuf,HECMW_Datatype datatype,HECMW_Comm comm)150 extern int HECMW_couple_intra_send_recv(int n_neighbor_pe, int *neighbor_pe,
151                                         int *sendbuf_index, void *sendbuf,
152                                         int *recvbuf_index, void *recvbuf,
153                                         HECMW_Datatype datatype,
154                                         HECMW_Comm comm) {
155   HECMW_Request *request_send = NULL, *request_recv = NULL;
156   HECMW_Status *status_send = NULL, *status_recv = NULL;
157   int rtc, i;
158 
159   if (n_neighbor_pe > 0) {
160     request_send =
161         (HECMW_Request *)HECMW_calloc(n_neighbor_pe, sizeof(HECMW_Request));
162     if (request_send == NULL) {
163       HECMW_set_error(errno, "");
164       goto error;
165     }
166     status_send =
167         (HECMW_Status *)HECMW_calloc(n_neighbor_pe, sizeof(HECMW_Status));
168     if (status_send == NULL) {
169       HECMW_set_error(errno, "");
170       goto error;
171     }
172     request_recv =
173         (HECMW_Request *)HECMW_calloc(n_neighbor_pe, sizeof(HECMW_Request));
174     if (request_recv == NULL) {
175       HECMW_set_error(errno, "");
176       goto error;
177     }
178     status_recv =
179         (HECMW_Status *)HECMW_calloc(n_neighbor_pe, sizeof(HECMW_Status));
180     if (status_recv == NULL) {
181       HECMW_set_error(errno, "");
182       goto error;
183     }
184   }
185 
186   if (datatype == HECMW_INT) {
187     int *_sendbuf = (int *)sendbuf;
188     int *_recvbuf = (int *)recvbuf;
189 
190     /* send */
191     for (i = 0; i < n_neighbor_pe; i++) {
192       rtc = HECMW_Isend(&_sendbuf[sendbuf_index[i]],
193                         sendbuf_index[i + 1] - sendbuf_index[i], datatype,
194                         neighbor_pe[i], 0, comm, &request_send[i]);
195       if (rtc != 0) goto error;
196     }
197 
198     /* receive */
199     for (i = 0; i < n_neighbor_pe; i++) {
200       rtc = HECMW_Irecv(&_recvbuf[recvbuf_index[i]],
201                         recvbuf_index[i + 1] - recvbuf_index[i], datatype,
202                         neighbor_pe[i], 0, comm, &request_recv[i]);
203       if (rtc != 0) goto error;
204     }
205   } else if (datatype == HECMW_DOUBLE) {
206     double *_sendbuf = (double *)sendbuf;
207     double *_recvbuf = (double *)recvbuf;
208 
209     /* send */
210     for (i = 0; i < n_neighbor_pe; i++) {
211       rtc = HECMW_Isend(&_sendbuf[sendbuf_index[i]],
212                         sendbuf_index[i + 1] - sendbuf_index[i], datatype,
213                         neighbor_pe[i], 0, comm, &request_send[i]);
214       if (rtc != 0) goto error;
215     }
216 
217     /* receive */
218     for (i = 0; i < n_neighbor_pe; i++) {
219       rtc = HECMW_Irecv(&_recvbuf[recvbuf_index[i]],
220                         recvbuf_index[i + 1] - recvbuf_index[i], datatype,
221                         neighbor_pe[i], 0, comm, &request_recv[i]);
222       if (rtc != 0) goto error;
223     }
224   } else if (datatype == HECMW_CHAR) {
225     char *_sendbuf = (char *)sendbuf;
226     char *_recvbuf = (char *)recvbuf;
227 
228     /* send */
229     for (i = 0; i < n_neighbor_pe; i++) {
230       rtc = HECMW_Isend(&_sendbuf[sendbuf_index[i]],
231                         sendbuf_index[i + 1] - sendbuf_index[i], datatype,
232                         neighbor_pe[i], 0, comm, &request_send[i]);
233       if (rtc != 0) goto error;
234     }
235 
236     /* receive */
237     for (i = 0; i < n_neighbor_pe; i++) {
238       rtc = HECMW_Irecv(&_recvbuf[recvbuf_index[i]],
239                         recvbuf_index[i + 1] - recvbuf_index[i], datatype,
240                         neighbor_pe[i], 0, comm, &request_recv[i]);
241       if (rtc != 0) goto error;
242     }
243   } else {
244     HECMW_set_error(HECMWCPL_E_MPI_DATATYPE, "");
245     goto error;
246   }
247 
248   /* wait */
249   if (n_neighbor_pe > 0) {
250     rtc = HECMW_Waitall(n_neighbor_pe, request_recv, status_recv);
251     if (rtc != 0) goto error;
252   }
253 
254   if (n_neighbor_pe > 0) {
255     rtc = HECMW_Waitall(n_neighbor_pe, request_send, status_send);
256     if (rtc != 0) goto error;
257   }
258 
259   HECMW_free(request_send);
260   HECMW_free(request_recv);
261   HECMW_free(status_send);
262   HECMW_free(status_recv);
263 
264   return 0;
265 
266 error:
267   HECMW_free(request_send);
268   HECMW_free(request_recv);
269   HECMW_free(status_send);
270   HECMW_free(status_recv);
271 
272   return -1;
273 }
274 
HECMW_couple_bcast(int n_neighbor_pe_send,int * neighbor_pe_send,int sendbuf_size,void * sendbuf,int n_neighbor_pe_recv,int * neighbor_pe_recv,int * recvbuf_index,void * recvbuf,HECMW_Datatype datatype,HECMW_Comm comm)275 extern int HECMW_couple_bcast(int n_neighbor_pe_send, int *neighbor_pe_send,
276                               int sendbuf_size, void *sendbuf,
277                               int n_neighbor_pe_recv, int *neighbor_pe_recv,
278                               int *recvbuf_index, void *recvbuf,
279                               HECMW_Datatype datatype, HECMW_Comm comm) {
280   HECMW_Request *request_send = NULL, *request_recv = NULL;
281   HECMW_Status *status_send = NULL, *status_recv = NULL;
282   int rtc, i;
283 
284   if (n_neighbor_pe_send > 0) {
285     request_send = (HECMW_Request *)HECMW_calloc(n_neighbor_pe_send,
286                                                  sizeof(HECMW_Request));
287     if (request_send == NULL) {
288       HECMW_set_error(errno, "");
289       goto error;
290     }
291     status_send =
292         (HECMW_Status *)HECMW_calloc(n_neighbor_pe_send, sizeof(HECMW_Status));
293     if (status_send == NULL) {
294       HECMW_set_error(errno, "");
295       goto error;
296     }
297   }
298   if (n_neighbor_pe_recv > 0) {
299     request_recv = (HECMW_Request *)HECMW_calloc(n_neighbor_pe_recv,
300                                                  sizeof(HECMW_Request));
301     if (request_recv == NULL) {
302       HECMW_set_error(errno, "");
303       goto error;
304     }
305     status_recv =
306         (HECMW_Status *)HECMW_calloc(n_neighbor_pe_recv, sizeof(HECMW_Status));
307     if (status_recv == NULL) {
308       HECMW_set_error(errno, "");
309       goto error;
310     }
311   }
312 
313   if (datatype == HECMW_INT) {
314     int *_sendbuf = (int *)sendbuf;
315     int *_recvbuf = (int *)recvbuf;
316 
317     /* send */
318     for (i = 0; i < n_neighbor_pe_send; i++) {
319       rtc = HECMW_Isend(&_sendbuf[0], sendbuf_size, datatype,
320                         neighbor_pe_send[i], 0, comm, &request_send[i]);
321       if (rtc != 0) goto error;
322     }
323 
324     /* receive */
325     for (i = 0; i < n_neighbor_pe_recv; i++) {
326       rtc = HECMW_Irecv(&_recvbuf[recvbuf_index[i]],
327                         recvbuf_index[i + 1] - recvbuf_index[i], datatype,
328                         neighbor_pe_recv[i], 0, comm, &request_recv[i]);
329       if (rtc != 0) goto error;
330     }
331   } else if (datatype == HECMW_DOUBLE) {
332     double *_sendbuf = (double *)sendbuf;
333     double *_recvbuf = (double *)recvbuf;
334 
335     /* send */
336     for (i = 0; i < n_neighbor_pe_send; i++) {
337       rtc = HECMW_Isend(&_sendbuf[0], sendbuf_size, datatype,
338                         neighbor_pe_send[i], 0, comm, &request_send[i]);
339       if (rtc != 0) goto error;
340     }
341 
342     /* receive */
343     for (i = 0; i < n_neighbor_pe_recv; i++) {
344       rtc = HECMW_Irecv(&_recvbuf[recvbuf_index[i]],
345                         recvbuf_index[i + 1] - recvbuf_index[i], datatype,
346                         neighbor_pe_recv[i], 0, comm, &request_recv[i]);
347       if (rtc != 0) goto error;
348     }
349   } else if (datatype == HECMW_CHAR) {
350     char *_sendbuf = (char *)sendbuf;
351     char *_recvbuf = (char *)recvbuf;
352 
353     /* send */
354     for (i = 0; i < n_neighbor_pe_send; i++) {
355       rtc = HECMW_Isend(&_sendbuf[0], sendbuf_size, datatype,
356                         neighbor_pe_send[i], 0, comm, &request_send[i]);
357       if (rtc != 0) goto error;
358     }
359 
360     /* receive */
361     for (i = 0; i < n_neighbor_pe_recv; i++) {
362       rtc = HECMW_Irecv(&_recvbuf[recvbuf_index[i]],
363                         recvbuf_index[i + 1] - recvbuf_index[i], datatype,
364                         neighbor_pe_recv[i], 0, comm, &request_recv[i]);
365       if (rtc != 0) goto error;
366     }
367   } else {
368     HECMW_set_error(HECMWCPL_E_MPI_DATATYPE, "");
369     goto error;
370   }
371 
372   /* wait */
373   if (n_neighbor_pe_recv > 0) {
374     rtc = HECMW_Waitall(n_neighbor_pe_recv, request_recv, status_recv);
375     if (rtc != 0) goto error;
376   }
377   if (n_neighbor_pe_send > 0) {
378     rtc = HECMW_Waitall(n_neighbor_pe_send, request_send, status_send);
379     if (rtc != 0) goto error;
380   }
381 
382   HECMW_free(request_send);
383   HECMW_free(request_recv);
384   HECMW_free(status_send);
385   HECMW_free(status_recv);
386 
387   return 0;
388 
389 error:
390   HECMW_free(request_send);
391   HECMW_free(request_recv);
392   HECMW_free(status_send);
393   HECMW_free(status_recv);
394   return -1;
395 }
396 #if 0
397 /*================================================================================================*/
398 
399 static int
400 send_recv_r2r_int(const struct hecmw_couple_comm *comm_src,
401 		const struct hecmw_couple_comm *comm_dst, int *buffer, int count)
402 {
403 	int n_pe_send = 0, n_pe_recv = 0, *pe_send = NULL, *pe_recv = NULL;
404 	int *sendbuf_index = NULL, *recvbuf_index = NULL, *sendbuf = NULL, *recvbuf = NULL;
405 	int size, rtc, i;
406 
407 	if(comm_src->is_root) {
408 		n_pe_send = 1;
409 
410 		pe_send = (int *)HECMW_malloc(sizeof(int)*n_pe_send);
411 		if(pe_send == NULL) {
412 			HECMW_set_error(errno, "");
413 			goto error;
414 		}
415 		pe_send[0] = comm_dst->root;
416 
417 		sendbuf_index = (int *)HECMW_calloc(n_pe_send+1, sizeof(int));
418 		if(sendbuf_index == NULL) {
419 			HECMW_set_error(errno, "");
420 			goto error;
421 		}
422 		sendbuf_index[1] = count;
423 
424 		sendbuf = (int *)HECMW_malloc(sizeof(int)*sendbuf_index[1]);
425 		if(sendbuf == NULL) {
426 			HECMW_set_error(errno, "");
427 			goto error;
428 		}
429 		for(i=0; i<sendbuf_index[1]; i++) {
430 			sendbuf[i] = buffer[i];
431 		}
432 	}
433 
434 	if(comm_dst->is_root) {
435 		n_pe_recv = 1;
436 
437 		pe_recv = (int *)HECMW_malloc(sizeof(int)*n_pe_recv);
438 		if(pe_recv == NULL) {
439 			HECMW_set_error(errno, "");
440 			goto error;
441 		}
442 		pe_recv[0] = comm_src->root;
443 
444 		recvbuf_index = (int *)HECMW_calloc(n_pe_recv+1, sizeof(int));
445 		if(recvbuf_index == NULL) {
446 			HECMW_set_error(errno, "");
447 			goto error;
448 		}
449 		recvbuf_index[1] = count;
450 
451 		recvbuf = (int *)HECMW_malloc(sizeof(int)*recvbuf_index[1]);
452 		if(recvbuf == NULL) {
453 			HECMW_set_error(errno, "");
454 			goto error;
455 		}
456 	}
457 
458 	rtc = HECMW_couple_inter_send_recv(n_pe_send, pe_send, sendbuf_index, sendbuf,
459 			n_pe_recv, pe_recv, recvbuf_index, recvbuf, HECMW_INT, HECMW_comm_get_comm());
460 	if(rtc) goto error;
461 
462 	if(comm_dst->is_root) {
463 		memcpy(buffer, recvbuf, size);
464 	}
465 return 0;
466 	HECMW_free(pe_send);
467 	HECMW_free(sendbuf_index);
468 	HECMW_free(sendbuf);
469 	HECMW_free(pe_recv);
470 	HECMW_free(recvbuf_index);
471 	HECMW_free(recvbuf);
472 	return 0;
473 
474 error:
475 	HECMW_free(pe_send);
476 	HECMW_free(sendbuf_index);
477 	HECMW_free(sendbuf);
478 	HECMW_free(pe_recv);
479 	HECMW_free(recvbuf_index);
480 	HECMW_free(recvbuf);
481 	return -1;
482 }
483 #endif
484 #if 0
485 
486 extern int
487 HECMW_couple_inter_bcast(char *boundary_id, void *sendbuf, int sendcount,
488 		void **recvbuf, int recvcount, HECMW_Datatype datatype, int direction)
489 {
490 	struct hecmw_couple_comm *comm_src = NULL, *comm_dst = NULL, *intercomm = NULL;
491 	int rtc, i;
492 
493 	if((intercomm = HECMW_couple_get_intercomm(boundary_id)) == NULL) goto error;
494 
495 	if(direction == HECMW_COUPLE_UNIT1_TO_UNIT2) {
496 		comm_src = HECMW_couple_get_intracomm(boundary_id, HECMW_COUPLE_UNIT1);
497 		comm_dst = HECMW_couple_get_intracomm(boundary_id, HECMW_COUPLE_UNIT2);
498 	} else if(direction == HECMW_COUPLE_UNIT2_TO_UNIT1) {
499 		comm_src = HECMW_couple_get_intracomm(boundary_id, HECMW_COUPLE_UNIT2);
500 		comm_dst = HECMW_couple_get_intracomm(boundary_id, HECMW_COUPLE_UNIT1);
501 	} else {
502 		HECMW_set_error(HECMWCPL_E_INVALID_DIRECTION, "");
503 		goto error;
504 	}
505 	if(comm_src == NULL || comm_dst == NULL) goto error;
506 
507 	if(datatype == HECMW_INT) {
508 		int n_src = 0, n_dst = 0, *src = NULL, *dst = NULL;
509 		int *_sendbuf = (int *)sendbuf;
510 		int *sendindex = NULL, *recvindex = NULL;
511 		int _recvcount, *_recvbuf = NULL;
512 
513 		if(comm_src->is_root) {
514 			n_dst = 1;
515 
516 			dst = (int *)HECMW_malloc(sizeof(int)*n_dst);
517 			if(dst == NULL) {
518 				HECMW_set_error(errno, "");
519 				goto error;
520 			}
521 			dst[0] = comm_dst->root;
522 
523 			sendindex = (int *)HECMW_calloc(n_dst+1, sizeof(int));
524 			if(sendindex == NULL) {
525 				HECMW_set_error(errno, "");
526 				goto error;
527 			}
528 			sendindex[0] = 0;
529 			sendindex[1] = 1;
530 
531 			_sendbuf = (int *)HECMW_malloc(sizeof(int)*sendindex[n_dst]);
532 			if(_sendbuf == NULL) {
533 				HECMW_set_error(errno, "");
534 				goto error;
535 			}
536 			_sendbuf[0] = sendcount;
537 		}
538 
539 		if(comm_dst->is_root) {
540 			n_src = 1;
541 
542 			src = (int *)HECMW_malloc(sizeof(int)*n_src);
543 			if(src == NULL) {
544 				HECMW_set_error(errno, "");
545 				goto error;
546 			}
547 			src[0] = comm_src->root;
548 
549 			recvindex = (int *)HECMW_calloc(n_src+1, sizeof(int));
550 			if(recvindex == NULL) {
551 				HECMW_set_error(errno, "");
552 				goto error;
553 			}
554 			recvindex[0] = 0;
555 			recvindex[1] = 1;
556 
557 			_recvbuf = (int *)HECMW_malloc(sizeof(int)*recvindex[n_src]);
558 			if(_recvbuf == NULL) {
559 				HECMW_set_error(errno, "");
560 				goto error;
561 			}
562 		}
563 
564 		rtc = HECMW_couple_inter_send_recv(n_dst, dst, sendindex, _sendbuf,
565 				n_src, src, recvindex, _recvbuf, HECMW_INT, intercomm->comm);
566 		if(rtc) goto error;
567 
568 		if(comm_dst->is_root) {
569 			recvcount = _recvbuf[0];
570 		}
571 
572 		HECMW_free(_sendbuf);
573 		HECMW_free(sendindex);
574 		HECMW_free(_recvbuf);
575 		HECMW_free(recvindex);
576 		_sendbuf = NULL;
577 		sendindex = NULL;
578 		_recvbuf = NULL;
579 		recvindex = NULL;
580 
581 
582 		if(comm_src->is_root) {
583 			n_dst = 1;
584 
585 			dst = (int *)HECMW_malloc(sizeof(int)*n_dst);
586 			if(dst == NULL) {
587 				HECMW_set_error(errno, "");
588 				goto error;
589 			}
590 			dst[0] = comm_dst->root;
591 
592 			sendindex = (int *)HECMW_calloc(n_dst+1, sizeof(int));
593 			if(sendindex == NULL) {
594 				HECMW_set_error(errno, "");
595 				goto error;
596 			}
597 			sendindex[1] = sendcount;
598 
599 			_sendbuf = (int *)HECMW_malloc(sizeof(int)*sendindex[n_dst]+1);
600 			if(_sendbuf == NULL) {
601 				HECMW_set_error(errno, "");
602 				goto error;
603 			}
604 			for(i=0; i<sendindex[n_dst]; i++) {
605 				_sendbuf[i] = sendbuf[i];
606 			}
607 		}
608 
609 		if(comm_dst->is_root) {
610 			n_src = 1;
611 
612 			src = (int *)HECMW_malloc(sizeof(int)*n_src);
613 			if(src == NULL) {
614 				HECMW_set_error(errno, "");
615 				goto error;
616 			}
617 			src[0] = comm_src->root;
618 
619 			recvindex = (int *)HECMW_calloc(n_src+1, sizeof(int));
620 			if(recvindex == NULL) {
621 				HECMW_set_error(errno, "");
622 				goto error;
623 			}
624 			recvindex[1] = recvcount;
625 
626 			_recvbuf = (int *)HECMW_malloc(sizeof(int)*recvindex[n_src]);
627 			if(_recvbuf == NULL) {
628 				HECMW_set_error(errno, "");
629 				goto error;
630 			}
631 		}
632 
633 		rtc = HECMW_couple_inter_send_recv(n_dst, dst, sendindex, _sendbuf,
634 				n_src, src, recvindex, _recvbuf, HECMW_INT, intercomm->comm);
635 		if(rtc) goto error;
636 
637 		if(comm_dst->is_member) {
638 			if(HECMW_Bcast(recvcount, 1, HECMW_INT, 0,  comm_dst->comm)) goto error;
639 
640 			recvbuf = HECMW_malloc(sizeof(int)*recvcount);
641 			if(recvbuf == NULL) {
642 				HECMW_set_error(errno, "");
643 				goto error;
644 			}
645 
646 			if(comm_dst->is_root) {
647 				for(i=0; i<recvcount; i++) {
648 					recvbuf[i] = _recvbuf[i];
649 				}
650 			}
651 			if(HECMW_Bcast(recvbuf, recvcount, HECMW_INT, 0, comm_dst->comm)) goto error;
652 		}
653 	}
654 
655 	return 0;
656 
657 error:
658 	HECMW_couple_free_comm(intercomm);
659 	HECMW_couple_free_comm(comm_src);
660 	HECMW_couple_free_comm(comm_dst);
661 	return -1;
662 }
663 
664 
665 
666 extern int
667 HECMW_couple_inter_barrier(const char *boundary_id)
668 {
669 	struct hecmw_couple_comm *intercomm = NULL;
670 	int rtc;
671 
672 	if((intercomm = HECMW_couple_get_intercomm(boundary_id)) == NULL) return -1;
673 
674 	rtc = HECMW_Barrier(intercomm->comm);
675 	if(rtc != HECMW_SUCCESS) goto error;
676 
677 	HECMW_couple_free_comm(intercomm);
678 
679 	return 0;
680 
681 error:
682 	HECMW_couple_free_comm(intercomm);
683 	return -1;
684 }
685 #endif
686