FrontISTR 5.2.0
Large-scale structural analysis program with finit element method
Loading...
Searching...
No Matches
hecmw_couple_inter_iftable.c
Go to the documentation of this file.
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_struct.h"
13#include "hecmw_msgno.h"
14#include "hecmw_common_define.h"
15#include "hecmw_error.h"
16#include "hecmw_comm.h"
17
18#include "hecmw_couple_comm.h"
19#include "hecmw_couple_define.h"
20#include "hecmw_couple_struct.h"
21#include "hecmw_couple_judge.h"
27
28#define MAX_NODE_SIZE 20
29
30#define INFINITE (1.0E+37)
31
32#define EPS (1.0E-06)
33
35 int n_node;
36
37 double *coord;
38};
39
40struct map_info {
41 int n;
42
43 int *id;
44
46
47 double *dot_product;
48
49 double *distance;
50};
51
52struct link_list {
53 int item;
54 struct link_list *next;
55};
56
58 int n;
59 struct link_list *list;
60};
61
63 int *index;
64 int *id;
65};
66
68 int n;
69 int *index;
70 int *pe;
71 int *id;
72};
73
75 int id;
76 int item;
78};
79
80/*================================================================================================*/
81
82static void free_link_list(struct link_list *r) {
83 struct link_list *p, *q;
84
85 p = r;
86 while (p) {
87 q = p->next;
88 HECMW_free(p);
89 p = q;
90 }
91 r = NULL;
92}
93
94static void free_link_list_map(struct link_list_map *r) {
95 struct link_list_map *p, *q;
96
97 p = r;
98 while (p) {
99 q = p->next;
100 HECMW_free(p);
101 p = q;
102 }
103 r = NULL;
104}
105
106static struct map_info *alloc_struct_map_info(void) {
107 struct map_info *p = NULL;
108
109 p = (struct map_info *)HECMW_malloc(sizeof(struct map_info));
110 if (p == NULL) {
111 HECMW_set_error(errno, "");
112 return NULL;
113 }
114
115 p->n = 0;
116 p->id = NULL;
117 p->n_positive = NULL;
118 p->dot_product = NULL;
119 p->distance = NULL;
120
121 return p;
122}
123
124static void free_struct_map_info(struct map_info *p) {
125 if (p == NULL) return;
126
127 HECMW_free(p->id);
131 HECMW_free(p);
132 p = NULL;
133}
134
136 struct hecmw_couple_inter_iftable *p) {
137 if (p == NULL) return;
138
145 HECMW_free(p);
146 p = NULL;
147}
148
150 void) {
152 int size;
153
154 size = sizeof(struct hecmw_couple_inter_iftable);
155 p = (struct hecmw_couple_inter_iftable *)HECMW_malloc(size);
156 if (p == NULL) {
157 HECMW_set_error(errno, "");
158 return NULL;
159 }
160
163 p->import_index = NULL;
164 p->import_item = NULL;
167 p->export_index = NULL;
168 p->export_item = NULL;
169
170 return p;
171}
172
174 const struct hecmw_couple_inter_iftable *p, FILE *fp) {
175 int i, j;
176
177 fprintf(fp, "*** Interface Table for Inter-communication\n");
178
179 fprintf(fp, "number of neighbor processes for import: %d\n",
181 fprintf(fp, "neighbor processes for import:\n");
182 for (i = 0; i < p->n_neighbor_pe_import; i++) {
183 fprintf(fp, "%d%c", p->neighbor_pe_import[i], (i + 1) % 10 ? ' ' : '\n');
184 }
185 if (i % 10) fprintf(fp, "\n");
186
187 fprintf(fp, "number of neighbor processes for export: %d\n",
189 fprintf(fp, "neighbor processes for export:\n");
190 for (i = 0; i < p->n_neighbor_pe_export; i++) {
191 fprintf(fp, "%d%c", p->neighbor_pe_export[i], (i + 1) % 10 ? ' ' : '\n');
192 }
193 if (i % 10) fprintf(fp, "\n");
194
195 fprintf(fp, "import index:\n");
196 for (i = 0; i < p->n_neighbor_pe_import; i++) {
197 fprintf(fp, "%d%c", p->import_index[i], (i + 1) % 10 ? ' ' : '\n');
198 }
199 if (i % 10) fprintf(fp, "\n");
200
201 fprintf(fp, "import item:\n");
202 for (i = 0; i < p->n_neighbor_pe_import; i++) {
203 for (j = p->import_index[i]; j < p->import_index[i + 1]; j++) {
204 fprintf(fp, "%d%c", p->import_item[j], (j + 1) % 10 ? ' ' : '\n');
205 }
206 }
207 if (j % 10) fprintf(fp, "\n");
208
209 fprintf(fp, "export index:\n");
210 for (i = 0; i < p->n_neighbor_pe_export; i++) {
211 fprintf(fp, "%d%c", p->export_index[i], (i + 1) % 10 ? ' ' : '\n');
212 }
213 if (i % 10) fprintf(fp, "\n");
214
215 fprintf(fp, "export item:\n");
216 for (i = 0; i < p->n_neighbor_pe_export; i++) {
217 for (j = p->export_index[i]; j < p->export_index[i + 1]; j++) {
218 fprintf(fp, "%d%c", p->export_item[j], (j + 1) % 10 ? ' ' : '\n');
219 }
220 }
221 if (j % 10) fprintf(fp, "\n");
222}
223
224/*================================================================================================*/
225
226static int bcast_mapped_point_d2s_n(
227 const struct hecmw_couple_mapped_point *mapped_point,
228 const struct hecmw_couple_comm *comm_src,
229 const struct hecmw_couple_comm *comm_dst,
230 const struct hecmw_couple_comm *intercomm,
231 struct hecmw_couple_mapped_point **all_mapped_point) {
232 int n_pe_send = 0, n_pe_recv = 0, *pe_send = NULL, *pe_recv = NULL;
233 int sendbuf_size = 0, *recvbuf_index = NULL, *sendbuf = NULL, *recvbuf = NULL;
234 int rtc, i;
235
236 /*
237 * send buffer (destination unit)
238 */
239 if (comm_dst->is_member) {
240 /* number of communication processes */
241 n_pe_send = comm_src->psize;
242
243 /* communication processes */
244 pe_send = (int *)HECMW_malloc(sizeof(int) * n_pe_send);
245 if (pe_send == NULL) {
246 HECMW_set_error(errno, "");
247 goto error;
248 }
249 for (i = 0; i < n_pe_send; i++) {
250 pe_send[i] = comm_src->ranks[i];
251 }
252
253 /* size of send buffer */
254 sendbuf_size = 1;
255
256 /* send buffer */
257 sendbuf = (int *)HECMW_malloc(sizeof(int) * (sendbuf_size + 1));
258 if (sendbuf == NULL) {
259 HECMW_set_error(errno, "");
260 goto error;
261 }
262 sendbuf[0] = mapped_point->n;
263 }
264
265 /*
266 * receive buffer (source unit)
267 */
268 if (comm_src->is_member) {
269 /* number of communication processes */
270 n_pe_recv = comm_dst->psize;
271
272 /* communication processes */
273 pe_recv = (int *)HECMW_malloc(sizeof(int) * n_pe_recv);
274 if (pe_recv == NULL) {
275 HECMW_set_error(errno, "");
276 goto error;
277 }
278 for (i = 0; i < n_pe_recv; i++) {
279 pe_recv[i] = comm_dst->ranks[i];
280 }
281
282 /* size of receive buffer */
283 recvbuf_index = (int *)HECMW_calloc(n_pe_recv + 1, sizeof(int));
284 if (recvbuf_index == NULL) {
285 HECMW_set_error(errno, "");
286 goto error;
287 }
288 for (i = 0; i < n_pe_recv; i++) {
289 recvbuf_index[i + 1] = recvbuf_index[i] + 1;
290 }
291
292 /* receive buffer */
293 recvbuf = (int *)HECMW_calloc(recvbuf_index[n_pe_recv] + 1, sizeof(int));
294 if (recvbuf == NULL) {
295 HECMW_set_error(errno, "");
296 goto error;
297 }
298 }
299
300 /*
301 * broadcasting
302 */
303 rtc = HECMW_couple_bcast(n_pe_send, pe_send, sendbuf_size, sendbuf, n_pe_recv,
304 pe_recv, recvbuf_index, recvbuf, HECMW_INT,
305 intercomm->comm);
306 if (rtc != 0) goto error;
307
308 if (comm_src->is_member) {
309 for (i = 0; i < comm_dst->psize; i++) {
310 all_mapped_point[i]->n = recvbuf[i];
311 }
312 }
313
314 HECMW_free(sendbuf);
315 HECMW_free(pe_send);
316 HECMW_free(recvbuf_index);
317 HECMW_free(recvbuf);
318 HECMW_free(pe_recv);
319 return 0;
320
321error:
322 HECMW_free(sendbuf);
323 HECMW_free(pe_send);
324 HECMW_free(recvbuf_index);
325 HECMW_free(recvbuf);
326 HECMW_free(pe_recv);
327 return -1;
328}
329
330static int bcast_mapped_point_d2s_coord(
331 const struct hecmw_couple_mapped_point *mapped_point,
332 const struct hecmw_couple_comm *comm_src,
333 const struct hecmw_couple_comm *comm_dst,
334 const struct hecmw_couple_comm *intercomm,
335 struct hecmw_couple_mapped_point **all_mapped_point) {
336 int n_pe_send = 0, n_pe_recv = 0, *pe_send = NULL, *pe_recv = NULL;
337 int sendbuf_size = 0, *recvbuf_index = NULL;
338 double *sendbuf = NULL, *recvbuf = NULL;
339 int node, size, rtc, i, j;
340
341 /*
342 * send buffer (destination unit)
343 */
344 if (comm_dst->is_member) {
345 /* number of communication processes */
346 n_pe_send = comm_src->psize;
347
348 /* communication processes */
349 pe_send = (int *)HECMW_malloc(sizeof(int) * n_pe_send);
350 if (pe_send == NULL) {
351 HECMW_set_error(errno, "");
352 goto error;
353 }
354 for (i = 0; i < n_pe_send; i++) {
355 pe_send[i] = comm_src->ranks[i];
356 }
357
358 /* size of send buffer */
359 sendbuf_size = mapped_point->n * 3;
360
361 /* send buffer */
362 sendbuf = (double *)HECMW_malloc(sizeof(double) * (sendbuf_size + 1));
363 if (sendbuf == NULL) {
364 HECMW_set_error(errno, "");
365 goto error;
366 }
367 for (i = 0; i < mapped_point->n * 3; i++) {
368 sendbuf[i] = mapped_point->coord[i];
369 }
370 }
371
372 /*
373 * receive buffer (source unit)
374 */
375 if (comm_src->is_member) {
376 /* number of communication processes */
377 n_pe_recv = comm_dst->psize;
378
379 /* communication processes */
380 pe_recv = (int *)HECMW_malloc(sizeof(int) * n_pe_recv);
381 if (pe_recv == NULL) {
382 HECMW_set_error(errno, "");
383 goto error;
384 }
385 for (i = 0; i < n_pe_recv; i++) {
386 pe_recv[i] = comm_dst->ranks[i];
387 }
388
389 /* size of receive buffer */
390 recvbuf_index = (int *)HECMW_calloc(n_pe_recv + 1, sizeof(int));
391 if (recvbuf_index == NULL) {
392 HECMW_set_error(errno, "");
393 goto error;
394 }
395 for (i = 0; i < n_pe_recv; i++) {
396 recvbuf_index[i + 1] = recvbuf_index[i] + all_mapped_point[i]->n * 3;
397 }
398
399 /* receive buffer */
400 recvbuf =
401 (double *)HECMW_malloc(sizeof(double) * (recvbuf_index[n_pe_recv] + 1));
402 if (recvbuf == NULL) {
403 HECMW_set_error(errno, "");
404 goto error;
405 }
406 }
407
408 /* broadcast */
409 rtc = HECMW_couple_bcast(n_pe_send, pe_send, sendbuf_size, sendbuf, n_pe_recv,
410 pe_recv, recvbuf_index, recvbuf, HECMW_DOUBLE,
411 intercomm->comm);
412 if (rtc != 0) goto error;
413
414 /* coordinates */
415 if (comm_src->is_member) {
416 for (i = 0; i < comm_dst->psize; i++) {
417 size = recvbuf_index[i + 1] - recvbuf_index[i];
418 HECMW_assert(size == all_mapped_point[i]->n * 3);
419 if (size == 0) continue;
420
421 all_mapped_point[i]->coord =
422 (double *)HECMW_malloc(sizeof(double) * size);
423 if (all_mapped_point[i]->coord == NULL) {
424 HECMW_set_error(errno, "");
425 goto error;
426 }
427
428 for (j = recvbuf_index[i]; j < recvbuf_index[i + 1]; j++) {
429 all_mapped_point[i]->coord[j - recvbuf_index[i]] = recvbuf[j];
430 }
431 }
432 }
433
434 HECMW_free(sendbuf);
435 HECMW_free(pe_send);
436 HECMW_free(recvbuf_index);
437 HECMW_free(recvbuf);
438 HECMW_free(pe_recv);
439 return 0;
440
441error:
442 HECMW_free(sendbuf);
443 HECMW_free(pe_send);
444 HECMW_free(recvbuf_index);
445 HECMW_free(recvbuf);
446 HECMW_free(pe_recv);
447
448 return -1;
449}
450
451static int bcast_mapped_point_d2s(
452 const struct hecmw_couple_mapped_point *mapped_point,
453 const struct hecmw_couple_comm *comm_src,
454 const struct hecmw_couple_comm *comm_dst,
455 const struct hecmw_couple_comm *intercomm,
456 struct hecmw_couple_mapped_point **all_mapped_point) {
457 int rtc, i;
458
459 if (comm_src->is_member) {
460 for (i = 0; i < comm_dst->psize; i++) {
461 all_mapped_point[i] = HECMW_couple_alloc_mapped_point();
462 if (all_mapped_point[i] == NULL) goto error;
463 }
464 }
465
466 if (bcast_mapped_point_d2s_n(mapped_point, comm_src, comm_dst, intercomm,
467 all_mapped_point))
468 goto error;
469 if (bcast_mapped_point_d2s_coord(mapped_point, comm_src, comm_dst, intercomm,
470 all_mapped_point))
471 goto error;
472
473 return 0;
474
475error:
476 if (all_mapped_point) {
477 for (i = 0; i < comm_dst->psize; i++) {
478 HECMW_couple_free_mapped_point(all_mapped_point[i]);
479 all_mapped_point[i] = NULL;
480 }
481 }
482 return -1;
483}
484
485/*================================================================================================*/
486
487static int bcast_bbox_d2s(const struct hecmw_couple_bounding_box *bbox_dst,
488 const struct hecmw_couple_comm *comm_src,
489 const struct hecmw_couple_comm *comm_dst,
490 const struct hecmw_couple_comm *intercomm,
491 struct hecmw_couple_box *all_dst_bbox) {
492 int n_pe_send = 0, n_pe_recv = 0, *pe_send = NULL, *pe_recv = NULL;
493 int sendbuf_size = 0, *recvbuf_index = NULL;
494 double *sendbuf = NULL, *recvbuf = NULL;
495 int rtc, i;
496 int N_BOUNDING_BOX_MEMBER = 6;
497
498 /*
499 * send buffer (destination unit)
500 */
501 if (comm_dst->is_member) {
502 /* number of neighboring processes */
503 n_pe_send = comm_src->psize;
504
505 /* neighboring processes */
506 pe_send = (int *)HECMW_malloc(sizeof(int) * n_pe_send);
507 if (pe_send == NULL) {
508 HECMW_set_error(errno, "");
509 goto error;
510 }
511 for (i = 0; i < n_pe_send; i++) {
512 pe_send[i] = comm_src->ranks[i];
513 }
514
515 /* size of send buffer */
516 sendbuf_size = N_BOUNDING_BOX_MEMBER;
517
518 /* send buffer */
519 sendbuf = (double *)HECMW_malloc(sizeof(double) * (sendbuf_size + 1));
520 if (sendbuf == NULL) {
521 HECMW_set_error(errno, "");
522 goto error;
523 }
524
525 sendbuf[0] = bbox_dst->enlarged->min_x;
526 sendbuf[1] = bbox_dst->enlarged->min_y;
527 sendbuf[2] = bbox_dst->enlarged->min_z;
528 sendbuf[3] = bbox_dst->enlarged->max_x;
529 sendbuf[4] = bbox_dst->enlarged->max_y;
530 sendbuf[5] = bbox_dst->enlarged->max_z;
531 }
532
533 /*
534 * receive buffer (source unit)
535 */
536 if (comm_src->is_member) {
537 /* number of communication processes */
538 n_pe_recv = comm_dst->psize;
539
540 /* communication processes */
541 pe_recv = (int *)HECMW_malloc(sizeof(int) * n_pe_recv);
542 if (pe_recv == NULL) {
543 HECMW_set_error(errno, "");
544 goto error;
545 }
546 for (i = 0; i < n_pe_recv; i++) {
547 pe_recv[i] = comm_dst->ranks[i];
548 }
549
550 /* size of receive buffer */
551 recvbuf_index = (int *)HECMW_calloc(n_pe_recv + 1, sizeof(int));
552 if (recvbuf_index == NULL) {
553 HECMW_set_error(errno, "");
554 goto error;
555 }
556 for (i = 0; i < n_pe_recv; i++) {
557 recvbuf_index[i + 1] = recvbuf_index[i] + N_BOUNDING_BOX_MEMBER;
558 }
559
560 /* receive buffer */
561 recvbuf =
562 (double *)HECMW_malloc(sizeof(double) * (recvbuf_index[n_pe_recv] + 1));
563 if (recvbuf == NULL) {
564 HECMW_set_error(errno, "");
565 goto error;
566 }
567 }
568
569 /*
570 * send and receive
571 */
572 rtc = HECMW_couple_bcast(n_pe_send, pe_send, sendbuf_size, sendbuf, n_pe_recv,
573 pe_recv, recvbuf_index, recvbuf, HECMW_DOUBLE,
574 intercomm->comm);
575 if (rtc != 0) goto error;
576
577 /*
578 * set received items
579 */
580 if (comm_src->is_member) {
581 for (i = 0; i < comm_dst->psize; i++) {
582 HECMW_assert(recvbuf_index[i + 1] - recvbuf_index[i] ==
583 N_BOUNDING_BOX_MEMBER);
584
585 all_dst_bbox[i].min_x = recvbuf[recvbuf_index[i]];
586 all_dst_bbox[i].min_y = recvbuf[recvbuf_index[i] + 1];
587 all_dst_bbox[i].min_z = recvbuf[recvbuf_index[i] + 2];
588 all_dst_bbox[i].max_x = recvbuf[recvbuf_index[i] + 3];
589 all_dst_bbox[i].max_y = recvbuf[recvbuf_index[i] + 4];
590 all_dst_bbox[i].max_z = recvbuf[recvbuf_index[i] + 5];
591 }
592 }
593
594 HECMW_free(sendbuf);
595 HECMW_free(pe_send);
596 HECMW_free(recvbuf_index);
597 HECMW_free(recvbuf);
598 HECMW_free(pe_recv);
599 return 0;
600
601error:
602 HECMW_free(sendbuf);
603 HECMW_free(pe_send);
604 HECMW_free(recvbuf_index);
605 HECMW_free(recvbuf);
606 HECMW_free(pe_recv);
607 return -1;
608}
609
610/*------------------------------------------------------------------------------------------------*/
611
612static int check_bbox_within_bbox(const struct hecmw_couple_box *box_src,
613 const struct hecmw_couple_box *box_dst) {
614 if (box_dst->min_x <= box_src->max_x && box_dst->max_x >= box_src->min_x &&
615 box_dst->min_y <= box_src->max_y && box_dst->max_y >= box_src->min_y &&
616 box_dst->min_z <= box_src->max_z && box_dst->max_z >= box_src->min_z) {
617 return 1;
618 }
619
620 return 0;
621}
622
623static int check_node_within_bbox(
624 const struct hecmw_couple_box *box_src,
625 const struct hecmw_couple_mapped_point *mapped_point, int *is_candidate) {
626 double coord_x, coord_y, coord_z;
627 int n, i;
628
629 for (n = 0, i = 0; i < mapped_point->n; i++) {
630 coord_x = mapped_point->coord[3 * i];
631 coord_y = mapped_point->coord[3 * i + 1];
632 coord_z = mapped_point->coord[3 * i + 2];
633
634 if (coord_x >= box_src->min_x && coord_x <= box_src->max_x &&
635 coord_y >= box_src->min_y && coord_y <= box_src->max_y &&
636 coord_z >= box_src->min_z && coord_z <= box_src->max_z) {
637 is_candidate[i] = 1;
638 n++;
639 } else {
640 is_candidate[i] = 0;
641 }
642 }
643
644 return (n != 0) ? 1 : 0;
645}
646
647static int set_candidate_node(
648 const struct hecmw_couple_bounding_box *bbox_src,
649 const struct hecmw_couple_bounding_box *bbox_dst,
650 const struct hecmw_couple_comm *comm_src,
651 const struct hecmw_couple_comm *comm_dst,
652 const struct hecmw_couple_comm *intercomm,
653 struct hecmw_couple_mapped_point **all_mapped_point, int **is_candidate) {
654 struct hecmw_couple_box *all_dst_bbox = NULL;
655 int size, rtc, i;
656
657 if (comm_src->is_member) {
658 size = sizeof(struct hecmw_couple_box) * comm_dst->psize;
659 all_dst_bbox = (struct hecmw_couple_box *)HECMW_malloc(size);
660 if (all_dst_bbox == NULL) {
661 HECMW_set_error(errno, "");
662 goto error;
663 }
664 for (i = 0; i < comm_dst->psize; i++) {
665 all_dst_bbox[i].min_x = 0.0;
666 all_dst_bbox[i].min_y = 0.0;
667 all_dst_bbox[i].min_z = 0.0;
668 all_dst_bbox[i].max_x = 0.0;
669 all_dst_bbox[i].max_y = 0.0;
670 all_dst_bbox[i].max_z = 0.0;
671 }
672 }
673
674 /* broadcast bounding box information from destination unit to source unit */
675 if (bcast_bbox_d2s(bbox_dst, comm_src, comm_dst, intercomm, all_dst_bbox))
676 goto error;
677
678 /* set candidate mapped nodes */
679 if (comm_src->is_member) {
680 for (i = 0; i < comm_dst->psize; i++) {
681 if (all_mapped_point[i]->n == 0) continue;
682
683 is_candidate[i] =
684 (int *)HECMW_calloc(all_mapped_point[i]->n, sizeof(int));
685 if (is_candidate[i] == NULL) {
686 HECMW_set_error(errno, "");
687 goto error;
688 }
689
690 if (check_bbox_within_bbox(bbox_src->enlarged, &all_dst_bbox[i])) {
691 check_node_within_bbox(bbox_src->enlarged, all_mapped_point[i],
692 is_candidate[i]);
693 }
694 }
695 }
696
697 HECMW_free(all_dst_bbox);
698 return 0;
699
700error:
701 HECMW_free(all_dst_bbox);
702 if (is_candidate) {
703 for (i = 0; i < comm_dst->psize; i++) {
704 HECMW_free(is_candidate[i]);
705 is_candidate[i] = NULL;
706 }
707 }
708 return -1;
709}
710
711/*================================================================================================*/
712
713static struct map_info_to_bgcell *map_node_to_bgcell(
714 const struct hecmwST_local_mesh *mesh_src,
715 const struct hecmw_couple_boundary *boundary_src,
716 const struct hecmw_couple_bounding_box *bbox_src,
717 const struct hecmw_couple_background_cell *bgcell_src) {
718 struct map_info_to_bgcell *map_to_bgcell = NULL;
719 struct link_list *bgcell_node_list = NULL, *p;
720 double coord_x, coord_y, coord_z;
721 int bgcell, node, ic, i, j, l, m, n;
722
723 map_to_bgcell = (struct map_info_to_bgcell *)HECMW_malloc(
724 sizeof(struct map_info_to_bgcell));
725 if (map_to_bgcell == NULL) {
726 HECMW_set_error(errno, "");
727 goto error;
728 }
729 map_to_bgcell->index = NULL;
730 map_to_bgcell->id = NULL;
731
732 if (bgcell_src->n == 0) return map_to_bgcell;
733
734 /* linked list */
735 bgcell_node_list = (struct link_list *)HECMW_malloc(sizeof(struct link_list) *
736 bgcell_src->n);
737 if (bgcell_node_list == NULL) {
738 HECMW_set_error(errno, "");
739 goto error;
740 }
741 for (i = 0; i < bgcell_src->n; i++) {
742 bgcell_node_list[i].item = 0;
743 bgcell_node_list[i].next = NULL;
744 }
745
746 for (ic = 0, i = 0; i < boundary_src->node->n; i++) {
747 node = boundary_src->node->item[i];
748 coord_x = mesh_src->node[3 * (node - 1)];
749 coord_y = mesh_src->node[3 * (node - 1) + 1];
750 coord_z = mesh_src->node[3 * (node - 1) + 2];
751
752 l = (coord_x - bbox_src->enlarged->min_x) / bgcell_src->dx;
753 m = (coord_y - bbox_src->enlarged->min_y) / bgcell_src->dy;
754 n = (coord_z - bbox_src->enlarged->min_z) / bgcell_src->dz;
755
756 if (l < 0) l = 0;
757 if (m < 0) m = 0;
758 if (n < 0) n = 0;
759 if (l >= bgcell_src->nx) l = bgcell_src->nx - 1;
760 if (m >= bgcell_src->ny) m = bgcell_src->ny - 1;
761 if (n >= bgcell_src->nz) n = bgcell_src->nz - 1;
762
763 bgcell = bgcell_src->nx * bgcell_src->ny * n + bgcell_src->nx * m + l;
764
765 p = (struct link_list *)HECMW_malloc(sizeof(struct link_list));
766 if (p == NULL) {
767 HECMW_set_error(errno, "");
768 goto error;
769 }
770 p->item = i;
771 p->next = bgcell_node_list[bgcell].next;
772 bgcell_node_list[bgcell].next = p;
773
774 ic++;
775 }
776
777 /* compressed 1-dimensional array */
778 map_to_bgcell->index = (int *)HECMW_calloc(bgcell_src->n + 1, sizeof(int));
779 if (map_to_bgcell->index == NULL) {
780 HECMW_set_error(errno, "");
781 goto error;
782 }
783 map_to_bgcell->id = (int *)HECMW_malloc(sizeof(int) * ic);
784 if (map_to_bgcell->id == NULL) {
785 HECMW_set_error(errno, "");
786 goto error;
787 }
788
789 for (ic = 0, i = 0; i < bgcell_src->n; i++) {
790 p = bgcell_node_list[i].next;
791 while (p) {
792 map_to_bgcell->id[ic++] = p->item;
793 p = p->next;
794 }
795 map_to_bgcell->index[i + 1] = ic;
796 }
797
798 /* free */
799 for (i = 0; i < bgcell_src->n; i++) {
800 free_link_list(bgcell_node_list[i].next);
801 }
802 HECMW_free(bgcell_node_list);
803
804 return map_to_bgcell;
805
806error:
807 for (i = 0; i < bgcell_src->n; i++) {
808 free_link_list(bgcell_node_list[i].next);
809 }
810 HECMW_free(bgcell_node_list);
811 if (map_to_bgcell) {
812 HECMW_free(map_to_bgcell->index);
813 HECMW_free(map_to_bgcell->id);
814 }
815
816 return NULL;
817}
818
819static struct map_info_to_bgcell *map_elem_to_bgcell(
820 const struct hecmwST_local_mesh *mesh_src,
821 const struct hecmw_couple_boundary *boundary_src,
822 const struct hecmw_couple_bounding_box *bbox_src,
823 const struct hecmw_couple_background_cell *bgcell_src) {
824 struct map_info_to_bgcell *map_to_bgcell = NULL;
825 struct link_list *bgcell_elem_list = NULL, *p;
826 double coord_x, coord_y, coord_z, min_x, min_y, min_z, max_x, max_y, max_z;
827 int min_l, min_m, min_n, max_l, max_m, max_n;
828 int bgcell, elem, node, ic, i, j, l, m, n;
829
830 map_to_bgcell = (struct map_info_to_bgcell *)HECMW_malloc(
831 sizeof(struct map_info_to_bgcell));
832 if (map_to_bgcell == NULL) {
833 HECMW_set_error(errno, "");
834 goto error;
835 }
836 map_to_bgcell->index = NULL;
837 map_to_bgcell->id = NULL;
838
839 if (bgcell_src->n == 0) return map_to_bgcell;
840
841 /* linked list */
842 bgcell_elem_list = (struct link_list *)HECMW_malloc(sizeof(struct link_list) *
843 bgcell_src->n);
844 if (bgcell_elem_list == NULL) {
845 HECMW_set_error(errno, "");
846 goto error;
847 }
848 for (i = 0; i < bgcell_src->n; i++) {
849 bgcell_elem_list[i].item = 0;
850 bgcell_elem_list[i].next = NULL;
851 }
852
853 for (ic = 0, i = 0; i < boundary_src->elem->n; i++) {
854 elem = boundary_src->elem->item[i];
855 min_x = min_y = min_z = +INFINITE;
856 max_x = max_y = max_z = -INFINITE;
857 for (j = mesh_src->elem_node_index[elem - 1];
858 j < mesh_src->elem_node_index[elem]; j++) {
859 node = mesh_src->elem_node_item[j];
860 coord_x = mesh_src->node[3 * (node - 1)];
861 coord_y = mesh_src->node[3 * (node - 1) + 1];
862 coord_z = mesh_src->node[3 * (node - 1) + 2];
863 if (coord_x < min_x) min_x = coord_x;
864 if (coord_y < min_y) min_y = coord_y;
865 if (coord_z < min_z) min_z = coord_z;
866 if (coord_x > max_x) max_x = coord_x;
867 if (coord_y > max_y) max_y = coord_y;
868 if (coord_z > max_z) max_z = coord_z;
869 }
870 min_x = min_x - (bbox_src->tolerance + EPS);
871 min_y = min_y - (bbox_src->tolerance + EPS);
872 min_z = min_z - (bbox_src->tolerance + EPS);
873 max_x = max_x + (bbox_src->tolerance + EPS);
874 max_y = max_y + (bbox_src->tolerance + EPS);
875 max_z = max_z + (bbox_src->tolerance + EPS);
876
877 min_l = (min_x - bbox_src->enlarged->min_x) / bgcell_src->dx;
878 min_m = (min_y - bbox_src->enlarged->min_y) / bgcell_src->dy;
879 min_n = (min_z - bbox_src->enlarged->min_z) / bgcell_src->dz;
880 max_l = (max_x - bbox_src->enlarged->max_x) / bgcell_src->dx;
881 max_m = (max_y - bbox_src->enlarged->max_y) / bgcell_src->dy;
882 max_n = (max_z - bbox_src->enlarged->max_z) / bgcell_src->dz;
883
884 if (min_l < 0) min_l = 0;
885 if (min_m < 0) min_m = 0;
886 if (min_n < 0) min_n = 0;
887 if (max_l < 0) max_l = 0;
888 if (max_m < 0) max_m = 0;
889 if (max_n < 0) max_n = 0;
890 if (min_l >= bgcell_src->nx) min_l = bgcell_src->nx - 1;
891 if (min_m >= bgcell_src->ny) min_m = bgcell_src->ny - 1;
892 if (min_n >= bgcell_src->nz) min_n = bgcell_src->nz - 1;
893 if (max_l >= bgcell_src->nx) max_l = bgcell_src->nx - 1;
894 if (max_m >= bgcell_src->ny) max_m = bgcell_src->ny - 1;
895 if (max_n >= bgcell_src->nz) max_n = bgcell_src->nz - 1;
896
897 for (l = min_l; l <= max_l; l++) {
898 for (m = min_m; m <= max_m; m++) {
899 for (n = min_n; n <= max_n; n++) {
900 bgcell = bgcell_src->nx * bgcell_src->ny * n + bgcell_src->nx * m + l;
901
902 p = (struct link_list *)HECMW_malloc(sizeof(struct link_list));
903 if (p == NULL) {
904 HECMW_set_error(errno, "");
905 goto error;
906 }
907 p->item = i;
908 p->next = bgcell_elem_list[bgcell].next;
909 bgcell_elem_list[bgcell].next = p;
910
911 ic++;
912 }
913 }
914 }
915 }
916
917 /* compressed 1-dimensional array */
918 map_to_bgcell->index = (int *)HECMW_calloc(bgcell_src->n + 1, sizeof(int));
919 if (map_to_bgcell->index == NULL) {
920 HECMW_set_error(errno, "");
921 goto error;
922 }
923 map_to_bgcell->id = (int *)HECMW_malloc(sizeof(int) * ic);
924 if (map_to_bgcell->id == NULL) {
925 HECMW_set_error(errno, "");
926 goto error;
927 }
928
929 for (ic = 0, i = 0; i < bgcell_src->n; i++) {
930 p = bgcell_elem_list[i].next;
931 while (p) {
932 map_to_bgcell->id[ic++] = p->item;
933 p = p->next;
934 }
935 map_to_bgcell->index[i + 1] = ic;
936 }
937
938 /* free */
939 for (i = 0; i < bgcell_src->n; i++) {
940 free_link_list(bgcell_elem_list[i].next);
941 }
942 HECMW_free(bgcell_elem_list);
943
944 return map_to_bgcell;
945
946error:
947 for (i = 0; i < bgcell_src->n; i++) {
948 free_link_list(bgcell_elem_list[i].next);
949 }
950 HECMW_free(bgcell_elem_list);
951 if (map_to_bgcell) {
952 HECMW_free(map_to_bgcell->index);
953 HECMW_free(map_to_bgcell->id);
954 }
955 return NULL;
956}
957
958static struct map_info_to_bgcell *map_surf_to_bgcell(
959 const struct hecmwST_local_mesh *mesh_src,
960 const struct hecmw_couple_boundary *boundary_src,
961 const struct hecmw_couple_bounding_box *bbox_src,
962 const struct hecmw_couple_background_cell *bgcell_src) {
963 struct map_info_to_bgcell *map_to_bgcell = NULL;
964 struct link_list *bgcell_surf_list = NULL, *p;
965 double coord_x, coord_y, coord_z, min_x, min_y, min_z, max_x, max_y, max_z;
966 int min_l, min_m, min_n, max_l, max_m, max_n;
967 int bgcell, elem, node, ic, i, j, l, m, n;
968
969 /* allocation */
970 map_to_bgcell = (struct map_info_to_bgcell *)HECMW_malloc(
971 sizeof(struct map_info_to_bgcell));
972 if (map_to_bgcell == NULL) {
973 HECMW_set_error(errno, "");
974 goto error;
975 }
976 map_to_bgcell->index = NULL;
977 map_to_bgcell->id = NULL;
978
979 if (bgcell_src->n == 0) return map_to_bgcell;
980
981 /* linked list */
982 bgcell_surf_list = (struct link_list *)HECMW_malloc(sizeof(struct link_list) *
983 bgcell_src->n);
984 if (bgcell_surf_list == NULL) {
985 HECMW_set_error(errno, "");
986 goto error;
987 }
988 for (i = 0; i < bgcell_src->n; i++) {
989 bgcell_surf_list[i].item = 0;
990 bgcell_surf_list[i].next = NULL;
991 }
992
993 for (ic = 0, i = 0; i < boundary_src->surf->n; i++) {
994 elem = boundary_src->surf->item[2 * i];
995 min_x = min_y = min_z = +INFINITE;
996 max_x = max_y = max_z = -INFINITE;
997 for (j = mesh_src->elem_node_index[elem - 1];
998 j < mesh_src->elem_node_index[elem]; j++) {
999 node = mesh_src->elem_node_item[j];
1000 coord_x = mesh_src->node[3 * (node - 1)];
1001 coord_y = mesh_src->node[3 * (node - 1) + 1];
1002 coord_z = mesh_src->node[3 * (node - 1) + 2];
1003 if (coord_x < min_x) min_x = coord_x;
1004 if (coord_y < min_y) min_y = coord_y;
1005 if (coord_z < min_z) min_z = coord_z;
1006 if (coord_x > max_x) max_x = coord_x;
1007 if (coord_y > max_y) max_y = coord_y;
1008 if (coord_z > max_z) max_z = coord_z;
1009 }
1010 min_x = min_x - (bbox_src->tolerance + EPS);
1011 min_y = min_y - (bbox_src->tolerance + EPS);
1012 min_z = min_z - (bbox_src->tolerance + EPS);
1013 max_x = max_x + (bbox_src->tolerance + EPS);
1014 max_y = max_y + (bbox_src->tolerance + EPS);
1015 max_z = max_z + (bbox_src->tolerance + EPS);
1016
1017 min_l = (min_x - bbox_src->enlarged->min_x) / bgcell_src->dx;
1018 min_m = (min_y - bbox_src->enlarged->min_y) / bgcell_src->dy;
1019 min_n = (min_z - bbox_src->enlarged->min_z) / bgcell_src->dz;
1020 max_l = (max_x - bbox_src->enlarged->min_x) / bgcell_src->dx;
1021 max_m = (max_y - bbox_src->enlarged->min_y) / bgcell_src->dy;
1022 max_n = (max_z - bbox_src->enlarged->min_z) / bgcell_src->dz;
1023
1024 if (min_l < 0) min_l = 0;
1025 if (min_m < 0) min_m = 0;
1026 if (min_n < 0) min_n = 0;
1027 if (max_l < 0) max_l = 0;
1028 if (max_m < 0) max_m = 0;
1029 if (max_n < 0) max_n = 0;
1030 if (min_l >= bgcell_src->nx) min_l = bgcell_src->nx - 1;
1031 if (min_m >= bgcell_src->ny) min_m = bgcell_src->ny - 1;
1032 if (min_n >= bgcell_src->nz) min_n = bgcell_src->nz - 1;
1033 if (max_l >= bgcell_src->nx) max_l = bgcell_src->nx - 1;
1034 if (max_m >= bgcell_src->ny) max_m = bgcell_src->ny - 1;
1035 if (max_n >= bgcell_src->nz) max_n = bgcell_src->nz - 1;
1036
1037 for (l = min_l; l <= max_l; l++) {
1038 for (m = min_m; m <= max_m; m++) {
1039 for (n = min_n; n <= max_n; n++) {
1040 bgcell = bgcell_src->nx * bgcell_src->ny * n + bgcell_src->nx * m + l;
1041 p = (struct link_list *)HECMW_malloc(sizeof(struct link_list));
1042 if (p == NULL) {
1043 HECMW_set_error(errno, "");
1044 goto error;
1045 }
1046 p->item = i;
1047 p->next = bgcell_surf_list[bgcell].next;
1048 bgcell_surf_list[bgcell].next = p;
1049
1050 ic++;
1051 }
1052 }
1053 }
1054 }
1055
1056 /* compressed 1-dimensional array */
1057 map_to_bgcell->index = (int *)HECMW_calloc(bgcell_src->n + 1, sizeof(int));
1058 if (map_to_bgcell->index == NULL) {
1059 HECMW_set_error(errno, "");
1060 goto error;
1061 }
1062 map_to_bgcell->id = (int *)HECMW_malloc(sizeof(int) * ic);
1063 if (map_to_bgcell->id == NULL) {
1064 HECMW_set_error(errno, "");
1065 goto error;
1066 }
1067
1068 for (ic = 0, i = 0; i < bgcell_src->n; i++) {
1069 for (p = bgcell_surf_list[i].next; p; p = p->next) {
1070 map_to_bgcell->id[ic++] = p->item;
1071 }
1072 map_to_bgcell->index[i + 1] = ic;
1073 }
1074
1075 /* free */
1076 for (i = 0; i < bgcell_src->n; i++) {
1077 free_link_list(bgcell_surf_list[i].next);
1078 }
1079 HECMW_free(bgcell_surf_list);
1080
1081 return map_to_bgcell;
1082
1083error:
1084 for (i = 0; i < bgcell_src->n; i++) {
1085 free_link_list(bgcell_surf_list[i].next);
1086 }
1087 HECMW_free(bgcell_surf_list);
1088 if (map_to_bgcell) {
1089 HECMW_free(map_to_bgcell->index);
1090 HECMW_free(map_to_bgcell->id);
1091 }
1092 return NULL;
1093}
1094
1095/*================================================================================================*/
1096
1097static int compare_mapping_info(int n_positive_old, double dot_product_old,
1098 double distance_old, int n_positive_new,
1099 double dot_product_new, double distance_new) {
1100 /*
1101 * 1st step: number of positive dot products
1102 */
1103 if (n_positive_old < 0) return 1; /* update */
1104 if (n_positive_new < n_positive_old) return 1; /* update */
1105 if (n_positive_new > n_positive_old) return 0; /* keep */
1106
1107 /*
1108 * 2nd step: dot product (if number of positive dot products is positive)
1109 */
1110 /* n_positive_new = n_positive_old > 0 */
1111 /* if(n_positive_new > 0) { */
1112 if (dot_product_old > 0 && dot_product_new < 0) return 0; /* keep
1113 */
1114 if (dot_product_old < 0 && dot_product_new > 0) return 1; /* update */
1115 /* }*/
1116
1117 /*
1118 * 3rd step: distance
1119 */
1120 if (distance_new < distance_old) return 1; /* update */
1121
1122 return 0; /* keep */
1123}
1124
1125static int map_point_to_surf(
1126 const struct hecmwST_local_mesh *mesh_src,
1127 const struct hecmw_couple_boundary *boundary_src,
1128 const struct hecmw_couple_bounding_box *bbox_src,
1129 const struct hecmw_couple_background_cell *bgcell_src,
1130 const struct hecmw_couple_mapped_point *mapped_point, int *is_candidate,
1131 const struct map_info_to_bgcell *map_to_bgcell, struct map_info *map_src) {
1132 double coord_x, coord_y, coord_z;
1133 int depth_x_before, depth_y_before, depth_z_before, depth_x_after,
1134 depth_y_after, depth_z_after;
1135 double dot_product, distance;
1136 int n_positive, elem, surf, bgcell, surf_id, nl, nm, nn, rtc, jstart, jfinal,
1137 i, j, l, m, n;
1138
1139 map_src->n = mapped_point->n;
1140 if (map_src->n == 0) return 0;
1141
1142 map_src->id = (int *)HECMW_malloc(sizeof(int) * map_src->n);
1143 if (map_src->id == NULL) {
1144 HECMW_set_error(errno, "");
1145 return -1;
1146 }
1147 map_src->n_positive = (int *)HECMW_malloc(sizeof(int) * map_src->n);
1148 if (map_src->n_positive == NULL) {
1149 HECMW_set_error(errno, "");
1150 return -1;
1151 }
1152 map_src->distance = (double *)HECMW_malloc(sizeof(double) * map_src->n);
1153 if (map_src->distance == NULL) {
1154 HECMW_set_error(errno, "");
1155 return -1;
1156 }
1157 map_src->dot_product = (double *)HECMW_malloc(sizeof(double) * map_src->n);
1158 if (map_src->dot_product == NULL) {
1159 HECMW_set_error(errno, "");
1160 return -1;
1161 }
1162 for (i = 0; i < map_src->n; i++) {
1163 map_src->id[i] = -1;
1164 map_src->n_positive[i] = -1;
1165 map_src->distance[i] = 0.0;
1166 map_src->dot_product[i] = 0.0;
1167 }
1168
1169 for (i = 0; i < mapped_point->n; i++) {
1170 if (is_candidate[i] == 0) continue;
1171
1172 coord_x = mapped_point->coord[3 * i];
1173 coord_y = mapped_point->coord[3 * i + 1];
1174 coord_z = mapped_point->coord[3 * i + 2];
1175
1176 /* background cell which includes mapped node */
1177 nl = (coord_x - bbox_src->enlarged->min_x) / bgcell_src->dx;
1178 nm = (coord_y - bbox_src->enlarged->min_y) / bgcell_src->dy;
1179 nn = (coord_z - bbox_src->enlarged->min_z) / bgcell_src->dz;
1180 if (nl < 0) nl = 0;
1181 if (nm < 0) nm = 0;
1182 if (nn < 0) nn = 0;
1183 if (nl >= bgcell_src->nx) nl = bgcell_src->nx - 1;
1184 if (nm >= bgcell_src->ny) nm = bgcell_src->ny - 1;
1185 if (nn >= bgcell_src->nz) nn = bgcell_src->nz - 1;
1186
1187 bgcell = bgcell_src->nx * bgcell_src->ny * nn + bgcell_src->nx * nm + nl;
1188
1189 /* mapping */
1190 for (j = map_to_bgcell->index[bgcell]; j < map_to_bgcell->index[bgcell + 1];
1191 j++) {
1192 surf_id = map_to_bgcell->id[j];
1193 elem = boundary_src->surf->item[2 * surf_id];
1194 surf = boundary_src->surf->item[2 * surf_id + 1];
1195
1196 if (mesh_src->elem_type[elem - 1] == HECMW_ETYPE_TET1) {
1197 n_positive =
1198 HECMW_couple_judge_tet1(mesh_src, elem, surf, coord_x, coord_y,
1199 coord_z, &dot_product, &distance);
1200 } else if (mesh_src->elem_type[elem - 1] == HECMW_ETYPE_HEX1) {
1201 n_positive =
1202 HECMW_couple_judge_hex1(mesh_src, elem, surf, coord_x, coord_y,
1203 coord_z, &dot_product, &distance);
1204 } else {
1206 return -1;
1207 }
1208
1209 if (n_positive >= 0) {
1210 rtc = compare_mapping_info(
1211 map_src->n_positive[i], map_src->dot_product[i],
1212 map_src->distance[i], n_positive, dot_product, distance);
1213 if (rtc == 1) {
1214 map_src->n_positive[i] = n_positive;
1215 map_src->dot_product[i] = dot_product;
1216 map_src->distance[i] = distance;
1217 map_src->id[i] = surf_id;
1218 }
1219 }
1220 }
1221 }
1222
1223 return 0;
1224}
1225
1226static int mapping_in_src(const struct hecmwST_local_mesh *mesh_src,
1227 const struct hecmw_couple_boundary *boundary_src,
1228 const struct hecmw_couple_bounding_box *bbox_src,
1229 const struct hecmw_couple_background_cell *bgcell_src,
1230 const struct hecmw_couple_comm *comm_dst,
1231 struct hecmw_couple_mapped_point **all_mapped_point,
1232 int **is_candidate, struct map_info **map_src) {
1233 struct map_info_to_bgcell *map_to_bgcell = NULL;
1234 int map_type, i;
1235
1236 /* mapping boundary surface to background cell */
1237 map_to_bgcell = (struct map_info_to_bgcell *)HECMW_malloc(
1238 sizeof(struct map_info_to_bgcell));
1239 if (map_to_bgcell == NULL) {
1240 HECMW_set_error(errno, "");
1241 goto error;
1242 }
1243 map_to_bgcell->index = NULL;
1244 map_to_bgcell->id = NULL;
1245
1246 /* mapping boundary nodes on destination side to boundary surface on source
1247 * side */
1248 map_type = HECMW_COUPLE_MAP_SURF_TO_SURF; /*@@*/
1249
1250 if (map_type == HECMW_COUPLE_MAP_SURF_TO_SURF) {
1251 map_to_bgcell =
1252 map_surf_to_bgcell(mesh_src, boundary_src, bbox_src, bgcell_src);
1253 if (map_to_bgcell == NULL) goto error;
1254
1255 for (i = 0; i < comm_dst->psize; i++) {
1256 if (map_point_to_surf(mesh_src, boundary_src, bbox_src, bgcell_src,
1257 all_mapped_point[i], is_candidate[i], map_to_bgcell,
1258 map_src[i]))
1259 goto error;
1260 }
1261
1262 } else {
1264 goto error;
1265 }
1266
1267 if (map_to_bgcell) {
1268 HECMW_free(map_to_bgcell->index);
1269 HECMW_free(map_to_bgcell->id);
1270 HECMW_free(map_to_bgcell);
1271 }
1272 return 0;
1273
1274error:
1275 if (map_to_bgcell) {
1276 HECMW_free(map_to_bgcell->index);
1277 HECMW_free(map_to_bgcell->id);
1278 HECMW_free(map_to_bgcell);
1279 }
1280 if (map_src) {
1281 for (i = 0; i < comm_dst->psize; i++) {
1282 free_struct_map_info(map_src[i]);
1283 }
1284 HECMW_free(map_src);
1285 }
1286 return -1;
1287}
1288
1289/*================================================================================================*/
1290
1291static int gather_id_s2d(struct map_info **map_src,
1292 const struct hecmw_couple_comm *comm_src,
1293 const struct hecmw_couple_comm *comm_dst,
1294 const struct hecmw_couple_comm *intercomm,
1295 struct map_info **map_dst) {
1296 int n_send_pe = 0, n_recv_pe = 0, *send_pe = NULL, *recv_pe = NULL;
1297 int *sendbuf_index = NULL, *recvbuf_index = NULL, *sendbuf = NULL,
1298 *recvbuf = NULL;
1299 int rtc, i, j;
1300
1301 /*
1302 * send buffer (source unit)
1303 */
1304 if (comm_src->is_member) {
1305 /* number of communication processes */
1306 n_send_pe = comm_dst->psize;
1307
1308 /* communication processes */
1309 send_pe = (int *)HECMW_malloc(sizeof(int) * n_send_pe);
1310 if (send_pe == NULL) {
1311 HECMW_set_error(errno, "");
1312 goto error;
1313 }
1314 for (i = 0; i < n_send_pe; i++) {
1315 send_pe[i] = comm_dst->ranks[i];
1316 }
1317
1318 /* size of send buffer */
1319 sendbuf_index = (int *)HECMW_calloc(n_send_pe + 1, sizeof(int));
1320 if (sendbuf_index == NULL) {
1321 HECMW_set_error(errno, "");
1322 goto error;
1323 }
1324 for (i = 0; i < n_send_pe; i++) {
1325 sendbuf_index[i + 1] = sendbuf_index[i] + map_src[i]->n;
1326 }
1327
1328 /* send buffer */
1329 sendbuf = (int *)HECMW_malloc(sizeof(int) * (sendbuf_index[n_send_pe] + 1));
1330 if (sendbuf == NULL) {
1331 HECMW_set_error(errno, "");
1332 goto error;
1333 }
1334 for (i = 0; i < comm_dst->psize; i++) {
1335 for (j = 0; j < map_src[i]->n; j++) {
1336 sendbuf[sendbuf_index[i] + j] = map_src[i]->id[j];
1337 }
1338 }
1339 }
1340
1341 /*
1342 * receive buffer (destination unit)
1343 */
1344 if (comm_dst->is_member) {
1345 /* number of communication processes */
1346 n_recv_pe = comm_src->psize;
1347
1348 /* communication processes */
1349 recv_pe = (int *)HECMW_malloc(sizeof(int) * n_recv_pe);
1350 if (recv_pe == NULL) {
1351 HECMW_set_error(errno, "");
1352 goto error;
1353 }
1354 for (i = 0; i < n_recv_pe; i++) {
1355 recv_pe[i] = comm_src->ranks[i];
1356 }
1357
1358 /* size of receive buffer */
1359 recvbuf_index = (int *)HECMW_calloc(n_recv_pe + 1, sizeof(int));
1360 if (recvbuf_index == NULL) {
1361 HECMW_set_error(errno, "");
1362 goto error;
1363 }
1364 for (i = 0; i < n_recv_pe; i++) {
1365 recvbuf_index[i + 1] = recvbuf_index[i] + map_dst[i]->n;
1366 }
1367
1368 /* receive buffer */
1369 recvbuf = (int *)HECMW_malloc(sizeof(int) * (recvbuf_index[n_recv_pe] + 1));
1370 if (recvbuf == NULL) {
1371 HECMW_set_error(errno, "");
1372 goto error;
1373 }
1374 }
1375
1376 /*
1377 * send and receive
1378 */
1379 rtc = HECMW_couple_inter_send_recv(n_send_pe, send_pe, sendbuf_index, sendbuf,
1380 n_recv_pe, recv_pe, recvbuf_index, recvbuf,
1381 HECMW_INT, intercomm->comm);
1382 if (rtc != 0) goto error;
1383
1384 /*
1385 * store received data
1386 */
1387 if (comm_dst->is_member) {
1388 for (i = 0; i < n_recv_pe; i++) {
1389 map_dst[i]->id = (int *)HECMW_calloc(map_dst[i]->n, sizeof(int));
1390 if (map_dst[i]->id == NULL) {
1391 HECMW_set_error(errno, "");
1392 goto error;
1393 }
1394 for (j = 0; j < map_dst[i]->n; j++) {
1395 map_dst[i]->id[j] = recvbuf[recvbuf_index[i] + j];
1396 }
1397 }
1398 }
1399
1400 HECMW_free(send_pe);
1401 HECMW_free(sendbuf_index);
1402 HECMW_free(sendbuf);
1403 HECMW_free(recv_pe);
1404 HECMW_free(recvbuf_index);
1405 HECMW_free(recvbuf);
1406 return 0;
1407
1408error:
1409 HECMW_free(send_pe);
1410 HECMW_free(sendbuf_index);
1411 HECMW_free(sendbuf);
1412 HECMW_free(recv_pe);
1413 HECMW_free(recvbuf_index);
1414 HECMW_free(recvbuf);
1415 return -1;
1416}
1417
1418static int gather_n_positive_s2d(struct map_info **map_src,
1419 const struct hecmw_couple_comm *comm_src,
1420 const struct hecmw_couple_comm *comm_dst,
1421 const struct hecmw_couple_comm *intercomm,
1422 struct map_info **map_dst) {
1423 int n_send_pe = 0, n_recv_pe = 0, *send_pe = NULL, *recv_pe = NULL;
1424 int *sendbuf_index = NULL, *recvbuf_index = NULL, *sendbuf = NULL,
1425 *recvbuf = NULL;
1426 int rtc, i, j;
1427
1428 /*
1429 * send buffer (source unit)
1430 */
1431 if (comm_src->is_member) {
1432 /* number of communication processes */
1433 n_send_pe = comm_dst->psize;
1434
1435 /* communication processes */
1436 send_pe = (int *)HECMW_malloc(sizeof(int) * n_send_pe);
1437 if (send_pe == NULL) {
1438 HECMW_set_error(errno, "");
1439 goto error;
1440 }
1441 for (i = 0; i < n_send_pe; i++) {
1442 send_pe[i] = comm_dst->ranks[i];
1443 }
1444
1445 /* size of send buffer */
1446 sendbuf_index = (int *)HECMW_calloc(n_send_pe + 1, sizeof(int));
1447 if (sendbuf_index == NULL) {
1448 HECMW_set_error(errno, "");
1449 goto error;
1450 }
1451 for (i = 0; i < n_send_pe; i++) {
1452 sendbuf_index[i + 1] = sendbuf_index[i] + map_src[i]->n;
1453 }
1454
1455 /* send buffer */
1456 sendbuf = (int *)HECMW_malloc(sizeof(int) * (sendbuf_index[n_send_pe] + 1));
1457 if (sendbuf == NULL) {
1458 HECMW_set_error(errno, "");
1459 goto error;
1460 }
1461 for (i = 0; i < comm_dst->psize; i++) {
1462 for (j = 0; j < map_src[i]->n; j++) {
1463 sendbuf[sendbuf_index[i] + j] = map_src[i]->n_positive[j];
1464 }
1465 }
1466 }
1467
1468 /*
1469 * receive buffer (destination unit)
1470 */
1471 if (comm_dst->is_member) {
1472 /* number of communication processes */
1473 n_recv_pe = comm_src->psize;
1474
1475 /* communication processes */
1476 recv_pe = (int *)HECMW_malloc(sizeof(int) * n_recv_pe);
1477 if (recv_pe == NULL) {
1478 HECMW_set_error(errno, "");
1479 goto error;
1480 }
1481 for (i = 0; i < n_recv_pe; i++) {
1482 recv_pe[i] = comm_src->ranks[i];
1483 }
1484
1485 /* size of receive buffer */
1486 recvbuf_index = (int *)HECMW_calloc(n_recv_pe + 1, sizeof(int));
1487 if (recvbuf_index == NULL) {
1488 HECMW_set_error(errno, "");
1489 goto error;
1490 }
1491 for (i = 0; i < n_recv_pe; i++) {
1492 recvbuf_index[i + 1] = recvbuf_index[i] + map_dst[i]->n;
1493 }
1494
1495 /* receive buffer */
1496 recvbuf = (int *)HECMW_malloc(sizeof(int) * (recvbuf_index[n_recv_pe] + 1));
1497 if (recvbuf == NULL) {
1498 HECMW_set_error(errno, "");
1499 goto error;
1500 }
1501 }
1502
1503 /*
1504 * send and receive
1505 */
1506 rtc = HECMW_couple_inter_send_recv(n_send_pe, send_pe, sendbuf_index, sendbuf,
1507 n_recv_pe, recv_pe, recvbuf_index, recvbuf,
1508 HECMW_INT, intercomm->comm);
1509 if (rtc != 0) goto error;
1510
1511 /*
1512 * store received data
1513 */
1514 if (comm_dst->is_member) {
1515 for (i = 0; i < n_recv_pe; i++) {
1516 map_dst[i]->n_positive = (int *)HECMW_calloc(map_dst[i]->n, sizeof(int));
1517 if (map_dst[i]->n_positive == NULL) {
1518 HECMW_set_error(errno, "");
1519 goto error;
1520 }
1521 for (j = 0; j < map_dst[i]->n; j++) {
1522 map_dst[i]->n_positive[j] = recvbuf[recvbuf_index[i] + j];
1523 }
1524 }
1525 }
1526
1527 HECMW_free(send_pe);
1528 HECMW_free(sendbuf_index);
1529 HECMW_free(sendbuf);
1530 HECMW_free(recv_pe);
1531 HECMW_free(recvbuf_index);
1532 HECMW_free(recvbuf);
1533 return 0;
1534
1535error:
1536 HECMW_free(send_pe);
1537 HECMW_free(sendbuf_index);
1538 HECMW_free(sendbuf);
1539 HECMW_free(recv_pe);
1540 HECMW_free(recvbuf_index);
1541 HECMW_free(recvbuf);
1542 return -1;
1543}
1544
1545static int gather_dot_product_s2d(struct map_info **map_src,
1546 const struct hecmw_couple_comm *comm_src,
1547 const struct hecmw_couple_comm *comm_dst,
1548 const struct hecmw_couple_comm *intercomm,
1549 struct map_info **map_dst) {
1550 int n_send_pe = 0, n_recv_pe = 0, *send_pe = NULL, *recv_pe = NULL;
1551 int *sendbuf_index = NULL, *recvbuf_index = NULL;
1552 double *sendbuf = NULL, *recvbuf = NULL;
1553 int rtc, i, j;
1554
1555 /*
1556 * send buffer (source unit)
1557 */
1558 if (comm_src->is_member) {
1559 /* number of communication processes */
1560 n_send_pe = comm_dst->psize;
1561
1562 /* communication processes */
1563 send_pe = (int *)HECMW_malloc(sizeof(int) * n_send_pe);
1564 if (send_pe == NULL) {
1565 HECMW_set_error(errno, "");
1566 goto error;
1567 }
1568 for (i = 0; i < n_send_pe; i++) {
1569 send_pe[i] = comm_dst->ranks[i];
1570 }
1571
1572 /* index of send buffer */
1573 sendbuf_index = (int *)HECMW_calloc(n_send_pe + 1, sizeof(int));
1574 if (sendbuf_index == NULL) {
1575 HECMW_set_error(errno, "");
1576 goto error;
1577 }
1578 for (i = 0; i < n_send_pe; i++) {
1579 sendbuf_index[i + 1] = sendbuf_index[i] + map_src[i]->n;
1580 }
1581
1582 /* send buffer */
1583 sendbuf =
1584 (double *)HECMW_malloc(sizeof(double) * (sendbuf_index[n_send_pe] + 1));
1585 if (sendbuf == NULL) {
1586 HECMW_set_error(errno, "");
1587 goto error;
1588 }
1589 for (i = 0; i < comm_dst->psize; i++) {
1590 for (j = 0; j < map_src[i]->n; j++) {
1591 sendbuf[sendbuf_index[i] + j] = map_src[i]->dot_product[j];
1592 }
1593 }
1594 }
1595
1596 /*
1597 * receive buffer (destination unit)
1598 */
1599 if (comm_dst->is_member) {
1600 /* number of communication processes */
1601 n_recv_pe = comm_src->psize;
1602
1603 /* communication processes */
1604 recv_pe = (int *)HECMW_malloc(sizeof(int) * n_recv_pe);
1605 if (recv_pe == NULL) {
1606 HECMW_set_error(errno, "");
1607 goto error;
1608 }
1609 for (i = 0; i < n_recv_pe; i++) {
1610 recv_pe[i] = comm_src->ranks[i];
1611 }
1612
1613 /* index of receive buffer */
1614 recvbuf_index = (int *)HECMW_calloc(n_recv_pe + 1, sizeof(int));
1615 if (recvbuf_index == NULL) {
1616 HECMW_set_error(errno, "");
1617 goto error;
1618 }
1619 for (i = 0; i < n_recv_pe; i++) {
1620 recvbuf_index[i + 1] = recvbuf_index[i] + map_dst[i]->n;
1621 }
1622
1623 /* receive buffer */
1624 recvbuf =
1625 (double *)HECMW_malloc(sizeof(double) * recvbuf_index[n_recv_pe] + 1);
1626 if (recvbuf == NULL) {
1627 HECMW_set_error(errno, "");
1628 goto error;
1629 }
1630 }
1631
1632 /*
1633 * send and receive
1634 */
1635 rtc = HECMW_couple_inter_send_recv(n_send_pe, send_pe, sendbuf_index, sendbuf,
1636 n_recv_pe, recv_pe, recvbuf_index, recvbuf,
1637 HECMW_DOUBLE, intercomm->comm);
1638 if (rtc != 0) goto error;
1639
1640 /*
1641 * store received data
1642 */
1643 if (comm_dst->is_member) {
1644 for (i = 0; i < n_recv_pe; i++) {
1645 map_dst[i]->dot_product =
1646 (double *)HECMW_malloc(sizeof(double) * map_dst[i]->n);
1647 if (map_dst[i]->dot_product == NULL) {
1648 HECMW_set_error(errno, "");
1649 goto error;
1650 }
1651 for (j = 0; j < map_dst[i]->n; j++) {
1652 map_dst[i]->dot_product[j] = recvbuf[recvbuf_index[i] + j];
1653 }
1654 }
1655 }
1656
1657 HECMW_free(send_pe);
1658 HECMW_free(sendbuf_index);
1659 HECMW_free(sendbuf);
1660 HECMW_free(recv_pe);
1661 HECMW_free(recvbuf_index);
1662 HECMW_free(recvbuf);
1663 return 0;
1664
1665error:
1666 HECMW_free(send_pe);
1667 HECMW_free(sendbuf_index);
1668 HECMW_free(sendbuf);
1669 HECMW_free(recv_pe);
1670 HECMW_free(recvbuf_index);
1671 HECMW_free(recvbuf);
1672 return -1;
1673}
1674
1675static int gather_distance_s2d(struct map_info **map_src,
1676 const struct hecmw_couple_comm *comm_src,
1677 const struct hecmw_couple_comm *comm_dst,
1678 const struct hecmw_couple_comm *intercomm,
1679 struct map_info **map_dst) {
1680 int n_send_pe = 0, n_recv_pe = 0, *send_pe = NULL, *recv_pe = NULL;
1681 int *sendbuf_index = NULL, *recvbuf_index = NULL;
1682 double *sendbuf = NULL, *recvbuf = NULL;
1683 int rtc, i, j;
1684
1685 /*
1686 * send buffer (source unit)
1687 */
1688 if (comm_src->is_member) {
1689 /* number of communication processes */
1690 n_send_pe = comm_dst->psize;
1691
1692 /* communication processes */
1693 send_pe = (int *)HECMW_malloc(sizeof(int) * n_send_pe);
1694 if (send_pe == NULL) {
1695 HECMW_set_error(errno, "");
1696 goto error;
1697 }
1698 for (i = 0; i < n_send_pe; i++) {
1699 send_pe[i] = comm_dst->ranks[i];
1700 }
1701
1702 /* index of send buffer */
1703 sendbuf_index = (int *)HECMW_calloc(n_send_pe + 1, sizeof(int));
1704 if (sendbuf_index == NULL) {
1705 HECMW_set_error(errno, "");
1706 goto error;
1707 }
1708 for (i = 0; i < n_send_pe; i++) {
1709 sendbuf_index[i + 1] = sendbuf_index[i] + map_src[i]->n;
1710 }
1711
1712 /* send buffer */
1713 sendbuf =
1714 (double *)HECMW_malloc(sizeof(double) * (sendbuf_index[n_send_pe] + 1));
1715 if (sendbuf == NULL) {
1716 HECMW_set_error(errno, "");
1717 goto error;
1718 }
1719 for (i = 0; i < comm_dst->psize; i++) {
1720 for (j = 0; j < map_src[i]->n; j++) {
1721 sendbuf[sendbuf_index[i] + j] = map_src[i]->distance[j];
1722 }
1723 }
1724 }
1725
1726 /* receive buffer */
1727 if (comm_dst->is_member) {
1728 /* number of communication processes */
1729 n_recv_pe = comm_src->psize;
1730
1731 /* communication processes */
1732 recv_pe = (int *)HECMW_malloc(sizeof(int) * n_recv_pe);
1733 if (recv_pe == NULL) {
1734 HECMW_set_error(errno, "");
1735 goto error;
1736 }
1737 for (i = 0; i < n_recv_pe; i++) {
1738 recv_pe[i] = comm_src->ranks[i];
1739 }
1740
1741 /* index of receive buffer */
1742 recvbuf_index = (int *)HECMW_calloc(n_recv_pe + 1, sizeof(int));
1743 if (recvbuf_index == NULL) {
1744 HECMW_set_error(errno, "");
1745 goto error;
1746 }
1747 for (i = 0; i < n_recv_pe; i++) {
1748 recvbuf_index[i + 1] = recvbuf_index[i] + map_dst[i]->n;
1749 }
1750
1751 /* receive buffer */
1752 recvbuf =
1753 (double *)HECMW_malloc(sizeof(double) * (recvbuf_index[n_recv_pe] + 1));
1754 if (recvbuf == NULL) {
1755 HECMW_set_error(errno, "");
1756 goto error;
1757 }
1758 }
1759
1760 /*
1761 * send and receive
1762 */
1763 rtc = HECMW_couple_inter_send_recv(n_send_pe, send_pe, sendbuf_index, sendbuf,
1764 n_recv_pe, recv_pe, recvbuf_index, recvbuf,
1765 HECMW_DOUBLE, intercomm->comm);
1766 if (rtc != 0) goto error;
1767
1768 /*
1769 * store received data
1770 */
1771 if (comm_dst->is_member) {
1772 for (i = 0; i < n_recv_pe; i++) {
1773 map_dst[i]->distance =
1774 (double *)HECMW_malloc(sizeof(double) * map_dst[i]->n);
1775 if (map_dst[i]->distance == NULL) {
1776 HECMW_set_error(errno, "");
1777 goto error;
1778 }
1779 for (j = 0; j < map_dst[i]->n; j++) {
1780 map_dst[i]->distance[j] = recvbuf[recvbuf_index[i] + j];
1781 }
1782 }
1783 }
1784
1785 HECMW_free(send_pe);
1786 HECMW_free(sendbuf_index);
1787 HECMW_free(sendbuf);
1788 HECMW_free(recv_pe);
1789 HECMW_free(recvbuf_index);
1790 HECMW_free(recvbuf);
1791 return 0;
1792
1793error:
1794 HECMW_free(send_pe);
1795 HECMW_free(sendbuf_index);
1796 HECMW_free(sendbuf);
1797 HECMW_free(recv_pe);
1798 HECMW_free(recvbuf_index);
1799 HECMW_free(recvbuf);
1800 return -1;
1801}
1802
1803/*------------------------------------------------------------------------------------------------*/
1804
1805static int gather_map_data_s2d(
1806 const struct hecmw_couple_mapped_point *mapped_point,
1807 struct map_info **map_src, const struct hecmw_couple_comm *comm_src,
1808 const struct hecmw_couple_comm *comm_dst,
1809 const struct hecmw_couple_comm *intercomm, struct map_info **map_dst) {
1810 int map_type, rtc, i;
1811
1812 if (comm_dst->is_member) {
1813 for (i = 0; i < comm_src->psize; i++) {
1814 map_dst[i] = alloc_struct_map_info();
1815 if (map_dst[i] == NULL) goto error;
1816
1817 map_dst[i]->n = mapped_point->n;
1818 }
1819 }
1820
1821 /*@@@ map_type = HECMW_couple_get_map_type(boundary_id); @@@*/
1823
1824 if (map_type == HECMW_COUPLE_MAP_NODE_TO_SURF) {
1825 if (gather_id_s2d(map_src, comm_src, comm_dst, intercomm, map_dst))
1826 goto error;
1827 if (gather_n_positive_s2d(map_src, comm_src, comm_dst, intercomm, map_dst))
1828 goto error;
1829 if (gather_dot_product_s2d(map_src, comm_src, comm_dst, intercomm, map_dst))
1830 goto error;
1831 if (gather_distance_s2d(map_src, comm_src, comm_dst, intercomm, map_dst))
1832 goto error;
1833
1834 } else {
1836 goto error;
1837 }
1838
1839 return 0;
1840
1841error:
1842 if (map_dst) {
1843 for (i = 0; i < comm_src->psize; i++) {
1844 free_struct_map_info(map_dst[i]);
1845 map_dst[i] = NULL;
1846 }
1847 }
1848 return -1;
1849}
1850
1851/*================================================================================================*/
1852
1853static struct link_list_map *set_mapping_surf(
1854 const struct hecmw_couple_mapped_point *mapped_point,
1855 const struct hecmw_couple_comm *comm_src, struct map_info **map_dst) {
1856 struct link_list_map *mapping_data_list = NULL, *p;
1857 double _dot_product, _distance;
1858 int _n_positive, _item, pe_index, index, size, rtc, n, i, j;
1859
1860 size = sizeof(struct link_list_map) * comm_src->psize;
1861 mapping_data_list = (struct link_list_map *)HECMW_malloc(size);
1862 if (mapping_data_list == NULL) {
1863 HECMW_set_error(errno, "");
1864 goto error;
1865 }
1866 for (i = 0; i < comm_src->psize; i++) {
1867 mapping_data_list[i].next = NULL;
1868 mapping_data_list[i].id = -1;
1869 mapping_data_list[i].item = -1;
1870 }
1871
1872 for (n = 0, i = 0; i < mapped_point->n; i++) {
1873 _n_positive = -1;
1874
1875 for (j = 0; j < comm_src->psize; j++) {
1876 if (map_dst[j]->n_positive[i] >= 0) {
1877 rtc = compare_mapping_info(
1878 _n_positive, _dot_product, _distance, map_dst[j]->n_positive[i],
1879 map_dst[j]->dot_product[i], map_dst[j]->distance[i]);
1880 if (rtc == 1) {
1881 pe_index = j;
1882 _item = map_dst[j]->id[i];
1883 _n_positive = map_dst[j]->n_positive[i];
1884 _dot_product = map_dst[j]->dot_product[i];
1885 _distance = map_dst[j]->distance[i];
1886 }
1887 }
1888 }
1889
1890 if (_n_positive >= 0) {
1891 p = (struct link_list_map *)HECMW_malloc(sizeof(struct link_list_map));
1892 if (p == NULL) {
1893 HECMW_set_error(errno, "");
1894 goto error;
1895 }
1896 p->next = mapping_data_list[pe_index].next;
1897 p->id = mapped_point->id[n++];
1898 p->item = _item;
1899 mapping_data_list[pe_index].next = p;
1900 }
1901 }
1902
1903 return mapping_data_list;
1904
1905error:
1906 if (mapping_data_list) {
1907 for (i = 0; i < comm_src->psize; i++) {
1908 free_link_list_map(mapping_data_list[i].next);
1909 }
1910 HECMW_free(mapping_data_list);
1911 }
1912
1913 return NULL;
1914}
1915
1916/*================================================================================================*/
1917
1918static int set_n_neighbor_pe_import(
1919 struct hecmw_couple_inter_iftable *inter_tbl,
1920 const struct hecmw_couple_comm *comm_src,
1921 struct link_list_map *mapping_data_list) {
1922 int n, i;
1923
1924 for (n = 0, i = 0; i < comm_src->psize; i++) {
1925 if (mapping_data_list[i].next) n++;
1926 }
1927 inter_tbl->n_neighbor_pe_import = n;
1928
1929 return 0;
1930}
1931
1932static int set_neighbor_pe_import(struct hecmw_couple_inter_iftable *inter_tbl,
1933 const struct hecmw_couple_comm *comm_src,
1934 struct link_list_map *mapping_data_list) {
1935 int size, n, i;
1936
1937 if (inter_tbl->n_neighbor_pe_import == 0) return 0;
1938
1939 size = sizeof(int) * inter_tbl->n_neighbor_pe_import;
1940 inter_tbl->neighbor_pe_import = (int *)HECMW_malloc(size);
1941 if (inter_tbl->neighbor_pe_import == NULL) {
1942 HECMW_set_error(errno, "");
1943 return -1;
1944 }
1945 for (n = 0, i = 0; i < comm_src->psize; i++) {
1946 if (mapping_data_list[i].next) {
1947 inter_tbl->neighbor_pe_import[n++] = comm_src->ranks[i];
1948 }
1949 }
1950 HECMW_assert(n == inter_tbl->n_neighbor_pe_import);
1951
1952 return 0;
1953}
1954
1955static int set_import_index(struct hecmw_couple_inter_iftable *inter_tbl,
1956 const struct hecmw_couple_comm *comm_src,
1957 struct link_list_map *mapping_data_list) {
1958 struct link_list_map *p;
1959 int nmemb, m, n, i;
1960
1961 nmemb = inter_tbl->n_neighbor_pe_import + 1;
1962 inter_tbl->import_index = (int *)HECMW_calloc(nmemb, sizeof(int));
1963 if (inter_tbl->import_index == NULL) {
1964 HECMW_set_error(errno, "");
1965 return -1;
1966 }
1967
1968 for (m = 0, n = 0, i = 0; i < comm_src->psize; i++) {
1969 if (mapping_data_list[i].next) {
1970 for (p = mapping_data_list[i].next; p; p = p->next) {
1971 n++;
1972 }
1973 inter_tbl->import_index[++m] = n;
1974 }
1975 }
1976 HECMW_assert(m == inter_tbl->n_neighbor_pe_import);
1977
1978 return 0;
1979}
1980
1981static int set_import_item(struct hecmw_couple_inter_iftable *inter_tbl,
1982 const struct hecmw_couple_comm *comm_src,
1983 struct link_list_map *mapping_data_list) {
1984 struct link_list_map *p;
1985 int size, n, i;
1986
1987 size = sizeof(int) * inter_tbl->import_index[inter_tbl->n_neighbor_pe_import];
1988 inter_tbl->import_item = (int *)HECMW_malloc(size);
1989 if (inter_tbl->import_item == NULL) {
1990 HECMW_set_error(errno, "");
1991 return -1;
1992 }
1993
1994 for (n = 0, i = 0; i < comm_src->psize; i++) {
1995 if (mapping_data_list[i].next) {
1996 for (p = mapping_data_list[i].next; p; p = p->next) {
1997 inter_tbl->import_item[n++] = p->id;
1998 }
1999 HECMW_assert(n == inter_tbl->import_index[i + 1]);
2000 }
2001 }
2002
2003 return 0;
2004}
2005
2006/*------------------------------------------------------------------------------------------------*/
2007
2008static int *set_export_data(struct hecmw_couple_inter_iftable *inter_tbl,
2009 const struct hecmw_couple_comm *comm_src,
2010 struct link_list_map *mapping_data_list) {
2011 struct link_list_map *p;
2012 int *export_data = NULL;
2013 int size, n, i;
2014
2015 size = sizeof(int) * inter_tbl->import_index[inter_tbl->n_neighbor_pe_import];
2016 export_data = (int *)HECMW_malloc(size);
2017 if (export_data == NULL) {
2018 HECMW_set_error(errno, "");
2019 return NULL;
2020 }
2021
2022 for (n = 0, i = 0; i < comm_src->psize; i++) {
2023 if (mapping_data_list[i].next) {
2024 for (p = mapping_data_list[i].next; p; p = p->next) {
2025 export_data[n++] = p->item;
2026 }
2027 HECMW_assert(n == inter_tbl->import_index[i + 1]);
2028 }
2029 }
2030
2031 return export_data;
2032}
2033
2034static int set_neighbor_info_import(
2035 struct hecmw_couple_inter_iftable *inter_tbl,
2036 struct link_list_map *mapping_data_list,
2037 const struct hecmw_couple_comm *comm_src) {
2038 int i;
2039
2040 /* number of neighboring domains */
2041 if (set_n_neighbor_pe_import(inter_tbl, comm_src, mapping_data_list))
2042 return -1;
2043
2044 /* neighboring domain */
2045 if (set_neighbor_pe_import(inter_tbl, comm_src, mapping_data_list)) return -1;
2046
2047 /* index for import node */
2048 if (set_import_index(inter_tbl, comm_src, mapping_data_list)) return -1;
2049
2050 /* import node */
2051 if (set_import_item(inter_tbl, comm_src, mapping_data_list)) return -1;
2052
2053 return 0;
2054}
2055
2056/*------------------------------------------------------------------------------------------------*/
2057
2058static int set_neighbor_pe_export(
2059 struct hecmw_couple_inter_iftable *inter_tbl,
2060 const struct hecmw_couple_comm *comm_src,
2061 const struct hecmw_couple_comm *comm_dst,
2062 const struct hecmw_couple_comm *intercomm,
2063 const struct link_list_map *mapping_data_list) {
2064 int n_send_pe = 0, n_recv_pe = 0;
2065 int *send_pe = NULL, *recv_pe = NULL;
2066 int *sendbuf_index = NULL, *recvbuf_index = NULL, *sendbuf = NULL,
2067 *recvbuf = NULL;
2068 int size, rtc, n, i;
2069
2070 /*
2071 * send buffer (destination unit)
2072 */
2073 if (comm_dst->is_member) {
2074 /* number of communication processes */
2075 n_send_pe = comm_src->psize;
2076
2077 /* communication processes */
2078 send_pe = (int *)HECMW_malloc(sizeof(int) * n_send_pe);
2079 if (send_pe == NULL) {
2080 HECMW_set_error(errno, "");
2081 goto error;
2082 }
2083 for (i = 0; i < comm_src->psize; i++) {
2084 send_pe[i] = comm_src->ranks[i];
2085 }
2086
2087 /* index of send buffer */
2088 sendbuf_index = (int *)HECMW_calloc(n_send_pe + 1, sizeof(int));
2089 if (sendbuf_index == NULL) {
2090 HECMW_set_error(errno, "");
2091 goto error;
2092 }
2093 for (i = 0; i < n_send_pe; i++) {
2094 sendbuf_index[i + 1] = sendbuf_index[i] + 1;
2095 }
2096
2097 /* send buffer */
2098 sendbuf = (int *)HECMW_malloc(sizeof(int) * (sendbuf_index[n_send_pe] + 1));
2099 if (sendbuf == NULL) {
2100 HECMW_set_error(errno, "");
2101 goto error;
2102 }
2103 for (i = 0; i < n_send_pe; i++) {
2104 if (mapping_data_list[i].next) {
2105 sendbuf[i] = 1;
2106 } else {
2107 sendbuf[i] = 0;
2108 }
2109 }
2110 }
2111
2112 /*
2113 * receive buffer (source unit)
2114 */
2115 if (comm_src->is_member) {
2116 /* number of communication processes */
2117 n_recv_pe = comm_dst->psize;
2118
2119 /* communication processes */
2120 recv_pe = (int *)HECMW_malloc(sizeof(int) * n_recv_pe);
2121 if (recv_pe == NULL) {
2122 HECMW_set_error(errno, "");
2123 goto error;
2124 }
2125 for (i = 0; i < comm_dst->psize; i++) {
2126 recv_pe[i] = comm_dst->ranks[i];
2127 }
2128
2129 /* index of receive buffer */
2130 recvbuf_index = (int *)HECMW_calloc(n_recv_pe + 1, sizeof(int));
2131 if (recvbuf_index == NULL) {
2132 HECMW_set_error(errno, "");
2133 goto error;
2134 }
2135 for (i = 0; i < n_recv_pe; i++) {
2136 recvbuf_index[i + 1] = recvbuf_index[i] + 1;
2137 }
2138
2139 /* receive buffer */
2140 recvbuf = (int *)HECMW_malloc(sizeof(int) * (recvbuf_index[n_recv_pe] + 1));
2141 if (recvbuf == NULL) {
2142 HECMW_set_error(errno, "");
2143 goto error;
2144 }
2145 }
2146
2147 /* send and receive */
2148 rtc = HECMW_couple_inter_send_recv(n_send_pe, send_pe, sendbuf_index, sendbuf,
2149 n_recv_pe, recv_pe, recvbuf_index, recvbuf,
2150 HECMW_INT, intercomm->comm);
2151 if (rtc != 0) goto error;
2152
2153 /*
2154 * set neighbor process for inter-communication (source unit)
2155 */
2156 if (comm_src->is_member) {
2157 for (n = 0, i = 0; i < comm_dst->psize; i++) {
2158 if (recvbuf[i] > 0) n++;
2159 }
2160 inter_tbl->n_neighbor_pe_export = n;
2161
2162 if (inter_tbl->n_neighbor_pe_export != 0) {
2163 size = sizeof(int) * inter_tbl->n_neighbor_pe_export;
2164 inter_tbl->neighbor_pe_export = (int *)HECMW_malloc(size);
2165 if (inter_tbl->neighbor_pe_export == NULL) {
2166 HECMW_set_error(errno, "");
2167 goto error;
2168 }
2169 for (n = 0, i = 0; i < comm_dst->psize; i++) {
2170 if (recvbuf[i] > 0) {
2171 inter_tbl->neighbor_pe_export[n++] = comm_dst->ranks[i];
2172 }
2173 }
2174 HECMW_assert(n == inter_tbl->n_neighbor_pe_export);
2175 }
2176 }
2177
2178 HECMW_free(send_pe);
2179 HECMW_free(sendbuf_index);
2180 HECMW_free(sendbuf);
2181 HECMW_free(recv_pe);
2182 HECMW_free(recvbuf_index);
2183 HECMW_free(recvbuf);
2184 return 0;
2185
2186error:
2187 HECMW_free(send_pe);
2188 HECMW_free(sendbuf_index);
2189 HECMW_free(sendbuf);
2190 HECMW_free(recv_pe);
2191 HECMW_free(recvbuf_index);
2192 HECMW_free(recvbuf);
2193 return -1;
2194}
2195
2196static int set_export_index(struct hecmw_couple_inter_iftable *inter_tbl,
2197 const struct hecmw_couple_comm *comm_src,
2198 const struct hecmw_couple_comm *comm_dst,
2199 const struct hecmw_couple_comm *intercomm) {
2200 int *sendbuf_index = NULL, *recvbuf_index = NULL, *sendbuf = NULL,
2201 *recvbuf = NULL;
2202 int size, rtc, i;
2203
2204 /*
2205 * send buffer (destination unit)
2206 */
2207 if (comm_dst->is_member) {
2208 /* index of send buffer */
2209 sendbuf_index =
2210 (int *)HECMW_calloc(inter_tbl->n_neighbor_pe_import + 1, sizeof(int));
2211 if (sendbuf_index == NULL) {
2212 HECMW_set_error(errno, "");
2213 goto error;
2214 }
2215 for (i = 0; i < inter_tbl->n_neighbor_pe_import; i++) {
2216 sendbuf_index[i + 1] = sendbuf_index[i] + 1;
2217 }
2218
2219 /* send buffer */
2220 sendbuf = (int *)HECMW_malloc(sizeof(int) *
2221 (inter_tbl->n_neighbor_pe_import + 1));
2222 if (sendbuf == NULL) {
2223 HECMW_set_error(errno, "");
2224 goto error;
2225 }
2226 for (i = 0; i < inter_tbl->n_neighbor_pe_import; i++) {
2227 sendbuf[i] = inter_tbl->import_index[i + 1] - inter_tbl->import_index[i];
2228 }
2229 }
2230
2231 /*
2232 * receive buffer (source unit)
2233 */
2234 if (comm_src->is_member) {
2235 /* index of receive buffer */
2236 recvbuf_index =
2237 (int *)HECMW_calloc(inter_tbl->n_neighbor_pe_export + 1, sizeof(int));
2238 if (recvbuf_index == NULL) {
2239 HECMW_set_error(errno, "");
2240 goto error;
2241 }
2242 for (i = 0; i < inter_tbl->n_neighbor_pe_export; i++) {
2243 recvbuf_index[i + 1] = recvbuf_index[i] + 1;
2244 }
2245
2246 /* receive buffer */
2247 recvbuf = (int *)HECMW_malloc(sizeof(int) *
2248 (inter_tbl->n_neighbor_pe_export + 1));
2249 if (recvbuf == NULL) {
2250 HECMW_set_error(errno, "");
2251 goto error;
2252 }
2253 }
2254
2255 if (inter_tbl->n_neighbor_pe_import == 0 &&
2256 inter_tbl->n_neighbor_pe_export == 0)
2257 return HECMW_SUCCESS;
2258
2259 /*
2260 * send and receive
2261 */
2263 inter_tbl->n_neighbor_pe_import, inter_tbl->neighbor_pe_import,
2264 sendbuf_index, sendbuf, inter_tbl->n_neighbor_pe_export,
2265 inter_tbl->neighbor_pe_export, recvbuf_index, recvbuf, HECMW_INT,
2266 intercomm->comm);
2267 if (rtc != 0) goto error;
2268
2269 /*
2270 * set index of export node for inter-communication (source unit)
2271 */
2272 if (comm_src->is_member) {
2273 inter_tbl->export_index = NULL;
2274 if (inter_tbl->n_neighbor_pe_export != 0) {
2275 size = inter_tbl->n_neighbor_pe_export + 1;
2276 inter_tbl->export_index = (int *)HECMW_calloc(size, sizeof(int));
2277 if (inter_tbl->export_index == NULL) {
2278 HECMW_set_error(errno, "");
2279 goto error;
2280 }
2281 for (i = 0; i < inter_tbl->n_neighbor_pe_export; i++) {
2282 inter_tbl->export_index[i + 1] =
2283 inter_tbl->export_index[i] + recvbuf[i];
2284 }
2285 }
2286 }
2287
2288 HECMW_free(sendbuf_index);
2289 HECMW_free(sendbuf);
2290 HECMW_free(recvbuf_index);
2291 HECMW_free(recvbuf);
2292 return 0;
2293
2294error:
2295 HECMW_free(sendbuf_index);
2296 HECMW_free(sendbuf);
2297 HECMW_free(recvbuf_index);
2298 HECMW_free(recvbuf);
2299 return -1;
2300}
2301
2302static int set_export_item(struct hecmw_couple_inter_iftable *inter_tbl,
2303 const struct hecmw_couple_comm *comm_src,
2304 const struct hecmw_couple_comm *comm_dst,
2305 const struct hecmw_couple_comm *intercomm,
2306 int *export_data) {
2307 int size, rtc, i;
2308
2309 if (inter_tbl->n_neighbor_pe_import == 0 &&
2310 inter_tbl->n_neighbor_pe_export == 0)
2311 return 0;
2312
2313 /*
2314 * receive buffer (source unit)
2315 */
2316 if (comm_src->is_member) {
2317 /* receive buffer */
2318 size = sizeof(int) *
2319 (inter_tbl->export_index[inter_tbl->n_neighbor_pe_export] + 1);
2320 inter_tbl->export_item = (int *)HECMW_malloc(size);
2321 if (inter_tbl->export_item == NULL) {
2322 HECMW_set_error(errno, "");
2323 goto error;
2324 }
2325 }
2326
2327 /*
2328 * send and receive
2329 */
2331 inter_tbl->n_neighbor_pe_import, inter_tbl->neighbor_pe_import,
2332 inter_tbl->import_index, export_data, inter_tbl->n_neighbor_pe_export,
2333 inter_tbl->neighbor_pe_export, inter_tbl->export_index,
2334 inter_tbl->export_item, HECMW_INT, intercomm->comm);
2335 if (rtc != 0) goto error;
2336
2337 return 0;
2338
2339error:
2340 return -1;
2341}
2342
2343static struct hecmw_couple_inter_iftable *set_inter_iftable(
2344 const struct hecmw_couple_comm *comm_src,
2345 const struct hecmw_couple_comm *comm_dst,
2346 const struct hecmw_couple_comm *intercomm, struct map_info **map_dst,
2347 const struct hecmw_couple_mapped_point *mapped_point) {
2348 struct hecmw_couple_inter_iftable *inter_tbl = NULL;
2349 struct link_list_map *mapping_data_list = NULL;
2350 int *export_data = NULL;
2351 int rtc;
2352
2353 /* allocation */
2355 if (inter_tbl == NULL) goto error;
2356
2357 /* import side */
2358 if (comm_dst->is_member) {
2359 mapping_data_list = set_mapping_surf(mapped_point, comm_src, map_dst);
2360 if (mapping_data_list == NULL) goto error;
2361
2362 rtc = set_neighbor_info_import(inter_tbl, mapping_data_list, comm_src);
2363 if (rtc != HECMW_SUCCESS) goto error;
2364
2365 export_data = set_export_data(inter_tbl, comm_src, mapping_data_list);
2366 if (export_data == NULL) goto error;
2367 }
2368
2369 /* export side */
2370 rtc = set_neighbor_pe_export(inter_tbl, comm_src, comm_dst, intercomm,
2371 mapping_data_list);
2372 if (rtc != HECMW_SUCCESS) goto error;
2373
2374 rtc = set_export_index(inter_tbl, comm_src, comm_dst, intercomm);
2375 if (rtc != HECMW_SUCCESS) goto error;
2376
2377 rtc = set_export_item(inter_tbl, comm_src, comm_dst, intercomm, export_data);
2378 if (rtc != HECMW_SUCCESS) goto error;
2379
2380 /* finalization */
2381 HECMW_free(export_data);
2382 return inter_tbl;
2383
2384error:
2385 HECMW_free(export_data);
2386 return NULL;
2387}
2388
2389/*================================================================================================*/
2390
2392 const struct hecmwST_local_mesh *mesh_src,
2393 const struct hecmwST_local_mesh *mesh_dst,
2394 const struct hecmw_couple_comm *comm_src,
2395 const struct hecmw_couple_comm *comm_dst,
2396 const struct hecmw_couple_comm *intercomm,
2397 const struct hecmw_couple_boundary *boundary_src,
2398 const struct hecmw_couple_bounding_box *bbox_src,
2399 const struct hecmw_couple_bounding_box *bbox_dst,
2400 const struct hecmw_couple_background_cell *bgcell_src,
2401 const struct hecmw_couple_mapped_point *mapped_point) {
2402 struct hecmw_couple_inter_iftable *inter_tbl = NULL;
2403 struct hecmw_couple_mapped_point **all_mapped_point = NULL;
2404 struct map_info **map_src = NULL, **map_dst = NULL;
2405 int **is_candidate = NULL;
2406 int size, rtc, i;
2407
2408 if (comm_src->is_member) {
2409 size = sizeof(struct hecmw_couple_mapped_point *) * comm_dst->psize;
2410 all_mapped_point = (struct hecmw_couple_mapped_point **)HECMW_malloc(size);
2411 if (all_mapped_point == NULL) {
2412 HECMW_set_error(errno, "");
2413 goto error;
2414 }
2415 for (i = 0; i < comm_dst->psize; i++) {
2416 all_mapped_point[i] = NULL;
2417 }
2418
2419 is_candidate = (int **)HECMW_malloc(sizeof(int *) * comm_dst->psize);
2420 if (is_candidate == NULL) {
2421 HECMW_set_error(errno, "");
2422 goto error;
2423 }
2424 for (i = 0; i < comm_dst->psize; i++) {
2425 is_candidate[i] = NULL;
2426 }
2427 }
2428
2429 rtc = bcast_mapped_point_d2s(mapped_point, comm_src, comm_dst, intercomm,
2430 all_mapped_point);
2431 if (rtc != HECMW_SUCCESS) goto error;
2432
2433 rtc = set_candidate_node(bbox_src, bbox_dst, comm_src, comm_dst, intercomm,
2434 all_mapped_point, is_candidate);
2435 if (rtc != HECMW_SUCCESS) goto error;
2436
2437 /* */
2438 if (comm_src->is_member) {
2439 map_src = (struct map_info **)HECMW_malloc(sizeof(struct map_info *) *
2440 comm_dst->psize);
2441 if (map_src == NULL) {
2442 HECMW_set_error(errno, "");
2443 goto error;
2444 }
2445 for (i = 0; i < comm_dst->psize; i++) {
2446 map_src[i] = NULL;
2447 }
2448 for (i = 0; i < comm_dst->psize; i++) {
2449 map_src[i] = alloc_struct_map_info();
2450 if (map_src[i] == NULL) goto error;
2451 }
2452 }
2453
2454 /* mapping on source unit */
2455 if (comm_src->is_member) {
2456 rtc = mapping_in_src(mesh_src, boundary_src, bbox_src, bgcell_src, comm_dst,
2457 all_mapped_point, is_candidate, map_src);
2458 if (rtc != HECMW_SUCCESS) goto error;
2459 }
2460
2461 if (all_mapped_point) {
2462 for (i = 0; i < comm_dst->psize; i++) {
2463 HECMW_couple_free_mapped_point(all_mapped_point[i]);
2464 }
2465 HECMW_free(all_mapped_point);
2466 }
2467 if (is_candidate) {
2468 for (i = 0; i < comm_dst->psize; i++) {
2469 HECMW_free(is_candidate[i]);
2470 }
2471 HECMW_free(is_candidate);
2472 }
2473
2474 /* mapping on destination unit */
2475 if (comm_dst->is_member) {
2476 map_dst = (struct map_info **)HECMW_malloc(sizeof(struct map_info *) *
2477 comm_dst->psize);
2478 if (map_dst == NULL) {
2479 HECMW_set_error(errno, "");
2480 goto error;
2481 }
2482 for (i = 0; i < comm_src->psize; i++) {
2483 map_dst[i] = NULL;
2484 }
2485 }
2486
2487 rtc = gather_map_data_s2d(mapped_point, map_src, comm_src, comm_dst,
2488 intercomm, map_dst);
2489 if (rtc != HECMW_SUCCESS) goto error;
2490
2491 /* construct interface table for inter-communicate */
2492 inter_tbl =
2493 set_inter_iftable(comm_src, comm_dst, intercomm, map_dst, mapped_point);
2494 if (inter_tbl == NULL) goto error;
2495
2496 return inter_tbl;
2497
2498error:
2499 if (all_mapped_point) {
2500 for (i = 0; i < comm_dst->psize; i++) {
2501 HECMW_couple_free_mapped_point(all_mapped_point[i]);
2502 }
2503 HECMW_free(all_mapped_point);
2504 }
2505 if (is_candidate) {
2506 for (i = 0; i < comm_dst->psize; i++) {
2507 HECMW_free(is_candidate[i]);
2508 }
2509 HECMW_free(is_candidate);
2510 }
2511 return NULL;
2512}
if(!(yy_init))
Definition: hecmw_ablex.c:1305
#define HECMW_ETYPE_HEX1
#define HECMW_ETYPE_TET1
#define HECMW_INT
Definition: hecmw_config.h:48
#define HECMW_DOUBLE
Definition: hecmw_config.h:50
#define HECMW_SUCCESS
Definition: hecmw_config.h:64
int 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)
int 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)
#define HECMWCPL_E_INVALID_MAPTYPE
#define HECMW_COUPLE_MAP_SURF_TO_SURF
#define HECMWCPL_E_NONSUPPORT_ETYPE
#define HECMW_COUPLE_MAP_NODE_TO_SURF
void HECMW_couple_free_inter_iftable(struct hecmw_couple_inter_iftable *p)
#define EPS
struct hecmw_couple_inter_iftable * HECMW_couple_alloc_inter_iftable(void)
#define INFINITE
struct hecmw_couple_inter_iftable * HECMW_couple_set_map_data(const struct hecmwST_local_mesh *mesh_src, const struct hecmwST_local_mesh *mesh_dst, const struct hecmw_couple_comm *comm_src, const struct hecmw_couple_comm *comm_dst, const struct hecmw_couple_comm *intercomm, const struct hecmw_couple_boundary *boundary_src, const struct hecmw_couple_bounding_box *bbox_src, const struct hecmw_couple_bounding_box *bbox_dst, const struct hecmw_couple_background_cell *bgcell_src, const struct hecmw_couple_mapped_point *mapped_point)
void HECMW_couple_print_inter_iftable(const struct hecmw_couple_inter_iftable *p, FILE *fp)
int HECMW_couple_judge_hex1(const struct hecmwST_local_mesh *local_mesh, int elem, int surf_id, double coord_px, double coord_py, double coord_pz, double *dot_product, double *distance)
int HECMW_couple_judge_tet1(const struct hecmwST_local_mesh *local_mesh, int elem, int surf_id, double coord_px, double coord_py, double coord_pz, double *dot_product, double *distance)
void HECMW_couple_free_mapped_point(struct hecmw_couple_mapped_point *p)
struct hecmw_couple_mapped_point * HECMW_couple_alloc_mapped_point(void)
int HECMW_set_error(int errorno, const char *fmt,...)
Definition: hecmw_error.c:37
#define NULL
#define HECMW_calloc(nmemb, size)
Definition: hecmw_malloc.h:21
#define HECMW_free(ptr)
Definition: hecmw_malloc.h:24
#define HECMW_malloc(size)
Definition: hecmw_malloc.h:20
#define HECMW_assert(cond)
Definition: hecmw_util.h:40
struct hecmw_couple_boundary_item * elem
struct hecmw_couple_boundary_item * node
struct hecmw_couple_boundary_item * surf
struct hecmw_couple_box * enlarged
struct link_list * list