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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1407 by gross, Mon Feb 4 06:45:48 2008 UTC revision 1639 by gross, Mon Jul 14 08:55:25 2008 UTC
# Line 1  Line 1 
   
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  /*******************************************************  /*******************************************************
# Line 11  Line 10 
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;
# Line 69  Paso_Coupler* Paso_Coupler_alloc(Paso_Sh Line 165  Paso_Coupler* Paso_Coupler_alloc(Paso_Sh
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) {
# Line 84  void Paso_Coupler_free(Paso_Coupler* in) Line 180  void Paso_Coupler_free(Paso_Coupler* in)
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);
# Line 99  void Paso_Coupler_free(Paso_Coupler* in) Line 194  void Paso_Coupler_free(Paso_Coupler* in)
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
# Line 156  void Paso_Coupler_startCollect(Paso_Coup Line 220  void Paso_Coupler_startCollect(Paso_Coup
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    
# Line 183  double* Paso_Coupler_finishCollect(Paso_ Line 246  double* Paso_Coupler_finishCollect(Paso_
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  }  }
   

Legend:
Removed from v.1407  
changed lines
  Added in v.1639

  ViewVC Help
Powered by ViewVC 1.1.26