void init_multisystem(t_commrec *cr, int nsim, char **multidirs,
                      int nfile, const t_filenm fnm[], gmx_bool bParFn)
{
    gmx_multisim_t *ms;
    int             nnodes, nnodpersim, sim, i, ftp;
    char            buf[256];
#ifdef GMX_MPI
    MPI_Group       mpi_group_world;
    int            *rank;
#endif

#ifndef GMX_MPI
    if (nsim > 1)
    {
        gmx_fatal(FARGS, "This binary is compiled without MPI support, can not do multiple simulations.");
    }
#endif

    nnodes  = cr->nnodes;
    if (nnodes % nsim != 0)
    {
        gmx_fatal(FARGS, "The number of ranks (%d) is not a multiple of the number of simulations (%d)", nnodes, nsim);
    }

    nnodpersim = nnodes/nsim;
    sim        = cr->nodeid/nnodpersim;

    if (debug)
    {
        fprintf(debug, "We have %d simulations, %d ranks per simulation, local simulation is %d\n", nsim, nnodpersim, sim);
    }

    snew(ms, 1);
    cr->ms   = ms;
    ms->nsim = nsim;
    ms->sim  = sim;
#ifdef GMX_MPI
    /* Create a communicator for the master nodes */
    snew(rank, ms->nsim);
    for (i = 0; i < ms->nsim; i++)
    {
        rank[i] = i*nnodpersim;
    }
    MPI_Comm_group(MPI_COMM_WORLD, &mpi_group_world);
    MPI_Group_incl(mpi_group_world, nsim, rank, &ms->mpi_group_masters);
    sfree(rank);
    MPI_Comm_create(MPI_COMM_WORLD, ms->mpi_group_masters,
                    &ms->mpi_comm_masters);

#if !defined(MPI_IN_PLACE_EXISTS)
    /* initialize the MPI_IN_PLACE replacement buffers */
    snew(ms->mpb, 1);
    ms->mpb->ibuf        = NULL;
    ms->mpb->libuf       = NULL;
    ms->mpb->fbuf        = NULL;
    ms->mpb->dbuf        = NULL;
    ms->mpb->ibuf_alloc  = 0;
    ms->mpb->libuf_alloc = 0;
    ms->mpb->fbuf_alloc  = 0;
    ms->mpb->dbuf_alloc  = 0;
#endif

#endif

    /* Reduce the intra-simulation communication */
    cr->sim_nodeid = cr->nodeid % nnodpersim;
    cr->nnodes     = nnodpersim;
#ifdef GMX_MPI
    MPI_Comm_split(MPI_COMM_WORLD, sim, cr->sim_nodeid, &cr->mpi_comm_mysim);
    cr->mpi_comm_mygroup = cr->mpi_comm_mysim;
    cr->nodeid           = cr->sim_nodeid;
#endif

    if (debug)
    {
        fprintf(debug, "This is simulation %d", cr->ms->sim);
        if (PAR(cr))
        {
            fprintf(debug, ", local number of ranks %d, local rank ID %d",
                    cr->nnodes, cr->sim_nodeid);
        }
        fprintf(debug, "\n\n");
    }

    if (multidirs)
    {
        if (debug)
        {
            fprintf(debug, "Changing to directory %s\n", multidirs[cr->ms->sim]);
        }
        gmx_chdir(multidirs[cr->ms->sim]);
    }
    else if (bParFn)
    {
        /* Patch output and tpx, cpt and rerun input file names */
        for (i = 0; (i < nfile); i++)
        {
            /* Because of possible multiple extensions per type we must look
             * at the actual file name
             */
            if (is_output(&fnm[i]) ||
                fnm[i].ftp == efTPX || fnm[i].ftp == efCPT ||
                strcmp(fnm[i].opt, "-rerun") == 0)
            {
                ftp = fn2ftp(fnm[i].fns[0]);
                par_fn(fnm[i].fns[0], ftp, cr, TRUE, FALSE, buf, 255);
                sfree(fnm[i].fns[0]);
                fnm[i].fns[0] = gmx_strdup(buf);
            }
        }
    }
}
Beispiel #2
0
/* Open the file to be processed. The handle variable holds internal
   info for the cpp emulator. Return integer status */
