|
|
|
1 |
/* $Id: Coupler.c 1306 2007-09-18 05:51:09Z ksteube $ */ |
/* $Id: Coupler.c 1306 2007-09-18 05:51:09Z ksteube $ */ |
2 |
|
|
3 |
/******************************************************* |
/******************************************************* |
10 |
* Licensed under the Open Software License version 3.0 |
* Licensed under the Open Software License version 3.0 |
11 |
* http://www.opensource.org/licenses/osl-3.0.php |
* http://www.opensource.org/licenses/osl-3.0.php |
12 |
* |
* |
13 |
*******************************************************/ |
************************************************************** |
14 |
|
* |
15 |
/**************************************************************/ |
* Paso: Connector and Coupler organizes the coupling with in a pattern/matrix |
16 |
|
* across processors |
17 |
|
* |
18 |
|
************************************************************** |
19 |
|
* |
20 |
|
* Author: gross@access.edu.au |
21 |
|
* |
22 |
|
**************************************************************/ |
23 |
|
|
24 |
/* Paso: Coupler organizes the coupling with in a pattern/matrix */ |
#include "Coupler.h" |
|
/* across processors */ |
|
25 |
|
|
26 |
/**************************************************************/ |
/************************************************************* |
27 |
|
* |
28 |
/* Author: gross@access.edu.au */ |
* allocates a Connector |
29 |
|
* |
30 |
|
**************************************************************/ |
31 |
|
|
32 |
/**************************************************************/ |
Paso_Connector* Paso_Connector_alloc(Paso_SharedComponents* send, |
33 |
|
Paso_SharedComponents* recv) |
34 |
|
{ |
35 |
|
Paso_Connector*out=NULL; |
36 |
|
Paso_resetError(); |
37 |
|
out=MEMALLOC(1,Paso_Connector); |
38 |
|
if ( send->mpi_info != recv->mpi_info ) { |
39 |
|
Paso_setError(SYSTEM_ERROR,"Paso_Coupler_alloc: send and recv mpi communicator don't match."); |
40 |
|
return NULL; |
41 |
|
} |
42 |
|
if ( send->local_length != recv->local_length ) { |
43 |
|
Paso_setError(SYSTEM_ERROR,"Paso_Coupler_alloc: local length of send and recv Paso_SharedComponents must match."); |
44 |
|
return NULL; |
45 |
|
} |
46 |
|
|
47 |
|
if (!Paso_checkPtr(out)) { |
48 |
|
out->send=Paso_SharedComponents_getReference(send); |
49 |
|
out->recv= Paso_SharedComponents_getReference(recv); |
50 |
|
out->mpi_info = Paso_MPIInfo_getReference(send->mpi_info); |
51 |
|
out->reference_counter=1; |
52 |
|
} |
53 |
|
if (Paso_noError()) { |
54 |
|
return out; |
55 |
|
} else { |
56 |
|
Paso_Connector_free(out); |
57 |
|
return NULL; |
58 |
|
} |
59 |
|
} |
60 |
|
|
61 |
#include "Coupler.h" |
/* returns a reference to Connector */ |
62 |
|
|
63 |
/**************************************************************/ |
Paso_Connector* Paso_Connector_getReference(Paso_Connector* in) { |
64 |
|
if (in!=NULL) { |
65 |
|
++(in->reference_counter); |
66 |
|
} |
67 |
|
return in; |
68 |
|
} |
69 |
|
|
70 |
|
/* deallocates a Connector: */ |
71 |
|
|
72 |
/* allocates a Coupler */ |
void Paso_Connector_free(Paso_Connector* in) { |
73 |
|
if (in!=NULL) { |
74 |
|
in->reference_counter--; |
75 |
|
if (in->reference_counter<=0) { |
76 |
|
Paso_SharedComponents_free(in->send); |
77 |
|
Paso_SharedComponents_free(in->recv); |
78 |
|
Paso_MPIInfo_free(in->mpi_info); |
79 |
|
MEMFREE(in); |
80 |
|
#ifdef Paso_TRACE |
81 |
|
printf("Paso_Coupler_dealloc: system matrix pattern as been deallocated.\n"); |
82 |
|
#endif |
83 |
|
} |
84 |
|
} |
85 |
|
} |
86 |
|
|
87 |
|
Paso_Connector* Paso_Connector_copy(Paso_Connector* in) { |
88 |
|
return Paso_Connector_unroll(in,1); |
89 |
|
} |
90 |
|
|
91 |
/**************************************************************/ |
Paso_Connector* Paso_Connector_unroll(Paso_Connector* in, index_t block_size) { |
92 |
|
Paso_SharedComponents *new_send_shcomp=NULL, *new_recv_shcomp=NULL; |
93 |
|
Paso_Connector *out=NULL; |
94 |
|
if (Paso_noError()) { |
95 |
|
if (block_size>1) { |
96 |
|
new_send_shcomp=Paso_SharedComponents_alloc(in->send->local_length, |
97 |
|
in->send->numNeighbors, |
98 |
|
in->send->neighbor, |
99 |
|
in->send->shared, |
100 |
|
in->send->offsetInShared, |
101 |
|
block_size,0,in->mpi_info); |
102 |
|
|
103 |
|
new_recv_shcomp=Paso_SharedComponents_alloc(in->recv->local_length, |
104 |
|
in->recv->numNeighbors, |
105 |
|
in->recv->neighbor, |
106 |
|
in->recv->shared, |
107 |
|
in->recv->offsetInShared, |
108 |
|
block_size,0,in->mpi_info); |
109 |
|
} else { |
110 |
|
new_send_shcomp=Paso_SharedComponents_getReference(in->send); |
111 |
|
new_recv_shcomp=Paso_SharedComponents_getReference(in->recv); |
112 |
|
} |
113 |
|
if (Paso_noError()) out=Paso_Connector_alloc(new_send_shcomp,new_recv_shcomp); |
114 |
|
} |
115 |
|
Paso_SharedComponents_free(new_send_shcomp); |
116 |
|
Paso_SharedComponents_free(new_recv_shcomp); |
117 |
|
if (Paso_noError()) { |
118 |
|
return out; |
119 |
|
} else { |
120 |
|
Paso_Connector_free(out); |
121 |
|
return NULL; |
122 |
|
} |
123 |
|
} |
124 |
|
/************************************************************* |
125 |
|
* |
126 |
|
* allocates a Connector |
127 |
|
* |
128 |
|
**************************************************************/ |
129 |
|
|
130 |
Paso_Coupler* Paso_Coupler_alloc(Paso_SharedComponents* send, |
Paso_Coupler* Paso_Coupler_alloc(Paso_Connector* connector, dim_t block_size) |
|
Paso_SharedComponents* recv) |
|
131 |
{ |
{ |
132 |
|
Paso_MPIInfo *mpi_info = connector->mpi_info; |
133 |
Paso_Coupler*out=NULL; |
Paso_Coupler*out=NULL; |
134 |
Paso_resetError(); |
Paso_resetError(); |
135 |
out=MEMALLOC(1,Paso_Coupler); |
out=MEMALLOC(1,Paso_Coupler); |
|
if ( send->mpi_info != recv->mpi_info ) { |
|
|
Paso_setError(SYSTEM_ERROR,"Paso_Coupler_alloc: send and recv mpi communicator don't match."); |
|
|
return NULL; |
|
|
} |
|
136 |
if (!Paso_checkPtr(out)) { |
if (!Paso_checkPtr(out)) { |
137 |
out->send=Paso_SharedComponents_getReference(send); |
out->data=NULL; |
138 |
|
out->block_size=block_size; |
139 |
|
out->connector=Paso_Connector_getReference(connector); |
140 |
out->send_buffer=NULL; |
out->send_buffer=NULL; |
|
out->recv= Paso_SharedComponents_getReference(recv); |
|
141 |
out->recv_buffer=NULL; |
out->recv_buffer=NULL; |
142 |
out->mpi_requests=NULL; |
out->mpi_requests=NULL; |
143 |
out->mpi_stati=NULL; |
out->mpi_stati=NULL; |
144 |
out->mpi_info = Paso_MPIInfo_getReference(send->mpi_info); |
out->mpi_info = Paso_MPIInfo_getReference(mpi_info); |
145 |
out->reference_counter=1; |
out->reference_counter=1; |
146 |
|
|
147 |
#ifdef PASO_MPI |
#ifdef PASO_MPI |
148 |
out->mpi_requests=MEMALLOC(send->numNeighbors+recv->numNeighbors,MPI_Request); |
out->mpi_requests=MEMALLOC(connector->send->numNeighbors+connector->recv->numNeighbors,MPI_Request); |
149 |
out->mpi_stati=MEMALLOC(send->numNeighbors+recv->numNeighbors,MPI_Status); |
out->mpi_stati=MEMALLOC(connector->send->numNeighbors+connector->recv->numNeighbors,MPI_Status); |
150 |
Paso_checkPtr(out->mpi_requests); |
Paso_checkPtr(out->mpi_requests); |
151 |
Paso_checkPtr(out->mpi_stati); |
Paso_checkPtr(out->mpi_stati); |
152 |
#endif |
#endif |
153 |
|
if (mpi_info->size>1) { |
154 |
|
out->send_buffer=MEMALLOC(connector->send->numSharedComponents * block_size,double); |
155 |
|
out->recv_buffer=MEMALLOC(connector->recv->numSharedComponents * block_size,double); |
156 |
|
Paso_checkPtr(out->send_buffer); |
157 |
|
Paso_checkPtr(out->recv_buffer); |
158 |
|
} |
159 |
} |
} |
160 |
if (Paso_noError()) { |
if (Paso_noError()) { |
161 |
return out; |
return out; |
165 |
} |
} |
166 |
} |
} |
167 |
|
|
168 |
/* returns a reference to in */ |
/* returns a reference to Coupler */ |
169 |
|
|
170 |
Paso_Coupler* Paso_Coupler_getReference(Paso_Coupler* in) { |
Paso_Coupler* Paso_Coupler_getReference(Paso_Coupler* in) { |
171 |
if (in!=NULL) { |
if (in!=NULL) { |
180 |
if (in!=NULL) { |
if (in!=NULL) { |
181 |
in->reference_counter--; |
in->reference_counter--; |
182 |
if (in->reference_counter<=0) { |
if (in->reference_counter<=0) { |
183 |
Paso_SharedComponents_free(in->send); |
Paso_Connector_free(in->connector); |
184 |
MEMFREE(in->send_buffer); |
MEMFREE(in->send_buffer); |
|
Paso_SharedComponents_free(in->recv); |
|
185 |
MEMFREE(in->recv_buffer); |
MEMFREE(in->recv_buffer); |
186 |
MEMFREE(in->mpi_requests); |
MEMFREE(in->mpi_requests); |
187 |
MEMFREE(in->mpi_stati); |
MEMFREE(in->mpi_stati); |
194 |
} |
} |
195 |
} |
} |
196 |
|
|
|
bool_t Paso_Coupler_bufferIsAllocated(Paso_Coupler* coupler) { |
|
|
return ( (coupler->send_buffer !=NULL) || (coupler->recv_buffer!=NULL) ); |
|
|
} |
|
|
|
|
|
void Paso_Coupler_allocBuffer(Paso_Coupler* coupler,dim_t block_size) |
|
|
{ |
|
|
Paso_MPIInfo *mpi_info = coupler->mpi_info; |
|
|
if (Paso_Coupler_bufferIsAllocated(coupler)) { |
|
|
Paso_setError(SYSTEM_ERROR,"Paso_Coupler_allocBuffer: coupler are still in use."); |
|
|
return; |
|
|
} |
|
|
coupler->block_size=block_size; |
|
|
if (coupler->mpi_info->size>1) { |
|
|
coupler->send_buffer=MEMALLOC(coupler->send->numSharedComponents * coupler->block_size,double); |
|
|
coupler->recv_buffer=MEMALLOC(coupler->recv->numSharedComponents * coupler->block_size,double); |
|
|
if (Paso_checkPtr(coupler->send_buffer) || Paso_checkPtr(coupler->recv_buffer) ) { |
|
|
TMPMEMFREE(coupler->send_buffer); |
|
|
TMPMEMFREE(coupler->recv_buffer); |
|
|
} |
|
|
} |
|
|
return; |
|
|
} |
|
|
void Paso_Coupler_freeBuffer(Paso_Coupler* coupler) |
|
|
{ |
|
|
|
|
|
if (coupler->mpi_info->size>1) { |
|
|
MEMFREE(coupler->send_buffer); |
|
|
MEMFREE(coupler->recv_buffer); |
|
|
} |
|
|
return; |
|
|
} |
|
197 |
|
|
198 |
void Paso_Coupler_startCollect(Paso_Coupler* coupler,const double* in) |
void Paso_Coupler_startCollect(Paso_Coupler* coupler,const double* in) |
199 |
{ |
{ |
200 |
Paso_MPIInfo *mpi_info = coupler->mpi_info; |
Paso_MPIInfo *mpi_info = coupler->mpi_info; |
201 |
dim_t block_size=coupler->block_size; |
dim_t block_size=coupler->block_size; |
202 |
size_t block_size_size=block_size*sizeof(double); |
size_t block_size_size=block_size*sizeof(double); |
203 |
dim_t i,j; |
dim_t i; |
204 |
|
coupler->data=(double*) in; |
205 |
if ( mpi_info->size>1) { |
if ( mpi_info->size>1) { |
206 |
/* start reveiving input */ |
/* start reveiving input */ |
|
#pragma omp master |
|
207 |
{ |
{ |
208 |
for (i=0; i< coupler->recv->numNeighbors; ++i) { |
for (i=0; i< coupler->connector->recv->numNeighbors; ++i) { |
209 |
#ifdef PASO_MPI |
#ifdef PASO_MPI |
210 |
MPI_Irecv(&(coupler->recv_buffer[coupler->recv->offsetInShared[i] * block_size]), |
MPI_Irecv(&(coupler->recv_buffer[coupler->connector->recv->offsetInShared[i] * block_size]), |
211 |
(coupler->recv->offsetInShared[i+1]- coupler->recv->offsetInShared[i])*block_size, |
(coupler->connector->recv->offsetInShared[i+1]- coupler->connector->recv->offsetInShared[i])*block_size, |
212 |
MPI_DOUBLE, |
MPI_DOUBLE, |
213 |
coupler->recv->neighbor[i], |
coupler->connector->recv->neighbor[i], |
214 |
mpi_info->msg_tag_counter+coupler->recv->neighbor[i], |
mpi_info->msg_tag_counter+coupler->connector->recv->neighbor[i], |
215 |
mpi_info->comm, |
mpi_info->comm, |
216 |
&(coupler->mpi_requests[i])); |
&(coupler->mpi_requests[i])); |
217 |
#endif |
#endif |
220 |
} |
} |
221 |
/* collect values into buffer */ |
/* collect values into buffer */ |
222 |
#pragma omp parallel for private(i) |
#pragma omp parallel for private(i) |
223 |
for (i=0; i < coupler->send->numSharedComponents;++i) { |
for (i=0; i < coupler->connector->send->numSharedComponents;++i) { |
224 |
memcpy(&(coupler->send_buffer[(block_size)*i]),&(in[ block_size * coupler->send->shared[i]]), block_size_size); |
memcpy(&(coupler->send_buffer[(block_size)*i]),&(in[ block_size * coupler->connector->send->shared[i]]), block_size_size); |
225 |
} |
} |
226 |
/* send buffer out */ |
/* send buffer out */ |
|
#pragma omp master |
|
227 |
{ |
{ |
228 |
for (i=0; i< coupler->send->numNeighbors; ++i) { |
for (i=0; i< coupler->connector->send->numNeighbors; ++i) { |
229 |
#ifdef PASO_MPI |
#ifdef PASO_MPI |
230 |
MPI_Issend(&(coupler->send_buffer[coupler->send->offsetInShared[i] * block_size]), |
MPI_Issend(&(coupler->send_buffer[coupler->connector->send->offsetInShared[i] * block_size]), |
231 |
(coupler->send->offsetInShared[i+1]- coupler->send->offsetInShared[i])*block_size, |
(coupler->connector->send->offsetInShared[i+1]- coupler->connector->send->offsetInShared[i])*block_size, |
232 |
MPI_DOUBLE, |
MPI_DOUBLE, |
233 |
coupler->send->neighbor[i], |
coupler->connector->send->neighbor[i], |
234 |
mpi_info->msg_tag_counter+mpi_info->rank, |
mpi_info->msg_tag_counter+mpi_info->rank, |
235 |
mpi_info->comm, |
mpi_info->comm, |
236 |
&(coupler->mpi_requests[i+ coupler->recv->numNeighbors])); |
&(coupler->mpi_requests[i+ coupler->connector->recv->numNeighbors])); |
237 |
#endif |
#endif |
238 |
} |
} |
239 |
} |
} |
240 |
mpi_info->msg_tag_counter+mpi_info->size; |
mpi_info->msg_tag_counter+=mpi_info->size; |
241 |
} |
} |
242 |
} |
} |
243 |
|
|
246 |
Paso_MPIInfo *mpi_info = coupler->mpi_info; |
Paso_MPIInfo *mpi_info = coupler->mpi_info; |
247 |
if ( mpi_info->size>1) { |
if ( mpi_info->size>1) { |
248 |
/* wait for receive */ |
/* wait for receive */ |
|
#pragma omp master |
|
|
{ |
|
249 |
#ifdef PASO_MPI |
#ifdef PASO_MPI |
250 |
MPI_Waitall(coupler->recv->numNeighbors+coupler->send->numNeighbors, |
MPI_Waitall(coupler->connector->recv->numNeighbors+coupler->connector->send->numNeighbors, |
251 |
coupler->mpi_requests, |
coupler->mpi_requests, |
252 |
coupler->mpi_stati); |
coupler->mpi_stati); |
253 |
#endif |
#endif |
|
} |
|
254 |
} |
} |
255 |
return coupler->recv_buffer; |
return coupler->recv_buffer; |
256 |
} |
} |
257 |
|
dim_t Paso_Coupler_getLocalLength(const Paso_Coupler* in) { |
258 |
|
return in->connector->send->local_length; |
259 |
|
|
260 |
Paso_Coupler* Paso_Coupler_unroll(Paso_Coupler* in, index_t block_size) { |
} |
261 |
Paso_SharedComponents *new_send_shcomp=NULL, *new_recv_shcomp=NULL; |
void Paso_Coupler_copyAll(const Paso_Coupler* src, Paso_Coupler* target) |
262 |
Paso_Coupler *out=NULL; |
{ |
263 |
if (Paso_noError()) { |
dim_t i; |
264 |
if (block_size>1) { |
#pragma omp parallel |
265 |
new_send_shcomp=Paso_SharedComponents_alloc(in->send->numNeighbors, |
{ |
266 |
in->send->neighbor, |
#pragma omp for private(i) |
267 |
in->send->shared, |
for (i =0; i< src->connector->recv->numSharedComponents * src->block_size; ++i) { |
268 |
in->send->offsetInShared, |
target->recv_buffer[i]=src->recv_buffer[i]; |
269 |
block_size,0,in->mpi_info); |
} |
270 |
|
#pragma omp for private(i) |
271 |
new_recv_shcomp=Paso_SharedComponents_alloc(in->recv->numNeighbors, |
for (i =0; i< Paso_Coupler_getLocalLength(src) * src->block_size; ++i) { |
272 |
in->recv->neighbor, |
target->data[i]=src->data[i]; |
|
in->recv->shared, |
|
|
in->recv->offsetInShared, |
|
|
block_size,0,in->mpi_info); |
|
|
} else { |
|
|
new_send_shcomp=Paso_SharedComponents_getReference(in->send); |
|
|
new_recv_shcomp=Paso_SharedComponents_getReference(in->recv); |
|
|
} |
|
|
if (Paso_noError()) out=Paso_Coupler_alloc(new_send_shcomp,new_recv_shcomp); |
|
273 |
} |
} |
274 |
Paso_SharedComponents_free(new_send_shcomp); |
} |
|
Paso_SharedComponents_free(new_recv_shcomp); |
|
|
if (Paso_noError()) { |
|
|
return out; |
|
|
} else { |
|
|
Paso_Coupler_free(out); |
|
|
return NULL; |
|
|
} |
|
|
|
|
275 |
} |
} |
|
|
|