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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26