Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
add mpich3 topo tests
authorAugustin Degomme <degomme@idpann.imag.fr>
Wed, 12 Mar 2014 09:35:58 +0000 (10:35 +0100)
committerAugustin Degomme <degomme@idpann.imag.fr>
Wed, 12 Mar 2014 09:40:36 +0000 (10:40 +0100)
They are not built or run for now, because features are not yet implemented

19 files changed:
buildtools/Cmake/DefinePackages.cmake
buildtools/Cmake/MakeExe.cmake
teshsuite/smpi/mpich3-test/topo/CMakeLists.txt [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/cartcreates.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/cartmap1.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/cartshift1.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/cartsuball.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/cartzero.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/dgraph_unwgt.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/dims1.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/dims2.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/distgraph1.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/graphcr.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/graphcr2.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/graphmap1.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/neighb_coll.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/testlist [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/topodup.c [new file with mode: 0644]
teshsuite/smpi/mpich3-test/topo/topotest.c [new file with mode: 0644]

index b2d079e..3cda367 100644 (file)
@@ -956,6 +956,7 @@ set(TESHSUITE_CMAKEFILES_TXT
   teshsuite/smpi/mpich3-test/coll/CMakeLists.txt
   teshsuite/smpi/mpich3-test/datatype/CMakeLists.txt
   teshsuite/smpi/mpich3-test/group/CMakeLists.txt
   teshsuite/smpi/mpich3-test/coll/CMakeLists.txt
   teshsuite/smpi/mpich3-test/datatype/CMakeLists.txt
   teshsuite/smpi/mpich3-test/group/CMakeLists.txt
+  teshsuite/smpi/mpich3-test/topo/CMakeLists.txt
   teshsuite/smpi/mpich3-test/init/CMakeLists.txt
   teshsuite/smpi/mpich3-test/pt2pt/CMakeLists.txt
   teshsuite/smpi/mpich3-test/f77/util/CMakeLists.txt
   teshsuite/smpi/mpich3-test/init/CMakeLists.txt
   teshsuite/smpi/mpich3-test/pt2pt/CMakeLists.txt
   teshsuite/smpi/mpich3-test/f77/util/CMakeLists.txt
index c854fb5..72ec2fc 100644 (file)
@@ -97,6 +97,7 @@ add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/coll)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/comm)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/datatype)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/group)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/comm)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/datatype)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/group)
+add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/topo)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/init)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/pt2pt)
 
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/init)
 add_subdirectory(${CMAKE_HOME_DIRECTORY}/teshsuite/smpi/mpich3-test/pt2pt)
 
