source: anuga_core/source/pypar-numeric/mpiext.c @ 5779

Last change on this file since 5779 was 5779, checked in by steve, 16 years ago

Added the old version of pypar which works with Numeric. Necessary for parallel code until we move anuga to numpy (and then we can use pypar as distribute via sourceforge).

File size: 25.2 KB
Line 
1/************************************************************************/
2/* PyPAR - Parallel Python using MPI                                    */
3/* Copyright (C) 2001, 2002, 2003 Ole M. Nielsen                        */
4/*                                                                      */
5/* See enclosed README file for details of installation and use.        */
6/*                                                                      */   
7/* This program is free software; you can redistribute it and/or modify */
8/* it under the terms of the GNU General Public License as published by */
9/* the Free Software Foundation; either version 2 of the License, or    */
10/* (at your option) any later version.                                  */
11/*                                                                      */     
12/* This program is distributed in the hope that it will be useful,      */
13/* but WITHOUT ANY WARRANTY; without even the implied warranty of       */
14/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        */
15/* GNU General Public License (http://www.gnu.org/copyleft/gpl.html)    */
16/* for more details.                                                    */
17/*                                                                      */
18/* You should have received a copy of the GNU General Public License    */
19/* along with this program; if not, write to the Free Software          */
20/*  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307*/
21/*                                                                      */
22/*                                                                      */
23/* Contact address: Ole.Nielsen@anu.edu.au                              */
24/*                                                                      */
25/* version (see __version__ in pypar.py)                                */
26/* date (see __date__ in pypar.py)                                      */
27/************************************************************************/
28
29
30#include "Python.h"
31#include "mpi.h"
32#include "math.h"
33#include "Numeric/arrayobject.h"
34
35/* to handle MPI constants export (shamelessly stolen from _cursesmodule.c)*/
36#define SetDictInt(string,ch) \
37        PyDict_SetItemString(ModDict, string, PyInt_FromLong((long) (ch)));
38
39/* Remap struct MPI_op to int (easier to handle by python)*/
40#define MAX 1
41#define MIN 2
42#define SUM 3
43#define PROD 4
44#define LAND 5
45#define BAND 6
46#define LOR 7
47#define BOR 8
48#define LXOR 9
49#define BXOR 10
50#define MAXLOC 11
51#define MINLOC 12
52/*#define REPLACE 13 // Not available on all MPI systems */
53
54
55static char errmsg[132];  /*Used to cretae exception messages*/
56
57int length(PyArrayObject *x) { 
58  /*Compute the total length of contiguous array
59  /*
60  /*Necessary for communicating multi dimensional arrays */
61 
62  int i, length;
63 
64  /* Compute total length of contiguous data */
65  length = 1;
66  for (i=0; i<x->nd; i++) {
67    length *= x->dimensions[i];
68  } 
69   
70  return length;
71} 
72
73
74MPI_Datatype type_map(PyArrayObject *x, int *count) { 
75  /* Return the MPI Datatype corresponding to                       
76  /* the Python data type as follows 
77  /*
78  /* TYPE    py_type  mpi_type  bytes  symbol
79  /* ----------------------------------------
80  /* INT       4        6         4      'i'
81  /* LONG      5        8         8      'l'
82  /* FLOAT     6       10         4      'f' 
83  /* DOUBLE    7       11         8      'd'
84  /*
85  /* Also return the total number of elements in the array
86  /*
87  /* The Python datatype COMPLEX ('F') and COMPLEX_DOUBLE ('D')
88  /* is treated as a special case to the absence of an
89  /* MPI_COMPLEX datatype:
90  /*
91  /* Complex arrays are mapped to float or double arrays with real
92  /* and imaginary parts alternating and count is updated. */
93 
94  int py_type;
95  MPI_Datatype mpi_type;
96
97  *count = length(x);
98   
99  py_type = x -> descr -> type_num;     
100  if (py_type == PyArray_DOUBLE) 
101    mpi_type = MPI_DOUBLE;
102  else if (py_type == PyArray_INT) 
103    mpi_type = MPI_INT;
104  else if (py_type == PyArray_CDOUBLE) {
105    mpi_type = MPI_DOUBLE;
106    (*count) *= 2;
107  } else if (py_type == PyArray_FLOAT) 
108    mpi_type = MPI_FLOAT;
109  else if (py_type == PyArray_LONG)   
110    mpi_type = MPI_LONG; 
111  else if (py_type == PyArray_CFLOAT) {
112    mpi_type = MPI_FLOAT;
113    (*count) *= 2;
114  } else {
115    PyErr_SetString(PyExc_ValueError, "Array must be of type int or float");
116    return NULL;
117  }     
118
119  /*printf("Types %d %d\n", py_type, mpi_type); */
120 
121  return mpi_type;
122}   
123
124
125MPI_Op op_map(int py_op) { 
126 
127  MPI_Op mpi_op;
128 
129  if (py_op == MAX) 
130    mpi_op = MPI_MAX;
131  else if (py_op == MIN)   
132    mpi_op = MPI_MIN; 
133  else if (py_op == SUM)   
134    mpi_op = MPI_SUM; 
135  else if (py_op == PROD)   
136    mpi_op = MPI_PROD; 
137  else if (py_op == LAND)   
138    mpi_op = MPI_LAND; 
139  else if (py_op == BAND)   
140    mpi_op = MPI_BAND; 
141  else if (py_op == LOR)   
142    mpi_op = MPI_LOR; 
143  else if (py_op == BOR)   
144    mpi_op = MPI_BOR; 
145  else if (py_op == LXOR)   
146    mpi_op = MPI_LXOR; 
147  else if (py_op == BXOR)   
148    mpi_op = MPI_BXOR; 
149  else if (py_op == MAXLOC)
150    mpi_op = MPI_MAXLOC;
151  else if (py_op == MINLOC)   
152    mpi_op = MPI_MINLOC; 
153  /*else if (py_op == REPLACE)*/   
154  /*  mpi_op = MPI_REPLACE; */ 
155  else {
156    PyErr_SetString(PyExc_ValueError, "Operation unknown");
157    return NULL;
158  }     
159 
160  return mpi_op;
161} 
162
163
164/*********************************************************/
165/* send_string                                           */
166/* Send string of characters                             */
167/*                                                       */
168/*********************************************************/
169static PyObject *send_string(PyObject *self, PyObject *args) {
170  char *s;
171  int destination, tag, length, error, myid;
172 
173  /* process the parameters */
174  if (!PyArg_ParseTuple(args, "s#ii", &s, &length, &destination, &tag))
175    return NULL;
176 
177  /* call the MPI routine */
178  error = MPI_Send(s, length, MPI_CHAR, destination, tag, MPI_COMM_WORLD);
179 
180  if (error != 0) {
181    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
182    sprintf(errmsg, "Proc %d: MPI_Send failed with error code %d\n", myid, error);
183    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg */
184    return NULL;
185  } 
186     
187  return Py_BuildValue("");
188}
189
190/**********************************************************/
191/* receive_string                                         */
192/* Receive string of characters                           */
193/*                                                        */
194/**********************************************************/
195static PyObject *receive_string(PyObject *self, PyObject *args) {
196  char *s;
197  int source, tag, length, error, st_length, myid; 
198  MPI_Status status;
199
200  /* process the parameters */
201  if (!PyArg_ParseTuple(args, "s#ii", &s, &length, &source, &tag))
202    return NULL;
203   
204  /* call the MPI routine */
205  error = MPI_Recv(s, length, MPI_CHAR, source, tag, MPI_COMM_WORLD, &status);
206
207  if (error != 0) {
208    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
209    sprintf(errmsg, "Proc %d: MPI_Recv failed with error code %d\n", myid, error);
210    PyErr_SetString(PyExc_RuntimeError, errmsg);   
211    return NULL;
212  } 
213     
214  MPI_Get_count(&status, MPI_CHAR, &st_length); 
215  /*status.st_length is not available in all MPI implementations
216  //Alternative is: MPI_Get_elements(MPI_Status *, MPI_Datatype, int *); */
217
218  /*Still include error msg in status in case exception is caught. */
219  return Py_BuildValue("(iiiii)", status.MPI_SOURCE, status.MPI_TAG,
220  status.MPI_ERROR, st_length, sizeof(char)); 
221}
222
223/**********************************************************/
224/* broadcast_string                                           */
225/* Broadcast string of characters                         */
226/*                                                        */
227/**********************************************************/
228static PyObject *broadcast_string(PyObject *self, PyObject *args) {
229  char *s;
230  int source, length, error, myid; 
231
232  /* process the parameters */
233  if (!PyArg_ParseTuple(args, "s#i", &s, &length, &source))
234    return NULL;
235   
236  /* call the MPI routine */
237  error = MPI_Bcast(s, length, MPI_CHAR, source, MPI_COMM_WORLD);
238  if (error != 0) {
239    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
240    sprintf(errmsg, "Proc %d: MPI_Bcast failed with error code %d\n", myid, error);
241    PyErr_SetString(PyExc_RuntimeError, errmsg);   
242    return NULL;
243  } 
244   
245  return Py_BuildValue(""); 
246}
247
248/**********************************************************/
249/* scatter_string                                         */
250/* Scatter string of characters                           */
251/*                                                        */
252/**********************************************************/
253static PyObject *scatter_string(PyObject *self, PyObject *args) {
254  char *s;
255  char *d;
256  int source, count, error, myid, numprocs; 
257
258  /* process the parameters */
259  if (!PyArg_ParseTuple(args, "s#si", &s, &count, &d, &source))
260    return NULL;
261   
262  error = MPI_Comm_size(MPI_COMM_WORLD,&numprocs);   
263  count = count/numprocs;
264 
265  /* call the MPI routine */
266  error = MPI_Scatter(s, count, MPI_CHAR, d, count, MPI_CHAR, source, MPI_COMM_WORLD);
267
268  if (error != 0) {
269    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
270    sprintf(errmsg, "Proc %d: MPI_Scatter failed with error code %d\n", myid, error);
271    PyErr_SetString(PyExc_RuntimeError, errmsg);   
272    return NULL;
273  } 
274   
275  return Py_BuildValue(""); 
276}
277
278/**********************************************************/
279/* gather_string                                         */
280/* Gather string of characters                           */
281/*                                                        */
282/**********************************************************/
283static PyObject *gather_string(PyObject *self, PyObject *args) {
284  char *s;
285  char *d;
286  int source, error, count, myid; 
287
288  /* process the parameters */
289  if (!PyArg_ParseTuple(args, "s#si", &s, &count, &d, &source))
290    return NULL;
291   
292  /* call the MPI routine */
293  error = MPI_Gather(s, count, MPI_CHAR, d, count,  MPI_CHAR, source, MPI_COMM_WORLD);
294 
295  if (error != 0) {
296    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
297    sprintf(errmsg, "Proc %d: MPI_Gather failed with error code %d\n", myid, error);
298    PyErr_SetString(PyExc_RuntimeError, errmsg);   
299    return NULL;
300  } 
301   
302  return Py_BuildValue(""); 
303}
304
305
306/**********************************************************/
307/* send_array                                             */
308/* Send Numeric array of type float, double, int, or long */
309/*                                                        */
310/**********************************************************/
311static PyObject *send_array(PyObject *self, PyObject *args) {
312  PyObject *input;
313  PyArrayObject *x;
314  int destination, tag, error, count, myid;
315  MPI_Datatype mpi_type;
316 
317  /* process the parameters */
318  if (!PyArg_ParseTuple(args, "Oii", &input, &destination, &tag))
319    return NULL;
320   
321  /*if (!PyArg_ParseTuple(args, "Oii", &x, &destination, &tag))*/
322  /* return NULL;     */
323   
324  /* Make Numeric array from general sequence type (no cost if already Numeric)*/   
325  x = (PyArrayObject *)
326    PyArray_ContiguousFromObject(input, PyArray_NOTYPE, 0, 0);
327   
328  /* Input check and determination of MPI type */         
329  mpi_type = type_map(x, &count);
330  if (!mpi_type) return NULL;
331   
332  /* call the MPI routine */
333  error = MPI_Send(x->data, count, mpi_type, destination, tag,\
334                   MPI_COMM_WORLD);
335  Py_DECREF(x);           
336 
337  if (error != 0) {
338    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
339    sprintf(errmsg, "Proc %d: MPI_Send failed with error code %d\n", myid, error);
340    PyErr_SetString(PyExc_RuntimeError, errmsg);   
341    return NULL;
342  } 
343   
344  return Py_BuildValue(""); 
345}
346
347/*************************************************************/
348/* receive_array                                             */
349/* Receive Numeric array of type float, double, int, or long */
350/*                                                           */
351/*************************************************************/
352static PyObject *receive_array(PyObject *self, PyObject *args) {
353  PyObject *input;
354  PyArrayObject *x;
355  int source, tag, error, st_length, size, count, myid;
356  MPI_Datatype mpi_type;
357  MPI_Status status;
358
359  /* process the parameters */
360  /*if (!PyArg_ParseTuple(args, "Oii", &input, &source, &tag))*/
361  /*  return NULL;*/
362   
363  if (!PyArg_ParseTuple(args, "Oii", &x, &source, &tag))
364    return NULL;   
365   
366  /* Make Numeric array from general sequence type (no cost if already Numeric)*/   
367  /*x = (PyArrayObject *) */
368  /*  PyArray_ContiguousFromObject(input, PyArray_NOTYPE, 0, 0);*/
369   
370  /* Input check and determination of MPI type */         
371  mpi_type = type_map(x, &count);
372  if (!mpi_type) return NULL; 
373     
374  /* call the MPI routine */
375  error =  MPI_Recv(x->data, count, mpi_type, source, tag, \
376                    MPI_COMM_WORLD, &status);
377         
378  /* Do not DECREF x as it must be returned to Python*/
379         
380  if (error != 0) {
381    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
382    sprintf(errmsg, "Proc %d: MPI_Recv failed with error code %d\n", myid, error);
383    PyErr_SetString(PyExc_RuntimeError, errmsg);   
384    return NULL;
385  } 
386   
387         
388  MPI_Get_count(&status, mpi_type, &st_length); 
389  /* status.st_length is not available in all MPI implementations*/
390  /*Alternative is: MPI_Get_elements(MPI_Status *, MPI_Datatype, int *);*/
391         
392     
393  /*FIXME: This might not be watertight on all platforms */
394  /* Need C equivalent to itemsize().*/
395  if (mpi_type == MPI_DOUBLE) {
396    size = sizeof(double);  /*8 */
397  } else if (mpi_type == MPI_LONG) {
398    size = sizeof(long); /*8? */
399  } else if (mpi_type == MPI_FLOAT) {
400    size = sizeof(float);
401  } else if (mpi_type == MPI_INT) {   
402    size = sizeof(int); 
403  } else {
404    size = 4; 
405  }
406   
407  return Py_BuildValue("(iiiii)", status.MPI_SOURCE, status.MPI_TAG,
408  status.MPI_ERROR, st_length, size); 
409}
410
411
412/*************************************************************/
413/* broadcast_array                                               */
414/* Broadcast Num.  array of type float, double, int, or long */
415/*                                                           */
416/*************************************************************/
417static PyObject *broadcast_array(PyObject *self, PyObject *args) {
418  PyArrayObject *x;
419  int source, error, count, myid;
420  MPI_Datatype mpi_type;
421  /*MPI_Status status;*/
422
423  /* process the parameters */
424  if (!PyArg_ParseTuple(args, "Oi", &x, &source))
425    return NULL;
426
427  /* Input check and determination of MPI type */         
428  mpi_type = type_map(x, &count);
429  if (!mpi_type) return NULL; 
430     
431  /* call the MPI routine */
432  error =  MPI_Bcast(x->data, count, mpi_type, source, \
433                     MPI_COMM_WORLD);
434         
435         
436  if (error != 0) {
437    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
438    sprintf(errmsg, "Proc %d: MPI_Bcast failed with error code %d\n", myid, error);
439    PyErr_SetString(PyExc_RuntimeError, errmsg);   
440    return NULL;
441  } 
442         
443  return Py_BuildValue("");
444}
445
446/*************************************************************/
447/* scatter_array                                             */
448/* Scatter Num.    array of type float, double, int, or long */
449/*                                                           */
450/*************************************************************/
451static PyObject *scatter_array(PyObject *self, PyObject *args) {
452  PyArrayObject *x;
453  PyArrayObject *d;
454  int source, error, count, myid, numprocs;
455  MPI_Datatype mpi_type;
456  /*MPI_Status status; */
457
458  /* process the parameters */
459  if (!PyArg_ParseTuple(args, "OOi", &x, &d, &source))
460    return NULL;
461
462  /* Input check and determination of MPI type */         
463  mpi_type = type_map(x, &count);
464  if (!mpi_type) return NULL; 
465   
466  error = MPI_Comm_size(MPI_COMM_WORLD,&numprocs);   
467  count = count/numprocs; 
468 
469  /* call the MPI routine */
470  error = MPI_Scatter(x->data, count, mpi_type, d->data, count, mpi_type, source, \
471                      MPI_COMM_WORLD);
472         
473  if (error != 0) {
474    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
475    sprintf(errmsg, "Proc %d: MPI_Scatter failed with error code %d\n", myid, error);
476    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
477    return NULL;
478  } 
479     
480  return Py_BuildValue("");
481}
482
483
484/*************************************************************/
485/* gather_array                                              */
486/* Gather Num.     array of type float, double, int, or long */
487/*                                                           */
488/*************************************************************/
489static PyObject *gather_array(PyObject *self, PyObject *args) {
490  PyArrayObject *x;
491  PyArrayObject *d;
492  int source, error, count, myid;
493  MPI_Datatype mpi_type;
494  /*MPI_Status status; */
495
496  /* process the parameters */
497  if (!PyArg_ParseTuple(args, "OOi", &x, &d, &source))
498    return NULL;
499
500  /* Input check and determination of MPI type */         
501  mpi_type = type_map(x, &count);
502  if (!mpi_type) return NULL; 
503     
504  /* call the MPI routine */
505  error =  MPI_Gather(x->data, count, mpi_type, d->data, count, mpi_type, source, \
506                      MPI_COMM_WORLD);
507
508  if (error != 0) {
509    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
510    sprintf(errmsg, "Proc %d: MPI_Gather failed with error code %d\n", myid, error);
511    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg */
512    return NULL;
513  } 
514 
515  return Py_BuildValue("");
516}
517
518
519
520/*************************************************************/
521/* reduce_array                                              */
522/* Reduce Num.     array of type float, double, int, or long */
523/*                                                           */
524/*************************************************************/
525static PyObject *reduce_array(PyObject *self, PyObject *args) {
526  PyArrayObject *x;
527  PyArrayObject *d;
528  int source, op, error, count, count1, myid;
529  MPI_Datatype mpi_type;
530  /*MPI_Status status;*/
531  MPI_Op mpi_op;
532
533  /* process the parameters */
534  if (!PyArg_ParseTuple(args, "OOii", &x, &d, &op, &source))
535    return NULL;
536   
537  /* Input check and determination of MPI type */         
538  mpi_type = type_map(x, &count);
539  if (!mpi_type) return NULL; 
540  if (mpi_type != type_map(d, &count1)) {
541    printf ("Input array and buffer must be of the same type\n");
542    return Py_BuildValue("i", -666);   
543  }
544
545  if (count != count1) {
546    printf ("Input array and buffer must have same length\n");
547    return Py_BuildValue("i", -666);   
548  }
549   
550  /* Input check and determination of MPI op */ 
551  /*printf("op: %d\n", op);         */
552  mpi_op = op_map(op);
553  if (!mpi_op) return NULL; 
554   
555  if (op == MAXLOC || op == MINLOC) {
556    /*not implemented*/
557    return Py_BuildValue("i", -666);
558  }
559  else {
560  /* call the MPI routine */
561  error =  MPI_Reduce(x->data, d->data, count, mpi_type, mpi_op, source, \
562         MPI_COMM_WORLD);
563  }
564         
565  if (error != 0) {
566    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
567    sprintf(errmsg, "Proc %d: MPI_Reduce failed with error code %d\n", myid, error);
568    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
569    return NULL;
570  } 
571 
572  return Py_BuildValue("");
573}
574
575/*********************************************************/
576/* MPI calls rank, size, finalize, abort                 */
577/*                                                       */
578/*********************************************************/
579
580static PyObject * rank(PyObject *self, PyObject *args) {
581  int error, myid;
582
583  error = MPI_Comm_rank(MPI_COMM_WORLD,&myid);
584  if (error != 0) {
585    sprintf(errmsg, "Proc ?: MPI_Comm_rank failed with error code %d\n", error);
586    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
587    return NULL;
588  } 
589 
590  return Py_BuildValue("i", myid);
591}
592
593static PyObject * size(PyObject *self, PyObject *args) {
594  int error, numprocs, myid; 
595 
596  error = MPI_Comm_size(MPI_COMM_WORLD,&numprocs);
597  if (error != 0) {
598    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
599    sprintf(errmsg, "Proc %d: MPI_Comm_size failed with error code %d\n", myid, error);
600    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
601    return NULL;
602  } 
603 
604  return Py_BuildValue("i", numprocs);
605}
606 
607static PyObject * Get_processor_name(PyObject *self, PyObject *args) { 
608  char processor_name[MPI_MAX_PROCESSOR_NAME];
609  int  error, namelen, myid;
610
611  error = MPI_Get_processor_name(processor_name,&namelen);
612  if (error != 0) {
613    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
614    sprintf(errmsg, "Proc %d: Get_processor_name failed with error code %d\n", myid, error);
615    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
616    return NULL;
617  } 
618 
619  return Py_BuildValue("s#", processor_name, namelen);
620}   
621
622static PyObject * init(PyObject *self, PyObject *args) { 
623  PyObject *input;
624
625  int i, error, myid;
626  int argc = 0; 
627  char **argv;   
628
629  /* process input parameters */
630  if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &input))
631    return NULL;
632
633  /* Reconstruct C-commandline */     
634  /*                           */ 
635  argc = PyList_Size(input); /*Number of commandline arguments*/
636  argv = (char**) malloc((argc+1)*sizeof(char*)); 
637 
638  for (i=0; i<argc; i++) 
639    argv[i] = PyString_AsString( PyList_GetItem(input, i) );
640   
641  argv[i] = NULL; /*Lam 7.0 requires last arg to be NULL  */
642 
643  error = MPI_Init(&argc, &argv); 
644  if (error != 0) {
645    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
646    sprintf(errmsg, "Proc ?: MPI_Init failed with error code %d\n", error);
647    PyErr_SetString(PyExc_RuntimeError, errmsg);   
648    return NULL;
649  } 
650
651  return Py_BuildValue(""); 
652} 
653
654
655static PyObject * initialized(PyObject *self, PyObject *args) { 
656  int error, flag, myid;
657 
658  error = MPI_Initialized(&flag);
659 
660  if (error != 0) {
661    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
662    sprintf(errmsg, "Proc %d: MPI_Initialized failed with error code %d\n", myid, error);
663    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
664    return NULL;
665  } 
666
667  return Py_BuildValue("i", flag); 
668} 
669
670 
671static PyObject * finalize(PyObject *self, PyObject *args) { 
672  int error, myid;
673
674  MPI_Comm_rank(MPI_COMM_WORLD, &myid); 
675 
676  error = MPI_Finalize();
677  if (error != 0) {
678    sprintf(errmsg, "Proc %d: MPI_Finalize failed with error code %d\n", myid, error);
679    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
680    return NULL;
681  } 
682   
683  return Py_BuildValue("");
684} 
685
686static PyObject * mpi_abort(PyObject *self, PyObject *args) { 
687  int error, code=0, myid;
688 
689  error = MPI_Abort(MPI_COMM_WORLD, code);
690  if (error != 0) {
691    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
692    sprintf(errmsg, "Proc %d: MPI_Abort failed with error code %d\n", myid, error);
693    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
694    return NULL;
695  } 
696 
697  return Py_BuildValue(""); 
698} 
699
700static PyObject * barrier(PyObject *self, PyObject *args) { 
701  int error, myid;
702 
703  error = MPI_Barrier(MPI_COMM_WORLD);
704  if (error != 0) {
705    MPI_Comm_rank(MPI_COMM_WORLD, &myid);   
706    sprintf(errmsg, "Proc %d: MPI_Barrier failed with error code %d\n", myid, error);
707    PyErr_SetString(PyExc_RuntimeError, errmsg);    /*raise ValueError, errmsg*/
708    return NULL;
709  } 
710 
711  return Py_BuildValue("");
712}   
713
714static PyObject * Wtime(PyObject *self, PyObject *args) {     
715  double t;
716 
717  t = MPI_Wtime();
718  return Py_BuildValue("d", t);     
719}     
720 
721 
722/**********************************/
723/* Method table for python module */
724/**********************************/
725
726static struct PyMethodDef MethodTable[] = {
727  {"size", size, METH_VARARGS}, 
728  {"rank", rank, METH_VARARGS}, 
729  {"barrier", barrier, METH_VARARGS},         
730  {"time", Wtime, METH_VARARGS},           
731  {"get_processor_name", Get_processor_name, METH_VARARGS},             
732  {"init", init, METH_VARARGS},         
733  {"initialized", initialized, METH_VARARGS},       
734  {"finalize", finalize, METH_VARARGS},       
735  {"abort", mpi_abort, METH_VARARGS},         
736  {"send_string", send_string, METH_VARARGS},
737  {"receive_string", receive_string, METH_VARARGS},     
738  {"broadcast_string", broadcast_string, METH_VARARGS},       
739  {"scatter_string", scatter_string, METH_VARARGS},       
740  {"gather_string", gather_string, METH_VARARGS},       
741  {"send_array", send_array, METH_VARARGS},
742  {"receive_array", receive_array, METH_VARARGS},   
743  {"broadcast_array", broadcast_array, METH_VARARGS},             
744  {"scatter_array", scatter_array, METH_VARARGS},             
745  {"gather_array", gather_array, METH_VARARGS},             
746  {"reduce_array", reduce_array, METH_VARARGS},             
747  {NULL, NULL}
748};
749
750
751/***************************/
752/* Module initialisation   */
753/***************************/
754
755
756void initmpiext(void){
757  PyObject *m, *ModDict;
758 
759  m = Py_InitModule("mpiext", MethodTable);
760 
761  /* to handle MPI symbolic constants*/
762  ModDict = PyModule_GetDict(m); 
763  SetDictInt("MPI_ANY_TAG", MPI_ANY_TAG);
764  SetDictInt("MPI_TAG_UB", MPI_TAG_UB); 
765  SetDictInt("MPI_ANY_SOURCE", MPI_ANY_SOURCE);
766  SetDictInt("MAX", MAX);
767  SetDictInt("MIN", MIN);
768  SetDictInt("SUM", SUM);
769  SetDictInt("PROD", PROD);
770  SetDictInt("LAND", LAND);
771  SetDictInt("BAND", BAND);
772  SetDictInt("LOR", LOR);
773  SetDictInt("BOR", BOR);
774  SetDictInt("LXOR", LXOR);
775  SetDictInt("BXOR", BXOR);
776  /*SetDictInt("MAXLOC", MAXLOC);*/
777  /*SetDictInt("MINLOC", MINLOC);*/
778  /*SetDictInt("REPLACE", REPLACE);*/
779
780  /*SetDictInt("MPI_COMM_WORLD", MPI_COMM_WORLD);  */
781   
782  import_array();     /*Necessary for handling of NumPY structures  */
783}
784
785 
786 
787
Note: See TracBrowser for help on using the repository browser.