Skip to content
Snippets Groups Projects
bexchange.c 6.12 KiB
Newer Older
  • Learn to ignore specific revisions
  • Debolskiy Andrey's avatar
    Debolskiy Andrey committed
    #include "parlib.h"
    
    /*  
     *  Error codes:
     *     0 - success
     *     1 - nonpositive number of dimensions
     *     2 - wrong communicated dimension
     *     3 - negative boundary width
     *     4 - nonpositive dimension
     *     5 - boundary width exceeds the array block length
     */
    int P_BExchange_init ( ndims, stride, blklen, bdim, overlap, datatype, 
    		comm, period, bexchange )
       int				ndims, *stride, *blklen, bdim, overlap[2], period;
       MPI_Datatype	datatype;
       MPI_Comm			comm;
    	BExchange		*bexchange;
    {
    	int				nproc, iproc, direct, idim, sendproc[2], recvproc[2];
    	int				count, strd, sbind[2], rbind[2], send[2], recv[2];
       MPI_Aint			fsize;
       MPI_Datatype	oldtype, btype[2];
       MPI_Request		sreq[2], rreq[2]; 
    
    /*
     * Check input parameters
     */
       if ( ndims < 1 ) {return 1;}
       if ( bdim < 1 || bdim > ndims ) {return 2;}
       if ( overlap[0] == 0 && overlap[1] == 0 ) {return 0;} /* success */
       for ( idim = 0; idim < ndims; idim++ ) {
          if ( stride[idim] <= 0 ) {return 4;}
       }
       for ( direct = 0; direct < 2; direct++ ) {
          if ( overlap[direct] < 0 ) {return 3;}
          if ( overlap[direct] > blklen[bdim-1] ) {return 5;}
       }
    /*
     * Define the number of processors in the group and the rank
     */
       MPI_Comm_size ( comm, &nproc );
       if ( nproc == 0 ) {return 0;} /* success */
       MPI_Comm_rank ( comm, &iproc );
       if ( iproc == MPI_UNDEFINED ) {return 0;} /* the process does not belong to the group */
       sendproc[0] = ( iproc == 0 ? nproc-1 : iproc-1 );
       recvproc[0] = ( iproc == nproc-1 ? 0 : iproc+1 );
    	sendproc[1] = recvproc[0];
    	recvproc[1] = sendproc[0];
       send[0] = iproc > 0 || period; 
       recv[0] = iproc < nproc-1 || period;
       send[1] = recv[0];
       recv[1] = send[0];
       MPI_Type_extent ( datatype, &fsize );
    /*
     * Define data types for the boundaries
     */
        for ( direct = 0; direct < 2; direct++ ) {
          if ( overlap[direct] > 0 ) {
             oldtype = datatype;
             strd = 1;
             for ( idim = 0; idim < ndims; idim++ ) {
                if ( idim+1 == bdim ) {
                   count = overlap[direct];
                } else {
                   count = blklen[idim];
                }
                MPI_Type_hvector ( count, 1, strd * fsize, oldtype, 
    					&btype[direct] );
                if ( idim > 0 ) {
                   MPI_Type_free ( &oldtype );
                }
                oldtype = btype[direct];
                strd = strd * stride[idim];
             }
             MPI_Type_commit ( &btype[direct] );
          }
       }
    /*
     * Determine the begining of boundaries
     */
       strd = 1;
       for ( idim = 0; idim < bdim - 1; idim++ ) {
          strd = strd * stride[idim];
       }
       sbind[0] = 0;
       rbind[0] = blklen[bdim-1]*strd;
       sbind[1] = (blklen[bdim-1]-overlap[1])*strd;
       rbind[1] = -overlap[1]*strd;
    
       for ( direct = 0; direct < 2; direct++ ) {
          bexchange->overlap[direct] = overlap[direct];
          bexchange->send[direct] = send[direct];
          bexchange->recv[direct] = recv[direct];
          bexchange->btype[direct] = btype[direct];
          bexchange->sendproc[direct] = sendproc[direct];
          bexchange->recvproc[direct] = recvproc[direct];
          bexchange->sbind[direct] = sbind[direct];
          bexchange->rbind[direct] = rbind[direct];
    	}
    	bexchange->comm = comm;
    	bexchange->fsize = fsize;
    	return 0;
    }
    
    int P_BExchange_start ( a, bexchange )
       void				*a; 
    	BExchange		*bexchange;
    {
    	int				direct, overlap[2], send[2], recv[2], btype[2]; 
    	int				sendproc[2], recvproc[2], sbind[2], rbind[2];
    	MPI_Comm			comm;
       MPI_Request		sreq[2], rreq[2]; 
       MPI_Aint			fsize;
    	char				*ach = (char *) a;
    
       for ( direct = 0; direct < 2; direct++ ) {
          overlap[direct] = bexchange->overlap[direct];
          send[direct] = bexchange->send[direct];
          recv[direct] = bexchange->recv[direct];
          btype[direct] = bexchange->btype[direct];
          sendproc[direct] = bexchange->sendproc[direct];
          recvproc[direct] = bexchange->recvproc[direct];
          sbind[direct] = bexchange->sbind[direct];
          rbind[direct] = bexchange->rbind[direct];
       }
    	comm = bexchange->comm;
    	fsize = bexchange->fsize;
    
       for ( direct = 0; direct < 2; direct++ ) {
          if ( overlap[direct] > 0 ) {
             if ( send[direct] ) {
                MPI_Isend ( ach+sbind[direct]*fsize, 1, btype[direct], 
    					sendproc[direct], 0, comm, &sreq[direct] );
             }
             if ( recv[direct] ) {
                MPI_Irecv ( ach+rbind[direct]*fsize, 1, btype[direct], 
    					recvproc[direct], 0, comm, &rreq[direct] );
             }
          }
       }
       for ( direct = 0; direct < 2; direct++ ) {
          bexchange->sreq[direct]=sreq[direct];
          bexchange->rreq[direct]=rreq[direct];
       }
    	return 0;
    }
    
    int P_BExchange_end ( bexchange ) 
    	BExchange    *bexchange;
    {
       MPI_Status		status;
       int 				direct, overlap[2], send[2], recv[2];
       MPI_Request		sreq[2], rreq[2]; 
    
       for ( direct = 0; direct < 2; direct++ ) {
          overlap[direct] = bexchange->overlap[direct];
          send[direct] = bexchange->send[direct];
          recv[direct] = bexchange->recv[direct];
          sreq[direct] = bexchange->sreq[direct];
          rreq[direct] = bexchange->rreq[direct];
       }
    
       for ( direct = 0; direct < 2; direct++ ) {
          if ( overlap[direct] > 0 ) {
             if ( send[direct] ) {
                MPI_Wait ( &sreq[direct], &status );
             }
             if ( recv[direct] ) {
                MPI_Wait ( &rreq[direct], &status );
             }
          }
       }
    	return 0;
    }
    
    int P_BExchange_free ( bexchange ) 
    	BExchange    *bexchange;
    {
       int direct, overlap[2];
       MPI_Datatype btype[2];
       for ( direct = 0; direct < 2; direct++ ) {
          overlap[direct] = bexchange->overlap[direct];
          btype[direct] = bexchange->btype[direct];
    	}
       for ( direct = 0; direct < 2; direct++ ) {
          if ( overlap[direct] > 0 ) {
             MPI_Type_free ( &btype[direct] );
          }
       }
    	return 0;
    }
    
    int P_BExchange ( a, ndims, stride, blklen, bdim, overlap, datatype,
    		comm, period )
       void *a; 
       MPI_Datatype datatype;
       int ndims, *stride, *blklen, bdim, overlap[2]; 
       int period;
       MPI_Comm comm;
    {
    	BExchange bexchange;
    	int ierr;
       if ( ierr = P_BExchange_init ( ndims, stride, blklen, bdim, overlap, 
    		datatype, comm, period, &bexchange ) != 0 ) { return ierr; }
       P_BExchange_start ( a, &bexchange );
       P_BExchange_end ( &bexchange );
       P_BExchange_free ( &bexchange );
       return 0;
    }