diff --git a/teshsuite/smpi/mpich3-test/topo/CMakeLists.txt b/teshsuite/smpi/mpich3-test/topo/CMakeLists.txt
new file mode 100644 (file)
index 0000000..6bc6b43
--- /dev/null
@@ -0,0 +1,87 @@
+cmake_minimum_required(VERSION 2.6)
+
+if(enable_smpi AND enable_smpi_MPICH3_testsuite)
+  if(WIN32)
+    set(CMAKE_C_FLAGS "-include ${CMAKE_HOME_DIRECTORY}/include/smpi/smpi_main.h")
+  else()
+    set(CMAKE_C_COMPILER "${CMAKE_BINARY_DIR}/smpi_script/bin/smpicc")
+    set(CMAKE_Fortran_COMPILER "${CMAKE_BINARY_DIR}/smpi_script/bin/smpiff")
+  endif()
+
+  set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_BINARY_DIR}")
+  include_directories("${CMAKE_HOME_DIRECTORY}/include/smpi")
+  include_directories("${CMAKE_CURRENT_SOURCE_DIR}/../include/")
+
+
+#  add_executable(cartcreates cartcreates.c)
+#  add_executable(cartmap1 cartmap1.c)
+#  add_executable(cartshift1 cartshift1.c)
+#  add_executable(cartsuball cartsuball.c)
+#  add_executable(cartzero cartzero.c)
+#  add_executable(dgraph_unwgt dgraph_unwgt.c)
+#  add_executable(dims1 dims1.c)
+#  add_executable(dims2 dims2.c)
+#  add_executable(distgraph1 distgraph1.c)
+#  add_executable(graphcr2 graphcr2.c)
+#  add_executable(graphcr graphcr.c)
+#  add_executable(graphmap1 graphmap1.c)
+#  add_executable(neighb_coll neighb_coll.c)
+#  add_executable(topodup topodup.c)
+#  add_executable(topotest topotest.c)
+
+
+#  target_link_libraries(cartcreates simgrid mtest_c)
+#  target_link_libraries(cartmap1 simgrid mtest_c)
+#  target_link_libraries(cartshift1 simgrid mtest_c)
+#  target_link_libraries(cartsuball simgrid mtest_c)
+#  target_link_libraries(cartzero simgrid mtest_c)
+#  target_link_libraries(dgraph_unwgt simgrid mtest_c)
+#  target_link_libraries(dims1 simgrid mtest_c)
+#  target_link_libraries(dims2 simgrid mtest_c)
+#  target_link_libraries(distgraph1 simgrid mtest_c)
+#  target_link_libraries(graphcr2 simgrid mtest_c)
+#  target_link_libraries(graphcr simgrid mtest_c)
+#  target_link_libraries(graphmap1 simgrid mtest_c)
+#  target_link_libraries(neighb_coll simgrid mtest_c)
+#  target_link_libraries(topodup simgrid mtest_c)
+#  target_link_libraries(topotest simgrid mtest_c)
+
+endif()
+
+set(tesh_files
+  ${tesh_files}
+  PARENT_SCOPE
+  )
+set(xml_files
+  ${xml_files}
+  PARENT_SCOPE
+  )
+set(examples_src
+ ${examples_src}
+ ${CMAKE_CURRENT_SOURCE_DIR}/cartcreates.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/cartmap1.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/cartshift1.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/cartsuball.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/cartzero.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/dgraph_unwgt.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/dims1.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/dims2.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/distgraph1.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/graphcr2.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/graphcr.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/graphmap1.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/neighb_coll.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/testlist
+ ${CMAKE_CURRENT_SOURCE_DIR}/topodup.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/topotest.c
+  PARENT_SCOPE
+  )
+set(bin_files
+  ${bin_files}
+  PARENT_SCOPE
+  )
+set(txt_files
+  ${txt_files}
+  ${CMAKE_CURRENT_SOURCE_DIR}/testlist
+  PARENT_SCOPE
+  )
diff --git a/teshsuite/smpi/mpich3-test/topo/cartcreates.c b/teshsuite/smpi/mpich3-test/topo/cartcreates.c
new file mode 100644 (file)
index 0000000..92365d7
--- /dev/null
@@ -0,0 +1,54 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include "mpitest.h"
+
+int main( int argc, char *argv[] )
+{
+    int errs = 0;
+    int size, rank;
+    int dims[2], periods[2];
+    MPI_Comm comm;
+
+    MTest_Init( &argc, &argv );
+
+    /* Create a new cartesian communicator in a subset of the processes */
+    MPI_Comm_size( MPI_COMM_WORLD, &size );
+    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+    if (size < 2) {
+       fprintf( stderr, "This test needs at least 2 processes\n" );
+       MPI_Abort( MPI_COMM_WORLD, 1 );
+    }
+    dims[0]    = size-1;
+    periods[0] = 1;
+    MPI_Cart_create( MPI_COMM_WORLD, 1, dims, periods, 0, &comm );
+
+    if (comm != MPI_COMM_NULL) {
+       int csize;
+       MPI_Comm_size( comm, &csize );
+       if (csize != dims[0]) {
+           errs++;
+           fprintf( stderr, 
+            "Sizes is wrong in cart communicator.  Is %d, should be %d\n", 
+            csize, dims[0] ); 
+       }
+       MPI_Barrier( comm );
+
+       MPI_Comm_free( &comm );
+    } 
+    else if (rank < dims[0]) {
+       errs++;
+       fprintf( stderr, "Communicator returned is null!" );
+    }
+
+    MTest_Finalize( errs );
+
+    MPI_Finalize();
+
+    return 0;
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/cartmap1.c b/teshsuite/smpi/mpich3-test/topo/cartmap1.c
new file mode 100644 (file)
index 0000000..1ce5ad8
--- /dev/null
@@ -0,0 +1,64 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include "mpitest.h"
+
+int main( int argc, char *argv[] )
+{
+    int errs = 0;
+    int dims[2];
+    int periods[2];
+    int size, rank, newrank;
+
+    MTest_Init( &argc, &argv );
+
+    MPI_Comm_size( MPI_COMM_WORLD, &size );
+    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+    
+    /* This defines a one dimensional cartision grid with a single point */
+    periods[0] = 1;
+    dims[0] = 1;
+
+    MPI_Cart_map( MPI_COMM_WORLD, 1, dims, periods, &newrank );
+    if (rank > 0) {
+       if (newrank != MPI_UNDEFINED) {
+           errs++;
+           printf( "rank outside of input communicator not UNDEFINED\n" );
+       }
+    }
+    else {
+       if (rank != newrank) {
+           errs++;
+           printf( "Newrank not defined and should be 0\n" );
+       }
+    }
+
+
+    /* As of MPI 2.1, a 0-dimensional topology is valid (its also a
+       point) */
+    MPI_Cart_map( MPI_COMM_WORLD, 0, dims, periods, &newrank );
+    if (rank > 0) {
+       if (newrank != MPI_UNDEFINED) {
+           errs++;
+           printf( "rank outside of input communicator not UNDEFINED\n" );
+       }
+    }
+    else {
+       /* rank == 0 */
+       if (rank != newrank) {
+           errs++;
+           printf( "Newrank not defined and should be 0\n" );
+       }
+    }
+
+
+    MTest_Finalize( errs );
+    MPI_Finalize();
+    return 0;
+  
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/cartshift1.c b/teshsuite/smpi/mpich3-test/topo/cartshift1.c
new file mode 100644 (file)
index 0000000..679f12c
--- /dev/null
@@ -0,0 +1,96 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include "mpitest.h"
+
+int main( int argc, char *argv[] )
+{
+    int errs = 0;
+    int size, rank;
+    int source, dest;
+    int dims[2], periods[2];
+    MPI_Comm comm;
+
+    MTest_Init( &argc, &argv );
+    
+    MPI_Comm_size( MPI_COMM_WORLD, &size );
+    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+    dims[0]    = size;
+    periods[0] = 1;
+    MPI_Cart_create( MPI_COMM_WORLD, 1, dims, periods, 0, &comm );
+    MPI_Cart_shift( comm, 0, 1, &source, &dest );
+    if (source != ((rank - 1 + size) % size)) {
+       errs++;
+       printf( "source for shift 1 is %d\n", source );
+    }
+    if (dest != ((rank + 1) % size)) {
+       errs++;
+       printf( "dest for shift 1 is %d\n", dest );
+    }
+    MPI_Cart_shift( comm, 0, 0, &source, &dest );
+    if (source != rank) {
+       errs++;
+       printf( "Source for shift 0 is %d\n", source );
+    }
+    if (dest != rank) {
+       errs++;
+       printf( "Dest for shift 0 is %d\n", dest );
+    }
+    MPI_Cart_shift( comm, 0, -1, &source, &dest );
+    if (source != ((rank + 1) % size)) {
+       errs++;
+       printf( "source for shift -1 is %d\n", source );
+    }
+    if (dest != ((rank - 1 + size) % size)) {
+       errs++;
+       printf( "dest for shift -1 is %d\n", dest );
+    }
+
+    /* Now, with non-periodic */
+    MPI_Comm_free( &comm );
+    periods[0] = 0;
+    MPI_Cart_create( MPI_COMM_WORLD, 1, dims, periods, 0, &comm );
+    MPI_Cart_shift( comm, 0, 1, &source, &dest );
+    if ((rank > 0 && source != (rank - 1)) || 
+       (rank == 0 && source != MPI_PROC_NULL)) {
+       errs++;
+       printf( "source for non-periodic shift 1 is %d\n", source );
+    }
+    if ((rank < size-1 && dest != rank + 1) || 
+       ((rank == size-1) && dest != MPI_PROC_NULL)) {
+       errs++;
+       printf( "dest for non-periodic shift 1 is %d\n", dest );
+    }
+    MPI_Cart_shift( comm, 0, 0, &source, &dest );
+    if (source != rank) {
+       errs++;
+       printf( "Source for non-periodic shift 0 is %d\n", source );
+    }
+    if (dest != rank) {
+       errs++;
+       printf( "Dest for non-periodic shift 0 is %d\n", dest );
+    }
+    MPI_Cart_shift( comm, 0, -1, &source, &dest );
+    if ((rank < size - 1 && source != rank + 1) ||
+       (rank == size - 1 && source != MPI_PROC_NULL)) {
+       
+       errs++;
+       printf( "source for non-periodic shift -1 is %d\n", source );
+    }
+    if ((rank > 0 && dest != rank - 1) ||
+       (rank == 0 && dest != MPI_PROC_NULL)) {
+       errs++;
+       printf( "dest for non-periodic shift -1 is %d\n", dest );
+    }
+    MPI_Comm_free( &comm );
+    
+    MTest_Finalize( errs );
+    MPI_Finalize();
+    return 0;
+  
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/cartsuball.c b/teshsuite/smpi/mpich3-test/topo/cartsuball.c
new file mode 100644 (file)
index 0000000..890db5a
--- /dev/null
@@ -0,0 +1,54 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include "mpitest.h"
+
+int main( int argc, char *argv[] )
+{
+    int errs = 0;
+    int size, dims[2], periods[2], remain[2];
+    int result, rank;
+    MPI_Comm comm, newcomm;
+
+    MTest_Init( &argc, &argv );
+
+    /* First, create a 1-dim cartesian communicator */
+    periods[0] = 0;
+    MPI_Comm_size( MPI_COMM_WORLD, &size );
+    dims[0] = size;
+    MPI_Cart_create( MPI_COMM_WORLD, 1, dims, periods, 0, &comm );
+    
+    /* Now, extract a communicator with no dimensions */
+    remain[0] = 0;
+    MPI_Cart_sub( comm, remain, &newcomm );
+
+    MPI_Comm_rank(comm, &rank);
+
+    if (rank == 0) {
+       /* This should be congruent to MPI_COMM_SELF */
+       MPI_Comm_compare( MPI_COMM_SELF, newcomm, &result );
+       if (result != MPI_CONGRUENT) {
+           errs++;
+           printf( "cart sub to size 0 did not give self\n" );
+       }
+       MPI_Comm_free( &newcomm );
+    }
+    else if (newcomm != MPI_COMM_NULL) {
+       errs++;
+       printf( "cart sub to size 0 did not give null\n" );
+    }
+
+    /* Free the new communicator so that storage leak tests will
+       be happy */
+    MPI_Comm_free( &comm );
+    
+    MTest_Finalize( errs );
+    MPI_Finalize();
+    return 0;
+  
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/cartzero.c b/teshsuite/smpi/mpich3-test/topo/cartzero.c
new file mode 100644 (file)
index 0000000..c8e601e
--- /dev/null
@@ -0,0 +1,92 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2008 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include "mpitest.h"
+
+/*  
+    Check that the MPI implementation properly handles zero-dimensional
+    Cartesian communicators - the original standard implies that these
+    should be consistent with higher dimensional topologies and thus 
+    these should work with any MPI implementation.  MPI 2.1 made this
+    requirement explicit.
+*/
+int main( int argc, char *argv[] )
+{
+    int errs = 0;
+    int size, rank, ndims;
+    MPI_Comm comm, newcomm;
+
+    MTest_Init( &argc, &argv );
+
+    /* Create a new cartesian communicator in a subset of the processes */
+    MPI_Comm_size( MPI_COMM_WORLD, &size );
+    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+    if (size < 2) {
+       fprintf( stderr, "This test needs at least 2 processes\n" );
+       MPI_Abort( MPI_COMM_WORLD, 1 );
+    }
+
+    MPI_Cart_create( MPI_COMM_WORLD, 0, NULL, NULL, 0, &comm );
+
+    if (comm != MPI_COMM_NULL) {
+       int csize;
+       MPI_Comm_size( comm, &csize );
+       if (csize != 1) {
+           errs++;
+           fprintf( stderr, 
+            "Sizes is wrong in cart communicator.  Is %d, should be 1\n", 
+            csize ); 
+       }
+
+       /* This function is not meaningful, but should not fail */
+       MPI_Dims_create(1, 0, NULL);
+
+       ndims = -1;
+       MPI_Cartdim_get(comm, &ndims);
+       if (ndims != 0) {
+           errs++;
+           fprintf(stderr, "MPI_Cartdim_get: ndims is %d, should be 0\n", ndims);
+       }
+
+       /* this function should not fail */
+       MPI_Cart_get(comm, 0, NULL, NULL, NULL);
+
+       MPI_Cart_rank(comm, NULL, &rank);
+       if (rank != 0) {
+           errs++;
+           fprintf(stderr, "MPI_Cart_rank: rank is %d, should be 0\n", rank);
+       }
+
+       /* this function should not fail */
+       MPI_Cart_coords(comm, 0, 0, NULL);
+
+       MPI_Cart_sub(comm, NULL, &newcomm);
+       ndims = -1;
+       MPI_Cartdim_get(newcomm, &ndims);
+       if (ndims != 0) {
+           errs++;
+           fprintf(stderr, 
+              "MPI_Cart_sub did not return zero-dimensional communicator\n");
+       }
+
+       MPI_Barrier( comm );
+
+       MPI_Comm_free( &comm );
+       MPI_Comm_free( &newcomm );
+    } 
+    else if (rank == 0) {
+       errs++;
+       fprintf( stderr, "Communicator returned is null!" );
+    }
+
+    MTest_Finalize( errs );
+
+    MPI_Finalize();
+
+    return 0;
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/dgraph_unwgt.c b/teshsuite/smpi/mpich3-test/topo/dgraph_unwgt.c
new file mode 100644 (file)
index 0000000..e29b3a4
--- /dev/null
@@ -0,0 +1,171 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "mpi.h"
+#include "mpitest.h"
+
+#define RING_NUM_NEIGHBORS   2
+
+static int validate_dgraph(MPI_Comm dgraph_comm)
+{
+    int         comm_topo;
+    int         src_sz, dest_sz;
+    int         wgt_flag, ierr;
+    int         srcs[RING_NUM_NEIGHBORS], dests[RING_NUM_NEIGHBORS];
+    int        *src_wgts, *dest_wgts;
+
+    int         world_rank, world_size;
+    int         idx, nbr_sep;
+
+    comm_topo = MPI_UNDEFINED;
+    MPI_Topo_test(dgraph_comm, &comm_topo);
+    switch (comm_topo) {
+        case MPI_DIST_GRAPH :
+            break;
+        default:
+            fprintf(stderr, "dgraph_comm is NOT of type MPI_DIST_GRAPH\n");
+            return 0;
+    }
+
+    ierr = MPI_Dist_graph_neighbors_count(dgraph_comm,
+                                          &src_sz, &dest_sz, &wgt_flag);
+    if (ierr != MPI_SUCCESS) {
+        fprintf(stderr, "MPI_Dist_graph_neighbors_count() fails!\n");
+        return 0;
+    }
+/*
+    else
+        fprintf(stderr, "MPI_Dist_graph_neighbors_count() succeeds!\n");
+*/
+
+    if (wgt_flag) {
+        fprintf(stderr, "dgraph_comm is NOT created with MPI_UNWEIGHTED\n");
+        return 0;
+    }
+/*
+    else
+        fprintf(stderr, "dgraph_comm is created with MPI_UNWEIGHTED\n");
+*/
+    if (src_sz != RING_NUM_NEIGHBORS || dest_sz != RING_NUM_NEIGHBORS) {
+        fprintf(stderr, "source or destination edge array is not of size %d.\n",
+                         RING_NUM_NEIGHBORS);
+        fprintf(stderr, "src_sz = %d, dest_sz = %d\n", src_sz, dest_sz);
+        return 0;
+    }
+
+    /*
+       src_wgts and dest_wgts could be anything, e.g. NULL, since
+       MPI_Dist_graph_neighbors_count() returns MPI_UNWEIGHTED.
+       Since this program has a Fortran77 version, and standard Fortran77
+       has no pointer and NULL, so use MPI_UNWEIGHTED for the weighted arrays.
+    */
+    src_wgts  = MPI_UNWEIGHTED;
+    dest_wgts = MPI_UNWEIGHTED;
+    ierr = MPI_Dist_graph_neighbors(dgraph_comm,
+                                    src_sz, srcs, src_wgts,
+                                    dest_sz, dests, dest_wgts);
+    if (ierr != MPI_SUCCESS) {
+        fprintf(stderr, "MPI_Dist_graph_neighbors() fails!\n");
+        return 0;
+    }
+/*
+    else
+        fprintf(stderr, "MPI_Dist_graph_neighbors() succeeds!\n");
+*/
+
+    /*
+       Check if the neighbors returned from MPI are really
+       the nearest neighbors within a ring.
+    */
+    MPI_Comm_size(MPI_COMM_WORLD, &world_size);
+    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
+    for (idx=0; idx < src_sz; idx++) {
+        nbr_sep = abs(srcs[idx] - world_rank);
+        if ( nbr_sep != 1 && nbr_sep != (world_size-1) ) {
+            fprintf(stderr, "srcs[%d]=%d is NOT a neighbor of my rank %d.\n",
+                            idx, srcs[idx], world_rank);
+            return 0;
+        }  
+    }
+    for (idx=0; idx < dest_sz; idx++) {
+        nbr_sep = abs(dests[idx] - world_rank);
+        if ( nbr_sep != 1 && nbr_sep != (world_size-1) ) {
+            fprintf(stderr, "dests[%d]=%d is NOT a neighbor of my rank %d.\n",
+                            idx, dests[idx], world_rank);
+            return 0;
+        }  
+    }
+
+    /*
+    fprintf(stderr, "dgraph_comm is of type MPI_DIST_GRAPH "
+                    "of a bidirectional ring.\n");
+    */
+    return 1;
+}
+
+/*
+   Specify a distributed graph of a bidirectional ring of the MPI_COMM_WORLD,
+   i.e. everyone only talks to left and right neighbors. 
+*/
+int main(int argc, char *argv[])
+{
+    MPI_Comm    dgraph_comm;
+    int         world_size, world_rank, ierr;
+    int         errs = 0;
+
+    int         src_sz, dest_sz;
+    int         degs[1];
+    int         srcs[RING_NUM_NEIGHBORS], dests[RING_NUM_NEIGHBORS];
+    
+    MTest_Init(&argc, &argv);
+    MPI_Comm_size(MPI_COMM_WORLD, &world_size);
+    MPI_Comm_rank(MPI_COMM_WORLD, &world_rank);
+
+    degs[0]  = 2;
+    srcs[0]  = world_rank;
+    dests[0] = world_rank-1 <  0          ? world_size-1 : world_rank-1 ;
+    dests[1] = world_rank+1 >= world_size ?            0 : world_rank+1 ;
+    ierr = MPI_Dist_graph_create(MPI_COMM_WORLD, 1, srcs, degs, dests,
+                                 MPI_UNWEIGHTED, MPI_INFO_NULL, 1,
+                                 &dgraph_comm);
+    if ( ierr != MPI_SUCCESS )  {
+        fprintf(stderr, "MPI_Dist_graph_create() fails!\n");
+        MPI_Abort(MPI_COMM_WORLD, 1);
+        return 1;
+    }
+    if (!validate_dgraph(dgraph_comm)) {
+        fprintf(stderr, "MPI_Dist_graph_create() does NOT create "
+                        "a bidirectional ring graph!\n");
+        MPI_Abort(MPI_COMM_WORLD, 1);
+        return 1;
+    }
+    MPI_Comm_free(&dgraph_comm);
+    
+    src_sz   = 2;
+    srcs[0]  = world_rank-1 <  0          ? world_size-1 : world_rank-1 ;
+    srcs[1]  = world_rank+1 >= world_size ?            0 : world_rank+1 ;
+    dest_sz  = 2;
+    dests[0] = world_rank-1 <  0          ? world_size-1 : world_rank-1 ;
+    dests[1] = world_rank+1 >= world_size ?            0 : world_rank+1 ;
+    ierr = MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD,
+                                          src_sz, srcs, MPI_UNWEIGHTED,
+                                          dest_sz, dests, MPI_UNWEIGHTED,
+                                          MPI_INFO_NULL, 1, &dgraph_comm);
+    if ( ierr != MPI_SUCCESS ) {
+        fprintf(stderr, "MPI_Dist_graph_create_adjacent() fails!\n");
+        MPI_Abort(MPI_COMM_WORLD, 1);
+        return 1;
+    }
+    if (!validate_dgraph(dgraph_comm)) {
+        fprintf(stderr, "MPI_Dist_graph_create_adjacent() does NOT create "
+                        "a bidirectional ring graph!\n");
+        MPI_Abort(MPI_COMM_WORLD, 1);
+        return 1;
+    }
+    MPI_Comm_free(&dgraph_comm);
+
+    MTest_Finalize(errs);
+    MPI_Finalize();
+    return 0;
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/dims1.c b/teshsuite/smpi/mpich3-test/topo/dims1.c
new file mode 100644 (file)
index 0000000..b429776
--- /dev/null
@@ -0,0 +1,144 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include "mpitest.h"
+
+int prodof( int ndims, const int dims[] );
+int increasing( int ndims, const int dims[] );
+
+int prodof( int ndims, const int dims[] )
+{
+    int i, prod=1;
+    for (i=0; i<ndims; i++) 
+       prod *= dims[i];
+    return prod;
+}
+
+int increasing( int ndims, const int dims[] )
+{
+    int i, err=0;
+    for (i=1; i<ndims; i++) {
+       if (dims[i] > dims[i-1]) {
+           printf ("%d = dims[%d] > dims[%d] = %d\n", dims[i], i, 
+                   i-1, dims[i-1] );
+           err = 1;
+       }
+    }
+    return err;
+}
+int main( int argc, char *argv[] )
+{
+    int errs = 0;
+    int dims[4], nnodes, ndims;
+
+    MTest_Init( &argc, &argv );
+
+    /* Test multiple dims create values.  For each, make sure that the 
+       product of dims is the number of input nodes */
+    nnodes = 2*3*5*7*11;
+    ndims  = 2;
+    dims[0] = dims[1] = 0;
+    MPI_Dims_create( nnodes, ndims, dims );
+    if (prodof(ndims,dims) != nnodes) {
+       errs++;
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+    if (increasing( ndims, dims )) {
+       errs++;
+       printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" );
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+
+    /* Test multiple dims create values.  For each, make sure that the 
+       product of dims is the number of input nodes */
+    nnodes = 2*7;
+    ndims  = 2;
+    dims[0] = dims[1] = 0;
+    MPI_Dims_create( nnodes, ndims, dims );
+    if (prodof(ndims,dims) != nnodes) {
+       errs++;
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+    if (increasing( ndims, dims )) {
+       errs++;
+       printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" );
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+
+    nnodes = 2*2*3*3*5*7*11;
+    ndims  = 2;
+    dims[0] = dims[1] = 0;
+    MPI_Dims_create( nnodes, ndims, dims );
+    if (prodof(ndims,dims) != nnodes) {
+       errs++;
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+    if (increasing( ndims, dims )) {
+       errs++;
+       printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" );
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+
+    nnodes = 11;
+    ndims  = 2;
+    dims[0] = dims[1] = 0;
+    MPI_Dims_create( nnodes, ndims, dims );
+    if (prodof(ndims,dims) != nnodes) {
+       errs++;
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+    if (increasing( ndims, dims )) {
+       errs++;
+       printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" );
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+
+    nnodes = 5*7*11;
+    ndims  = 4;
+    dims[0] = dims[1] = dims[2] = dims[3] = 0;
+    MPI_Dims_create( nnodes, ndims, dims );
+    if (prodof(ndims,dims) != nnodes) {
+       errs++;
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+    if (increasing( ndims, dims )) {
+       errs++;
+       printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" );
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+
+    nnodes = 64;
+    ndims  = 4;
+    dims[0] = dims[1] = dims[2] = dims[3] = 0;
+    MPI_Dims_create( nnodes, ndims, dims );
+    if (prodof(ndims,dims) != nnodes) {
+       errs++;
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+    if (increasing( ndims, dims )) {
+       errs++;
+       printf( "dims create returned a decomposition with increasing dimensions (see MPI-1 standard section 6.5)\n" );
+       printf( "dims create returned the wrong decomposition for %d in %d dims\n",
+               nnodes, ndims );
+    }
+
+    MTest_Finalize( errs );
+    MPI_Finalize();
+    return 0;
+  
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/dims2.c b/teshsuite/smpi/mpich3-test/topo/dims2.c
new file mode 100644 (file)
index 0000000..aa453eb
--- /dev/null
@@ -0,0 +1,93 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include "mpitest.h"
+
+int prodof( int, const int[] );
+/*
+ * Test edge cases of Dims_create
+ */
+int prodof( int ndims, const int dims[] )
+{
+    int i, prod=1;
+    for (i=0; i<ndims; i++) 
+       prod *= dims[i];
+    return prod;
+}
+
+int main( int argc, char *argv[] )
+{
+    int errs = 0;
+    int dims[4], nnodes;
+
+    MTest_Init( &argc, &argv );
+
+    /* 2 dimensional tests */
+    for (nnodes=1; nnodes <= 32; nnodes = nnodes * 2) {
+       dims[0] = 0;
+       dims[1] = nnodes;
+       
+       MPI_Dims_create( nnodes, 2, dims );
+       if (prodof(2, dims) != nnodes) {
+           errs++;
+           printf( "Dims_create returned the wrong decomposition.  " );
+           printf( "Is [%d x %d], should be 1 x %d\n", dims[0], dims[1], 
+                   nnodes );
+       }
+       
+       /* Try calling Dims_create with nothing to do (all dimensions
+          specified) */
+       dims[0] = 1;
+       dims[1] = nnodes;
+       MPI_Dims_create( nnodes, 2, dims );
+       if (prodof(2, dims) != nnodes) {
+           errs++;
+           printf( "Dims_create returned the wrong decomposition (all given).  " );
+           printf( "Is [%d x %d], should be 1 x %d\n", dims[0], dims[1], 
+                   nnodes );
+       }
+
+    }
+
+    /* 4 dimensional tests */
+    for (nnodes=4; nnodes <= 32; nnodes = nnodes * 2) {
+       dims[0] = 0;
+       dims[1] = nnodes/2;
+       dims[2] = 0;
+       dims[3] = 2;
+       
+       MPI_Dims_create( nnodes, 4, dims );
+       if (prodof(4, dims) != nnodes) {
+           errs++;
+           printf( "Dims_create returned the wrong decomposition.  " );
+           printf( "Is [%d x %d x %d x %d], should be 1 x %d x 1 x 2\n", 
+                   dims[0], dims[1], dims[2], dims[3],
+                   nnodes/2 );
+       }
+       
+       /* Try calling Dims_create with nothing to do (all dimensions
+          specified) */
+       dims[0] = 1;
+       dims[1] = nnodes/2;
+       dims[2] = 1;
+       dims[3] = 2;
+       MPI_Dims_create( nnodes, 4, dims );
+       if (prodof(4, dims) != nnodes) {
+           errs++;
+           printf( "Dims_create returned the wrong decomposition (all given).  " );
+           printf( "Is [%d x %d x %d x %d], should be 1 x %d x 1 x 2\n", 
+                   dims[0], dims[1], dims[2], dims[3],
+                   nnodes/2 );
+       }
+
+    }
+
+    MTest_Finalize( errs );
+    MPI_Finalize();
+    return 0;
+  
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/distgraph1.c b/teshsuite/smpi/mpich3-test/topo/distgraph1.c
new file mode 100644 (file)
index 0000000..de42586
--- /dev/null
@@ -0,0 +1,572 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+
+#include "mpi.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include "mpitest.h"
+
+#define NUM_GRAPHS 10
+#define MAX_WEIGHT 100
+
+/* convenience globals */
+int size, rank;
+
+/* We need MPI 2.2 to be able to compile the following routines. */
+#if MTEST_HAVE_MIN_MPI_VERSION(2,2)
+
+/* Maybe use a bit vector instead? */
+int **layout;
+
+#define MAX_LAYOUT_NAME_LEN 256
+char graph_layout_name[MAX_LAYOUT_NAME_LEN] = {'\0'};
+
+static void create_graph_layout(int graph_num)
+{
+    int i, j;
+
+    if (rank == 0) {
+        switch (graph_num) {
+            case 0:
+                strncpy(graph_layout_name, "deterministic complete graph", MAX_LAYOUT_NAME_LEN);
+                for (i = 0; i < size; i++)
+                    for (j = 0; j < size; j++)
+                        layout[i][j] = (i + 2) * (j + 1);
+                break;
+            case 1:
+                strncpy(graph_layout_name, "every other edge deleted", MAX_LAYOUT_NAME_LEN);
+                for (i = 0; i < size; i++)
+                    for (j = 0; j < size; j++)
+                        layout[i][j] = (j % 2 ? (i + 2) * (j + 1) : 0);
+                break;
+            case 2:
+                strncpy(graph_layout_name, "only self-edges", MAX_LAYOUT_NAME_LEN);
+                for (i = 0; i < size; i++) {
+                    for (j = 0; j < size; j++) {
+                        if (i == rank && j == rank)
+                            layout[i][j] = 10 * (i + 1);
+                        else
+                            layout[i][j] = 0;
+                    }
+                }
+                break;
+            case 3:
+                strncpy(graph_layout_name, "no edges", MAX_LAYOUT_NAME_LEN);
+                for (i = 0; i < size; i++)
+                    for (j = 0; j < size; j++)
+                        layout[i][j] = 0;
+                break;
+            default:
+                strncpy(graph_layout_name, "a random incomplete graph", MAX_LAYOUT_NAME_LEN);
+                srand(graph_num);
+
+                /* Create a connectivity graph; layout[i,j]==w represents an outward
+                 * connectivity from i to j with weight w, w==0 is no edge. */
+                for (i = 0; i < size; i++) {
+                    for (j = 0; j < size; j++) {
+                        /* disable about a third of the edges */
+                        if (((rand() * 1.0) / RAND_MAX) < 0.33)
+                            layout[i][j] = 0;
+                        else
+                            layout[i][j] = rand() % MAX_WEIGHT;
+                    }
+                }
+                break;
+        }
+    }
+
+    /* because of the randomization we must determine the graph on rank 0 and
+     * send the layout to all other processes */
+    MPI_Bcast(graph_layout_name, MAX_LAYOUT_NAME_LEN, MPI_CHAR, 0, MPI_COMM_WORLD);
+    for (i = 0; i < size; ++i) {
+        MPI_Bcast(layout[i], size, MPI_INT, 0, MPI_COMM_WORLD);
+    }
+}
+
+static int verify_comm(MPI_Comm comm)
+{
+    int local_errs = 0;
+    int i, j;
+    int indegree, outdegree, weighted;
+    int *sources, *sweights, *destinations, *dweights;
+    int use_dup;
+    int topo_type = MPI_UNDEFINED;
+    MPI_Comm dupcomm = MPI_COMM_NULL;
+
+    sources = (int *) malloc(size * sizeof(int));
+    sweights = (int *) malloc(size * sizeof(int));
+    destinations = (int *) malloc(size * sizeof(int));
+    dweights = (int *) malloc(size * sizeof(int));
+
+    for (use_dup = 0; use_dup <= 1; ++use_dup) {
+        if (!use_dup) {
+            MPI_Dist_graph_neighbors_count(comm, &indegree, &outdegree, &weighted);
+        }
+        else {
+            MPI_Comm_dup(comm, &dupcomm);
+            comm = dupcomm; /* caller retains original comm value */
+        }
+
+        MPI_Topo_test(comm, &topo_type);
+        if (topo_type != MPI_DIST_GRAPH) {
+            fprintf(stderr, "topo_type != MPI_DIST_GRAPH\n");
+            ++local_errs;
+        }
+
+        j = 0;
+        for (i = 0; i < size; i++)
+            if (layout[i][rank])
+                j++;
+        if (j != indegree) {
+            fprintf(stderr, "indegree does not match, expected=%d got=%d, layout='%s'\n", indegree, j, graph_layout_name);
+            ++local_errs;
+        }
+
+        j = 0;
+        for (i = 0; i < size; i++)
+            if (layout[rank][i])
+                j++;
+        if (j != outdegree) {
+            fprintf(stderr, "outdegree does not match, expected=%d got=%d, layout='%s'\n", outdegree, j, graph_layout_name);
+            ++local_errs;
+        }
+
+        if ((indegree || outdegree) && (weighted == 0)) {
+            fprintf(stderr, "MPI_Dist_graph_neighbors_count thinks the graph is not weighted\n");
+            ++local_errs;
+        }
+
+
+        MPI_Dist_graph_neighbors(comm, indegree, sources, sweights, outdegree, destinations, dweights);
+
+        /* For each incoming and outgoing edge in the matrix, search if
+         * the query function listed it in the sources. */
+        for (i = 0; i < size; i++) {
+            if (layout[i][rank]) {
+                for (j = 0; j < indegree; j++) {
+                    assert(sources[j] >= 0);
+                    assert(sources[j] < size);
+                    if (sources[j] == i)
+                        break;
+                }
+                if (j == indegree) {
+                    fprintf(stderr, "no edge from %d to %d specified\n", i, rank);
+                    ++local_errs;
+                }
+                else {
+                    if (sweights[j] != layout[i][rank]) {
+                        fprintf(stderr, "incorrect weight for edge (%d,%d): %d instead of %d\n",
+                                i, rank, sweights[j], layout[i][rank]);
+                        ++local_errs;
+                    }
+                }
+            }
+            if (layout[rank][i]) {
+                for (j = 0; j < outdegree; j++) {
+                    assert(destinations[j] >= 0);
+                    assert(destinations[j] < size);
+                    if (destinations[j] == i)
+                        break;
+                }
+                if (j == outdegree) {
+                    fprintf(stderr, "no edge from %d to %d specified\n", rank, i);
+                    ++local_errs;
+                }
+                else {
+                    if (dweights[j] != layout[rank][i]) {
+                        fprintf(stderr, "incorrect weight for edge (%d,%d): %d instead of %d\n",
+                                rank, i, dweights[j], layout[rank][i]);
+                        ++local_errs;
+                    }
+                }
+            }
+        }
+
+        /* For each incoming and outgoing edge in the sources, we should
+         * have an entry in the matrix */
+        for (i = 0; i < indegree; i++) {
+            if (layout[sources[i]][rank] != sweights[i]) {
+                fprintf(stderr, "edge (%d,%d) has a weight %d instead of %d\n", i, rank,
+                        sweights[i], layout[sources[i]][rank]);
+                ++local_errs;
+            }
+        }
+        for (i = 0; i < outdegree; i++) {
+            if (layout[rank][destinations[i]] != dweights[i]) {
+                fprintf(stderr, "edge (%d,%d) has a weight %d instead of %d\n", rank, i,
+                        dweights[i], layout[rank][destinations[i]]);
+                ++local_errs;
+            }
+        }
+
+    }
+
+    if (dupcomm != MPI_COMM_NULL)
+        MPI_Comm_free(&dupcomm);
+
+    return local_errs;
+}
+
+#endif /* At least MPI 2.2 */
+
+int main(int argc, char *argv[])
+{
+    int errs = 0;
+    int i, j, k, p;
+    int indegree, outdegree, reorder;
+    int check_indegree, check_outdegree, check_weighted;
+    int *sources, *sweights, *destinations, *dweights, *degrees;
+    MPI_Comm comm;
+
+    MTest_Init(&argc, &argv);
+
+    MPI_Comm_size(MPI_COMM_WORLD, &size);
+    MPI_Comm_rank(MPI_COMM_WORLD, &rank);
+
+#if MTEST_HAVE_MIN_MPI_VERSION(2,2)
+    layout = (int **) malloc(size * sizeof(int *));
+    assert(layout);
+    for (i = 0; i < size; i++) {
+        layout[i] = (int *) malloc(size * sizeof(int));
+        assert(layout[i]);
+    }
+    /* alloc size*size ints to handle the all-on-one-process case */
+    sources = (int *) malloc(size * size * sizeof(int));
+    sweights = (int *) malloc(size * size * sizeof(int));
+    destinations = (int *) malloc(size * size * sizeof(int));
+    dweights = (int *) malloc(size * size * sizeof(int));
+    degrees = (int *) malloc(size * size * sizeof(int));
+
+    for (i = 0; i < NUM_GRAPHS; i++) {
+        create_graph_layout(i);
+        if (rank == 0) {
+            MTestPrintfMsg( 1, "using graph layout '%s'\n", graph_layout_name );
+        }
+
+        /* MPI_Dist_graph_create_adjacent */
+        if (rank == 0) {
+            MTestPrintfMsg( 1, "testing MPI_Dist_graph_create_adjacent\n" );
+        }
+        indegree = 0;
+        k = 0;
+        for (j = 0; j < size; j++) {
+            if (layout[j][rank]) {
+                indegree++;
+                sources[k] = j;
+                sweights[k++] = layout[j][rank];
+            }
+        }
+
+        outdegree = 0;
+        k = 0;
+        for (j = 0; j < size; j++) {
+            if (layout[rank][j]) {
+                outdegree++;
+                destinations[k] = j;
+                dweights[k++] = layout[rank][j];
+            }
+        }
+
+        for (reorder = 0; reorder <= 1; reorder++) {
+            MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, indegree, sources, sweights,
+                                           outdegree, destinations, dweights, MPI_INFO_NULL,
+                                           reorder, &comm);
+            MPI_Barrier(comm);
+            errs += verify_comm(comm);
+            MPI_Comm_free(&comm);
+        }
+
+        /* a weak check that passing MPI_UNWEIGHTED doesn't cause
+         * create_adjacent to explode */
+        MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, indegree, sources, MPI_UNWEIGHTED,
+                                       outdegree, destinations, MPI_UNWEIGHTED, MPI_INFO_NULL,
+                                       reorder, &comm);
+        MPI_Barrier(comm);
+        /* intentionally no verify here, weights won't match */
+        MPI_Comm_free(&comm);
+
+
+        /* MPI_Dist_graph_create() where each process specifies its
+         * outgoing edges */
+        if (rank == 0) {
+            MTestPrintfMsg( 1, 
+                          "testing MPI_Dist_graph_create w/ outgoing only\n" );
+        }
+        sources[0] = rank;
+        k = 0;
+        for (j = 0; j < size; j++) {
+            if (layout[rank][j]) {
+                destinations[k] = j;
+                dweights[k++] = layout[rank][j];
+            }
+        }
+        degrees[0] = k;
+        for (reorder = 0; reorder <= 1; reorder++) {
+            MPI_Dist_graph_create(MPI_COMM_WORLD, 1, sources, degrees, destinations, dweights,
+                                  MPI_INFO_NULL, reorder, &comm);
+            MPI_Barrier(comm);
+            errs += verify_comm(comm);
+            MPI_Comm_free(&comm);
+        }
+
+
+        /* MPI_Dist_graph_create() where each process specifies its
+         * incoming edges */
+        if (rank == 0) {
+            MTestPrintfMsg( 1, 
+                         "testing MPI_Dist_graph_create w/ incoming only\n" );
+        }
+        k = 0;
+        for (j = 0; j < size; j++) {
+            if (layout[j][rank]) {
+                sources[k] = j;
+                sweights[k] = layout[j][rank];
+                degrees[k] = 1;
+                destinations[k++] = rank;
+            }
+        }
+        for (reorder = 0; reorder <= 1; reorder++) {
+            MPI_Dist_graph_create(MPI_COMM_WORLD, k, sources, degrees, destinations, sweights,
+                                  MPI_INFO_NULL, reorder, &comm);
+            MPI_Barrier(comm);
+            errs += verify_comm(comm);
+            MPI_Comm_free(&comm);
+        }
+
+
+        /* MPI_Dist_graph_create() where rank 0 specifies the entire
+         * graph */
+        if (rank == 0) {
+            MTestPrintfMsg( 1, 
+               "testing MPI_Dist_graph_create w/ rank 0 specifies only\n" );
+        }
+        p = 0;
+        for (j = 0; j < size; j++) {
+            for (k = 0; k < size; k++) {
+                if (layout[j][k]) {
+                    sources[p] = j;
+                    sweights[p] = layout[j][k];
+                    degrees[p] = 1;
+                    destinations[p++] = k;
+                }
+            }
+        }
+        for (reorder = 0; reorder <= 1; reorder++) {
+            MPI_Dist_graph_create(MPI_COMM_WORLD, (rank == 0) ? p : 0, sources, degrees,
+                                  destinations, sweights, MPI_INFO_NULL, reorder, &comm);
+            MPI_Barrier(comm);
+            errs += verify_comm(comm);
+            MPI_Comm_free(&comm);
+        }
+
+        /* MPI_Dist_graph_create() where rank 0 specifies the entire
+         * graph and all other ranks pass NULL.  Can catch implementation
+         * problems when MPI_UNWEIGHTED==NULL. */
+        if (rank == 0) {
+            MTestPrintfMsg( 1, 
+           "testing MPI_Dist_graph_create w/ rank 0 specifies only -- NULLs\n");
+        }
+        p = 0;
+        for (j = 0; j < size; j++) {
+            for (k = 0; k < size; k++) {
+                if (layout[j][k]) {
+                    sources[p] = j;
+                    sweights[p] = layout[j][k];
+                    degrees[p] = 1;
+                    destinations[p++] = k;
+                }
+            }
+        }
+        for (reorder = 0; reorder <= 1; reorder++) {
+            if (rank == 0) {
+                MPI_Dist_graph_create(MPI_COMM_WORLD, p, sources, degrees,
+                                      destinations, sweights, MPI_INFO_NULL, reorder, &comm);
+            }
+            else {
+                MPI_Dist_graph_create(MPI_COMM_WORLD, 0, NULL, NULL,
+                                      NULL, NULL, MPI_INFO_NULL, reorder, &comm);
+            }
+            MPI_Barrier(comm);
+            errs += verify_comm(comm);
+            MPI_Comm_free(&comm);
+        }
+
+    }
+
+    /* now tests that don't depend on the layout[][] array */
+
+    /* The MPI-2.2 standard recommends implementations set
+     * MPI_UNWEIGHTED==NULL, but this leads to an ambiguity.  The draft
+     * MPI-3.0 standard specifically recommends _not_ setting it equal
+     * to NULL. */
+    if (MPI_UNWEIGHTED == NULL) {
+        fprintf(stderr, "MPI_UNWEIGHTED should not be NULL\n");
+        ++errs;
+    }
+
+    /* MPI_Dist_graph_create() with no graph */
+    if (rank == 0) {
+        MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ no graph\n" );
+    }
+    for (reorder = 0; reorder <= 1; reorder++) {
+        MPI_Dist_graph_create(MPI_COMM_WORLD, 0, sources, degrees,
+                              destinations, sweights, MPI_INFO_NULL, reorder, &comm);
+        MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted);
+        if (!check_weighted) {
+            fprintf(stderr, "expected weighted == TRUE for the \"no graph\" case\n");
+            ++errs;
+        }
+        MPI_Comm_free(&comm);
+    }
+
+    /* MPI_Dist_graph_create() with no graph -- passing MPI_WEIGHTS_EMPTY 
+       instead */
+    /* NOTE that MPI_WEIGHTS_EMPTY was added in MPI-3 and does not 
+       appear before then.  This part of the test thus requires a check
+       on the MPI major version */
+#if MPI_VERSION >= 3
+    if (rank == 0) {
+        MTestPrintfMsg( 1, "testing MPI_Dist_graph_create w/ no graph\n" );
+    }
+    for (reorder = 0; reorder <= 1; reorder++) {
+        MPI_Dist_graph_create(MPI_COMM_WORLD, 0, sources, degrees,
+                              destinations, MPI_WEIGHTS_EMPTY, MPI_INFO_NULL, reorder, &comm);
+        MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted);
+        if (!check_weighted) {
+            fprintf(stderr, "expected weighted == TRUE for the \"no graph -- MPI_WEIGHTS_EMPTY\" case\n");
+            ++errs;
+        }
+        MPI_Comm_free(&comm);
+    }
+#endif
+
+    /* MPI_Dist_graph_create() with no graph -- passing NULLs instead */
+    if (rank == 0) {
+        MTestPrintfMsg( 1, 
+                      "testing MPI_Dist_graph_create w/ no graph -- NULLs\n" );
+    }
+    for (reorder = 0; reorder <= 1; reorder++) {
+        MPI_Dist_graph_create(MPI_COMM_WORLD, 0, NULL, NULL,
+                              NULL, NULL, MPI_INFO_NULL, reorder, &comm);
+        MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted);
+        /* ambiguous if they are equal, only check when they are distinct values. */
+        if (MPI_UNWEIGHTED != NULL) {
+            if (!check_weighted) {
+                fprintf(stderr, "expected weighted == TRUE for the \"no graph -- NULLs\" case\n");
+                ++errs;
+            }
+        }
+        MPI_Comm_free(&comm);
+    }
+
+    /* MPI_Dist_graph_create() with no graph -- passing NULLs+MPI_UNWEIGHTED instead */
+    if (rank == 0) {
+        MTestPrintfMsg( 1, 
+        "testing MPI_Dist_graph_create w/ no graph -- NULLs+MPI_UNWEIGHTED\n" );
+    }
+    for (reorder = 0; reorder <= 1; reorder++) {
+        MPI_Dist_graph_create(MPI_COMM_WORLD, 0, NULL, NULL,
+                              NULL, MPI_UNWEIGHTED, MPI_INFO_NULL, reorder, &comm);
+        MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted);
+        /* ambiguous if they are equal, only check when they are distinct values. */
+        if (MPI_UNWEIGHTED != NULL) {
+            if (check_weighted) {
+                fprintf(stderr, "expected weighted == FALSE for the \"no graph -- NULLs+MPI_UNWEIGHTED\" case\n");
+                ++errs;
+            }
+        }
+        MPI_Comm_free(&comm);
+    }
+
+    /* MPI_Dist_graph_create_adjacent() with no graph */
+    if (rank == 0) {
+        MTestPrintfMsg( 1, 
+                     "testing MPI_Dist_graph_create_adjacent w/ no graph\n" );
+    }
+    for (reorder = 0; reorder <= 1; reorder++) {
+        MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, sources, sweights,
+                              0, destinations, dweights, MPI_INFO_NULL, reorder, &comm);
+        MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted);
+        if (!check_weighted) {
+            fprintf(stderr, "expected weighted == TRUE for the \"no graph\" case\n");
+            ++errs;
+        }
+        MPI_Comm_free(&comm);
+    }
+
+    /* MPI_Dist_graph_create_adjacent() with no graph -- passing MPI_WEIGHTS_EMPTY instead */
+    /* NOTE that MPI_WEIGHTS_EMPTY was added in MPI-3 and does not 
+       appear before then.  This part of the test thus requires a check
+       on the MPI major version */
+#if MPI_VERSION >= 3
+    if (rank == 0) {
+        MTestPrintfMsg( 1, 
+  "testing MPI_Dist_graph_create_adjacent w/ no graph -- MPI_WEIGHTS_EMPTY\n" );
+    }
+    for (reorder = 0; reorder <= 1; reorder++) {
+        MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, sources, MPI_WEIGHTS_EMPTY,
+                              0, destinations, MPI_WEIGHTS_EMPTY, MPI_INFO_NULL, reorder, &comm);
+        MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted);
+        if (!check_weighted) {
+            fprintf(stderr, "expected weighted == TRUE for the \"no graph -- MPI_WEIGHTS_EMPTY\" case\n");
+            ++errs;
+        }
+        MPI_Comm_free(&comm);
+    }
+#endif
+
+    /* MPI_Dist_graph_create_adjacent() with no graph -- passing NULLs instead */
+    if (rank == 0) {
+        MTestPrintfMsg( 1, 
+              "testing MPI_Dist_graph_create_adjacent w/ no graph -- NULLs\n" );
+    }
+    for (reorder = 0; reorder <= 1; reorder++) {
+        MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, NULL, NULL,
+                              0, NULL, NULL, MPI_INFO_NULL, reorder, &comm);
+        MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted);
+        /* ambiguous if they are equal, only check when they are distinct values. */
+        if (MPI_UNWEIGHTED != NULL) {
+            if (!check_weighted) {
+                fprintf(stderr, "expected weighted == TRUE for the \"no graph -- NULLs\" case\n");
+                ++errs;
+            }
+        }
+        MPI_Comm_free(&comm);
+    }
+
+    /* MPI_Dist_graph_create_adjacent() with no graph -- passing NULLs+MPI_UNWEIGHTED instead */
+    if (rank == 0) {
+        MTestPrintfMsg( 1, 
+"testing MPI_Dist_graph_create_adjacent w/ no graph -- NULLs+MPI_UNWEIGHTED\n");
+    }
+    for (reorder = 0; reorder <= 1; reorder++) {
+        MPI_Dist_graph_create_adjacent(MPI_COMM_WORLD, 0, NULL, MPI_UNWEIGHTED,
+                              0, NULL, MPI_UNWEIGHTED, MPI_INFO_NULL, reorder, &comm);
+        MPI_Dist_graph_neighbors_count(comm, &check_indegree, &check_outdegree, &check_weighted);
+        /* ambiguous if they are equal, only check when they are distinct values. */
+        if (MPI_UNWEIGHTED != NULL) {
+            if (check_weighted) {
+                fprintf(stderr, "expected weighted == FALSE for the \"no graph -- NULLs+MPI_UNWEIGHTED\" case\n");
+                ++errs;
+            }
+        }
+        MPI_Comm_free(&comm);
+    }
+
+
+    for (i = 0; i < size; i++)
+        free(layout[i]);
+    free(layout);
+#endif
+
+    MTest_Finalize(errs);
+    MPI_Finalize();
+
+    return 0;
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/graphcr.c b/teshsuite/smpi/mpich3-test/topo/graphcr.c
new file mode 100644 (file)
index 0000000..2bfac48
--- /dev/null
@@ -0,0 +1,34 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include "mpitest.h"
+
+/*
+static char MTEST_Descrip[] = "Create a communicator with a graph that contains no processes";
+*/
+
+int main( int argc, char *argv[] )
+{
+    int errs = 0;
+    int *index = 0, *edges = 0;
+    MPI_Comm comm;
+
+    MTest_Init( &argc, &argv );
+
+    /* MPI 2.1, page 246, lines 29-30 make it clear that this is a valid
+       (not erroneous) call that must return MPI_COMM_NULL */
+    MPI_Graph_create( MPI_COMM_WORLD, 0, index, edges, 0, &comm );
+    if (comm != MPI_COMM_NULL) {
+       errs++;
+       fprintf( stderr, "Expected MPI_COMM_NULL from empty graph create\n" );
+    }
+       
+    MTest_Finalize( errs );
+    MPI_Finalize();
+    return 0;
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/graphcr2.c b/teshsuite/smpi/mpich3-test/topo/graphcr2.c
new file mode 100644 (file)
index 0000000..6d5fd2a
--- /dev/null
@@ -0,0 +1,70 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpitest.h"
+
+/*
+static char MTEST_Descrip[] = "Create a communicator with a graph that contains null edges and one that contains duplicate edges";
+*/
+
+int main( int argc, char *argv[] )
+{
+    int errs = 0;
+    int *index = 0, *edges = 0;
+    int rank, size, i, j, crank, csize;
+    MPI_Comm comm;
+
+    MTest_Init( &argc, &argv );
+
+    MPI_Comm_size( MPI_COMM_WORLD, &size );
+    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+
+    index = (int *)malloc( size*sizeof(int) );
+    edges = (int *)malloc( size*sizeof(int) );
+    for (i=0; i<size; i++) {
+       index[i] = 1;
+       edges[i] = i;
+    }
+    /* As of MPI 2.1, self edges are permitted */
+    MPI_Graph_create( MPI_COMM_WORLD, size, index, edges, 0, &comm );
+    MPI_Comm_rank( comm, &crank );
+    MPI_Comm_size( comm, &csize );
+    if (csize != size) {
+       errs ++;
+       fprintf( stderr, "Graph create with self links has size %d should be %d", csize, size );
+    }
+    free( index );
+    free( edges );
+    MPI_Comm_free( &comm );
+
+    /* Create a graph with duplicate links */
+    index = (int *)malloc( size * sizeof(int) );
+    edges = (int *)malloc( size * 2 * sizeof(int) );
+    j = 0;
+    for (i=0; i<size; i++) {
+       index[i]   = j + 2;
+       edges[j++] = (i + 1) % size;
+       edges[j++] = (i + 1) % size; 
+    }
+    /* As of MPI 2.1, duplicate edges are permitted */
+    MPI_Graph_create( MPI_COMM_WORLD, size, index, edges, 0, &comm );
+    MPI_Comm_rank( comm, &crank );
+    MPI_Comm_size( comm, &csize );
+    if (csize != size) {
+       errs ++;
+       fprintf( stderr, "Graph create with duplicate links has size %d should be %d", csize, size );
+    }
+    free( index );
+    free( edges );
+    MPI_Comm_free( &comm );
+
+    MTest_Finalize( errs );
+    MPI_Finalize();
+    return 0;
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/graphmap1.c b/teshsuite/smpi/mpich3-test/topo/graphmap1.c
new file mode 100644 (file)
index 0000000..4102db3
--- /dev/null
@@ -0,0 +1,40 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include "mpitest.h"
+
+int main( int argc, char *argv[] )
+{
+    int errs = 0;
+    int newrank, merr, rank;
+    int index[2], edges[2];
+
+    MTest_Init( &argc, &argv );
+
+    MPI_Comm_rank( MPI_COMM_WORLD, &rank );
+    /* Graph map where there are no nodes for this process */
+    MPI_Comm_set_errhandler( MPI_COMM_WORLD, MPI_ERRORS_RETURN );
+    /* Here is a singleton graph, containing only the root process */
+    index[0] = 0;
+    edges[0] = 0;
+    merr = MPI_Graph_map( MPI_COMM_WORLD, 1, index, edges, &newrank );
+    if (merr) {
+       errs++;
+       printf( "Graph map returned an error\n" );
+       MTestPrintError( merr );
+    }
+    if (rank != 0 && newrank != MPI_UNDEFINED) {
+       errs++;
+       printf( "Graph map with no local nodes did not return MPI_UNDEFINED\n" );
+    }
+    
+    MTest_Finalize( errs );
+    MPI_Finalize();
+    return 0;
+  
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/neighb_coll.c b/teshsuite/smpi/mpich3-test/topo/neighb_coll.c
new file mode 100644 (file)
index 0000000..0c4a7fd
--- /dev/null
@@ -0,0 +1,179 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *  (C) 2012 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <mpi.h>
+#include "mpitest.h"
+
+#if !defined(USE_STRICT_MPI) && defined(MPICH)
+#define TEST_NEIGHB_COLL 1
+#endif
+
+/* assert-like macro that bumps the err count and emits a message */
+#define check(x_)                                                                 \
+    do {                                                                          \
+        if (!(x_)) {                                                              \
+            ++errs;                                                               \
+            if (errs < 10) {                                                      \
+                fprintf(stderr, "check failed: (%s), line %d\n", #x_, __LINE__); \
+            }                                                                     \
+        }                                                                         \
+    } while (0)
+
+int main(int argc, char *argv[])
+{
+    int errs = 0;
+    int wrank, wsize;
+    int periods[1] = { 0 };
+    MPI_Comm cart, dgraph, graph;
+
+    MPI_Init(&argc, &argv);
+    MPI_Comm_rank(MPI_COMM_WORLD, &wrank);
+    MPI_Comm_size(MPI_COMM_WORLD, &wsize);
+
+#if defined(TEST_NEIGHB_COLL)
+    /* a basic test for the 10 (5 patterns x {blocking,nonblocking}) MPI-3
+     * neighborhood collective routines */
+
+    /* (wrap)--> 0 <--> 1 <--> ... <--> p-1 <--(wrap) */
+    MPI_Cart_create(MPI_COMM_WORLD, 1, &wsize, periods, /*reorder=*/0, &cart);
+
+    /* allgather */
+    {
+        int sendbuf[1] = { wrank };
+        int recvbuf[2] = { 0xdeadbeef, 0xdeadbeef };
+
+        /* should see one send to each neighbor (rank-1 and rank+1) and one receive
+         * each from same */
+        MPI_Neighbor_allgather(sendbuf, 1, MPI_INT, recvbuf, 1, MPI_INT, cart);
+
+        if (wrank == 0)
+            check(recvbuf[0] == 0xdeadbeef);
+        else
+            check(recvbuf[0] == wrank - 1);
+
+        if (wrank == wsize - 1)
+            check(recvbuf[1] == 0xdeadbeef);
+        else
+            check(recvbuf[1] == wrank + 1);
+    }
+
+    /* allgatherv */
+    {
+        int sendbuf[1]    = { wrank };
+        int recvbuf[2]    = { 0xdeadbeef, 0xdeadbeef };
+        int recvcounts[2] = { 1, 1 };
+        int displs[2]     = { 1, 0};
+
+        /* should see one send to each neighbor (rank-1 and rank+1) and one receive
+         * each from same, but put them in opposite slots in the buffer */
+        MPI_Neighbor_allgatherv(sendbuf, 1, MPI_INT, recvbuf, recvcounts, displs, MPI_INT, cart);
+
+        if (wrank == 0)
+            check(recvbuf[1] == 0xdeadbeef);
+        else
+            check(recvbuf[1] == wrank - 1);
+
+        if (wrank == wsize - 1)
+            check(recvbuf[0] == 0xdeadbeef);
+        else
+            check(recvbuf[0] == wrank + 1);
+    }
+
+    /* alltoall */
+    {
+        int sendbuf[2]    = { -(wrank+1), wrank+1 };
+        int recvbuf[2]    = { 0xdeadbeef, 0xdeadbeef };
+
+        /* should see one send to each neighbor (rank-1 and rank+1) and one
+         * receive each from same */
+        MPI_Neighbor_alltoall(sendbuf, 1, MPI_INT, recvbuf, 1, MPI_INT, cart);
+
+        if (wrank == 0)
+            check(recvbuf[0] == 0xdeadbeef);
+        else
+            check(recvbuf[0] == wrank);
+
+        if (wrank == wsize - 1)
+            check(recvbuf[1] == 0xdeadbeef);
+        else
+            check(recvbuf[1] == -(wrank + 2));
+    }
+
+    /* alltoallv */
+    {
+        int sendbuf[2]    = { -(wrank+1), wrank+1 };
+        int recvbuf[2]    = { 0xdeadbeef, 0xdeadbeef };
+        int sendcounts[2] = { 1, 1 };
+        int recvcounts[2] = { 1, 1 };
+        int sdispls[2]    = { 0, 1 };
+        int rdispls[2]    = { 1, 0 };
+
+        /* should see one send to each neighbor (rank-1 and rank+1) and one receive
+         * each from same, but put them in opposite slots in the buffer */
+        MPI_Neighbor_alltoallv(sendbuf, sendcounts, sdispls, MPI_INT,
+                                recvbuf, recvcounts, rdispls, MPI_INT,
+                                cart);
+
+        if (wrank == 0)
+            check(recvbuf[1] == 0xdeadbeef);
+        else
+            check(recvbuf[1] == wrank);
+
+        if (wrank == wsize - 1)
+            check(recvbuf[0] == 0xdeadbeef);
+        else
+            check(recvbuf[0] == -(wrank + 2));
+    }
+
+    /* alltoallw */
+    {
+        int sendbuf[2]            = { -(wrank+1), wrank+1 };
+        int recvbuf[2]            = { 0xdeadbeef, 0xdeadbeef };
+        int sendcounts[2]         = { 1, 1 };
+        int recvcounts[2]         = { 1, 1 };
+        MPI_Aint sdispls[2]       = { 0, sizeof(int) };
+        MPI_Aint rdispls[2]       = { sizeof(int), 0 };
+        MPI_Datatype sendtypes[2] = { MPI_INT, MPI_INT };
+        MPI_Datatype recvtypes[2] = { MPI_INT, MPI_INT };
+
+        /* should see one send to each neighbor (rank-1 and rank+1) and one receive
+         * each from same, but put them in opposite slots in the buffer */
+        MPI_Neighbor_alltoallw(sendbuf, sendcounts, sdispls, sendtypes,
+                                recvbuf, recvcounts, rdispls, recvtypes,
+                                cart);
+
+        if (wrank == 0)
+            check(recvbuf[1] == 0xdeadbeef);
+        else
+            check(recvbuf[1] == wrank);
+
+        if (wrank == wsize - 1)
+            check(recvbuf[0] == 0xdeadbeef);
+        else
+            check(recvbuf[0] == -(wrank + 2));
+    }
+
+
+    MPI_Comm_free(&cart);
+#endif /* defined(TEST_NEIGHB_COLL) */
+
+    MPI_Reduce((wrank == 0 ? MPI_IN_PLACE : &errs), &errs, 1, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD);
+    if (wrank == 0) {
+        if (errs) {
+            printf("found %d errors\n", errs);
+        }
+        else {
+            printf(" No errors\n");
+        }
+    }
+    MPI_Finalize();
+
+    return 0;
+}
+
diff --git a/teshsuite/smpi/mpich3-test/topo/testlist b/teshsuite/smpi/mpich3-test/topo/testlist
new file mode 100644 (file)
index 0000000..0ec8867
--- /dev/null
@@ -0,0 +1,21 @@
+#need Cart implem
+#cartmap1 4
+#cartzero 4
+#cartshift1 4
+#cartsuball 4
+#cartcreates 4
+#need MPI_Dims_create
+#dims1 4
+#dims2 1
+#need MPI_Error_class, MPI_Comm_remote_size, MPI_Graph_map
+#graphmap1 4
+#need MPI_Topo_test, MPI_Cart_create
+#topotest 4
+#need MPI_Cart_create, MPI_Cart_get, MPI_Comm_remote_size, MPI_Dims_create ...
+#topodup 4
+#need MPI_Graph*
+#graphcr 4
+#graphcr2 4
+#distgraph1 4 mpiversion=2.2
+#dgraph_unwgt 4 mpiversion=2.2
+#neighb_coll 4 mpiversion=3.0
diff --git a/teshsuite/smpi/mpich3-test/topo/topodup.c b/teshsuite/smpi/mpich3-test/topo/topodup.c
new file mode 100644 (file)
index 0000000..f1c5515
--- /dev/null
@@ -0,0 +1,129 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "mpitest.h"
+
+int main( int argc, char *argv[] )
+{
+    int errs = 0, i, k;
+    int dims[2], periods[2], wsize;
+    int outdims[2], outperiods[2], outcoords[2];
+    int topo_type;
+    int *index, *edges, *outindex, *outedges;
+    MPI_Comm comm1, comm2;
+
+    MTest_Init( &argc, &argv );
+
+    MPI_Comm_size( MPI_COMM_WORLD, &wsize );
+
+    /* Create a cartesian topology, get its characteristics, then 
+       dup it and check that the new communicator has the same properties */
+    dims[0] = dims[1] = 0;
+    MPI_Dims_create( wsize, 2, dims );
+    periods[0] = periods[1] = 0;
+    MPI_Cart_create( MPI_COMM_WORLD, 2, dims, periods, 0, &comm1 );
+
+    MPI_Comm_dup( comm1, &comm2 );
+    MPI_Topo_test( comm2, &topo_type );
+    if (topo_type != MPI_CART) {
+       errs++;
+       printf( "Topo type of duped cart was not cart\n" );
+    }
+    else {
+       MPI_Cart_get( comm2, 2, outdims, outperiods, outcoords );
+       for (i=0; i<2; i++) {
+           if (outdims[i] != dims[i]) {
+               errs++;
+               printf( "%d = outdims[%d] != dims[%d] = %d\n", outdims[i],
+                       i, i, dims[i] );
+           }
+           if (outperiods[i] != periods[i]) {
+               errs++;
+               printf( "%d = outperiods[%d] != periods[%d] = %d\n", 
+                       outperiods[i], i, i, periods[i] );
+           }
+       }
+    }
+    MPI_Comm_free( &comm2 );
+    MPI_Comm_free( &comm1 );
+
+    /* Now do the same with a graph topology */
+    if (wsize >= 3) {
+       index = (int*)malloc(wsize * sizeof(int) );
+       edges = (int*)malloc(wsize * 2 * sizeof(int) );
+       if (!index || !edges) {
+           printf( "Unable to allocate %d words for index or edges\n", 
+                   3 * wsize );
+           MPI_Abort( MPI_COMM_WORLD, 1 );
+       }
+       index[0] = 2;
+       for (i=1; i<wsize; i++) {
+           index[i] = 2 + index[i-1];
+       }
+       k=0;
+       for (i=0; i<wsize; i++) {
+           edges[k++] = (i-1+wsize) % wsize;
+           edges[k++] = (i+1) % wsize;
+       }
+       MPI_Graph_create( MPI_COMM_WORLD, wsize, index, edges, 0, &comm1 );
+       MPI_Comm_dup( comm1, &comm2 );
+       MPI_Topo_test( comm2, &topo_type );
+       if (topo_type != MPI_GRAPH) {
+           errs++;
+           printf( "Topo type of duped graph was not graph\n" );
+       }
+       else {
+           int nnodes, nedges;
+           MPI_Graphdims_get( comm2, &nnodes, &nedges );
+           if (nnodes != wsize) {
+               errs++;
+               printf( "Nnodes = %d, should be %d\n", nnodes, wsize );
+           }
+           if (nedges != 2*wsize) {
+               errs++;
+               printf( "Nedges = %d, should be %d\n", nedges, 2*wsize );
+           }
+           outindex = (int*)malloc(wsize * sizeof(int) );
+           outedges = (int*)malloc(wsize * 2 * sizeof(int) );
+           if (!outindex || !outedges) {
+               printf( "Unable to allocate %d words for outindex or outedges\n", 
+                       3 * wsize );
+               MPI_Abort( MPI_COMM_WORLD, 1 );
+           }
+           
+           MPI_Graph_get( comm2, wsize, 2*wsize, outindex, outedges );
+           for (i=0; i<wsize; i++) {
+               if (index[i] != outindex[i]) {
+                   printf( "%d = index[%d] != outindex[%d] = %d\n",
+                           index[i], i, i, outindex[i] );
+                   errs++;
+               }
+           }
+           for (i=0; i<2*wsize; i++) {
+               if (edges[i] != outedges[i]) {
+                   printf( "%d = edges[%d] != outedges[%d] = %d\n",
+                           edges[i], i, i, outedges[i] );
+                   errs++;
+               }
+           }
+           free( outindex );
+           free( outedges );
+       }
+       free( index );
+       free( edges );
+
+       MPI_Comm_free( &comm2 );
+       MPI_Comm_free( &comm1 );
+    }
+    
+    MTest_Finalize( errs );
+    MPI_Finalize();
+    return 0;
+  
+}
diff --git a/teshsuite/smpi/mpich3-test/topo/topotest.c b/teshsuite/smpi/mpich3-test/topo/topotest.c
new file mode 100644 (file)
index 0000000..64d8e08
--- /dev/null
@@ -0,0 +1,45 @@
+/* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
+/*
+ *
+ *  (C) 2003 by Argonne National Laboratory.
+ *      See COPYRIGHT in top-level directory.
+ */
+#include "mpi.h"
+#include <stdio.h>
+#include "mpitest.h"
+
+int main( int argc, char *argv[] )
+{
+    int errs = 0;
+    int topo_type, size, dims[1], periods[1];
+    MPI_Comm comm;
+
+    MTest_Init( &argc, &argv );
+
+    /* Check that topo test returns the correct type, including 
+       MPI_UNDEFINED */
+
+    MPI_Topo_test( MPI_COMM_WORLD, &topo_type );
+    if (topo_type != MPI_UNDEFINED) {
+       errs++;
+       printf( "Topo type of comm world is not UNDEFINED\n" );
+    }
+
+    MPI_Comm_size( MPI_COMM_WORLD, &size );
+    dims[0] = size;
+    periods[0] = 0;
+    MPI_Cart_create( MPI_COMM_WORLD, 1, dims, periods, 0, &comm );
+    MPI_Topo_test( comm, &topo_type );
+    if (topo_type != MPI_CART) {
+       errs++;
+       printf( "Topo type of cart comm is not CART\n" );
+    }
+
+    MPI_Comm_free( &comm );
+    /* FIXME: still need graph example */
+
+    MTest_Finalize( errs );
+    MPI_Finalize();
+    return 0;
+  
+}