int cpp_open_file(const char *filenm, gmx_cpp_t *handle, char **cppopts)
{
    gmx_cpp_t    cpp;
    char        *buf, *pdum;
    char        *ptr, *ptr2;
    int          i;
    unsigned int i1;

    /* First process options, they might be necessary for opening files
       (especially include statements). */
    i  = 0;
    if (cppopts)
    {
        while (cppopts[i])
        {
            if (strstr(cppopts[i], "-I") == cppopts[i])
            {
                add_include(cppopts[i]+2);
            }
            if (strstr(cppopts[i], "-D") == cppopts[i])
            {
                /* If the option contains a =, split it into name and value. */
                ptr = strchr(cppopts[i], '=');
                if (ptr)
                {
                    buf = gmx_strndup(cppopts[i] + 2, ptr - cppopts[i] - 2);
                    add_define(buf, ptr + 1);
                    sfree(buf);
                }
                else
                {
                    add_define(cppopts[i] + 2, NULL);
                }
            }
            i++;
        }
    }
    if (debug)
    {
        fprintf(debug, "GMXCPP: added %d command line arguments\n", i);
    }

    snew(cpp, 1);
    *handle      = cpp;
    cpp->fn      = NULL;
    /* Find the file. First check whether it is in the current directory. */
    if (gmx_fexist(filenm))
    {
        cpp->fn = gmx_strdup(filenm);
    }
    else
    {
        /* If not, check all the paths given with -I. */
        for (i = 0; i < nincl; ++i)
        {
            snew(buf, strlen(incl[i]) + strlen(filenm) + 2);
            sprintf(buf, "%s/%s", incl[i], filenm);
            if (gmx_fexist(buf))
            {
                cpp->fn = buf;
                break;
            }
            sfree(buf);
        }
        /* If still not found, check the Gromacs library search path. */
        if (!cpp->fn)
        {
            cpp->fn = low_gmxlibfn(filenm, FALSE, FALSE);
        }
    }
    if (!cpp->fn)
    {
        gmx_fatal(FARGS, "Topology include file \"%s\" not found", filenm);
    }
    if (NULL != debug)
    {
        fprintf(debug, "GMXCPP: cpp file open %s\n", cpp->fn);
    }
    /* If the file name has a path component, we need to change to that
     * directory. Note that we - just as C - always use UNIX path separators
     * internally in include file names.
     */
    ptr  = strrchr(cpp->fn, '/');
    ptr2 = strrchr(cpp->fn, DIR_SEPARATOR);

    if (ptr == NULL || (ptr2 != NULL && ptr2 > ptr))
    {
        ptr = ptr2;
    }
    if (ptr == NULL)
    {
        cpp->path = NULL;
        cpp->cwd  = NULL;
    }
    else
    {
        cpp->path = cpp->fn;
        *ptr      = '\0';
        cpp->fn   = gmx_strdup(ptr+1);
        snew(cpp->cwd, STRLEN);

        gmx_getcwd(cpp->cwd, STRLEN);
        if (NULL != debug)
        {
            fprintf(debug, "GMXCPP: cwd %s\n", cpp->cwd);
        }
        gmx_chdir(cpp->path);

        if (NULL != debug)
        {
            fprintf(debug, "GMXCPP: chdir to %s\n", cpp->path);
        }
    }
    cpp->line_len = 0;
    cpp->line     = NULL;
    cpp->line_nr  = 0;
    cpp->nifdef   = 0;
    cpp->ifdefs   = NULL;
    cpp->child    = NULL;
    cpp->parent   = NULL;
    if (cpp->fp == NULL)
    {
        if (NULL != debug)
        {
            fprintf(debug, "GMXCPP: opening file %s\n", cpp->fn);
        }
        cpp->fp = fopen(cpp->fn, "r");
    }
    if (cpp->fp == NULL)
    {
        switch (errno)
        {
            case EINVAL:
            default:
                return eCPP_UNKNOWN;
        }
    }
    return eCPP_OK;
}
Beispiel #3
0
/* Close the file! Return integer status. */
int cpp_close_file(gmx_cpp_t *handlep)
{
    int       i;
    gmx_cpp_t handle = (gmx_cpp_t)*handlep;

    if (!handle)
    {
        return eCPP_INVALID_HANDLE;
    }
    if (!handle->fp)
    {
        return eCPP_FILE_NOT_OPEN;
    }
    if (debug)
    {
        fprintf(debug, "GMXCPP: closing file %s\n", handle->fn);
    }
    fclose(handle->fp);
    if (NULL != handle->cwd)
    {
        if (NULL != debug)
        {
            fprintf(debug, "GMXCPP: chdir to %s\n", handle->cwd);
        }
        gmx_chdir(handle->cwd);
    }

    if (0)
    {
        switch (errno)
        {
            case 0:
                break;
            case ENOENT:
                return eCPP_FILE_NOT_FOUND;
            case EBADF:
                return eCPP_FILE_NOT_OPEN;
            case EINTR:
                return eCPP_INTERRUPT;
            default:
                if (debug)
                {
                    fprintf(debug, "Strange stuff closing file, errno = %d", errno);
                }
                return eCPP_UNKNOWN;
        }
    }
    handle->fp      = NULL;
    handle->line_nr = 0;
    if (NULL != handle->fn)
    {
        sfree(handle->fn);
        handle->fn = NULL;
    }
    if (NULL != handle->line)
    {
        sfree(handle->line);
        handle->line = NULL;
    }
    if (NULL != handle->ifdefs)
    {
        sfree(handle->ifdefs);
    }
    handle->nifdef = 0;
    if (NULL != handle->path)
    {
        sfree(handle->path);
    }
    if (NULL != handle->cwd)
    {
        sfree(handle->cwd);
    }

    return eCPP_OK;
}
Beispiel #4
0
gmx_multisim_t *init_multisystem(MPI_Comm                         comm,
                                 gmx::ArrayRef<const std::string> multidirs)
{
    gmx_multisim_t *ms;
#if GMX_MPI
    MPI_Group       mpi_group_world;
    int            *rank;
#endif

    if (multidirs.empty())
    {
        return nullptr;
    }

    if (!GMX_LIB_MPI && !multidirs.empty())
    {
        gmx_fatal(FARGS, "mdrun -multidir is only supported when GROMACS has been "
                  "configured with a proper external MPI library.");
    }

    if (multidirs.size() == 1)
    {
        /* NOTE: It would be nice if this special case worked, but this requires checks/tests. */
        gmx_fatal(FARGS, "To run mdrun in multiple simulation mode, more then one "
                  "actual simulation is required. The single simulation case is not supported.");
    }

#if GMX_MPI
    int numRanks;
    MPI_Comm_size(comm, &numRanks);
    if (numRanks % multidirs.size() != 0)
    {
        gmx_fatal(FARGS, "The number of ranks (%d) is not a multiple of the number of simulations (%td)", numRanks, multidirs.size());
    }

    int numRanksPerSim = numRanks/multidirs.size();
    int rankWithinComm;
    MPI_Comm_rank(comm, &rankWithinComm);

    if (debug)
    {
        fprintf(debug, "We have %td simulations, %d ranks per simulation, local simulation is %d\n", multidirs.size(), numRanksPerSim, rankWithinComm/numRanksPerSim);
    }

    ms       = new gmx_multisim_t;
    ms->nsim = multidirs.size();
    ms->sim  = rankWithinComm/numRanksPerSim;
    /* Create a communicator for the master nodes */
    snew(rank, ms->nsim);
    for (int i = 0; i < ms->nsim; i++)
    {
        rank[i] = i*numRanksPerSim;
    }
    MPI_Comm_group(comm, &mpi_group_world);
    MPI_Group_incl(mpi_group_world, ms->nsim, rank, &ms->mpi_group_masters);
    sfree(rank);
    MPI_Comm_create(MPI_COMM_WORLD, ms->mpi_group_masters,
                    &ms->mpi_comm_masters);

#if !MPI_IN_PLACE_EXISTS
    /* initialize the MPI_IN_PLACE replacement buffers */
    snew(ms->mpb, 1);
    ms->mpb->ibuf        = NULL;
    ms->mpb->libuf       = NULL;
    ms->mpb->fbuf        = NULL;
    ms->mpb->dbuf        = NULL;
    ms->mpb->ibuf_alloc  = 0;
    ms->mpb->libuf_alloc = 0;
    ms->mpb->fbuf_alloc  = 0;
    ms->mpb->dbuf_alloc  = 0;
#endif

    // TODO This should throw upon error
    gmx_chdir(multidirs[ms->sim].c_str());
#else
    GMX_UNUSED_VALUE(comm);
    ms = nullptr;
#endif

    return ms;
}