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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1562 - (show annotations)
Wed May 21 13:04:40 2008 UTC (11 years, 5 months ago) by gross
File MIME type: text/plain
File size: 9549 byte(s)
The algebraic upwinding with MPI. The case of boundary constraint needs still some attention. 


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 if (Paso_noError()) {
54 return out;
55 } else {
56 Paso_Connector_free(out);
57 return NULL;
58 }
59 }
60
61 /* 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 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 #ifdef Paso_TRACE
80 printf("Paso_Coupler_dealloc: system matrix pattern as been deallocated.\n");
81 #endif
82 }
83 }
84 }
85
86 Paso_Connector* Paso_Connector_copy(Paso_Connector* in) {
87 return Paso_Connector_unroll(in,1);
88 }
89
90 Paso_Connector* Paso_Connector_unroll(Paso_Connector* in, index_t block_size) {
91 Paso_SharedComponents *new_send_shcomp=NULL, *new_recv_shcomp=NULL;
92 Paso_Connector *out=NULL;
93 if (Paso_noError()) {
94 if (block_size>1) {
95 new_send_shcomp=Paso_SharedComponents_alloc(in->send->local_length,
96 in->send->numNeighbors,
97 in->send->neighbor,
98 in->send->shared,
99 in->send->offsetInShared,
100 block_size,0,in->mpi_info);
101
102 new_recv_shcomp=Paso_SharedComponents_alloc(in->recv->local_length,
103 in->recv->numNeighbors,
104 in->recv->neighbor,
105 in->recv->shared,
106 in->recv->offsetInShared,
107 block_size,0,in->mpi_info);
108 } else {
109 new_send_shcomp=Paso_SharedComponents_getReference(in->send);
110 new_recv_shcomp=Paso_SharedComponents_getReference(in->recv);
111 }
112 if (Paso_noError()) out=Paso_Connector_alloc(new_send_shcomp,new_recv_shcomp);
113 }
114 Paso_SharedComponents_free(new_send_shcomp);
115 Paso_SharedComponents_free(new_recv_shcomp);
116 if (Paso_noError()) {
117 return out;
118 } else {
119 Paso_Connector_free(out);
120 return NULL;
121 }
122 }
123 /*************************************************************
124 *
125 * allocates a Connector
126 *
127 **************************************************************/
128
129 Paso_Coupler* Paso_Coupler_alloc(Paso_Connector* connector, dim_t block_size)
130 {
131 Paso_MPIInfo *mpi_info = connector->mpi_info;
132 Paso_Coupler*out=NULL;
133 Paso_resetError();
134 out=MEMALLOC(1,Paso_Coupler);
135 if (!Paso_checkPtr(out)) {
136 out->data=NULL;
137 out->block_size=block_size;
138 out->connector=Paso_Connector_getReference(connector);
139 out->send_buffer=NULL;
140 out->recv_buffer=NULL;
141 out->mpi_requests=NULL;
142 out->mpi_stati=NULL;
143 out->mpi_info = Paso_MPIInfo_getReference(mpi_info);
144 out->reference_counter=1;
145
146 #ifdef PASO_MPI
147 out->mpi_requests=MEMALLOC(connector->send->numNeighbors+connector->recv->numNeighbors,MPI_Request);
148 out->mpi_stati=MEMALLOC(connector->send->numNeighbors+connector->recv->numNeighbors,MPI_Status);
149 Paso_checkPtr(out->mpi_requests);
150 Paso_checkPtr(out->mpi_stati);
151 #endif
152 if (mpi_info->size>1) {
153 out->send_buffer=MEMALLOC(connector->send->numSharedComponents * block_size,double);
154 out->recv_buffer=MEMALLOC(connector->recv->numSharedComponents * block_size,double);
155 Paso_checkPtr(out->send_buffer);
156 Paso_checkPtr(out->recv_buffer);
157 }
158 }
159 if (Paso_noError()) {
160 return out;
161 } else {
162 Paso_Coupler_free(out);
163 return NULL;
164 }
165 }
166
167 /* returns a reference to Coupler */
168
169 Paso_Coupler* Paso_Coupler_getReference(Paso_Coupler* in) {
170 if (in!=NULL) {
171 ++(in->reference_counter);
172 }
173 return in;
174 }
175
176 /* deallocates a Coupler: */
177
178 void Paso_Coupler_free(Paso_Coupler* in) {
179 if (in!=NULL) {
180 in->reference_counter--;
181 if (in->reference_counter<=0) {
182 Paso_Connector_free(in->connector);
183 MEMFREE(in->send_buffer);
184 MEMFREE(in->recv_buffer);
185 MEMFREE(in->mpi_requests);
186 MEMFREE(in->mpi_stati);
187 Paso_MPIInfo_free(in->mpi_info);
188 MEMFREE(in);
189 #ifdef Paso_TRACE
190 printf("Paso_Coupler_dealloc: system matrix pattern as been deallocated.\n");
191 #endif
192 }
193 }
194 }
195
196
197 void Paso_Coupler_startCollect(Paso_Coupler* coupler,double* in)
198 {
199 Paso_MPIInfo *mpi_info = coupler->mpi_info;
200 dim_t block_size=coupler->block_size;
201 size_t block_size_size=block_size*sizeof(double);
202 dim_t i,j;
203 coupler->data=in;
204 if ( mpi_info->size>1) {
205 /* start reveiving input */
206 {
207 for (i=0; i< coupler->connector->recv->numNeighbors; ++i) {
208 #ifdef PASO_MPI
209 MPI_Irecv(&(coupler->recv_buffer[coupler->connector->recv->offsetInShared[i] * block_size]),
210 (coupler->connector->recv->offsetInShared[i+1]- coupler->connector->recv->offsetInShared[i])*block_size,
211 MPI_DOUBLE,
212 coupler->connector->recv->neighbor[i],
213 mpi_info->msg_tag_counter+coupler->connector->recv->neighbor[i],
214 mpi_info->comm,
215 &(coupler->mpi_requests[i]));
216 #endif
217
218 }
219 }
220 /* collect values into buffer */
221 #pragma omp parallel for private(i)
222 for (i=0; i < coupler->connector->send->numSharedComponents;++i) {
223 memcpy(&(coupler->send_buffer[(block_size)*i]),&(in[ block_size * coupler->connector->send->shared[i]]), block_size_size);
224 }
225 /* send buffer out */
226 {
227 for (i=0; i< coupler->connector->send->numNeighbors; ++i) {
228 #ifdef PASO_MPI
229 MPI_Issend(&(coupler->send_buffer[coupler->connector->send->offsetInShared[i] * block_size]),
230 (coupler->connector->send->offsetInShared[i+1]- coupler->connector->send->offsetInShared[i])*block_size,
231 MPI_DOUBLE,
232 coupler->connector->send->neighbor[i],
233 mpi_info->msg_tag_counter+mpi_info->rank,
234 mpi_info->comm,
235 &(coupler->mpi_requests[i+ coupler->connector->recv->numNeighbors]));
236 #endif
237 }
238 }
239 mpi_info->msg_tag_counter+=mpi_info->size;
240 }
241 }
242
243 double* Paso_Coupler_finishCollect(Paso_Coupler* coupler)
244 {
245 Paso_MPIInfo *mpi_info = coupler->mpi_info;
246 if ( mpi_info->size>1) {
247 /* wait for receive */
248 #ifdef PASO_MPI
249 MPI_Waitall(coupler->connector->recv->numNeighbors+coupler->connector->send->numNeighbors,
250 coupler->mpi_requests,
251 coupler->mpi_stati);
252 #endif
253 }
254 return coupler->recv_buffer;
255 }
256 dim_t Paso_Coupler_getLocalLength(const Paso_Coupler* in) {
257 return in->connector->send->local_length;
258
259 }
260 void Paso_Coupler_copyAll(const Paso_Coupler* src, Paso_Coupler* target)
261 {
262 dim_t i;
263 #pragma omp parallel
264 {
265 #pragma omp for private(i)
266 for (i =0; i< src->connector->recv->numSharedComponents * src->block_size; ++i) {
267 target->recv_buffer[i]=src->recv_buffer[i];
268 }
269 #pragma omp for private(i)
270 for (i =0; i< Paso_Coupler_getLocalLength(src) * src->block_size; ++i) {
271 target->data[i]=src->data[i];
272 }
273 }
274 }

  ViewVC Help
Powered by ViewVC 1.1.26