-:    0:Source:/home/MPI/testing/mpich2/mpich2/src/mpi/topo/graphcreate.c
        -:    0:Graph:graphcreate.gcno
        -:    0:Data:graphcreate.gcda
        -:    0:Runs:609
        -:    0:Programs:164
        -:    1:/* -*- Mode: C; c-basic-offset:4 ; -*- */
        -:    2:/*
        -:    3: *
        -:    4: *  (C) 2001 by Argonne National Laboratory.
        -:    5: *      See COPYRIGHT in top-level directory.
        -:    6: */
        -:    7:
        -:    8:#include "mpiimpl.h"
        -:    9:#include "topo.h"
        -:   10:
        -:   11:/* -- Begin Profiling Symbol Block for routine MPI_Graph_create */
        -:   12:#if defined(HAVE_PRAGMA_WEAK)
        -:   13:#pragma weak MPI_Graph_create = PMPI_Graph_create
        -:   14:#elif defined(HAVE_PRAGMA_HP_SEC_DEF)
        -:   15:#pragma _HP_SECONDARY_DEF PMPI_Graph_create  MPI_Graph_create
        -:   16:#elif defined(HAVE_PRAGMA_CRI_DUP)
        -:   17:#pragma _CRI duplicate MPI_Graph_create as PMPI_Graph_create
        -:   18:#endif
        -:   19:/* -- End Profiling Symbol Block */
        -:   20:
        -:   21:/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
        -:   22:   the MPI routines */
        -:   23:#ifndef MPICH_MPI_FROM_PMPI
        -:   24:#undef MPI_Graph_create
        -:   25:#define MPI_Graph_create PMPI_Graph_create
        -:   26:
        -:   27:#endif
        -:   28:
        -:   29:/* Note on index and indx - index is an (old) function name in string.h; 
        -:   30:   while it is valid to use it as a variable or parameter name, it can 
        -:   31:   solicit warning messages from the compiler.  To avoid those, the name
        -:   32:   indx is used instead of index in this file */
        -:   33:
        -:   34:/* Define MPICH_MPI_FROM_PMPI if weak symbols are not supported to build
        -:   35:   the MPI routines */
        -:   36:#ifndef MPICH_MPI_FROM_PMPI
        -:   37:int MPIR_Graph_create( const MPID_Comm *comm_ptr, int nnodes, 
        -:   38:		       const int indx[], const int edges[], int reorder, 
        -:   39:		       MPI_Comm *comm_graph)
       92:   40:{
        -:   41:    static const char FCNAME[] = "MPIR_Graph_create";
       92:   42:    int mpi_errno = MPI_SUCCESS;
        -:   43:    int i, nedges;
       92:   44:    MPID_Comm *newcomm_ptr = NULL;
       92:   45:    MPIR_Topology *graph_ptr = NULL;
       92:   46:    MPIU_CHKPMEM_DECL(3);
        -:   47:
        -:   48:    /* Set this to null in case there is an error */
       92:   49:    *comm_graph = MPI_COMM_NULL;
        -:   50:
        -:   51:    /* Create a new communicator */
       92:   52:    if (reorder) {
        -:   53:	int nrank;
        -:   54:	MPI_Comm ncomm;
       62:   55:	MPIU_THREADPRIV_DECL;
        -:   56:
       62:   57:	MPIU_THREADPRIV_GET;
        -:   58:
        -:   59:	/* Allow the cart map routine to remap the assignment of ranks to 
        -:   60:	   processes */
       62:   61:	MPIR_Nest_incr();
       62:   62:	mpi_errno = NMPI_Graph_map( comm_ptr->handle, nnodes, 
        -:   63:				    (int *)indx, (int *)edges, 
        -:   64:				    &nrank );
        -:   65:	/* Create the new communicator with split, since we need to reorder
        -:   66:	   the ranks (including the related internals, such as the connection
        -:   67:	   tables */
       62:   68:	if (mpi_errno == 0) {
       62:   69:	    mpi_errno = NMPI_Comm_split( comm_ptr->handle, 
        -:   70:				nrank == MPI_UNDEFINED ? MPI_UNDEFINED : 1,
        -:   71:				nrank, &ncomm );
       62:   72:	    if (!mpi_errno) {
       62:   73:		MPID_Comm_get_ptr( ncomm, newcomm_ptr );
        -:   74:	    }
        -:   75:	}
       62:   76:	MPIR_Nest_decr();
        -:   77:    }
        -:   78:    else {
        -:   79:	/* Just use the first nnodes processes in the communicator */
       30:   80:	mpi_errno = MPIR_Comm_copy( (MPID_Comm *)comm_ptr, nnodes, 
        -:   81:				    &newcomm_ptr );
        -:   82:    }
       92:   83:    if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:   84:
        -:   85:
        -:   86:    /* If this process is not in the resulting communicator, return a 
        -:   87:       null communicator and exit */
       92:   88:    if (!newcomm_ptr) {
        1:   89:	*comm_graph = MPI_COMM_NULL;
        1:   90:	goto fn_exit;
        -:   91:    }
        -:   92:
       91:   93:    nedges = indx[nnodes-1];
       91:   94:    MPIU_CHKPMEM_MALLOC(graph_ptr,MPIR_Topology*,sizeof(MPIR_Topology),
        -:   95:			mpi_errno,"graph_ptr");
        -:   96:    
       91:   97:    graph_ptr->kind = MPI_GRAPH;
       91:   98:    graph_ptr->topo.graph.nnodes = nnodes;
       91:   99:    graph_ptr->topo.graph.nedges = nedges;
      182:  100:    MPIU_CHKPMEM_MALLOC(graph_ptr->topo.graph.index,int*,
        -:  101:			nnodes*sizeof(int),mpi_errno,"graph.index");
       91:  102:    MPIU_CHKPMEM_MALLOC(graph_ptr->topo.graph.edges,int*,
        -:  103:			nedges*sizeof(int),mpi_errno,"graph.edges");
      520:  104:    for (i=0; i<nnodes; i++) 
      429:  105:	graph_ptr->topo.graph.index[i] = indx[i];
      873:  106:    for (i=0; i<nedges; i++) 
      782:  107:	graph_ptr->topo.graph.edges[i] = edges[i];
        -:  108:
        -:  109:    /* Finally, place the topology onto the new communicator and return the
        -:  110:       handle */
       91:  111:    mpi_errno = MPIR_Topology_put( newcomm_ptr, graph_ptr );
       91:  112:    if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  113:    
       91:  114:    *comm_graph = newcomm_ptr->handle;
        -:  115:    
        -:  116:    /* ... end of body of routine ... */
        -:  117:
       92:  118:  fn_exit:
       92:  119:    return mpi_errno;
        -:  120:
        -:  121:  fn_fail:
        -:  122:    /* --BEGIN ERROR HANDLING-- */
    #####:  123:    MPIU_CHKPMEM_REAP();
        -:  124:#   ifdef HAVE_ERROR_CHECKING
        -:  125:    {
    #####:  126:	mpi_errno = MPIR_Err_create_code(
        -:  127:	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, 
        -:  128:	    "**mpi_graph_create",
        -:  129:	    "**mpi_graph_create %C %d %p %p %d %p", comm_ptr->handle, 
        -:  130:	    nnodes, indx, 
        -:  131:	    edges, reorder, comm_graph);
        -:  132:    }
        -:  133:#   endif
    #####:  134:    mpi_errno = MPIR_Err_return_comm( (MPID_Comm*)comm_ptr, FCNAME, mpi_errno );
    #####:  135:    goto fn_exit;
        -:  136:    /* --END ERROR HANDLING-- */
        -:  137:}
        -:  138:#endif
        -:  139:
        -:  140:#undef FUNCNAME
        -:  141:#define FUNCNAME MPI_Graph_create
        -:  142:
        -:  143:/*@
        -:  144:MPI_Graph_create - Makes a new communicator to which topology information
        -:  145:                 has been attached
        -:  146:
        -:  147:Input Parameters:
        -:  148:+ comm_old - input communicator without topology (handle) 
        -:  149:. nnodes - number of nodes in graph (integer) 
        -:  150:. indx - array of integers describing node degrees (see below) 
        -:  151:. edges - array of integers describing graph edges (see below) 
        -:  152:- reorder - ranking may be reordered (true) or not (false) (logical) 
        -:  153:
        -:  154:Output Parameter:
        -:  155:. comm_graph - communicator with graph topology added (handle) 
        -:  156:
        -:  157:Notes:
        -:  158:Each process must provide a description of the entire graph, not just the
        -:  159:neigbors of the calling process.  
        -:  160:
        -:  161:Algorithm:
        -:  162:We ignore the 'reorder' info currently.
        -:  163:
        -:  164:.N ThreadSafe
        -:  165:
        -:  166:.N Fortran
        -:  167:
        -:  168:.N Errors
        -:  169:.N MPI_SUCCESS
        -:  170:.N MPI_ERR_TOPOLOGY
        -:  171:.N MPI_ERR_COMM
        -:  172:.N MPI_ERR_ARG
        -:  173:
        -:  174:@*/
        -:  175:int MPI_Graph_create(MPI_Comm comm_old, int nnodes, int *indx, int *edges, 
        -:  176:		     int reorder, MPI_Comm *comm_graph)
      106:  177:{
        -:  178:    static const char FCNAME[] = "MPI_Graph_create";
      106:  179:    int mpi_errno = MPI_SUCCESS;
        -:  180:    int i;
      106:  181:    MPID_Comm *comm_ptr = NULL;
      106:  182:    MPIU_THREADPRIV_DECL;
        -:  183:    MPID_MPI_STATE_DECL(MPID_STATE_MPI_GRAPH_CREATE);
        -:  184:
      106:  185:    MPIR_ERRTEST_INITIALIZED_ORDIE();
        -:  186:    
      106:  187:    MPIU_THREAD_CS_ENTER(ALLFUNC,);
        -:  188:    MPID_MPI_FUNC_ENTER(MPID_STATE_MPI_GRAPH_CREATE);
        -:  189:    
        -:  190:    /* Validate parameters, especially handles needing to be converted */
        -:  191:#   ifdef HAVE_ERROR_CHECKING
        -:  192:    {
        -:  193:        MPID_BEGIN_ERROR_CHECKS;
        -:  194:        {
      106:  195:	    MPIR_ERRTEST_COMM(comm_old, mpi_errno);
      106:  196:            if (mpi_errno != MPI_SUCCESS) goto fn_fail;
        -:  197:        }
        -:  198:        MPID_END_ERROR_CHECKS;
        -:  199:    }
        -:  200:#   endif
        -:  201:    
        -:  202:    /* Convert MPI object handles to object pointers */
      104:  203:    MPID_Comm_get_ptr( comm_old, comm_ptr );
        -:  204:
        -:  205:    /* Validate parameters and objects (post conversion) */
        -:  206:#   ifdef HAVE_ERROR_CHECKING
        -:  207:    {
        -:  208:        MPID_BEGIN_ERROR_CHECKS;
        -:  209:        {
        -:  210:            /* Validate comm_ptr */
      104:  211:            MPID_Comm_valid_ptr( comm_ptr, mpi_errno );
        -:  212:	    /* If comm_ptr is not valid, it will be reset to null */
      104:  213:	    if (comm_ptr) {
      104:  214:		MPIR_ERRTEST_COMM_INTRA(comm_ptr,mpi_errno);
        -:  215:	    }
      104:  216:	    MPIR_ERRTEST_ARGNEG(nnodes,"nnodes",mpi_errno);
      104:  217:	    if (nnodes > 0) {
       98:  218:		MPIR_ERRTEST_ARGNULL(indx,"index",mpi_errno);
       98:  219:		MPIR_ERRTEST_ARGNULL(edges,"edges",mpi_errno);
        -:  220:	    }
      104:  221:	    MPIR_ERRTEST_ARGNULL(comm_graph,"comm_graph",mpi_errno);
      104:  222:            if (mpi_errno) goto fn_fail;
        -:  223:        }
        -:  224:        MPID_END_ERROR_CHECKS;
        -:  225:    }
        -:  226:#   endif /* HAVE_ERROR_CHECKING */
        -:  227:
        -:  228:#   ifdef HAVE_ERROR_CHECKING
        -:  229:    {
        -:  230:        MPID_BEGIN_ERROR_CHECKS;
        -:  231:        {
      102:  232:	    int comm_size = comm_ptr->remote_size;
        -:  233:
        -:  234:	    /* Check that the communicator is large enough */
      102:  235:	    if (nnodes > comm_size) {
        2:  236:		mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, 
        -:  237:						  MPIR_ERR_RECOVERABLE, 
        -:  238:						  FCNAME, __LINE__, 
        -:  239:						  MPI_ERR_ARG,
        -:  240:				  "**topotoolarge", "**topotoolarge %d %d",
        -:  241:					  nnodes, comm_size );
        -:  242:	    }
        -:  243:	    
        -:  244:	    /* Perform the remaining tests only if nnodes is valid.  
        -:  245:	       This avoids SEGVs from accessing invalid parts of the
        -:  246:	       edges or index arrays */
      102:  247:            if (mpi_errno) goto fn_fail;
        -:  248:	    
        -:  249:	    /* Check that index is monotone nondecreasing */
        -:  250:	    /* Use ERR_ARG instead of ERR_TOPOLOGY because there is no
        -:  251:	       topology yet */
      542:  252:	    for (i=0; i<nnodes; i++) {
      442:  253:		if (indx[i] < 0) {
    #####:  254:		    mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, 
        -:  255:						      MPIR_ERR_RECOVERABLE, 
        -:  256:						      FCNAME, __LINE__, 
        -:  257:						      MPI_ERR_ARG,
        -:  258:			      "**indexneg", "**indexneg %d %d", i, indx[i] );
        -:  259:		}
      442:  260:		if (i+1<nnodes && indx[i] > indx[i+1]) {
    #####:  261:		    mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, 
        -:  262:						      MPIR_ERR_RECOVERABLE, 
        -:  263:						      FCNAME, __LINE__, 
        -:  264:						      MPI_ERR_ARG,
        -:  265:			   "**indexnonmonotone", "**indexnonmonotone %d %d %d",
        -:  266:					      i, indx[i], indx[i+1] );
        -:  267:		}
        -:  268:	    }
        -:  269:
        -:  270:	    /* Check that edge number is in range. Note that the 
        -:  271:	       edges refer to a rank in the communicator, and can 
        -:  272:	       be greater than nnodes */
      100:  273:	    if (nnodes > 0) { 
      896:  274:		for (i=0; i<indx[nnodes-1]; i++) {
      800:  275:		    if (edges[i] > comm_size || edges[i] < 0) {
        8:  276:			mpi_errno = MPIR_Err_create_code( MPI_SUCCESS, 
        -:  277:							  MPIR_ERR_RECOVERABLE,
        -:  278:							  FCNAME, __LINE__, 
        -:  279:							  MPI_ERR_ARG,
        -:  280:				  "**edgeoutrange", "**edgeoutrange %d %d %d", 
        -:  281:						  i, edges[i], comm_size );
        -:  282:		    }
        -:  283:		}
        -:  284:	    }
        -:  285:	    /* 
        -:  286:	     * As of MPI 2.1, null edges are expressly permitted, so this 
        -:  287:	     * test is no longer needed.
        -:  288:	     */
        -:  289:#if 0
        -:  290:	    /* We could also check that no edge is from a node to itself.
        -:  291:	       This gives us an excuse to run over the entire arrays. 
        -:  292:	       This test could be combined with the above to make the code
        -:  293:	       shorter.
        -:  294:	    */
        -:  295:	    if (!mpi_errno) {
        -:  296:		int j=0;
        -:  297:		for (i=0; i<nnodes && !mpi_errno; i++) {
        -:  298:		    for (;j<indx[i]; j++) {
        -:  299:			if (edges[j] == i) {
        -:  300:			    mpi_errno = MPIR_Err_create_code( MPI_SUCCESS,
        -:  301:						      MPIR_ERR_RECOVERABLE, 
        -:  302:						      FCNAME, __LINE__, 
        -:  303:						      MPI_ERR_ARG,
        -:  304:				     "**nulledge", "**nulledge %d %d", i, j );
        -:  305:			    break;
        -:  306:			}
        -:  307:		    }
        -:  308:		}
        -:  309:	    }
        -:  310:#endif
        -:  311:	    
      100:  312:            if (mpi_errno) goto fn_fail;
        -:  313:        }
        -:  314:        MPID_END_ERROR_CHECKS;
        -:  315:    }
        -:  316:#   endif /* HAVE_ERROR_CHECKING */
        -:  317:
        -:  318:    /* ... body of routine ...  */
        -:  319:    
        -:  320:    /* Test for empty communicator */
       96:  321:    if (nnodes == 0) {
        4:  322:	*comm_graph = MPI_COMM_NULL;
        4:  323:	goto fn_exit;
        -:  324:    }
        -:  325:
       92:  326:    if (comm_ptr->topo_fns != NULL && 
        -:  327:	comm_ptr->topo_fns->graphCreate != NULL) {
    #####:  328:	mpi_errno = comm_ptr->topo_fns->graphCreate( comm_ptr, nnodes, 
        -:  329:						     (const int *)indx,
        -:  330:						     (const int *)edges, 
        -:  331:						     reorder, comm_graph );
        -:  332:    }	
        -:  333:    else {
       92:  334:	mpi_errno = MPIR_Graph_create( comm_ptr, nnodes, 
        -:  335:				       (const int *)indx,
        -:  336:				       (const int *)edges, 
        -:  337:				       reorder, comm_graph );
        -:  338:    }
       92:  339:    if (mpi_errno) goto fn_fail;
        -:  340:
        -:  341:    /* ... end of body of routine ... */
        -:  342:
      106:  343:  fn_exit:
        -:  344:    MPID_MPI_FUNC_EXIT(MPID_STATE_MPI_GRAPH_CREATE);
      106:  345:    MPIU_THREAD_CS_EXIT(ALLFUNC,);
      106:  346:    return mpi_errno;
        -:  347:
       10:  348:  fn_fail:
        -:  349:    /* --BEGIN ERROR HANDLING-- */
        -:  350:#   ifdef HAVE_ERROR_CHECKING
        -:  351:    {
       10:  352:	mpi_errno = MPIR_Err_create_code(
        -:  353:	    mpi_errno, MPIR_ERR_RECOVERABLE, FCNAME, __LINE__, MPI_ERR_OTHER, 
        -:  354:	    "**mpi_graph_create",
        -:  355:	    "**mpi_graph_create %C %d %p %p %d %p", comm_old, nnodes, indx, 
        -:  356:	    edges, reorder, comm_graph);
        -:  357:    }
        -:  358:#   endif
       10:  359:    mpi_errno = MPIR_Err_return_comm( comm_ptr, FCNAME, mpi_errno );
       10:  360:    goto fn_exit;
        -:  361:    /* --END ERROR HANDLING-- */
        -:  362:}