| 1 | #BHEADER**********************************************************************
|
|---|
| 2 | # Copyright (c) 2008, Lawrence Livermore National Security, LLC.
|
|---|
| 3 | # Produced at the Lawrence Livermore National Laboratory.
|
|---|
| 4 | # This file is part of HYPRE. See file COPYRIGHT for details.
|
|---|
| 5 | #
|
|---|
| 6 | # HYPRE is free software; you can redistribute it and/or modify it under the
|
|---|
| 7 | # terms of the GNU Lesser General Public License (as published by the Free
|
|---|
| 8 | # Software Foundation) version 2.1 dated February 1999.
|
|---|
| 9 | #
|
|---|
| 10 | # $Revision: 2.4 $
|
|---|
| 11 | #EHEADER**********************************************************************
|
|---|
| 12 |
|
|---|
| 13 |
|
|---|
| 14 | README for the hypre_DataExchangeList() function
|
|---|
| 15 |
|
|---|
| 16 | **************
|
|---|
| 17 | * Purpose: *
|
|---|
| 18 | **************
|
|---|
| 19 |
|
|---|
| 20 | This function allows a processor (i) to "contact" a list of processors
|
|---|
| 21 | with a message containing a variable amount of data. The processors
|
|---|
| 22 | in the list do not know that they will be contacted by processor
|
|---|
| 23 | i. These processors must then send a "response" message back to
|
|---|
| 24 | processor i, and the response message can also contain any amount of
|
|---|
| 25 | data.
|
|---|
| 26 |
|
|---|
| 27 | Essentially, the user gives the function a list of processors and
|
|---|
| 28 | corresponding lists of data (of any type) to send to each processor.
|
|---|
| 29 | The function returns lists of data (the "responses") from each of the
|
|---|
| 30 | contacted processors. The user must write a function that dictates
|
|---|
| 31 | how to create a response message based on a contact message.
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 | ***************
|
|---|
| 35 | * Function: *
|
|---|
| 36 | ***************
|
|---|
| 37 |
|
|---|
| 38 | int hypre_DataExchangeList(int num_contacts,
|
|---|
| 39 | int *contact_proc_list, void *contact_send_buf,
|
|---|
| 40 | int *contact_send_buf_starts, int contact_obj_size,
|
|---|
| 41 | int response_obj_size,
|
|---|
| 42 | hypre_DataExchangeResponse *response_obj,
|
|---|
| 43 | int max_response_size, int rnum,
|
|---|
| 44 | MPI_Comm comm, void **p_response_recv_buf,
|
|---|
| 45 | int **p_response_recv_buf_starts)
|
|---|
| 46 |
|
|---|
| 47 |
|
|---|
| 48 | *****************
|
|---|
| 49 | * Parameters: *
|
|---|
| 50 | *****************
|
|---|
| 51 |
|
|---|
| 52 | num_contacts = the number of processors to contact
|
|---|
| 53 |
|
|---|
| 54 | contact_proc_list = list of processors to contact
|
|---|
| 55 |
|
|---|
| 56 | contact_send_buf = array of data to send - data may be any type
|
|---|
| 57 | (ints, doubles, structures, etc.).
|
|---|
| 58 |
|
|---|
| 59 | contact_send_buf_starts = index into contact_send_buf
|
|---|
| 60 | corresponding to contact_proc_list. For example, processor
|
|---|
| 61 | (contact_proc_list[j]) is sent the buffer
|
|---|
| 62 | contact_send_buf[contact_send_buf_starts[j]], and this buffer is
|
|---|
| 63 | of size (contact_send_buf_starts[j+1] - contact_send_buf_starts[j]).
|
|---|
| 64 |
|
|---|
| 65 | contact_obj_size = sizeof() one data item (int, double, structure, etc.) in
|
|---|
| 66 | contact_send_buf. THIS NEEDS TO BE THE SAME
|
|---|
| 67 | NUMBER FOR ALL PROCESSORS.
|
|---|
| 68 |
|
|---|
| 69 | response_obj_size = sizeof() one data item in response_recv_buf(int,
|
|---|
| 70 | double, structure, etc.) THIS NEEDS TO BE THE SAME
|
|---|
| 71 | NUMBER FOR ALL PROCESSORS.
|
|---|
| 72 |
|
|---|
| 73 | response_obj = this will give us the function we need to fill the
|
|---|
| 74 | response as well as any data we might need to
|
|---|
| 75 | accomplish that (more details below.)
|
|---|
| 76 |
|
|---|
| 77 |
|
|---|
| 78 | max_response_size - this number indicates the size of the
|
|---|
| 79 | array of data that the contacting processor expects back in a single response.
|
|---|
| 80 | This should be a reasonable estimate - not an absolute upper bound!
|
|---|
| 81 | If a contacted processor needs to respond with more than
|
|---|
| 82 | max_response_size data, then a second communication is used - this is
|
|---|
| 83 | transparent to the user and occurs inside hypre_DataExchangeList().
|
|---|
| 84 | Choosing a max_response_size that is way too large will result in
|
|---|
| 85 | the passing of overly large messages. THIS NEEDS TO BE THE SAME
|
|---|
| 86 | NUMBER FOR ALL PROCESSORS.
|
|---|
| 87 |
|
|---|
| 88 |
|
|---|
| 89 | rnum = two consecutive calls to this function should have
|
|---|
| 90 | different rnums. Recommend alternating rnum = 1 and rnum=2 - these
|
|---|
| 91 | flags will be even (so odd numbered tags could be used in calling
|
|---|
| 92 | code in between). THIS NEEDS TO BE THE SAME
|
|---|
| 93 | NUMBER FOR ALL PROCESSORS.
|
|---|
| 94 |
|
|---|
| 95 |
|
|---|
| 96 | comm = MPI_COMM
|
|---|
| 97 |
|
|---|
| 98 | p_response_recv_buf = (OUTPUT) where to receive the responses -
|
|---|
| 99 | memory will be allocated in this function (do not preallocate)
|
|---|
| 100 |
|
|---|
| 101 | p_response_recv_buf_starts = (OUTPUT) index of p_response_buf corresponding to
|
|---|
| 102 | contact_buf_list - memory will be allocated in this function
|
|---|
| 103 |
|
|---|
| 104 | **********************
|
|---|
| 105 | * Response Object: *
|
|---|
| 106 | **********************
|
|---|
| 107 |
|
|---|
| 108 | This object has a function pointer to assign before including it in a
|
|---|
| 109 | call to hypre_DataExchangeList(). In addition, one or more of the void
|
|---|
| 110 | pointers may be set. Each item in the structure is explained below.
|
|---|
| 111 |
|
|---|
| 112 | typedef struct
|
|---|
| 113 | {
|
|---|
| 114 | int (*fill_response)(void* recv_buf,
|
|---|
| 115 | int contact_size, int contact_proc,
|
|---|
| 116 | void* response_obj, MPI_Comm comm,
|
|---|
| 117 | void** response_buf, int* response_message_size, );
|
|---|
| 118 | int send_response_overhead;
|
|---|
| 119 | int send_response_storage;
|
|---|
| 120 | void *data1;
|
|---|
| 121 | void *data2;
|
|---|
| 122 |
|
|---|
| 123 | } hypre_DataExchangeResponse;
|
|---|
| 124 |
|
|---|
| 125 |
|
|---|
| 126 | int (*fill_response)(void* recv_buf,
|
|---|
| 127 | int contact_size, int contact_proc,
|
|---|
| 128 | void* response_obj, MPI_Comm comm,
|
|---|
| 129 | void** response_buf,
|
|---|
| 130 | int* response_message_size, );
|
|---|
| 131 |
|
|---|
| 132 | The user writes a function to assign to this pointer. This function
|
|---|
| 133 | is called by hypre_DataExchangeList() upon receipt of a contact message
|
|---|
| 134 | and must determine a response. The data from the contact message is
|
|---|
| 135 | stored in recv_buf, where contact_size indicates the number of
|
|---|
| 136 | objects and contact_proc indicates the processor that made the
|
|---|
| 137 | contact. The user will know the data type and can manipulate
|
|---|
| 138 | recv_buf accordingly. Likewise, the user can populate response_buf as
|
|---|
| 139 | desired - this will constitute the response message. The user must
|
|---|
| 140 | indicate the size of the response in response_message_size. Note
|
|---|
| 141 | that response_message_size and contact_size are NOT in bytes - but
|
|---|
| 142 | rather the number of objects sent (i.e. contact size = 4 if four
|
|---|
| 143 | integers or structures were sent).
|
|---|
| 144 |
|
|---|
| 145 | Note 1: If the desired response to contact messages is a NULL
|
|---|
| 146 | response (a confirmation), simply assign response_message_size to
|
|---|
| 147 | zero - do NOT set the response_buf to NULL.
|
|---|
| 148 |
|
|---|
| 149 | Note 2: cast the response_obj argument to a hypre_DataExchangeResponse
|
|---|
| 150 | object to access the data fields.
|
|---|
| 151 |
|
|---|
| 152 | send_response_storage - this number indicates the amount of storage
|
|---|
| 153 | (again not in bytes) available for the response_buf
|
|---|
| 154 | objects. The user should make sure they do not need to write a
|
|---|
| 155 | larger amount of data than is available. If more storage is needed
|
|---|
| 156 | then adjust the send_response_storage variable to indicate the new size
|
|---|
| 157 | desired. Then realloc response_buf to size (send_response_storage +
|
|---|
| 158 | send_response_overhead)*(size of response object).
|
|---|
| 159 |
|
|---|
| 160 | send_response_overhead - this is extra overhead needed by
|
|---|
| 161 | hypre_DataExchangeList. Include this if you need to realloc response_buf
|
|---|
| 162 | (see previous entry). This is determined by the hypre_DataExchangeFunction().
|
|---|
| 163 |
|
|---|
| 164 | data1, data2 - these are void pointers that the user may want
|
|---|
| 165 | to assign to data from the program that calls exchangeDataList()
|
|---|
| 166 | in the event that (1) certain data is needed to formulate an
|
|---|
| 167 | appropriate response or (2) data needs to be saved from the
|
|---|
| 168 | contacts to be manipulated after hypre_DataExchangeList() completes.
|
|---|
| 169 |
|
|---|