~vcs-imports/escript-finley/trunk

« back to all changes in this revision

Viewing changes to esysUtils/src/Esys_MPI.c

  • Committer: jfenwick
  • Date: 2010-10-11 01:48:14 UTC
  • Revision ID: svn-v4:77569008-7704-0410-b7a0-a92fef0b09fd:trunk:3259
Merging dudley and scons updates from branches

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*******************************************************
 
3
*
 
4
* Copyright (c) 2003-2010 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 <stdlib.h>
 
16
#include <stdio.h>
 
17
#include <string.h>
 
18
 
 
19
 
 
20
#include "Esys_MPI.h"
 
21
#include "index.h"
 
22
#include "mem.h"
 
23
#include "error.h"
 
24
 
 
25
 
 
26
/* allocate memory for an mpi_comm, and find the communicator details */
 
27
Esys_MPIInfo* Esys_MPIInfo_alloc( MPI_Comm comm )
 
28
{
 
29
  #ifdef ESYS_MPI
 
30
    int error;
 
31
  #endif
 
32
 
 
33
  Esys_MPIInfo *out=NULL;
 
34
 
 
35
  out = MEMALLOC( 1, Esys_MPIInfo );
 
36
  
 
37
  out->reference_counter = 0;
 
38
  out->msg_tag_counter = 0;
 
39
  #ifdef ESYS_MPI
 
40
     error = MPI_Comm_rank( comm, &out->rank )==MPI_SUCCESS && MPI_Comm_size( comm, &out->size )==MPI_SUCCESS;
 
41
     if( !error ) {
 
42
       Esys_setError( ESYS_MPI_ERROR, "Esys_MPIInfo_alloc : error finding comm rank/size" );
 
43
     }
 
44
  
 
45
     out->comm = comm;
 
46
  #else
 
47
     out->rank=0;
 
48
     out->size=1;
 
49
     out->comm=-1;
 
50
  #endif
 
51
  out->reference_counter++;
 
52
 
 
53
  return out;
 
54
}
 
55
 
 
56
/* free memory for an mpi_comm */
 
57
void Esys_MPIInfo_free( Esys_MPIInfo *in )
 
58
{
 
59
  if( in && !(--in->reference_counter) )
 
60
    MEMFREE( in );
 
61
}
 
62
 
 
63
Esys_MPIInfo *Esys_MPIInfo_getReference( Esys_MPIInfo* in )
 
64
{
 
65
  if (in!=NULL) 
 
66
    ++(in->reference_counter);
 
67
  
 
68
  return in;
 
69
}
 
70
/* N = #CPUs, k is a CPU number but out of range or even negative. Return a CPU number in 0...n-1. */
 
71
index_t Esys_MPIInfo_mod(index_t n, index_t k) 
 
72
{
 
73
    index_t q, out=0;
 
74
    if (n>1) {
 
75
        q=k/n;
 
76
        if (k>0) {
 
77
           out=k-n*q;
 
78
        } else if (k<0) {
 
79
           out=k-n*(q-1);
 
80
        }
 
81
    }
 
82
    return out;
 
83
}
 
84
 
 
85
void Esys_MPIInfo_Split( Esys_MPIInfo *mpi_info, dim_t N, dim_t* local_N,index_t* offset) 
 
86
{
 
87
   int rest=0;
 
88
   int s=mpi_info->size;
 
89
   int r=mpi_info->rank;
 
90
   *local_N=N/s;
 
91
   rest=N-(*local_N)*s;
 
92
   if (r<rest) {
 
93
       (*local_N)++;
 
94
       (*offset)=(*local_N)*r;
 
95
   } else {
 
96
       (*offset)=(*local_N)*r+rest;
 
97
   }
 
98
}
 
99
 
 
100
 
 
101
dim_t Esys_MPIInfo_setDistribution(Esys_MPIInfo* mpi_info ,index_t min_id,index_t max_id,index_t* distribution) {
 
102
   int rest=0, p;
 
103
   dim_t out;
 
104
   int s=mpi_info->size;
 
105
   dim_t N=max_id-min_id+1;
 
106
   if (N>0) {
 
107
      int local_N=N/s;
 
108
      rest=N-local_N*s;
 
109
      for (p=0; p<s; ++p) {
 
110
         if (p<rest) {
 
111
             distribution[p]=min_id+(local_N+1)*p;
 
112
             out=local_N+1;
 
113
         } else {
 
114
             distribution[p]=min_id+rest+local_N*p;
 
115
         }
 
116
      }
 
117
      distribution[s]=max_id+1;
 
118
      if (rest==0) {
 
119
         return local_N;
 
120
      } else {
 
121
         return local_N+1;
 
122
      }
 
123
  } else {
 
124
      for (p=0; p<s+1; ++p) distribution[p]=min_id;
 
125
      return 0;
 
126
  }
 
127
}
 
128
 
 
129
/* checks that there is no error accross all processes in a communicator */
 
130
/* NOTE : does not make guarentee consistency of error string on each process */
 
131
bool_t Esys_MPIInfo_noError( Esys_MPIInfo *mpi_info )
 
132
{
 
133
  int errorLocal = Esys_noError() ? 0 : 1;
 
134
  int errorGlobal = errorLocal;
 
135
 
 
136
  return (errorGlobal==0);
 
137
}
 
138
 
 
139
/**************************************************
 
140
                 WRAPPERS 
 
141
**************************************************/
 
142
 
 
143
int Esys_MPIInfo_initialized( void )
 
144
{
 
145
  #ifdef ESYS_MPI
 
146
     int error=0, initialised=0;
 
147
     error = MPI_Initialized( &initialised );
 
148
     if( error!=MPI_SUCCESS )
 
149
         Esys_setError( ESYS_MPI_ERROR, "mpi_initialised : MPI error" );
 
150
     return initialised;
 
151
  #else
 
152
     return TRUE;
 
153
  #endif
 
154
}
 
155
 
 
156
/* Append MPI rank to file name if multiple MPI processes */
 
157
char *Esys_MPI_appendRankToFileName(const char *fileName, int mpi_size, int mpi_rank) {
 
158
  /* Make plenty of room for the mpi_rank number and terminating '\0' */
 
159
  char *newFileName = TMPMEMALLOC(strlen(fileName)+20,char);
 
160
  strncpy(newFileName, fileName, strlen(fileName)+1);
 
161
  if (mpi_size>1) sprintf(newFileName+strlen(newFileName), ".%04d", mpi_rank);
 
162
  return(newFileName);
 
163
}
 
164