• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

contrib/maloc/src/psh/vcom.c

00001 /*
00002  * ***************************************************************************
00003  * MALOC = < Minimal Abstraction Layer for Object-oriented C >
00004  * Copyright (C) 1994--2008 Michael Holst
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
00019  *
00020  * rcsid="$Id: vcom.c,v 1.24 2008/03/12 05:13:58 fetk Exp $"
00021  * ***************************************************************************
00022  */
00023 
00024 /*
00025  * ***************************************************************************
00026  * File:     vcom.c
00027  *
00028  * Purpose:  Class Vcom: methods.
00029  *
00030  * Author:   Nathan Baker and Michael Holst
00031  * ***************************************************************************
00032  */
00033 
00034 #include "vcom_p.h"
00035 
00036 VEMBED(rcsid="$Id: vcom.c,v 1.24 2008/03/12 05:13:58 fetk Exp $")
00037 
00038 /*
00039  * ***************************************************************************
00040  * Class Vcom: Inlineable methods
00041  * ***************************************************************************
00042  */
00043 #if !defined(VINLINE_MALOC)
00044 
00045 #endif /* if !defined(VINLINE_MALOC) */
00046 
00047 /*
00048  * ***************************************************************************
00049  * Class Vcom: Non-inlineable methods
00050  * ***************************************************************************
00051  */
00052 
00053 /*
00054  * ***************************************************************************
00055  * Routine:  Vcom_init
00056  *
00057  * Purpose:  The Vmp initializer.
00058  *
00059  * Author:   Michael Holst
00060  * ***************************************************************************
00061  */
00062 VPUBLIC int Vcom_init(int *argc, char ***argv)
00063 {
00064 #if defined(HAVE_MPI_H)
00065     return (MPI_SUCCESS == MPI_Init(argc,argv));
00066 #else
00067     return 1;
00068 #endif
00069 }
00070 
00071 /*
00072  * ***************************************************************************
00073  * Routine:  Vcom_finalize
00074  *
00075  * Purpose:   The Vmp finalizerr.
00076  *
00077  * Author:   Michael Holst
00078  * ***************************************************************************
00079  */
00080 VPUBLIC int Vcom_finalize(void)
00081 {
00082 #if defined(HAVE_MPI_H)
00083     return (MPI_SUCCESS == MPI_Finalize());
00084 #else
00085     return 1;
00086 #endif
00087 }
00088 
00089 /*
00090  * ***************************************************************************
00091  * Routine:  Vcom_ctor
00092  *
00093  * Purpose:  Construct the communications object
00094  *
00095  * Notes:    This routine sets up data members of class and initializes MPI.  
00096  *
00097  * Author:   Nathan Baker and Michael Holst
00098  * ***************************************************************************
00099  */
00100 VPUBLIC Vcom* Vcom_ctor(int commtype)
00101 {
00102     int rc;
00103     Vcom *thee = VNULL;
00104 
00105     /* Set up the structure */
00106     thee       = Vmem_malloc( VNULL, 1, sizeof(Vcom) );
00107     thee->core = Vmem_malloc( VNULL, 1, sizeof(Vcom_core) );
00108     
00109     /* Call the real constructor */
00110     rc = Vcom_ctor2(thee, commtype);
00111 
00112     /* Destroy the guy if something went wrong */
00113     if (rc == 0) {
00114         Vmem_free( VNULL, 1, sizeof(Vcom_core), (void**)&(thee->core) );
00115         Vmem_free( VNULL, 1, sizeof(Vcom), (void**)&thee );
00116     }
00117  
00118     return thee;
00119 }
00120 
00121 /*
00122  * ***************************************************************************
00123  * Routine:  Vcom_ctor2
00124  *
00125  * Purpose:  Construct the communications object
00126  *
00127  * Notes:    This routine sets up data members of class and initializes MPI.
00128  *
00129  *           This is broken into two parts to be callable from FORTRAN.
00130  *
00131  * Author:   Nathan Baker and Michael Holst
00132  * ***************************************************************************
00133  */
00134 VPUBLIC int Vcom_ctor2(Vcom *thee, int commtype)
00135 {
00136     int rc = 0;
00137 
00138 #if defined(HAVE_MPI_H)
00139     char estr[MPI_MAX_ERROR_STRING];
00140     int elen, dummy;
00141     Vcom_core *core = thee->core;
00142 #endif
00143 
00144     /*
00145      * See what type of communications we should use.  Maybe each type of
00146      * communications object should have its own ctor2() function.
00147      */
00148     switch ( commtype ) {
00149       case 1:             /* MPI 1.1 */
00150         thee->type = commtype;
00151 
00152 #if defined(HAVE_MPI_H)
00153 
00154         /* Start up MPI */
00155         rc = MPI_Initialized(&dummy);
00156         if (rc != MPI_SUCCESS) {
00157             MPI_Error_string(rc, estr, &elen);
00158             Vnm_print(2, "Vcom_ctor2: MPI_Init returned error: %s\n", 
00159               estr);
00160             return 0;
00161         } 
00162 
00163         /* Get the total number of processors */
00164         rc = MPI_Comm_size(MPI_COMM_WORLD, &(thee->mpi_size));
00165         if (rc != MPI_SUCCESS) {
00166             MPI_Error_string(rc, estr, &elen);
00167             Vnm_print(2, "Vcom_ctor2: MPI_Comm_size returned error: %s\n", 
00168               estr);
00169             return 0;
00170         }
00171 
00172         /* Get my processor rank */
00173         rc = MPI_Comm_rank(MPI_COMM_WORLD, &(thee->mpi_rank));
00174         if (rc != MPI_SUCCESS) {
00175             MPI_Error_string(rc, estr, &elen);
00176             Vnm_print(2, "Vcom_ctor2: MPI_Comm_rank returned error: %s\n", 
00177               estr);
00178             return 0;
00179         }
00180 
00181         /* Construct the communications group including all processors */
00182         core->mpi_comm = MPI_COMM_WORLD;
00183 
00184         /* Initialize Vnm with MPI rank */
00185         Vnm_setIoTag(thee->mpi_rank, thee->mpi_size);
00186 
00187         /* Some i/o */
00188         Vnm_print(2,"Vcom_ctor2: process %d of %d is ALIVE!\n",
00189             thee->mpi_rank, thee->mpi_size);
00190 
00191         rc = 1;
00192         break;
00193 
00194 #else  /* defined(HAVE_MPI_H) */
00195 
00196         /* this might not be an error if this is a sequential code... */
00197         rc = 1;
00198         break;
00199 
00200 #endif /* defined(HAVE_MPI_H) */
00201 
00202       default:
00203         Vnm_print(2, "Vcom_ctor2: Invalid communications type!\n");
00204         rc = 0;
00205 
00206     } /* switch (commtype) */
00207 
00208     return rc;
00209 }
00210 
00211 /*
00212  * ***************************************************************************
00213  * Routine:  Vcom_resize
00214  *
00215  * Purpose:  Resize (shrink) the communications group to include only newsize
00216  *           number of processors
00217  *
00218  * Notes:    Obsolete processes are given rank of -1 and size of 0
00219  *
00220  * Returns:  1 if sucessful
00221  *
00222  * Author:   Nathan Baker 
00223  * ***************************************************************************
00224  */
00225 VPUBLIC int Vcom_resize(Vcom *thee, int newsize)
00226 {
00227 #if defined(HAVE_MPI_H) 
00228     int color;
00229     MPI_Comm oldcomm;
00230     Vcom_core *core = thee->core;
00231 #endif
00232 
00233     switch (thee->type) {
00234         case 1:  /* MPI 1.1 */
00235 #if defined(HAVE_MPI_H)
00236             /* This is a no-op for obsolete processes */
00237             if (core->mpi_comm == MPI_COMM_NULL) return 1;
00238             Vcom_barr(thee);
00239             /* Split the communications group.  We will ignore all processes
00240              * with rank outside the desired size */
00241             if (newsize > thee->mpi_size) {
00242                 Vnm_print(2, "Vcom_resize:  Requested number of processors (%d) greater than original size (%d)!\n", newsize, thee->mpi_size);
00243                 return 0;
00244             }
00245             if (thee->mpi_rank < newsize) color = 0; 
00246             else color = MPI_UNDEFINED;
00247             MPI_Comm_dup(core->mpi_comm, &oldcomm);
00248             if (MPI_Comm_split(oldcomm, color, 0, &(core->mpi_comm)) 
00249               != MPI_SUCCESS) {
00250                 Vnm_print(2, "Vcom_resize:  Failed to split communicator!\n");
00251                 return 0;
00252             } 
00253             MPI_Comm_free(&oldcomm);
00254             if (core->mpi_comm != MPI_COMM_NULL) {
00255                 MPI_Comm_rank(core->mpi_comm, &(thee->mpi_rank));
00256                 MPI_Comm_size(core->mpi_comm, &(thee->mpi_size));
00257             } else {
00258                 thee->mpi_rank = -1;
00259                 thee->mpi_size = 0;
00260             }
00261             Vnm_print(0, "Vcom_resize: New comm size = %d\n", thee->mpi_size);
00262             return 1;
00263 #else
00264             Vnm_print(2, "Vcom_resize: Not compiled with MPI!\n");
00265             return 0;
00266 #endif
00267             break;
00268         default:
00269             Vnm_print(2, "Vcom_resize: Invalid communications type!\n");
00270             return 0;
00271     }
00272 }
00273 
00274 /*
00275  * ***************************************************************************
00276  * Routine:  Vcom_dtor
00277  *
00278  * Purpose:  Destroy the communications object
00279  *
00280  * Author:   Nathan Baker and Michael Holst
00281  * ***************************************************************************
00282  */
00283 VPUBLIC void Vcom_dtor(Vcom **thee)
00284 {
00285     if ((*thee) != VNULL) {
00286         Vcom_dtor2(*thee);
00287         Vmem_free( VNULL, 1, sizeof(Vcom_core), (void**)&((*thee)->core) );
00288         Vmem_free( VNULL, 1, sizeof(Vcom), (void**)thee );
00289     }
00290 }
00291 
00292 /*
00293  * ***************************************************************************
00294  * Routine:  Vcom_dtor2
00295  *
00296  * Purpose:  Destroy the communications object
00297  *
00298  * Notes:    This is broken into two parts to be callable from FORTRAN.
00299  *
00300  * Author:   Nathan Baker and Michael Holst
00301  * ***************************************************************************
00302  */
00303 VPUBLIC void Vcom_dtor2(Vcom *thee)
00304 {
00305 #if defined(HAVE_MPI_H)
00306     int err;
00307     Vcom_core *core = thee->core;
00308 #endif
00309 
00310     /*
00311      * Do various things depending on what type of communications object
00312      * this is.  Maybe each object type should have its own dtor2() function.
00313      */
00314     switch (thee->type) {
00315 
00316       case 1:  /* MPI 1.1 */
00317 #if defined(HAVE_MPI_H)
00318         /* Destroy the communicator */
00319         if ((core->mpi_comm != MPI_COMM_NULL) && 
00320             (core->mpi_comm != MPI_COMM_WORLD)) {
00321             Vnm_print(0, "Vcom_dtor2:  Freeing MPI communicator...\n");
00322             MPI_Comm_free(&(core->mpi_comm));
00323         }
00324 
00325 #if 0
00326         err = MPI_Finalize();
00327         if (err != MPI_SUCCESS) {
00328             Vnm_print(2, "Vcom_dtor2: MPI_Finalize returned %d\n", err);
00329         }
00330 #endif
00331 #endif
00332       default:
00333         return;
00334     }
00335 } 
00336 
00337 /*
00338  * ***************************************************************************
00339  * Routine:  Vcom_send
00340  *
00341  * Purpose:  Send a buffer.  Returns 1 on success.
00342  *
00343  * Args:     des   = rank of receiving processor
00344  *           buf   = buffer containing message
00345  *           len   = number of items (of declared type) in buffer
00346  *           type  = type of items in message
00347  *                   0 => MPI_BYTE
00348  *                   1 => MPI_INT
00349  *                   2 => MPI_DOUBLE
00350  *                   3 => MPI_CHAR
00351  *           block = toggles blocking on (=1) and off (=0)
00352  *
00353  * Returns:  1 if successful
00354  *
00355  * Author:   Nathan Baker and Michael Holst
00356  * ***************************************************************************
00357  */
00358 VPUBLIC int Vcom_send(Vcom *thee, int des, void *buf, int len, int type, 
00359     int block)
00360 {
00361 #if defined(HAVE_MPI_H)
00362     int tag = VCOM_MPI_TAG;  /* MPI tag */
00363     MPI_Datatype datatype;
00364     Vcom_core *core = thee->core;
00365 #endif
00366 
00367     int err = 1;             /* Error flag (success = 1) */
00368 
00369     /* Bail if we've received any errors */
00370     VASSERT(thee != VNULL);
00371 
00372     if (thee->error != 0) {
00373         Vnm_print(2, "Vcom_send:  Have non-zero error state (%d)!\n",
00374           thee->error);
00375         return 0;
00376     }
00377 
00378     /* Figure out data type to use */
00379 #if defined(HAVE_MPI_H)
00380     switch(type) {
00381         case 0: 
00382             datatype = MPI_BYTE;
00383             break;
00384         case 1: 
00385             datatype = MPI_INT;
00386             break;
00387         case 2:
00388             datatype = MPI_DOUBLE;
00389             break;
00390         case 3:
00391             datatype = MPI_CHAR;
00392             break;
00393         default:
00394             Vnm_print(2, "Vcom_send: Bogus datatype (%d), bailing!\n", type);
00395             return 0;
00396     }
00397 #endif
00398 
00399     /* Send routine depends on comm object type */
00400     switch(thee->type) {
00401 
00402       case 1: /* MPI 1.1 */
00403 #if defined(HAVE_MPI_H)
00404         if (core->mpi_comm == MPI_COMM_NULL) return 1;
00405         /* To block or not to block... */
00406         if (block == 1) {
00407             err = MPI_Send(buf, len, datatype, des, tag, core->mpi_comm);
00408             err = (MPI_SUCCESS == err);
00409         } else { /* if (block == 1) */
00410             err = MPI_Isend(buf, len, datatype, des, tag, core->mpi_comm,
00411                   &(core->mpi_request));
00412             err = (MPI_SUCCESS == err);
00413         } /* if (block == 1) */
00414 #else
00415         Vnm_print(2, "Vcom_send: Vcom not compiled with MPI!\n");
00416         return 0;
00417 #endif
00418         break; 
00419       default:
00420         Vnm_print(2, "Vcom_send: Invalid communications type!\n");
00421         return 0;
00422     }
00423 
00424     return err;
00425 }
00426 
00427 /*
00428  * ***************************************************************************
00429  * Routine:  Vcom_recv
00430  *
00431  * Purpose:  Receive a (character) buffer.  Returns 1 on success.  
00432  *
00433  * Args:     src   = rank of sending processor
00434  *           buf   = pointer to buffer of previously allocated memory
00435  *           len   = number of items (of declared type) in buffer
00436  *           type  = type of items in message
00437  *                   0 => MPI_BYTE
00438  *                   1 => MPI_INT
00439  *                   2 => MPI_DOUBLE
00440  *                   3 => MPI_CHAR
00441  *           block = toggles blocking on (=1) and off (=0)
00442  *
00443  * Returns:  1 if successful
00444  * 
00445  * Notes:    The blocking flag is present, but not used.  All receives are
00446  *           assumed to be blocking.  A non-blocking receive would be *very* 
00447  *           ugly to implement (signals or something?).
00448  *
00449  * Author:   Nathan Baker and Michael Holst
00450  * ***************************************************************************
00451  */
00452 VPUBLIC int Vcom_recv(Vcom *thee, int src, void *buf, int len, int type,
00453     int block)
00454 {
00455     int err = 0;             /* Error flag (success = 1) */
00456 
00457 #if defined(HAVE_MPI_H)
00458     int tag = VCOM_MPI_TAG;  /* MPI tag */
00459     MPI_Datatype datatype;
00460     Vcom_core *core = thee->core;
00461 #endif
00462 
00463     /* Bail if we've received any errors */
00464     VASSERT(thee != VNULL);
00465     if (thee->error != 0) {
00466         Vnm_print(2, "Vcom_send:  Have non-zero error state (%d)!\n",
00467           thee->error);
00468         return 0;
00469     }
00470 
00471 
00472 #if defined(HAVE_MPI_H)
00473     switch(type) {
00474         case 0:
00475             datatype = MPI_BYTE;
00476             break;
00477         case 1:
00478             datatype = MPI_INT;
00479             break;
00480         case 2:
00481             datatype = MPI_DOUBLE;
00482             break;
00483         case 3:
00484             datatype = MPI_CHAR;
00485             break;
00486         default:
00487             Vnm_print(2, "Vcom_recv: Bogus datatype (%d), bailing!\n", type);
00488             return 0;
00489     }
00490 #endif
00491 
00492     /* Send routine depends on comm object type */
00493     switch(thee->type) {
00494 
00495       case 1: /* MPI 1.1 */
00496 #if defined(HAVE_MPI_H)
00497         if (core->mpi_comm == MPI_COMM_NULL) return 1;
00498         /* To block or not to block... */
00499         if (block == 1) {
00500             err = MPI_Recv(buf, len, datatype, src, tag, 
00501                   core->mpi_comm, &(core->mpi_status));
00502             err = (MPI_SUCCESS == err);
00503         } else {
00504             Vnm_print(2, "Vcom_recv: WARNING! Non-blocking receive not implemented!\n");
00505             return 0;
00506         }
00507 #else
00508         Vnm_print(2, "Vcom_recv: Vcom not compiled with MPI!\n");
00509         return 0;
00510 #endif
00511 
00512         break; 
00513       default:
00514         Vnm_print(2, "Vcom_recv: Invalid communications type!\n");
00515         return 0;
00516     }
00517     return err;
00518 }
00519 
00520 /*
00521  * ***************************************************************************
00522  * Routine:  Vcom_size
00523  *
00524  * Purpose:  Get the number of PEs in communicator
00525  *
00526  * Returns:  Number of PEs or -1 if error
00527  * 
00528  * Author:   Nathan Baker and Michael Holst
00529  * ***************************************************************************
00530  */
00531 VPUBLIC int Vcom_size(Vcom *thee)
00532 {
00533 #if defined(HAVE_MPI_H)
00534     Vcom_core *core = thee->core;
00535 #endif
00536 
00537     VASSERT(thee != VNULL);
00538 
00539     if ( thee->type == 1) {
00540 #if defined(HAVE_MPI_H)
00541         if (core->mpi_comm == MPI_COMM_NULL) return 0;
00542         return thee->mpi_size;
00543 #else
00544         return 1;
00545 #endif
00546     } else { return -1; }
00547 }
00548 
00549 /*
00550  * ***************************************************************************
00551  * Routine:  Vcom_rank
00552  *
00553  * Purpose:  Get the ID of the local PE
00554  *
00555  * Returns:  PE rank or -1 if error
00556  * 
00557  * Author:   Nathan Baker and Michael Holst
00558  * ***************************************************************************
00559  */
00560 VPUBLIC int Vcom_rank(Vcom *thee)
00561 {
00562 #if defined(HAVE_MPI_H)
00563     Vcom_core *core = thee->core;
00564 #endif
00565 
00566     VASSERT(thee != VNULL);
00567 
00568     if ( thee->type == 1) {
00569 #if defined(HAVE_MPI_H)
00570         if (core->mpi_comm == MPI_COMM_NULL) return -1;
00571         return thee->mpi_rank;
00572 #else
00573         return 0;
00574 #endif
00575     } else { return -1; }
00576 }
00577 
00578 /*
00579  * ***************************************************************************
00580  * Routine:  Vcom_barr
00581  *
00582  * Purpose:  Synchronization barrier.
00583  *
00584  * Returns:  1 if succesful
00585  * 
00586  * Author:   Michael Holst
00587  * ***************************************************************************
00588  */
00589 VPUBLIC int Vcom_barr(Vcom *thee)
00590 {
00591 #if defined(HAVE_MPI_H)
00592     int err;
00593     Vcom_core *core = thee->core;
00594 #endif
00595 
00596     VASSERT(thee != VNULL);
00597 
00598     if ( thee->type == 1) {
00599 
00600 #if defined(HAVE_MPI_H)
00601         if (core->mpi_comm != MPI_COMM_NULL) {
00602             err = MPI_Barrier(core->mpi_comm);
00603             return (err == MPI_SUCCESS);
00604         } else return 1;
00605 #else
00606         Vnm_print(2, "Vcom_barr: Vcom not compiled with MPI!\n");
00607         return 0;
00608 #endif
00609     } else {
00610         Vnm_print(2, "Vcom_barr: Invalid communications type!\n");
00611         return 0;
00612     }
00613     return 0;
00614 }
00615 
00616 /*
00617  * ***************************************************************************
00618  * Routine:  Vcom_getCount
00619  *
00620  * Purpose:  Perform a blocking probe to get the length (in number of items of
00621  *           specified type) of an incoming message and place it in the 
00622  *           argument ``length".
00623  *
00624  *           type  = type of items in message
00625  *                   0 => MPI_BYTE
00626  *                   1 => MPI_INT
00627  *                   2 => MPI_DOUBLE
00628  *                   3 => MPI_CHAR
00629  * 
00630  * Author:   Nathan Baker
00631  * ***************************************************************************
00632  */
00633 VPUBLIC int Vcom_getCount(Vcom *thee, int src, int *length, int type)
00634 {
00635 #if defined(HAVE_MPI_H)
00636     MPI_Datatype datatype;
00637     Vcom_core *core = thee->core;
00638 #endif
00639 
00640     VASSERT(thee != VNULL);
00641 
00642 #if defined(HAVE_MPI_H)
00643     switch(type) {
00644         case 0:
00645             datatype = MPI_BYTE;
00646             break;
00647         case 1:
00648             datatype = MPI_INT;
00649             break;
00650         case 2:
00651             datatype = MPI_DOUBLE;
00652             break;
00653         case 3:
00654             datatype = MPI_CHAR;
00655             break;
00656         default:
00657             Vnm_print(2,"Vcom_getCount: Bogus datatype (%d), bailing!\n",type);
00658             return 0;
00659     }
00660 #endif
00661 
00662     if ( thee->type == 1) {
00663 #if defined(HAVE_MPI_H)
00664         if (core->mpi_comm == MPI_COMM_NULL) return 1;
00665         MPI_Probe(src, VCOM_MPI_TAG, core->mpi_comm, &(core->mpi_status));
00666         return MPI_Get_count(&(core->mpi_status), datatype, length);
00667 #else
00668         Vnm_print(2, "Vcom_getCount: Vcom not compiled with MPI!\n");
00669         return -1;
00670 #endif
00671     } else { return -1; }
00672 }
00673 
00674 /*
00675  * ***************************************************************************
00676  * Routine:  Vcom_reduce
00677  *
00678  * Purpose:  Perform a reduction of the data across all processors.  This is
00679  *           equivalent (and in the case of MPI is identical to) MPI_Allreduce.
00680  *           Basically, the specified operations are appleed to each member of
00681  *           the sendbuf across all processors and the results are written to
00682  *           recvbuf.
00683  *
00684  * Args:     sendbuf = buffer containing `length` items of the specified type
00685  *                     to be operated on
00686  *           recvbuf = buffer containing `length` items of the specified type
00687  *                     after operation
00688  *           length = number of items 
00689  *           type  = type of items in message
00690  *                   0 => MPI_BYTE
00691  *                   1 => MPI_INT
00692  *                   2 => MPI_DOUBLE
00693  *                   3 => MPI_CHAR
00694  *           op = operation to perform
00695  *                0 => MPI_SUM
00696  *                1 => MPI_PROD
00697  *                2 => MPI_MIN
00698  *                3 => MPI_MAX
00699  * 
00700  * Author:   Nathan Baker
00701  * ***************************************************************************
00702  */
00703 VPUBLIC int Vcom_reduce(Vcom *thee, void *sendbuf, void *recvbuf, int length,
00704     int type, int op)
00705 {
00706     int memsize;
00707 
00708 #if defined(HAVE_MPI_H)
00709     MPI_Datatype datatype;
00710     MPI_Op optype;
00711     Vcom_core *core = thee->core;
00712 #endif
00713 
00714     VASSERT(thee != VNULL);
00715 
00716 #if defined(HAVE_MPI_H)
00717     switch(type) {
00718         case 0:
00719             datatype = MPI_BYTE;
00720             break;
00721         case 1:
00722             datatype = MPI_INT;
00723             break;
00724         case 2:
00725             datatype = MPI_DOUBLE;
00726             break;
00727         case 3:
00728             datatype = MPI_CHAR;
00729             break;
00730         default:
00731             Vnm_print(2, "Vcom_recv: Bogus datatype (%d), bailing!\n", type);
00732             return 0;
00733     }
00734     switch(op) {
00735         case 0: 
00736             optype = MPI_SUM;
00737             break;
00738         case 1: 
00739             optype = MPI_PROD;
00740             break;
00741         case 2: 
00742             optype = MPI_MIN;
00743             break;
00744         case 3: 
00745             optype = MPI_MAX;
00746             break;
00747         default:
00748             Vnm_print(2, "Vcom_reduce: Bogus optype (%d), bailing!\n", type);
00749             return 0;
00750     }
00751 #endif
00752 
00753     if ( thee->type == 1) {
00754 
00755 #if defined(HAVE_MPI_H)
00756 
00757         if (core->mpi_comm == MPI_COMM_NULL) return 1;
00758         return MPI_Allreduce(sendbuf, recvbuf, length, datatype, optype, 
00759           core->mpi_comm);
00760 
00761 #else
00762         Vnm_print(0, "Vcom_reduce:  Not compiled with MPI, doing simple copy.\n");
00763         switch(type) {
00764             case 0:
00765                 memsize = 1;
00766                 break;
00767             case 1:
00768                 memsize = sizeof(int);
00769                 break;
00770             case 2:
00771                 memsize = sizeof(double);
00772                 break;
00773             case 3:
00774                 memsize = sizeof(char);
00775                 break;
00776             default:
00777                 Vnm_print(2, "Vcom_recv: Bogus datatype (%d), bailing!\n", type);
00778                 return 0;
00779         }
00780 
00781         memcpy(recvbuf, sendbuf, memsize*length);
00782         return 1;
00783 
00784 #endif
00785 
00786     } else { return -1; }
00787 }
00788 

Generated on Wed Oct 20 2010 11:12:15 for APBS by  doxygen 1.7.2