/[escript]/trunk/paso/src/Coupler.c
ViewVC logotype

Contents of /trunk/paso/src/Coupler.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2385 - (show annotations)
Wed Apr 15 03:52:38 2009 UTC (10 years, 5 months ago) by gross
File MIME type: text/plain
File size: 9899 byte(s)
two fixes dealing with zero samples under MPI
1
2 /*******************************************************
3 *
4 * Copyright (c) 2003-2008 by University of Queensland
5 * Earth Systems Science Computational Center (ESSCC)
6 * http://www.uq.edu.au/esscc
7 *
8 * Primary Business: Queensland, Australia
9 * Licensed under the Open Software License version 3.0
10 * http://www.opensource.org/licenses/osl-3.0.php
11 *
12 *******************************************************/
13
14
15 #include "Coupler.h"
16
17 /*************************************************************
18 *
19 * allocates a Connector
20 *
21 **************************************************************/
22
23 Paso_Connector* Paso_Connector_alloc(Paso_SharedComponents* send,
24 Paso_SharedComponents* recv)
25 {
26 Paso_Connector*out=NULL;
27 Paso_resetError();
28 out=MEMALLOC(1,Paso_Connector);
29 if ( send->mpi_info != recv->mpi_info ) {
30 Paso_setError(SYSTEM_ERROR,"Paso_Coupler_alloc: send and recv mpi communicator don't match.");
31 return NULL;
32 }
33 if ( send->local_length != recv->local_length ) {
34 Paso_setError(SYSTEM_ERROR,"Paso_Coupler_alloc: local length of send and recv Paso_SharedComponents must match.");
35 return NULL;
36 }
37
38 if (!Paso_checkPtr(out)) {
39 out->send=Paso_SharedComponents_getReference(send);
40 out->recv= Paso_SharedComponents_getReference(recv);
41 out->mpi_info = Paso_MPIInfo_getReference(send->mpi_info);
42 out->reference_counter=1;
43
44 /*
45 { int i;
46 for (i=0; i< out->recv->numNeighbors; ++i)
47 printf("Coupler: %d receive %d data at %d from %d\n",send->mpi_info->rank,out->recv->offsetInShared[i+1]- out->recv->offsetInShared[i],
48 out->recv->offsetInShared[i],out->recv->neighbor[i]);
49 for (i=0; i< out->send->numNeighbors; ++i)
50 printf("Coupler: %d send %d data at %d to %d\n",send->mpi_info->rank,out->send->offsetInShared[i+1]- out->send->offsetInShared[i],
51 out->send->offsetInShared[i],out->send->neighbor[i]);
52 }
53 */
54
55 }
56 if (Paso_noError()) {
57 return out;
58 } else {
59 Paso_Connector_free(out);
60 return NULL;
61 }
62 }
63
64 /* returns a reference to Connector */
65
66 Paso_Connector* Paso_Connector_getReference(Paso_Connector* in) {
67 if (in!=NULL) {
68 ++(in->reference_counter);
69 }
70 return in;
71 }
72
73 /* deallocates a Connector: */
74
75 void Paso_Connector_free(Paso_Connector* in) {
76 if (in!=NULL) {
77 in->reference_counter--;
78 if (in->reference_counter<=0) {
79 Paso_SharedComponents_free(in->send);
80 Paso_SharedComponents_free(in->recv);
81 Paso_MPIInfo_free(in->mpi_info);
82 MEMFREE(in);
83 #ifdef Paso_TRACE
84 printf("Paso_Coupler_dealloc: system matrix pattern as been deallocated.\n");
85 #endif
86 }
87 }
88 }
89
90 Paso_Connector* Paso_Connector_copy(Paso_Connector* in) {
91 return Paso_Connector_unroll(in,1);
92 }
93
94 Paso_Connector* Paso_Connector_unroll(Paso_Connector* in, index_t block_size) {
95 Paso_SharedComponents *new_send_shcomp=NULL, *new_recv_shcomp=NULL;
96 Paso_Connector *out=NULL;
97 if (Paso_noError()) {
98 if (block_size>1) {
99 new_send_shcomp=Paso_SharedComponents_alloc(in->send->local_length,
100 in->send->numNeighbors,
101 in->send->neighbor,
102 in->send->shared,
103 in->send->offsetInShared,
104 block_size,0,in->mpi_info);
105
106 new_recv_shcomp=Paso_SharedComponents_alloc(in->recv->local_length,
107 in->recv->numNeighbors,
108 in->recv->neighbor,
109 in->recv->shared,
110 in->recv->offsetInShared,
111 block_size,0,in->mpi_info);
112 } else {
113 new_send_shcomp=Paso_SharedComponents_getReference(in->send);
114 new_recv_shcomp=Paso_SharedComponents_getReference(in->recv);
115 }
116 if (Paso_noError()) out=Paso_Connector_alloc(new_send_shcomp,new_recv_shcomp);
117 }
118 Paso_SharedComponents_free(new_send_shcomp);
119 Paso_SharedComponents_free(new_recv_shcomp);
120 if (Paso_noError()) {
121 return out;
122 } else {
123 Paso_Connector_free(out);
124 return NULL;
125 }
126 }
127 /*************************************************************
128 *
129 * allocates a Connector
130 *
131 **************************************************************/
132
133 Paso_Coupler* Paso_Coupler_alloc(Paso_Connector* connector, dim_t block_size)
134 {
135 Paso_MPIInfo *mpi_info = connector->mpi_info;
136 Paso_Coupler*out=NULL;
137 Paso_resetError();
138 out=MEMALLOC(1,Paso_Coupler);
139 if (!Paso_checkPtr(out)) {
140 out->data=NULL;
141 out->block_size=block_size;
142 out->connector=Paso_Connector_getReference(connector);
143 out->send_buffer=NULL;
144 out->recv_buffer=NULL;
145 out->mpi_requests=NULL;
146 out->mpi_stati=NULL;
147 out->mpi_info = Paso_MPIInfo_getReference(mpi_info);
148 out->reference_counter=1;
149
150 #ifdef PASO_MPI
151 out->mpi_requests=MEMALLOC(connector->send->numNeighbors+connector->recv->numNeighbors,MPI_Request);
152 out->mpi_stati=MEMALLOC(connector->send->numNeighbors+connector->recv->numNeighbors,MPI_Status);
153 Paso_checkPtr(out->mpi_requests);
154 Paso_checkPtr(out->mpi_stati);
155 #endif
156 if (mpi_info->size>1) {
157 out->send_buffer=MEMALLOC(connector->send->numSharedComponents * block_size,double);
158 out->recv_buffer=MEMALLOC(connector->recv->numSharedComponents * block_size,double);
159 Paso_checkPtr(out->send_buffer);
160 Paso_checkPtr(out->recv_buffer);
161 }
162 }
163 if (Paso_noError()) {
164 return out;
165 } else {
166 Paso_Coupler_free(out);
167 return NULL;
168 }
169 }
170
171 /* returns a reference to Coupler */
172
173 Paso_Coupler* Paso_Coupler_getReference(Paso_Coupler* in) {
174 if (in!=NULL) {
175 ++(in->reference_counter);
176 }
177 return in;
178 }
179
180 /* deallocates a Coupler: */
181
182 void Paso_Coupler_free(Paso_Coupler* in) {
183 if (in!=NULL) {
184 in->reference_counter--;
185 if (in->reference_counter<=0) {
186 Paso_Connector_free(in->connector);
187 MEMFREE(in->send_buffer);
188 MEMFREE(in->recv_buffer);
189 MEMFREE(in->mpi_requests);
190 MEMFREE(in->mpi_stati);
191 Paso_MPIInfo_free(in->mpi_info);
192 MEMFREE(in);
193 #ifdef Paso_TRACE
194 printf("Paso_Coupler_dealloc: system matrix pattern as been deallocated.\n");
195 #endif
196 }
197 }
198 }
199
200
201 void Paso_Coupler_startCollect(Paso_Coupler* coupler,const double* in)
202 {
203 Paso_MPIInfo *mpi_info = coupler->mpi_info;
204 dim_t block_size=coupler->block_size;
205 size_t block_size_size=block_size*sizeof(double);
206 dim_t i;
207 coupler->data=(double*) in;
208 if ( mpi_info->size>1) {
209 /* start reveiving input */
210 {
211 for (i=0; i< coupler->connector->recv->numNeighbors; ++i) {
212 #ifdef PASO_MPI
213 MPI_Irecv(&(coupler->recv_buffer[coupler->connector->recv->offsetInShared[i] * block_size]),
214 (coupler->connector->recv->offsetInShared[i+1]- coupler->connector->recv->offsetInShared[i])*block_size,
215 MPI_DOUBLE,
216 coupler->connector->recv->neighbor[i],
217 mpi_info->msg_tag_counter+coupler->connector->recv->neighbor[i],
218 mpi_info->comm,
219 &(coupler->mpi_requests[i]));
220 #endif
221
222 }
223 }
224 /* collect values into buffer */
225 if (block_size>1) {
226 #pragma omp parallel for private(i)
227 for (i=0; i < coupler->connector->send->numSharedComponents;++i) {
228 memcpy(&(coupler->send_buffer[(block_size)*i]),&(in[ block_size * coupler->connector->send->shared[i]]), block_size_size);
229 }
230 } else {
231 #pragma omp parallel for private(i)
232 for (i=0; i < coupler->connector->send->numSharedComponents;++i) coupler->send_buffer[i]=in[coupler->connector->send->shared[i]];
233 }
234 /* send buffer out */
235 {
236 for (i=0; i< coupler->connector->send->numNeighbors; ++i) {
237 #ifdef PASO_MPI
238 MPI_Issend(&(coupler->send_buffer[coupler->connector->send->offsetInShared[i] * block_size]),
239 (coupler->connector->send->offsetInShared[i+1]- coupler->connector->send->offsetInShared[i])*block_size,
240 MPI_DOUBLE,
241 coupler->connector->send->neighbor[i],
242 mpi_info->msg_tag_counter+mpi_info->rank,
243 mpi_info->comm,
244 &(coupler->mpi_requests[i+ coupler->connector->recv->numNeighbors]));
245 #endif
246 }
247 }
248 mpi_info->msg_tag_counter+=mpi_info->size;
249 }
250 }
251
252 double* Paso_Coupler_finishCollect(Paso_Coupler* coupler)
253 {
254 Paso_MPIInfo *mpi_info = coupler->mpi_info;
255 if ( mpi_info->size>1) {
256 /* wait for receive */
257 #ifdef PASO_MPI
258 MPI_Waitall(coupler->connector->recv->numNeighbors+coupler->connector->send->numNeighbors,
259 coupler->mpi_requests,
260 coupler->mpi_stati);
261 #endif
262 }
263
264 return coupler->recv_buffer;
265 }
266 dim_t Paso_Coupler_getLocalLength(const Paso_Coupler* in) {
267 return in->connector->send->local_length;
268 }
269 void Paso_Coupler_copyAll(const Paso_Coupler* src, Paso_Coupler* target)
270 {
271 dim_t i;
272 #pragma omp parallel
273 {
274 #pragma omp for private(i)
275 for (i =0; i< src->connector->recv->numSharedComponents * src->block_size; ++i) {
276 target->recv_buffer[i]=src->recv_buffer[i];
277 }
278 #pragma omp for private(i)
279 for (i =0; i< Paso_Coupler_getLocalLength(src) * src->block_size; ++i) {
280 target->data[i]=src->data[i];
281 }
282 }
283 }

  ViewVC Help
Powered by ViewVC 1.1.26