Beispiel #1
0
gmx_mdoutf_t init_mdoutf(FILE *fplog, int nfile, const t_filenm fnm[],
                         int mdrun_flags, const t_commrec *cr,
                         const t_inputrec *ir, gmx_mtop_t *top_global,
                         const output_env_t oenv, gmx_wallcycle_t wcycle)
{
    gmx_mdoutf_t  of;
    char          filemode[3];
    gmx_bool      bAppendFiles, bCiteTng = FALSE;
    int           i;

    snew(of, 1);

    of->fp_trn       = NULL;
    of->fp_ene       = NULL;
    of->fp_xtc       = NULL;
    of->tng          = NULL;
    of->tng_low_prec = NULL;
    of->fp_dhdl      = NULL;
    of->fp_field     = NULL;

    of->eIntegrator             = ir->eI;
    of->bExpanded               = ir->bExpanded;
    of->elamstats               = ir->expandedvals->elamstats;
    of->simulation_part         = ir->simulation_part;
    of->x_compression_precision = static_cast<int>(ir->x_compression_precision);
    of->wcycle                  = wcycle;

    if (MASTER(cr))
    {
        bAppendFiles = (mdrun_flags & MD_APPENDFILES);

        of->bKeepAndNumCPT = (mdrun_flags & MD_KEEPANDNUMCPT);

        sprintf(filemode, bAppendFiles ? "a+" : "w+");

        if ((EI_DYNAMICS(ir->eI) || EI_ENERGY_MINIMIZATION(ir->eI))
#ifndef GMX_FAHCORE
            &&
            !(EI_DYNAMICS(ir->eI) &&
              ir->nstxout == 0 &&
              ir->nstvout == 0 &&
              ir->nstfout == 0)
#endif
            )
        {
            const char *filename;
            filename = ftp2fn(efTRN, nfile, fnm);
            switch (fn2ftp(filename))
            {
                case efTRR:
                case efTRN:
                    of->fp_trn = gmx_trr_open(filename, filemode);
                    break;
                case efTNG:
                    gmx_tng_open(filename, filemode[0], &of->tng);
                    if (filemode[0] == 'w')
                    {
                        gmx_tng_prepare_md_writing(of->tng, top_global, ir);
                    }
                    bCiteTng = TRUE;
                    break;
                default:
                    gmx_incons("Invalid full precision file format");
            }
        }
        if (EI_DYNAMICS(ir->eI) &&
            ir->nstxout_compressed > 0)
        {
            const char *filename;
            filename = ftp2fn(efCOMPRESSED, nfile, fnm);
            switch (fn2ftp(filename))
            {
                case efXTC:
                    of->fp_xtc                  = open_xtc(filename, filemode);
                    break;
                case efTNG:
                    gmx_tng_open(filename, filemode[0], &of->tng_low_prec);
                    if (filemode[0] == 'w')
                    {
                        gmx_tng_prepare_low_prec_writing(of->tng_low_prec, top_global, ir);
                    }
                    bCiteTng = TRUE;
                    break;
                default:
                    gmx_incons("Invalid reduced precision file format");
            }
        }
        if (EI_DYNAMICS(ir->eI) || EI_ENERGY_MINIMIZATION(ir->eI))
        {
            of->fp_ene = open_enx(ftp2fn(efEDR, nfile, fnm), filemode);
        }
        of->fn_cpt = opt2fn("-cpo", nfile, fnm);

        if ((ir->efep != efepNO || ir->bSimTemp) && ir->fepvals->nstdhdl > 0 &&
            (ir->fepvals->separate_dhdl_file == esepdhdlfileYES ) &&
            EI_DYNAMICS(ir->eI))
        {
            if (bAppendFiles)
            {
                of->fp_dhdl = gmx_fio_fopen(opt2fn("-dhdl", nfile, fnm), filemode);
            }
            else
            {
                of->fp_dhdl = open_dhdl(opt2fn("-dhdl", nfile, fnm), ir, oenv);
            }
        }

        if (opt2bSet("-field", nfile, fnm) &&
            (ir->ex[XX].n || ir->ex[YY].n || ir->ex[ZZ].n))
        {
            if (bAppendFiles)
            {
                of->fp_field = gmx_fio_fopen(opt2fn("-field", nfile, fnm),
                                             filemode);
            }
            else
            {
                of->fp_field = xvgropen(opt2fn("-field", nfile, fnm),
                                        "Applied electric field", "Time (ps)",
                                        "E (V/nm)", oenv);
            }
        }

        /* Set up atom counts so they can be passed to actual
           trajectory-writing routines later. Also, XTC writing needs
           to know what (and how many) atoms might be in the XTC
           groups, and how to look up later which ones they are. */
        of->natoms_global       = top_global->natoms;
        of->groups              = &top_global->groups;
        of->natoms_x_compressed = 0;
        for (i = 0; (i < top_global->natoms); i++)
        {
            if (ggrpnr(of->groups, egcCompressedX, i) == 0)
            {
                of->natoms_x_compressed++;
            }
        }
    }

    if (bCiteTng)
    {
        please_cite(fplog, "Lundborg2014");
    }

    return of;
}
Beispiel #2
0
gmx_repl_ex_t
init_replica_exchange(FILE                            *fplog,
                      const gmx_multisim_t            *ms,
                      int                              numAtomsInSystem,
                      const t_inputrec                *ir,
                      const ReplicaExchangeParameters &replExParams)
{
    real                pres;
    int                 i, j;
    struct gmx_repl_ex *re;
    gmx_bool            bTemp;
    gmx_bool            bLambda = FALSE;

    fprintf(fplog, "\nInitializing Replica Exchange\n");

    if (!isMultiSim(ms) || ms->nsim == 1)
    {
        gmx_fatal(FARGS, "Nothing to exchange with only one replica, maybe you forgot to set the -multidir option of mdrun?");
    }
    if (!EI_DYNAMICS(ir->eI))
    {
        gmx_fatal(FARGS, "Replica exchange is only supported by dynamical simulations");
        /* Note that PAR(cr) is defined by cr->nnodes > 1, which is
         * distinct from isMultiSim(ms). A multi-simulation only runs
         * with real MPI parallelism, but this does not imply PAR(cr)
         * is true!
         *
         * Since we are using a dynamical integrator, the only
         * decomposition is DD, so PAR(cr) and DOMAINDECOMP(cr) are
         * synonymous. The only way for cr->nnodes > 1 to be true is
         * if we are using DD. */
    }

    snew(re, 1);

    re->repl     = ms->sim;
    re->nrepl    = ms->nsim;
    snew(re->q, ereENDSINGLE);

    fprintf(fplog, "Repl  There are %d replicas:\n", re->nrepl);

    /* We only check that the number of atoms in the systms match.
     * This, of course, do not guarantee that the systems are the same,
     * but it does guarantee that we can perform replica exchange.
     */
    check_multi_int(fplog, ms, numAtomsInSystem, "the number of atoms", FALSE);
    check_multi_int(fplog, ms, ir->eI, "the integrator", FALSE);
    check_multi_int64(fplog, ms, ir->init_step+ir->nsteps, "init_step+nsteps", FALSE);
    const int nst = replExParams.exchangeInterval;
    check_multi_int64(fplog, ms, (ir->init_step+nst-1)/nst,
                      "first exchange step: init_step/-replex", FALSE);
    check_multi_int(fplog, ms, ir->etc, "the temperature coupling", FALSE);
    check_multi_int(fplog, ms, ir->opts.ngtc,
                    "the number of temperature coupling groups", FALSE);
    check_multi_int(fplog, ms, ir->epc, "the pressure coupling", FALSE);
    check_multi_int(fplog, ms, ir->efep, "free energy", FALSE);
    check_multi_int(fplog, ms, ir->fepvals->n_lambda, "number of lambda states", FALSE);

    re->temp = ir->opts.ref_t[0];
    for (i = 1; (i < ir->opts.ngtc); i++)
    {
        if (ir->opts.ref_t[i] != re->temp)
        {
            fprintf(fplog, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
            fprintf(stderr, "\nWARNING: The temperatures of the different temperature coupling groups are not identical\n\n");
        }
    }

    re->type = -1;
    bTemp    = repl_quantity(ms, re, ereTEMP, re->temp);
    if (ir->efep != efepNO)
    {
        bLambda = repl_quantity(ms, re, ereLAMBDA, static_cast<real>(ir->fepvals->init_fep_state));
    }
    if (re->type == -1)  /* nothing was assigned */
    {
        gmx_fatal(FARGS, "The properties of the %d systems are all the same, there is nothing to exchange", re->nrepl);
    }
    if (bLambda && bTemp)
    {
        re->type = ereTL;
    }

    if (bTemp)
    {
        please_cite(fplog, "Sugita1999a");
        if (ir->epc != epcNO)
        {
            re->bNPT = TRUE;
            fprintf(fplog, "Repl  Using Constant Pressure REMD.\n");
            please_cite(fplog, "Okabe2001a");
        }
        if (ir->etc == etcBERENDSEN)
        {
            gmx_fatal(FARGS, "REMD with the %s thermostat does not produce correct potential energy distributions, consider using the %s thermostat instead",
                      ETCOUPLTYPE(ir->etc), ETCOUPLTYPE(etcVRESCALE));
        }
    }
    if (bLambda)
    {
        if (ir->fepvals->delta_lambda != 0)   /* check this? */
        {
            gmx_fatal(FARGS, "delta_lambda is not zero");
        }
    }
    if (re->bNPT)
    {
        snew(re->pres, re->nrepl);
        if (ir->epct == epctSURFACETENSION)
        {
            pres = ir->ref_p[ZZ][ZZ];
        }
        else
        {
            pres = 0;
            j    = 0;
            for (i = 0; i < DIM; i++)
            {
                if (ir->compress[i][i] != 0)
                {
                    pres += ir->ref_p[i][i];
                    j++;
                }
            }
            pres /= j;
        }
        re->pres[re->repl] = pres;
        gmx_sum_sim(re->nrepl, re->pres, ms);
    }

    /* Make an index for increasing replica order */
    /* only makes sense if one or the other is varying, not both!
       if both are varying, we trust the order the person gave. */
    snew(re->ind, re->nrepl);
    for (i = 0; i < re->nrepl; i++)
    {
        re->ind[i] = i;
    }

    if (re->type < ereENDSINGLE)
    {

        for (i = 0; i < re->nrepl; i++)
        {
            for (j = i+1; j < re->nrepl; j++)
            {
                if (re->q[re->type][re->ind[j]] < re->q[re->type][re->ind[i]])
                {
                    /* Unordered replicas are supposed to work, but there
                     * is still an issues somewhere.
                     * Note that at this point still re->ind[i]=i.
                     */
                    gmx_fatal(FARGS, "Replicas with indices %d < %d have %ss %g > %g, please order your replicas on increasing %s",
                              i, j,
                              erename[re->type],
                              re->q[re->type][i], re->q[re->type][j],
                              erename[re->type]);
                }
                else if (re->q[re->type][re->ind[j]] == re->q[re->type][re->ind[i]])
                {
                    gmx_fatal(FARGS, "Two replicas have identical %ss", erename[re->type]);
                }
            }
        }
    }

    /* keep track of all the swaps, starting with the initial placement. */
    snew(re->allswaps, re->nrepl);
    for (i = 0; i < re->nrepl; i++)
    {
        re->allswaps[i] = re->ind[i];
    }

    switch (re->type)
    {
        case ereTEMP:
            fprintf(fplog, "\nReplica exchange in temperature\n");
            for (i = 0; i < re->nrepl; i++)
            {
                fprintf(fplog, " %5.1f", re->q[re->type][re->ind[i]]);
            }
            fprintf(fplog, "\n");
            break;
        case ereLAMBDA:
            fprintf(fplog, "\nReplica exchange in lambda\n");
            for (i = 0; i < re->nrepl; i++)
            {
                fprintf(fplog, " %3d", static_cast<int>(re->q[re->type][re->ind[i]]));
            }
            fprintf(fplog, "\n");
            break;
        case ereTL:
            fprintf(fplog, "\nReplica exchange in temperature and lambda state\n");
            for (i = 0; i < re->nrepl; i++)
            {
                fprintf(fplog, " %5.1f", re->q[ereTEMP][re->ind[i]]);
            }
            fprintf(fplog, "\n");
            for (i = 0; i < re->nrepl; i++)
            {
                fprintf(fplog, " %5d", static_cast<int>(re->q[ereLAMBDA][re->ind[i]]));
            }
            fprintf(fplog, "\n");
            break;
        default:
            gmx_incons("Unknown replica exchange quantity");
    }
    if (re->bNPT)
    {
        fprintf(fplog, "\nRepl  p");
        for (i = 0; i < re->nrepl; i++)
        {
            fprintf(fplog, " %5.2f", re->pres[re->ind[i]]);
        }

        for (i = 0; i < re->nrepl; i++)
        {
            if ((i > 0) && (re->pres[re->ind[i]] < re->pres[re->ind[i-1]]))
            {
                fprintf(fplog, "\nWARNING: The reference pressures decrease with increasing temperatures\n\n");
                fprintf(stderr, "\nWARNING: The reference pressures decrease with increasing temperatures\n\n");
            }
        }
    }
    re->nst = nst;
    if (replExParams.randomSeed == -1)
    {
        if (isMasterSim(ms))
        {
            re->seed = static_cast<int>(gmx::makeRandomSeed());
        }
        else
        {
            re->seed = 0;
        }
        gmx_sumi_sim(1, &(re->seed), ms);
    }
    else
    {
        re->seed = replExParams.randomSeed;
    }
    fprintf(fplog, "\nReplica exchange interval: %d\n", re->nst);
    fprintf(fplog, "\nReplica random seed: %d\n", re->seed);

    re->nattempt[0] = 0;
    re->nattempt[1] = 0;

    snew(re->prob_sum, re->nrepl);
    snew(re->nexchange, re->nrepl);
    snew(re->nmoves, re->nrepl);
    for (i = 0; i < re->nrepl; i++)
    {
        snew(re->nmoves[i], re->nrepl);
    }
    fprintf(fplog, "Replica exchange information below: ex and x = exchange, pr = probability\n");

    /* generate space for the helper functions so we don't have to snew each time */

    snew(re->destinations, re->nrepl);
    snew(re->incycle, re->nrepl);
    snew(re->tmpswap, re->nrepl);
    snew(re->cyclic, re->nrepl);
    snew(re->order, re->nrepl);
    for (i = 0; i < re->nrepl; i++)
    {
        snew(re->cyclic[i], re->nrepl+1);
        snew(re->order[i], re->nrepl);
    }
    /* allocate space for the functions storing the data for the replicas */
    /* not all of these arrays needed in all cases, but they don't take
       up much space, since the max size is nrepl**2 */
    snew(re->prob, re->nrepl);
    snew(re->bEx, re->nrepl);
    snew(re->beta, re->nrepl);
    snew(re->Vol, re->nrepl);
    snew(re->Epot, re->nrepl);
    snew(re->de, re->nrepl);
    for (i = 0; i < re->nrepl; i++)
    {
        snew(re->de[i], re->nrepl);
    }
    re->nex = replExParams.numExchanges;
    return re;
}
Beispiel #3
0
static real calc_delta(FILE *fplog, gmx_bool bPrint, struct gmx_repl_ex *re, int a, int b, int ap, int bp)
{

    real   ediff, dpV, delta = 0;
    real  *Epot = re->Epot;
    real  *Vol  = re->Vol;
    real **de   = re->de;
    real  *beta = re->beta;

    /* Two cases; we are permuted and not.  In all cases, setting ap = a and bp = b will reduce
       to the non permuted case */

    switch (re->type)
    {
        case ereTEMP:
            /*
             * Okabe et. al. Chem. Phys. Lett. 335 (2001) 435-439
             */
            ediff = Epot[b] - Epot[a];
            delta = -(beta[bp] - beta[ap])*ediff;
            break;
        case ereLAMBDA:
            /* two cases:  when we are permuted, and not.  */
            /* non-permuted:
               ediff =  E_new - E_old
                     =  [H_b(x_a) + H_a(x_b)] - [H_b(x_b) + H_a(x_a)]
                     =  [H_b(x_a) - H_a(x_a)] + [H_a(x_b) - H_b(x_b)]
                     =  de[b][a] + de[a][b] */

            /* permuted:
               ediff =  E_new - E_old
                     =  [H_bp(x_a) + H_ap(x_b)] - [H_bp(x_b) + H_ap(x_a)]
                     =  [H_bp(x_a) - H_ap(x_a)] + [H_ap(x_b) - H_bp(x_b)]
                     =  [H_bp(x_a) - H_a(x_a) + H_a(x_a) - H_ap(x_a)] + [H_ap(x_b) - H_b(x_b) + H_b(x_b) - H_bp(x_b)]
                     =  [H_bp(x_a) - H_a(x_a)] - [H_ap(x_a) - H_a(x_a)] + [H_ap(x_b) - H_b(x_b)] - H_bp(x_b) - H_b(x_b)]
                     =  (de[bp][a] - de[ap][a]) + (de[ap][b] - de[bp][b])    */
            /* but, in the current code implementation, we flip configurations, not indices . . .
               So let's examine that.
                     =  [H_b(x_ap) - H_a(x_a)] - [H_a(x_ap) - H_a(x_a)] + [H_a(x_bp) - H_b(x_b)] - H_b(x_bp) - H_b(x_b)]
                     =  [H_b(x_ap) - H_a(x_ap)]  + [H_a(x_bp) - H_b(x_pb)]
                     = (de[b][ap] - de[a][ap]) + (de[a][bp] - de[b][bp]
                     So, if we exchange b<=> bp and a<=> ap, we return to the same result.
                     So the simple solution is to flip the
                     position of perturbed and original indices in the tests.
             */

            ediff = (de[bp][a] - de[ap][a]) + (de[ap][b] - de[bp][b]);
            delta = ediff*beta[a]; /* assume all same temperature in this case */
            break;
        case ereTL:
            /* not permuted:  */
            /* delta =  reduced E_new - reduced E_old
                     =  [beta_b H_b(x_a) + beta_a H_a(x_b)] - [beta_b H_b(x_b) + beta_a H_a(x_a)]
                     =  [beta_b H_b(x_a) - beta_a H_a(x_a)] + [beta_a H_a(x_b) - beta_b H_b(x_b)]
                     =  [beta_b dH_b(x_a) + beta_b H_a(x_a) - beta_a H_a(x_a)] +
                        [beta_a dH_a(x_b) + beta_a H_b(x_b) - beta_b H_b(x_b)]
                     =  [beta_b dH_b(x_a) + [beta_a dH_a(x_b) +
                        beta_b (H_a(x_a) - H_b(x_b)]) - beta_a (H_a(x_a) - H_b(x_b))
                     =  beta_b dH_b(x_a) + beta_a dH_a(x_b) - (beta_b - beta_a)(H_b(x_b) - H_a(x_a) */
            /* delta = beta[b]*de[b][a] + beta[a]*de[a][b] - (beta[b] - beta[a])*(Epot[b] - Epot[a]; */
            /* permuted (big breath!) */
            /*   delta =  reduced E_new - reduced E_old
                     =  [beta_bp H_bp(x_a) + beta_ap H_ap(x_b)] - [beta_bp H_bp(x_b) + beta_ap H_ap(x_a)]
                     =  [beta_bp H_bp(x_a) - beta_ap H_ap(x_a)] + [beta_ap H_ap(x_b) - beta_bp H_bp(x_b)]
                     =  [beta_bp H_bp(x_a) - beta_ap H_ap(x_a)] + [beta_ap H_ap(x_b) - beta_bp H_bp(x_b)]
                        - beta_pb H_a(x_a) + beta_ap H_a(x_a) + beta_pb H_a(x_a) - beta_ap H_a(x_a)
                        - beta_ap H_b(x_b) + beta_bp H_b(x_b) + beta_ap H_b(x_b) - beta_bp H_b(x_b)
                     =  [(beta_bp H_bp(x_a) - beta_bp H_a(x_a)) - (beta_ap H_ap(x_a) - beta_ap H_a(x_a))] +
                        [(beta_ap H_ap(x_b)  - beta_ap H_b(x_b)) - (beta_bp H_bp(x_b) - beta_bp H_b(x_b))]
             + beta_pb H_a(x_a) - beta_ap H_a(x_a) + beta_ap H_b(x_b) - beta_bp H_b(x_b)
                     =  [beta_bp (H_bp(x_a) - H_a(x_a)) - beta_ap (H_ap(x_a) - H_a(x_a))] +
                        [beta_ap (H_ap(x_b) - H_b(x_b)) - beta_bp (H_bp(x_b) - H_b(x_b))]
             + beta_pb (H_a(x_a) - H_b(x_b))  - beta_ap (H_a(x_a) - H_b(x_b))
                     =  ([beta_bp de[bp][a] - beta_ap de[ap][a]) + beta_ap de[ap][b]  - beta_bp de[bp][b])
             + (beta_pb-beta_ap)(H_a(x_a) - H_b(x_b))  */
            delta = beta[bp]*(de[bp][a] - de[bp][b]) + beta[ap]*(de[ap][b] - de[ap][a]) - (beta[bp]-beta[ap])*(Epot[b]-Epot[a]);
            break;
        default:
            gmx_incons("Unknown replica exchange quantity");
    }
    if (bPrint)
    {
        fprintf(fplog, "Repl %d <-> %d  dE_term = %10.3e (kT)\n", a, b, delta);
    }
    if (re->bNPT)
    {
        /* revist the calculation for 5.0.  Might be some improvements. */
        dpV = (beta[ap]*re->pres[ap]-beta[bp]*re->pres[bp])*(Vol[b]-Vol[a])/PRESFAC;
        if (bPrint)
        {
            fprintf(fplog, "  dpV = %10.3e  d = %10.3e\n", dpV, delta + dpV);
        }
        delta += dpV;
    }
    return delta;
}
Beispiel #4
0
//! Do the real arithmetic for filling the pbc struct
static void low_set_pbc(t_pbc *pbc, int ePBC,
                        const ivec dd_pbc, const matrix box)
{
    int         order[3] = { 0, -1, 1 };
    ivec        bPBC;
    const char *ptr;

    pbc->ePBC      = ePBC;
    pbc->ndim_ePBC = ePBC2npbcdim(ePBC);

    copy_mat(box, pbc->box);
    pbc->max_cutoff2    = 0;
    pbc->dim            = -1;
    pbc->ntric_vec      = 0;

    for (int i = 0; (i < DIM); i++)
    {
        pbc->fbox_diag[i]  =  box[i][i];
        pbc->hbox_diag[i]  =  pbc->fbox_diag[i]*0.5;
        pbc->mhbox_diag[i] = -pbc->hbox_diag[i];
    }

    ptr = check_box(ePBC, box);
    if (ePBC == epbcNONE)
    {
        pbc->ePBCDX = epbcdxNOPBC;
    }
    else if (ptr)
    {
        fprintf(stderr,   "Warning: %s\n", ptr);
        pr_rvecs(stderr, 0, "         Box", box, DIM);
        fprintf(stderr,   "         Can not fix pbc.\n\n");
        pbc->ePBCDX = epbcdxUNSUPPORTED;
    }
    else
    {
        if (ePBC == epbcSCREW && NULL != dd_pbc)
        {
            /* This combinated should never appear here */
            gmx_incons("low_set_pbc called with screw pbc and dd_nc != NULL");
        }

        int npbcdim = 0;
        for (int i = 0; i < DIM; i++)
        {
            if ((dd_pbc && dd_pbc[i] == 0) || (ePBC == epbcXY && i == ZZ))
            {
                bPBC[i] = 0;
            }
            else
            {
                bPBC[i] = 1;
                npbcdim++;
            }
        }
        switch (npbcdim)
        {
            case 1:
                /* 1D pbc is not an mdp option and it is therefore only used
                 * with single shifts.
                 */
                pbc->ePBCDX = epbcdx1D_RECT;
                for (int i = 0; i < DIM; i++)
                {
                    if (bPBC[i])
                    {
                        pbc->dim = i;
                    }
                }
                GMX_ASSERT(pbc->dim < DIM, "Dimension for PBC incorrect");
                for (int i = 0; i < pbc->dim; i++)
                {
                    if (pbc->box[pbc->dim][i] != 0)
                    {
                        pbc->ePBCDX = epbcdx1D_TRIC;
                    }
                }
                break;
            case 2:
                pbc->ePBCDX = epbcdx2D_RECT;
                for (int i = 0; i < DIM; i++)
                {
                    if (!bPBC[i])
                    {
                        pbc->dim = i;
                    }
                }
                for (int i = 0; i < DIM; i++)
                {
                    if (bPBC[i])
                    {
                        for (int j = 0; j < i; j++)
                        {
                            if (pbc->box[i][j] != 0)
                            {
                                pbc->ePBCDX = epbcdx2D_TRIC;
                            }
                        }
                    }
                }
                break;
            case 3:
                if (ePBC != epbcSCREW)
                {
                    if (TRICLINIC(box))
                    {
                        pbc->ePBCDX = epbcdxTRICLINIC;
                    }
                    else
                    {
                        pbc->ePBCDX = epbcdxRECTANGULAR;
                    }
                }
                else
                {
                    pbc->ePBCDX = (box[ZZ][YY] == 0 ? epbcdxSCREW_RECT : epbcdxSCREW_TRIC);
                    if (pbc->ePBCDX == epbcdxSCREW_TRIC)
                    {
                        fprintf(stderr,
                                "Screw pbc is not yet implemented for triclinic boxes.\n"
                                "Can not fix pbc.\n");
                        pbc->ePBCDX = epbcdxUNSUPPORTED;
                    }
                }
                break;
            default:
                gmx_fatal(FARGS, "Incorrect number of pbc dimensions with DD: %d",
                          npbcdim);
        }
        pbc->max_cutoff2 = max_cutoff2(ePBC, box);

        if (pbc->ePBCDX == epbcdxTRICLINIC ||
            pbc->ePBCDX == epbcdx2D_TRIC ||
            pbc->ePBCDX == epbcdxSCREW_TRIC)
        {
            if (debug)
            {
                pr_rvecs(debug, 0, "Box", box, DIM);
                fprintf(debug, "max cutoff %.3f\n", sqrt(pbc->max_cutoff2));
            }
            /* We will only need single shifts here */
            for (int kk = 0; kk < 3; kk++)
            {
                int k = order[kk];
                if (!bPBC[ZZ] && k != 0)
                {
                    continue;
                }
                for (int jj = 0; jj < 3; jj++)
                {
                    int j = order[jj];
                    if (!bPBC[YY] && j != 0)
                    {
                        continue;
                    }
                    for (int ii = 0; ii < 3; ii++)
                    {
                        int i = order[ii];
                        if (!bPBC[XX] && i != 0)
                        {
                            continue;
                        }
                        /* A shift is only useful when it is trilinic */
                        if (j != 0 || k != 0)
                        {
                            rvec trial;
                            rvec pos;
                            real d2old = 0;
                            real d2new = 0;

                            for (int d = 0; d < DIM; d++)
                            {
                                trial[d] = i*box[XX][d] + j*box[YY][d] + k*box[ZZ][d];
                                /* Choose the vector within the brick around 0,0,0 that
                                 * will become the shortest due to shift try.
                                 */
                                if (d == pbc->dim)
                                {
                                    trial[d] = 0;
                                    pos[d]   = 0;
                                }
                                else
                                {
                                    if (trial[d] < 0)
                                    {
                                        pos[d] = std::min( pbc->hbox_diag[d], -trial[d]);
                                    }
                                    else
                                    {
                                        pos[d] = std::max(-pbc->hbox_diag[d], -trial[d]);
                                    }
                                }
                                d2old += gmx::square(pos[d]);
                                d2new += gmx::square(pos[d] + trial[d]);
                            }
                            if (BOX_MARGIN*d2new < d2old)
                            {
                                /* Check if shifts with one box vector less do better */
                                gmx_bool bUse = TRUE;
                                for (int dd = 0; dd < DIM; dd++)
                                {
                                    int shift = (dd == 0 ? i : (dd == 1 ? j : k));
                                    if (shift)
                                    {
                                        real d2new_c = 0;
                                        for (int d = 0; d < DIM; d++)
                                        {
                                            d2new_c += gmx::square(pos[d] + trial[d] - shift*box[dd][d]);
                                        }
                                        if (d2new_c <= BOX_MARGIN*d2new)
                                        {
                                            bUse = FALSE;
                                        }
                                    }
                                }
                                if (bUse)
                                {
                                    /* Accept this shift vector. */
                                    if (pbc->ntric_vec >= MAX_NTRICVEC)
                                    {
                                        fprintf(stderr, "\nWARNING: Found more than %d triclinic correction vectors, ignoring some.\n"
                                                "  There is probably something wrong with your box.\n", MAX_NTRICVEC);
                                        pr_rvecs(stderr, 0, "         Box", box, DIM);
                                    }
                                    else
                                    {
                                        copy_rvec(trial, pbc->tric_vec[pbc->ntric_vec]);
                                        pbc->tric_shift[pbc->ntric_vec][XX] = i;
                                        pbc->tric_shift[pbc->ntric_vec][YY] = j;
                                        pbc->tric_shift[pbc->ntric_vec][ZZ] = k;
                                        pbc->ntric_vec++;

                                        if (debug)
                                        {
                                            fprintf(debug, "  tricvec %2d = %2d %2d %2d  %5.2f %5.2f  %5.2f %5.2f %5.2f  %5.2f %5.2f %5.2f\n",
                                                    pbc->ntric_vec, i, j, k,
                                                    sqrt(d2old), sqrt(d2new),
                                                    trial[XX], trial[YY], trial[ZZ],
                                                    pos[XX], pos[YY], pos[ZZ]);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Beispiel #5
0
static void dd_collect_cg(gmx_domdec_t  *dd,
                          const t_state *state_local)
{
    if (state_local->ddp_count == dd->comm->master_cg_ddp_count)
    {
        /* The master has the correct distribution */
        return;
    }

    gmx::ArrayRef<const int> atomGroups;
    int                      nat_home = 0;

    if (state_local->ddp_count == dd->ddp_count)
    {
        /* The local state and DD are in sync, use the DD indices */
        atomGroups = gmx::constArrayRefFromArray(dd->globalAtomGroupIndices.data(), dd->ncg_home);
        nat_home   = dd->comm->atomRanges.numHomeAtoms();
    }
    else if (state_local->ddp_count_cg_gl == state_local->ddp_count)
    {
        /* The DD is out of sync with the local state, but we have stored
         * the cg indices with the local state, so we can use those.
         */
        const t_block &cgs_gl = dd->comm->cgs_gl;

        atomGroups = state_local->cg_gl;
        nat_home   = 0;
        for (const int &i : atomGroups)
        {
            nat_home += cgs_gl.index[i + 1] - cgs_gl.index[i];
        }
    }
    else
    {
        gmx_incons("Attempted to collect a vector for a state for which the charge group distribution is unknown");
    }

    AtomDistribution *ma = dd->ma.get();

    /* Collect the charge group and atom counts on the master */
    int localBuffer[2] = { static_cast<int>(atomGroups.size()), nat_home };
    dd_gather(dd, 2*sizeof(int), localBuffer,
              DDMASTER(dd) ? ma->intBuffer.data() : nullptr);

    if (DDMASTER(dd))
    {
        int groupOffset = 0;
        for (int rank = 0; rank < dd->nnodes; rank++)
        {
            auto &domainGroups       = ma->domainGroups[rank];
            int   numGroups          = ma->intBuffer[2*rank];

            domainGroups.atomGroups  = gmx::constArrayRefFromArray(ma->atomGroups.data() + groupOffset, numGroups);

            domainGroups.numAtoms    = ma->intBuffer[2*rank + 1];

            groupOffset             += numGroups;
        }

        if (debug)
        {
            fprintf(debug, "Initial charge group distribution: ");
            for (int rank = 0; rank < dd->nnodes; rank++)
            {
                fprintf(debug, " %td", ma->domainGroups[rank].atomGroups.size());
            }
            fprintf(debug, "\n");
        }

        /* Make byte counts and indices */
        int offset = 0;
        for (int rank = 0; rank < dd->nnodes; rank++)
        {
            int numGroups                     = ma->domainGroups[rank].atomGroups.size();
            ma->intBuffer[rank]               = numGroups*sizeof(int);
            ma->intBuffer[dd->nnodes + rank]  = offset*sizeof(int);
            offset                           += numGroups;
        }
    }

    /* Collect the charge group indices on the master */
    dd_gatherv(dd,
               atomGroups.size()*sizeof(int), atomGroups.data(),
               DDMASTER(dd) ? ma->intBuffer.data() : nullptr,
               DDMASTER(dd) ? ma->intBuffer.data() + dd->nnodes : nullptr,
               DDMASTER(dd) ? ma->atomGroups.data() : nullptr);

    dd->comm->master_cg_ddp_count = state_local->ddp_count;
}
Beispiel #6
0
void get_pdb_atomnumber(const t_atoms *atoms, gmx_atomprop_t aps)
{
    int    i, atomnumber, len;
    size_t k;
    char   anm[6], anm_copy[6], *ptr;
    char   nc = '\0';
    real   eval;

    if (!atoms->pdbinfo)
    {
        gmx_incons("Trying to deduce atomnumbers when no pdb information is present");
    }
    for (i = 0; (i < atoms->nr); i++)
    {
        std::strcpy(anm, atoms->pdbinfo[i].atomnm);
        std::strcpy(anm_copy, atoms->pdbinfo[i].atomnm);
        bool atomNumberSet = false;
        len        = strlen(anm);
        if ((anm[0] != ' ') && ((len <= 2) || !std::isdigit(anm[2])))
        {
            anm_copy[2] = nc;
            if (gmx_atomprop_query(aps, epropElement, "???", anm_copy, &eval))
            {
                atomnumber    = std::round(eval);
                atomNumberSet = true;
            }
            else
            {
                anm_copy[1] = nc;
                if (gmx_atomprop_query(aps, epropElement, "???", anm_copy, &eval))
                {
                    atomnumber    = std::round(eval);
                    atomNumberSet = true;
                }
            }
        }
        if (!atomNumberSet)
        {
            k = 0;
            while ((k < std::strlen(anm)) && (std::isspace(anm[k]) || std::isdigit(anm[k])))
            {
                k++;
            }
            anm_copy[0] = anm[k];
            anm_copy[1] = nc;
            if (gmx_atomprop_query(aps, epropElement, "???", anm_copy, &eval))
            {
                atomnumber    = std::round(eval);
                atomNumberSet = true;
            }
        }
        if (atomNumberSet)
        {
            atoms->atom[i].atomnumber = atomnumber;
            ptr = gmx_atomprop_element(aps, atomnumber);
            if (debug)
            {
                fprintf(debug, "Atomnumber for atom '%s' is %d\n",
                        anm, atomnumber);
            }
        }
        else
        {
            ptr = NULL;
        }
        std::strncpy(atoms->atom[i].elem, ptr == NULL ? "" : ptr, 4);
    }
}
/* Set CPU affinity. Can be important for performance.
   On some systems (e.g. Cray) CPU Affinity is set by default.
   But default assigning doesn't work (well) with only some ranks
   having threads. This causes very low performance.
   External tools have cumbersome syntax for setting affinity
   in the case that only some ranks have threads.
   Thus it is important that GROMACS sets the affinity internally
   if only PME is using threads.
 */
void
gmx_set_thread_affinity(FILE                *fplog,
                        const t_commrec     *cr,
                        gmx_hw_opt_t        *hw_opt,
                        const gmx_hw_info_t *hwinfo)
{
    int        nth_affinity_set, thread0_id_node,
               nthread_local, nthread_node, nthread_hw_max, nphyscore;
    int        offset;
    const int *locality_order;
    int        rc;

    if (hw_opt->thread_affinity == threadaffOFF)
    {
        /* Nothing to do */
        return;
    }

    /* If the tMPI thread affinity setting is not supported encourage the user
     * to report it as it's either a bug or an exotic platform which we might
     * want to support. */
    if (tMPI_Thread_setaffinity_support() != TMPI_SETAFFINITY_SUPPORT_YES)
    {
        /* we know Mac OS doesn't support setting thread affinity, so there's
           no point in warning the user in that case. In any other case
           the user might be able to do something about it. */
#ifndef __APPLE__
        md_print_warn(NULL, fplog,
                      "Can not set thread affinities on the current platform. On NUMA systems this\n"
                      "can cause performance degradation. If you think your platform should support\n"
                      "setting affinities, contact the GROMACS developers.");
#endif  /* __APPLE__ */
        return;
    }

    /* threads on this MPI process or TMPI thread */
    if (cr->duty & DUTY_PP)
    {
        nthread_local = gmx_omp_nthreads_get(emntNonbonded);
    }
    else
    {
        nthread_local = gmx_omp_nthreads_get(emntPME);
    }

    /* map the current process to cores */
    thread0_id_node = 0;
    nthread_node    = nthread_local;
#ifdef GMX_MPI
    if (PAR(cr) || MULTISIM(cr))
    {
        /* We need to determine a scan of the thread counts in this
         * compute node.
         */
        MPI_Comm comm_intra;

        MPI_Comm_split(MPI_COMM_WORLD,
                       gmx_physicalnode_id_hash(), cr->rank_intranode,
                       &comm_intra);
        MPI_Scan(&nthread_local, &thread0_id_node, 1, MPI_INT, MPI_SUM, comm_intra);
        /* MPI_Scan is inclusive, but here we need exclusive */
        thread0_id_node -= nthread_local;
        /* Get the total number of threads on this physical node */
        MPI_Allreduce(&nthread_local, &nthread_node, 1, MPI_INT, MPI_SUM, comm_intra);
        MPI_Comm_free(&comm_intra);
    }
#endif

    if (hw_opt->thread_affinity == threadaffAUTO &&
        nthread_node != hwinfo->nthreads_hw_avail)
    {
        if (nthread_node > 1 && nthread_node < hwinfo->nthreads_hw_avail)
        {
            md_print_warn(cr, fplog,
                          "NOTE: The number of threads is not equal to the number of (logical) cores\n"
                          "      and the -pin option is set to auto: will not pin thread to cores.\n"
                          "      This can lead to significant performance degradation.\n"
                          "      Consider using -pin on (and -pinoffset in case you run multiple jobs).\n");
        }

        return;
    }

    offset = 0;
    if (hw_opt->core_pinning_offset != 0)
    {
        offset = hw_opt->core_pinning_offset;
        md_print_info(cr, fplog, "Applying core pinning offset %d\n", offset);
    }

    rc = get_thread_affinity_layout(fplog, cr, hwinfo,
                                    nthread_node,
                                    offset, &hw_opt->core_pinning_stride,
                                    &locality_order);

    if (rc != 0)
    {
        /* Incompatible layout, don't pin, warning was already issued */
        return;
    }

    /* Set the per-thread affinity. In order to be able to check the success
     * of affinity settings, we will set nth_affinity_set to 1 on threads
     * where the affinity setting succeded and to 0 where it failed.
     * Reducing these 0/1 values over the threads will give the total number
     * of threads on which we succeeded.
     */
    nth_affinity_set = 0;
#pragma omp parallel num_threads(nthread_local) reduction(+:nth_affinity_set)
    {
        int      thread_id, thread_id_node;
        int      index, core;
        gmx_bool setaffinity_ret;

        thread_id      = gmx_omp_get_thread_num();
        thread_id_node = thread0_id_node + thread_id;
        index          = offset + thread_id_node*hw_opt->core_pinning_stride;
        if (locality_order != NULL)
        {
            core = locality_order[index];
        }
        else
        {
            core = index;
        }

        setaffinity_ret = tMPI_Thread_setaffinity_single(tMPI_Thread_self(), core);

        /* store the per-thread success-values of the setaffinity */
        nth_affinity_set = (setaffinity_ret == 0);

        if (debug)
        {
            fprintf(debug, "On rank %2d, thread %2d, index %2d, core %2d the affinity setting returned %d\n",
                    cr->nodeid, gmx_omp_get_thread_num(), index, core, setaffinity_ret);
        }
    }

    if (nth_affinity_set > nthread_local)
    {
        char msg[STRLEN];

        sprintf(msg, "Looks like we have set affinity for more threads than "
                "we have (%d > %d)!\n", nth_affinity_set, nthread_local);
        gmx_incons(msg);
    }
    else
    {
        /* check & warn if some threads failed to set their affinities */
        if (nth_affinity_set != nthread_local)
        {
            char sbuf1[STRLEN], sbuf2[STRLEN];

            /* sbuf1 contains rank info, while sbuf2 OpenMP thread info */
            sbuf1[0] = sbuf2[0] = '\0';
            /* Only add rank info if we have more than one rank. */
            if (cr->nnodes > 1)
            {
#ifdef GMX_MPI
#ifdef GMX_THREAD_MPI
                sprintf(sbuf1, "In tMPI thread #%d: ", cr->nodeid);
#else           /* GMX_LIB_MPI */
                sprintf(sbuf1, "In MPI process #%d: ", cr->nodeid);
#endif
#endif          /* GMX_MPI */
            }

            if (nthread_local > 1)
            {
                sprintf(sbuf2, "for %d/%d thread%s ",
                        nthread_local - nth_affinity_set, nthread_local,
                        nthread_local > 1 ? "s" : "");
            }

            md_print_warn(NULL, fplog,
                          "WARNING: %sAffinity setting %sfailed.\n"
                          "         This can cause performance degradation! If you think your setting are\n"
                          "         correct, contact the GROMACS developers.",
                          sbuf1, sbuf2);
        }
    }
    return;
}
Beispiel #8
0
bool constrain(FILE *fplog,bool bLog,bool bEner,
	       struct gmx_constr *constr,
	       t_idef *idef,t_inputrec *ir,
	       t_commrec *cr,
	       int step,int delta_step,
	       t_mdatoms *md,
	       rvec *x,rvec *xprime,rvec *min_proj,matrix box,
	       real lambda,real *dvdlambda,
	       rvec *v,tensor *vir,
	       t_nrnb *nrnb,int econq)
{
  bool    bOK;
  int     start,homenr;
  int     i,j;
  int     ncons,error;
  tensor  rmdr;
  real    invdt,vir_fac,t;
  t_ilist *settle;
  int     nsettle;
  real    mO,mH,dOH,dHH;
  t_pbc   pbc;

  if (econq == econqForce && !EI_ENERGY_MINIMIZATION(ir->eI))
    gmx_incons("constrain called for forces while not doing energy minimization, can not do this while the LINCS and SETTLE constraint connection matrices are mass weighted");

  bOK = TRUE;

  start  = md->start;
  homenr = md->homenr;
  if (ir->delta_t == 0)
    invdt = 0;
  else
    invdt  = 1/ir->delta_t;

  if (ir->efep != efepNO && EI_DYNAMICS(ir->eI)) {
    /* Set the constraint lengths for the step at which this configuration
     * is meant to be. The invmasses should not be changed.
     */
    lambda += delta_step*ir->delta_lambda;
  }

  if (vir != NULL)
    clear_mat(rmdr);
    
  where();
  if (constr->lincsd) {
    bOK = constrain_lincs(fplog,bLog,bEner,ir,step,constr->lincsd,md,cr->dd,
			  x,xprime,min_proj,box,lambda,dvdlambda,
			  invdt,v,vir!=NULL,rmdr,
			  econq,nrnb,
			  constr->maxwarn,&constr->warncount_lincs);
    if (!bOK && constr->maxwarn >= 0 && fplog)
      fprintf(fplog,"Constraint error in algorithm %s at step %d\n",
	      econstr_names[econtLINCS],step);
  }
  
  if (constr->nblocks > 0) {
    if (econq != econqCoord)
      gmx_fatal(FARGS,"Internal error, SHAKE called for constraining something else than coordinates");

    bOK = bshakef(fplog,homenr,md->invmass,constr->nblocks,constr->sblock,
		  idef,ir,box,x,xprime,nrnb,
		  constr->lagr,lambda,dvdlambda,
		  invdt,v,vir!=NULL,rmdr,constr->maxwarn>=0);
    if (!bOK && constr->maxwarn >= 0 && fplog)
      fprintf(fplog,"Constraint error in algorithm %s at step %d\n",
	      econstr_names[econtSHAKE],step);
  }
  
  settle  = &idef->il[F_SETTLE];
  if (settle->nr > 0) {
    nsettle = settle->nr/2;
    mO   = md->massT[settle->iatoms[1]];
    mH   = md->massT[settle->iatoms[1]+1];
    dOH  = idef->iparams[settle->iatoms[0]].settle.doh;
    dHH  = idef->iparams[settle->iatoms[0]].settle.dhh;

    switch (econq) {
    case econqCoord:
      csettle(fplog,nsettle,settle->iatoms,x[0],xprime[0],dOH,dHH,mO,mH,
	      invdt,v[0],vir!=NULL,rmdr,&error);
      inc_nrnb(nrnb,eNR_SETTLE,nsettle);
      if (v != NULL)
	inc_nrnb(nrnb,eNR_CONSTR_V,nsettle*3);
      if (vir != NULL)
	inc_nrnb(nrnb,eNR_CONSTR_VIR,nsettle*3);
    
      bOK = (error < 0);
      if (!bOK && constr->maxwarn >= 0) {
	char buf[256];
	sprintf(buf,
		"\nt = %.3f ps: Water molecule starting at atom %d can not be "
		"settled.\nCheck for bad contacts and/or reduce the timestep.\n",
		ir->init_t+step*ir->delta_t,
		ddglatnr(cr->dd,settle->iatoms[error*2+1]));
	if (fplog)
	  fprintf(fplog,"%s",buf);
	fprintf(stderr,"%s",buf);
	constr->warncount_settle++;
	if (constr->warncount_settle > constr->maxwarn)
	  too_many_constraint_warnings(-1,constr->warncount_settle);
	break;
      case econqVeloc:
      case econqDeriv:
      case econqForce:
	settle_proj(fplog,nsettle,settle->iatoms,x,dOH,dHH,
		    md->invmass[settle->iatoms[1]],
		    md->invmass[settle->iatoms[1]+1],
		    xprime,min_proj,vir!=NULL,rmdr);

	/* This is an overestimate */
	inc_nrnb(nrnb,eNR_SETTLE,nsettle);
	break;
      case econqDeriv_FlexCon:
	/* Nothing to do, since the are no flexible constraints in settles */
	break;
      default:
	gmx_incons("Unknown constraint quantity for settle");
      }
    }
  }

  if (vir != NULL) {
    switch (econq) {
    case econqCoord:
      vir_fac = 0.5/(ir->delta_t*ir->delta_t);
      break;
    case econqVeloc:
      /* Assume that these are velocities */
      vir_fac = 0.5/ir->delta_t;
      break;
    case econqForce:
      vir_fac = 0.5;
      break;
    default:
      vir_fac = 0;
      gmx_incons("Unsupported constraint quantity for virial");
    }
    for(i=0; i<DIM; i++)
      for(j=0; j<DIM; j++)
	(*vir)[i][j] = vir_fac*rmdr[i][j];
  }

  if (!bOK && constr->maxwarn >= 0) 
    dump_confs(fplog,step,constr->warn_mtop,start,homenr,cr,x,xprime,box);

  if (econq == econqCoord) {
      if (ir->ePull == epullCONSTRAINT) {
        if (EI_DYNAMICS(ir->eI)) {
              t = ir->init_t + (step + delta_step)*ir->delta_t;
          } else {
              t = ir->init_t;
          }
          set_pbc(&pbc,ir->ePBC,box);
          pull_constraint(ir->pull,md,&pbc,cr,ir->delta_t,t,x,xprime,v,*vir);
      }
      if (constr->ed && delta_step > 0) {
        /* apply the essential dynamcs constraints here */
        do_edsam(ir,step,md,cr,xprime,v,box,constr->ed);
      }
  }
  
  return bOK;
}
Beispiel #9
0
static void update_topol(char *topinout,int p_num,int n_num,
			 const char *p_name,const char *n_name,char *grpname)
{
#define TEMP_FILENM "temp.top"
  FILE *fpin,*fpout;
  char  buf[STRLEN],buf2[STRLEN],*temp;
  int  line,i,nsol;
  bool bMolecules;
  
  printf("\nProcessing topology\n");
  fpin = ffopen(topinout,"r");
  fpout= ffopen(TEMP_FILENM,"w");
  
  line=0;
  bMolecules = FALSE;
  while (fgets(buf, STRLEN, fpin)) {
    line++;
    strcpy(buf2,buf);
    if ((temp=strchr(buf2,'\n')) != NULL)
      temp[0]='\0';
    ltrim(buf2);
    if (buf2[0]=='[') {
      buf2[0]=' ';
      if ((temp=strchr(buf2,'\n')) != NULL)
	temp[0]='\0';
      rtrim(buf2);
      if (buf2[strlen(buf2)-1]==']') {
	buf2[strlen(buf2)-1]='\0';
	ltrim(buf2);
	rtrim(buf2);
	bMolecules=(strcasecmp(buf2,"molecules")==0);
      }
    } 
    if (bMolecules) {
      /* check if this is a line with solvent molecules */
      sscanf(buf,"%s",buf2);
      if (strcasecmp(buf2,grpname)==0) {
	sscanf(buf,"%*s %d",&i);
	nsol = i-p_num-n_num;
	if (nsol < 0) 
	  gmx_incons("Not enough water");
	else {
	  printf("Replacing %d solute molecules in topology file (%s) "
		 " by %d %s and %d %s ions.\n",
		 nsol,topinout,p_num,p_name,n_num,n_name);
	  fprintf(fpout,"%-10s  %d\n",grpname,nsol);  
	  fprintf(fpout,"%-10s  %d\n",p_name,p_num);  
	  fprintf(fpout,"%-10s  %d\n",n_name,n_num);  
	}
      } else
	fprintf(fpout,"%s",buf);
    } else
      fprintf(fpout,"%s",buf);
  }
  fclose(fpin);
  fclose(fpout);
  /* use ffopen to generate backup of topinout */
  fpout=ffopen(topinout,"w");
  fclose(fpout);
  rename(TEMP_FILENM,topinout);
#undef TEMP_FILENM
}
Beispiel #10
0
static void fill_ang(int nft, int *ft, int fac,
                     int nr[], int *index[], int ft_ind[], t_topology *top,
                     gmx_bool bNoH, real hq)
{
    int         f, ftype, i, j, indg, nr_fac;
    gmx_bool    bUse;
    t_idef     *idef;
    t_atom     *atom;
    t_iatom    *ia;


    idef = &top->idef;
    atom = top->atoms.atom;

    for (f = 0; f < nft; f++)
    {
        ftype = ft[f];
        ia    = idef->il[ftype].iatoms;
        for (i = 0; (i < idef->il[ftype].nr); )
        {
            indg = ft_ind[ia[0]];
            if (indg == -1)
            {
                gmx_incons("Routine fill_ang");
            }
            bUse = TRUE;
            if (bNoH)
            {
                for (j = 0; j < fac; j++)
                {
                    if (atom[ia[1+j]].m < 1.5)
                    {
                        bUse = FALSE;
                    }
                }
            }
            if (hq)
            {
                for (j = 0; j < fac; j++)
                {
                    if (atom[ia[1+j]].m < 1.5 && fabs(atom[ia[1+j]].q) < hq)
                    {
                        bUse = FALSE;
                    }
                }
            }
            if (bUse)
            {
                if (nr[indg] % 1000 == 0)
                {
                    srenew(index[indg], fac*(nr[indg]+1000));
                }
                nr_fac = fac*nr[indg];
                for (j = 0; (j < fac); j++)
                {
                    index[indg][nr_fac+j] = ia[j+1];
                }
                nr[indg]++;
            }
            ia += interaction_function[ftype].nratoms+1;
            i  += interaction_function[ftype].nratoms+1;
        }
    }
}
Beispiel #11
0
int gmx_pme_recv_coeffs_coords(struct gmx_pme_pp *pme_pp,
                               int               *natoms,
                               real             **chargeA,
                               real             **chargeB,
                               real             **sqrt_c6A,
                               real             **sqrt_c6B,
                               real             **sigmaA,
                               real             **sigmaB,
                               matrix             box,
                               rvec             **x,
                               rvec             **f,
                               int               *maxshift_x,
                               int               *maxshift_y,
                               gmx_bool          *bFreeEnergy_q,
                               gmx_bool          *bFreeEnergy_lj,
                               real              *lambda_q,
                               real              *lambda_lj,
                               gmx_bool          *bEnerVir,
                               int               *pme_flags,
                               gmx_int64_t       *step,
                               ivec               grid_size,
                               real              *ewaldcoeff_q,
                               real              *ewaldcoeff_lj)
{
    int                  nat = 0, status;

    *pme_flags = 0;
#if GMX_MPI
    gmx_pme_comm_n_box_t cnb;
    int                  messages;

    cnb.flags  = 0;
    messages   = 0;
    do
    {

        /* Receive the send count, box and time step from the peer PP node */
        MPI_Recv(&cnb, sizeof(cnb), MPI_BYTE,
                 pme_pp->node_peer, eCommType_CNB,
                 pme_pp->mpi_comm_mysim, MPI_STATUS_IGNORE);

        if (debug)
        {
            fprintf(debug, "PME only rank receiving:%s%s%s%s%s\n",
                    (cnb.flags & PP_PME_CHARGE)        ? " charges" : "",
                    (cnb.flags & PP_PME_COORD )        ? " coordinates" : "",
                    (cnb.flags & PP_PME_FINISH)        ? " finish" : "",
                    (cnb.flags & PP_PME_SWITCHGRID)    ? " switch grid" : "",
                    (cnb.flags & PP_PME_RESETCOUNTERS) ? " reset counters" : "");
        }

        if (cnb.flags & PP_PME_SWITCHGRID)
        {
            /* Special case, receive the new parameters and return */
            copy_ivec(cnb.grid_size, grid_size);
            *ewaldcoeff_q  = cnb.ewaldcoeff_q;
            *ewaldcoeff_lj = cnb.ewaldcoeff_lj;
            return pmerecvqxSWITCHGRID;
        }

        if (cnb.flags & PP_PME_RESETCOUNTERS)
        {
            /* Special case, receive the step and return */
            *step = cnb.step;

            return pmerecvqxRESETCOUNTERS;
        }

        if (cnb.flags & (PP_PME_CHARGE | PP_PME_SQRTC6 | PP_PME_SIGMA))
        {
            /* Receive the send counts from the other PP nodes */
            for (int sender = 0; sender < pme_pp->nnode; sender++)
            {
                if (pme_pp->node[sender] == pme_pp->node_peer)
                {
                    pme_pp->nat[sender] = cnb.natoms;
                }
                else
                {
                    MPI_Irecv(&(pme_pp->nat[sender]), sizeof(pme_pp->nat[0]),
                              MPI_BYTE,
                              pme_pp->node[sender], eCommType_CNB,
                              pme_pp->mpi_comm_mysim, &pme_pp->req[messages++]);
                }
            }
            MPI_Waitall(messages, pme_pp->req, pme_pp->stat);
            messages = 0;

            nat = 0;
            for (int sender = 0; sender < pme_pp->nnode; sender++)
            {
                nat += pme_pp->nat[sender];
            }

            if (nat > pme_pp->nalloc)
            {
                pme_pp->nalloc = over_alloc_dd(nat);
                if (cnb.flags & PP_PME_CHARGE)
                {
                    srenew(pme_pp->chargeA, pme_pp->nalloc);
                }
                if (cnb.flags & PP_PME_CHARGEB)
                {
                    srenew(pme_pp->chargeB, pme_pp->nalloc);
                }
                if (cnb.flags & PP_PME_SQRTC6)
                {
                    srenew(pme_pp->sqrt_c6A, pme_pp->nalloc);
                }
                if (cnb.flags & PP_PME_SQRTC6B)
                {
                    srenew(pme_pp->sqrt_c6B, pme_pp->nalloc);
                }
                if (cnb.flags & PP_PME_SIGMA)
                {
                    srenew(pme_pp->sigmaA, pme_pp->nalloc);
                }
                if (cnb.flags & PP_PME_SIGMAB)
                {
                    srenew(pme_pp->sigmaB, pme_pp->nalloc);
                }
                srenew(pme_pp->x, pme_pp->nalloc);
                srenew(pme_pp->f, pme_pp->nalloc);
            }

            /* maxshift is sent when the charges are sent */
            *maxshift_x = cnb.maxshift_x;
            *maxshift_y = cnb.maxshift_y;

            /* Receive the charges in place */
            for (int q = 0; q < eCommType_NR; q++)
            {
                real *charge_pp;

                if (!(cnb.flags & (PP_PME_CHARGE<<q)))
                {
                    continue;
                }
                switch (q)
                {
                    case eCommType_ChargeA: charge_pp = pme_pp->chargeA;  break;
                    case eCommType_ChargeB: charge_pp = pme_pp->chargeB;  break;
                    case eCommType_SQRTC6A: charge_pp = pme_pp->sqrt_c6A; break;
                    case eCommType_SQRTC6B: charge_pp = pme_pp->sqrt_c6B; break;
                    case eCommType_SigmaA:  charge_pp = pme_pp->sigmaA;   break;
                    case eCommType_SigmaB:  charge_pp = pme_pp->sigmaB;   break;
                    default: gmx_incons("Wrong eCommType");
                }
                nat = 0;
                for (int sender = 0; sender < pme_pp->nnode; sender++)
                {
                    if (pme_pp->nat[sender] > 0)
                    {
                        MPI_Irecv(charge_pp+nat,
                                  pme_pp->nat[sender]*sizeof(real),
                                  MPI_BYTE,
                                  pme_pp->node[sender], q,
                                  pme_pp->mpi_comm_mysim,
                                  &pme_pp->req[messages++]);
                        nat += pme_pp->nat[sender];
                        if (debug)
                        {
                            fprintf(debug, "Received from PP rank %d: %d %s\n",
                                    pme_pp->node[sender], pme_pp->nat[sender],
                                    (q == eCommType_ChargeA ||
                                     q == eCommType_ChargeB) ? "charges" : "params");
                        }
                    }
                }
            }

            pme_pp->flags_charge = cnb.flags;
        }

        if (cnb.flags & PP_PME_COORD)
        {
            if (!(pme_pp->flags_charge & (PP_PME_CHARGE | PP_PME_SQRTC6)))
            {
                gmx_incons("PME-only rank received coordinates before charges and/or C6-values"
                           );
            }

            /* The box, FE flag and lambda are sent along with the coordinates
             *  */
            copy_mat(cnb.box, box);
            *bFreeEnergy_q  = ((cnb.flags & GMX_PME_DO_COULOMB) &&
                               (cnb.flags & PP_PME_FEP_Q));
            *bFreeEnergy_lj = ((cnb.flags & GMX_PME_DO_LJ) &&
                               (cnb.flags & PP_PME_FEP_LJ));
            *lambda_q       = cnb.lambda_q;
            *lambda_lj      = cnb.lambda_lj;
            *bEnerVir       = (cnb.flags & PP_PME_ENER_VIR);
            *pme_flags      = cnb.flags;

            if (*bFreeEnergy_q && !(pme_pp->flags_charge & PP_PME_CHARGEB))
            {
                gmx_incons("PME-only rank received free energy request, but "
                           "did not receive B-state charges");
            }

            if (*bFreeEnergy_lj && !(pme_pp->flags_charge & PP_PME_SQRTC6B))
            {
                gmx_incons("PME-only rank received free energy request, but "
                           "did not receive B-state C6-values");
            }

            /* Receive the coordinates in place */
            nat = 0;
            for (int sender = 0; sender < pme_pp->nnode; sender++)
            {
                if (pme_pp->nat[sender] > 0)
                {
                    MPI_Irecv(pme_pp->x[nat], pme_pp->nat[sender]*sizeof(rvec),
                              MPI_BYTE,
                              pme_pp->node[sender], eCommType_COORD,
                              pme_pp->mpi_comm_mysim, &pme_pp->req[messages++]);
                    nat += pme_pp->nat[sender];
                    if (debug)
                    {
                        fprintf(debug, "Received from PP rank %d: %d "
                                "coordinates\n",
                                pme_pp->node[sender], pme_pp->nat[sender]);
                    }
                }
            }
        }

        /* Wait for the coordinates and/or charges to arrive */
        MPI_Waitall(messages, pme_pp->req, pme_pp->stat);
        messages = 0;
    }
    while (!(cnb.flags & (PP_PME_COORD | PP_PME_FINISH)));
    status = ((cnb.flags & PP_PME_FINISH) ? pmerecvqxFINISH : pmerecvqxX);

    *step = cnb.step;
#else
    GMX_UNUSED_VALUE(box);
    GMX_UNUSED_VALUE(maxshift_x);
    GMX_UNUSED_VALUE(maxshift_y);
    GMX_UNUSED_VALUE(bFreeEnergy_q);
    GMX_UNUSED_VALUE(bFreeEnergy_lj);
    GMX_UNUSED_VALUE(lambda_q);
    GMX_UNUSED_VALUE(lambda_lj);
    GMX_UNUSED_VALUE(bEnerVir);
    GMX_UNUSED_VALUE(step);
    GMX_UNUSED_VALUE(grid_size);
    GMX_UNUSED_VALUE(ewaldcoeff_q);
    GMX_UNUSED_VALUE(ewaldcoeff_lj);

    status = pmerecvqxX;
#endif

    *natoms   = nat;
    *chargeA  = pme_pp->chargeA;
    *chargeB  = pme_pp->chargeB;
    *sqrt_c6A = pme_pp->sqrt_c6A;
    *sqrt_c6B = pme_pp->sqrt_c6B;
    *sigmaA   = pme_pp->sigmaA;
    *sigmaB   = pme_pp->sigmaB;
    *x        = pme_pp->x;
    *f        = pme_pp->f;

    return status;
}
//! This function is documented in the header file
void nbnxn_gpu_init_pairlist(gmx_nbnxn_ocl_t        *nb,
                             const nbnxn_pairlist_t *h_plist,
                             int                     iloc)
{
    char             sbuf[STRLEN];
    // Timing accumulation should happen only if there was work to do
    // because getLastRangeTime() gets skipped with empty lists later
    // which leads to the counter not being reset.
    bool             bDoTime    = ((nb->bDoTime == CL_TRUE) && h_plist->nsci > 0);
    cl_command_queue stream     = nb->stream[iloc];
    cl_plist_t      *d_plist    = nb->plist[iloc];

    if (d_plist->na_c < 0)
    {
        d_plist->na_c = h_plist->na_ci;
    }
    else
    {
        if (d_plist->na_c != h_plist->na_ci)
        {
            sprintf(sbuf, "In cu_init_plist: the #atoms per cell has changed (from %d to %d)",
                    d_plist->na_c, h_plist->na_ci);
            gmx_incons(sbuf);
        }
    }

    if (bDoTime)
    {
        nb->timers->pl_h2d[iloc].openTimingRegion(stream);
        nb->timers->didPairlistH2D[iloc] = true;
    }

    // TODO most of this function is same in CUDA and OpenCL, move into the header
    Context context = nb->dev_rundata->context;

    reallocateDeviceBuffer(&d_plist->sci, h_plist->nsci,
                           &d_plist->nsci, &d_plist->sci_nalloc, context);
    copyToDeviceBuffer(&d_plist->sci, h_plist->sci, 0, h_plist->nsci,
                       stream, GpuApiCallBehavior::Async,
                       bDoTime ? nb->timers->pl_h2d[iloc].fetchNextEvent() : nullptr);

    reallocateDeviceBuffer(&d_plist->cj4, h_plist->ncj4,
                           &d_plist->ncj4, &d_plist->cj4_nalloc, context);
    copyToDeviceBuffer(&d_plist->cj4, h_plist->cj4, 0, h_plist->ncj4,
                       stream, GpuApiCallBehavior::Async,
                       bDoTime ? nb->timers->pl_h2d[iloc].fetchNextEvent() : nullptr);

    reallocateDeviceBuffer(&d_plist->imask, h_plist->ncj4*c_nbnxnGpuClusterpairSplit,
                           &d_plist->nimask, &d_plist->imask_nalloc, context);

    reallocateDeviceBuffer(&d_plist->excl, h_plist->nexcl,
                           &d_plist->nexcl, &d_plist->excl_nalloc, context);
    copyToDeviceBuffer(&d_plist->excl, h_plist->excl, 0, h_plist->nexcl,
                       stream, GpuApiCallBehavior::Async,
                       bDoTime ? nb->timers->pl_h2d[iloc].fetchNextEvent() : nullptr);

    if (bDoTime)
    {
        nb->timers->pl_h2d[iloc].closeTimingRegion(stream);
    }

    /* need to prune the pair list during the next step */
    d_plist->haveFreshList = true;
}
/*! \brief Returns the kinds of electrostatics and Vdw OpenCL
 *  kernels that will be used.
 *
 * Respectively, these values are from enum eelOcl and enum
 * evdwOcl. */
static void
map_interaction_types_to_gpu_kernel_flavors(const interaction_const_t *ic,
                                            int                        combRule,
                                            int                       *gpu_eeltype,
                                            int                       *gpu_vdwtype)
{
    if (ic->vdwtype == evdwCUT)
    {
        switch (ic->vdw_modifier)
        {
            case eintmodNONE:
            case eintmodPOTSHIFT:
                switch (combRule)
                {
                    case ljcrNONE:
                        *gpu_vdwtype = evdwOclCUT;
                        break;
                    case ljcrGEOM:
                        *gpu_vdwtype = evdwOclCUTCOMBGEOM;
                        break;
                    case ljcrLB:
                        *gpu_vdwtype = evdwOclCUTCOMBLB;
                        break;
                    default:
                        gmx_incons("The requested LJ combination rule is not implemented in the OpenCL GPU accelerated kernels!");
                }
                break;
            case eintmodFORCESWITCH:
                *gpu_vdwtype = evdwOclFSWITCH;
                break;
            case eintmodPOTSWITCH:
                *gpu_vdwtype = evdwOclPSWITCH;
                break;
            default:
                gmx_incons("The requested VdW interaction modifier is not implemented in the GPU accelerated kernels!");
        }
    }
    else if (ic->vdwtype == evdwPME)
    {
        if (ic->ljpme_comb_rule == ljcrGEOM)
        {
            *gpu_vdwtype = evdwOclEWALDGEOM;
        }
        else
        {
            *gpu_vdwtype = evdwOclEWALDLB;
        }
    }
    else
    {
        gmx_incons("The requested VdW type is not implemented in the GPU accelerated kernels!");
    }

    if (ic->eeltype == eelCUT)
    {
        *gpu_eeltype = eelOclCUT;
    }
    else if (EEL_RF(ic->eeltype))
    {
        *gpu_eeltype = eelOclRF;
    }
    else if ((EEL_PME(ic->eeltype) || ic->eeltype == eelEWALD))
    {
        /* Initially rcoulomb == rvdw, so it's surely not twin cut-off. */
        *gpu_eeltype = nbnxn_gpu_pick_ewald_kernel_type(false);
    }
    else
    {
        /* Shouldn't happen, as this is checked when choosing Verlet-scheme */
        gmx_incons("The requested electrostatics type is not implemented in the GPU accelerated kernels!");
    }
}
Beispiel #14
0
void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                       t_forcerec *fr,      t_inputrec *ir,
                       t_idef     *idef,    t_commrec  *cr,
                       t_nrnb     *nrnb,    gmx_wallcycle_t wcycle,
                       t_mdatoms  *md,
                       t_grpopts  *opts,
                       rvec       x[],      history_t  *hist,
                       rvec       f[],
                       rvec       f_longrange[],
                       gmx_enerdata_t *enerd,
                       t_fcdata   *fcd,
                       gmx_mtop_t     *mtop,
                       gmx_localtop_t *top,
                       gmx_genborn_t *born,
                       t_atomtypes *atype,
                       gmx_bool       bBornRadii,
                       matrix     box,
                       t_lambda   *fepvals,
                       real       *lambda,
                       t_graph    *graph,
                       t_blocka   *excl,
                       rvec       mu_tot[],
                       int        flags,
                       float      *cycles_pme)
{
    int         i, j, status;
    int         donb_flags;
    gmx_bool    bDoEpot, bSepDVDL, bSB;
    int         pme_flags;
    matrix      boxs;
    rvec        box_size;
    real        Vsr, Vlr, Vcorr = 0;
    t_pbc       pbc;
    real        dvdgb;
    char        buf[22];
    double      clam_i, vlam_i;
    real        dvdl_dum[efptNR], dvdl, dvdl_nb[efptNR], lam_i[efptNR];
    real        dvdlsum;

#ifdef GMX_MPI
    double  t0 = 0.0, t1, t2, t3; /* time measurement for coarse load balancing */
#endif

#define PRINT_SEPDVDL(s, v, dvdlambda) if (bSepDVDL) {fprintf(fplog, sepdvdlformat, s, v, dvdlambda); }

    GMX_MPE_LOG(ev_force_start);
    set_pbc(&pbc, fr->ePBC, box);

    /* reset free energy components */
    for (i = 0; i < efptNR; i++)
    {
        dvdl_nb[i]  = 0;
        dvdl_dum[i] = 0;
    }

    /* Reset box */
    for (i = 0; (i < DIM); i++)
    {
        box_size[i] = box[i][i];
    }

    bSepDVDL = (fr->bSepDVDL && do_per_step(step, ir->nstlog));
    debug_gmx();

    /* do QMMM first if requested */
    if (fr->bQMMM)
    {
        enerd->term[F_EQM] = calculate_QMMM(cr, x, f, fr, md);
    }

    if (bSepDVDL)
    {
        fprintf(fplog, "Step %s: non-bonded V and dVdl for node %d:\n",
                gmx_step_str(step, buf), cr->nodeid);
    }

    /* Call the short range functions all in one go. */
    GMX_MPE_LOG(ev_do_fnbf_start);

#ifdef GMX_MPI
    /*#define TAKETIME ((cr->npmenodes) && (fr->timesteps < 12))*/
#define TAKETIME FALSE
    if (TAKETIME)
    {
        MPI_Barrier(cr->mpi_comm_mygroup);
        t0 = MPI_Wtime();
    }
#endif

    if (ir->nwall)
    {
        /* foreign lambda component for walls */
        dvdl = do_walls(ir, fr, box, md, x, f, lambda[efptVDW],
                        enerd->grpp.ener[egLJSR], nrnb);
        PRINT_SEPDVDL("Walls", 0.0, dvdl);
        enerd->dvdl_lin[efptVDW] += dvdl;
    }

    /* If doing GB, reset dvda and calculate the Born radii */
    if (ir->implicit_solvent)
    {
        wallcycle_sub_start(wcycle, ewcsNONBONDED);

        for (i = 0; i < born->nr; i++)
        {
            fr->dvda[i] = 0;
        }

        if (bBornRadii)
        {
            calc_gb_rad(cr, fr, ir, top, atype, x, &(fr->gblist), born, md, nrnb);
        }

        wallcycle_sub_stop(wcycle, ewcsNONBONDED);
    }

    where();
    /* We only do non-bonded calculation with group scheme here, the verlet
     * calls are done from do_force_cutsVERLET(). */
    if (fr->cutoff_scheme == ecutsGROUP && (flags & GMX_FORCE_NONBONDED))
    {
        donb_flags = 0;
        /* Add short-range interactions */
        donb_flags |= GMX_NONBONDED_DO_SR;

        if (flags & GMX_FORCE_FORCES)
        {
            donb_flags |= GMX_NONBONDED_DO_FORCE;
        }
        if (flags & GMX_FORCE_ENERGY)
        {
            donb_flags |= GMX_NONBONDED_DO_POTENTIAL;
        }
        if (flags & GMX_FORCE_DO_LR)
        {
            donb_flags |= GMX_NONBONDED_DO_LR;
        }

        wallcycle_sub_start(wcycle, ewcsNONBONDED);
        do_nonbonded(cr, fr, x, f, f_longrange, md, excl,
                     &enerd->grpp, box_size, nrnb,
                     lambda, dvdl_nb, -1, -1, donb_flags);

        /* If we do foreign lambda and we have soft-core interactions
         * we have to recalculate the (non-linear) energies contributions.
         */
        if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) && fepvals->sc_alpha != 0)
        {
            for (i = 0; i < enerd->n_lambda; i++)
            {
                for (j = 0; j < efptNR; j++)
                {
                    lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]);
                }
                reset_foreign_enerdata(enerd);
                do_nonbonded(cr, fr, x, f, f_longrange, md, excl,
                             &(enerd->foreign_grpp), box_size, nrnb,
                             lam_i, dvdl_dum, -1, -1,
                             (donb_flags & ~GMX_NONBONDED_DO_FORCE) | GMX_NONBONDED_DO_FOREIGNLAMBDA);
                sum_epot(&ir->opts, &(enerd->foreign_grpp), enerd->foreign_term);
                enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT];
            }
        }
        wallcycle_sub_stop(wcycle, ewcsNONBONDED);
        where();
    }

    /* If we are doing GB, calculate bonded forces and apply corrections
     * to the solvation forces */
    /* MRS: Eventually, many need to include free energy contribution here! */
    if (ir->implicit_solvent)
    {
        wallcycle_sub_start(wcycle, ewcsBONDED);
        calc_gb_forces(cr, md, born, top, atype, x, f, fr, idef,
                       ir->gb_algorithm, ir->sa_algorithm, nrnb, bBornRadii, &pbc, graph, enerd);
        wallcycle_sub_stop(wcycle, ewcsBONDED);
    }

#ifdef GMX_MPI
    if (TAKETIME)
    {
        t1          = MPI_Wtime();
        fr->t_fnbf += t1-t0;
    }
#endif

    if (fepvals->sc_alpha != 0)
    {
        enerd->dvdl_nonlin[efptVDW] += dvdl_nb[efptVDW];
    }
    else
    {
        enerd->dvdl_lin[efptVDW] += dvdl_nb[efptVDW];
    }

    if (fepvals->sc_alpha != 0)

    /* even though coulomb part is linear, we already added it, beacuse we
       need to go through the vdw calculation anyway */
    {
        enerd->dvdl_nonlin[efptCOUL] += dvdl_nb[efptCOUL];
    }
    else
    {
        enerd->dvdl_lin[efptCOUL] += dvdl_nb[efptCOUL];
    }

    Vsr = 0;
    if (bSepDVDL)
    {
        for (i = 0; i < enerd->grpp.nener; i++)
        {
            Vsr +=
                (fr->bBHAM ?
                 enerd->grpp.ener[egBHAMSR][i] :
                 enerd->grpp.ener[egLJSR][i])
                + enerd->grpp.ener[egCOULSR][i] + enerd->grpp.ener[egGB][i];
        }
        dvdlsum = dvdl_nb[efptVDW] + dvdl_nb[efptCOUL];
        PRINT_SEPDVDL("VdW and Coulomb SR particle-p.", Vsr, dvdlsum);
    }
    debug_gmx();

    GMX_MPE_LOG(ev_do_fnbf_finish);

    if (debug)
    {
        pr_rvecs(debug, 0, "fshift after SR", fr->fshift, SHIFTS);
    }

    /* Shift the coordinates. Must be done before bonded forces and PPPM,
     * but is also necessary for SHAKE and update, therefore it can NOT
     * go when no bonded forces have to be evaluated.
     */

    /* Here sometimes we would not need to shift with NBFonly,
     * but we do so anyhow for consistency of the returned coordinates.
     */
    if (graph)
    {
        shift_self(graph, box, x);
        if (TRICLINIC(box))
        {
            inc_nrnb(nrnb, eNR_SHIFTX, 2*graph->nnodes);
        }
        else
        {
            inc_nrnb(nrnb, eNR_SHIFTX, graph->nnodes);
        }
    }
    /* Check whether we need to do bondeds or correct for exclusions */
    if (fr->bMolPBC &&
        ((flags & GMX_FORCE_BONDED)
         || EEL_RF(fr->eeltype) || EEL_FULL(fr->eeltype)))
    {
        /* Since all atoms are in the rectangular or triclinic unit-cell,
         * only single box vector shifts (2 in x) are required.
         */
        set_pbc_dd(&pbc, fr->ePBC, cr->dd, TRUE, box);
    }
    debug_gmx();

    if (flags & GMX_FORCE_BONDED)
    {
        GMX_MPE_LOG(ev_calc_bonds_start);

        wallcycle_sub_start(wcycle, ewcsBONDED);
        calc_bonds(fplog, cr->ms,
                   idef, x, hist, f, fr, &pbc, graph, enerd, nrnb, lambda, md, fcd,
                   DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL, atype, born,
                   flags,
                   fr->bSepDVDL && do_per_step(step, ir->nstlog), step);

        /* Check if we have to determine energy differences
         * at foreign lambda's.
         */
        if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL) &&
            idef->ilsort != ilsortNO_FE)
        {
            if (idef->ilsort != ilsortFE_SORTED)
            {
                gmx_incons("The bonded interactions are not sorted for free energy");
            }
            for (i = 0; i < enerd->n_lambda; i++)
            {
                reset_foreign_enerdata(enerd);
                for (j = 0; j < efptNR; j++)
                {
                    lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]);
                }
                calc_bonds_lambda(fplog, idef, x, fr, &pbc, graph, &(enerd->foreign_grpp), enerd->foreign_term, nrnb, lam_i, md,
                                  fcd, DOMAINDECOMP(cr) ? cr->dd->gatindex : NULL);
                sum_epot(&ir->opts, &(enerd->foreign_grpp), enerd->foreign_term);
                enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT];
            }
        }
        debug_gmx();
        GMX_MPE_LOG(ev_calc_bonds_finish);
        wallcycle_sub_stop(wcycle, ewcsBONDED);
    }

    where();

    *cycles_pme = 0;
    if (EEL_FULL(fr->eeltype))
    {
        bSB = (ir->nwall == 2);
        if (bSB)
        {
            copy_mat(box, boxs);
            svmul(ir->wall_ewald_zfac, boxs[ZZ], boxs[ZZ]);
            box_size[ZZ] *= ir->wall_ewald_zfac;
        }

        clear_mat(fr->vir_el_recip);

        if (fr->bEwald)
        {
            Vcorr = 0;
            dvdl  = 0;

            /* With the Verlet scheme exclusion forces are calculated
             * in the non-bonded kernel.
             */
            /* The TPI molecule does not have exclusions with the rest
             * of the system and no intra-molecular PME grid contributions
             * will be calculated in gmx_pme_calc_energy.
             */
            if ((ir->cutoff_scheme == ecutsGROUP && fr->n_tpi == 0) ||
                ir->ewald_geometry != eewg3D ||
                ir->epsilon_surface != 0)
            {
                int nthreads, t;

                wallcycle_sub_start(wcycle, ewcsEWALD_CORRECTION);

                if (fr->n_tpi > 0)
                {
                    gmx_fatal(FARGS, "TPI with PME currently only works in a 3D geometry with tin-foil boundary conditions");
                }

                nthreads = gmx_omp_nthreads_get(emntBonded);
#pragma omp parallel for num_threads(nthreads) schedule(static)
                for (t = 0; t < nthreads; t++)
                {
                    int     s, e, i;
                    rvec   *fnv;
                    tensor *vir;
                    real   *Vcorrt, *dvdlt;
                    if (t == 0)
                    {
                        fnv    = fr->f_novirsum;
                        vir    = &fr->vir_el_recip;
                        Vcorrt = &Vcorr;
                        dvdlt  = &dvdl;
                    }
                    else
                    {
                        fnv    = fr->f_t[t].f;
                        vir    = &fr->f_t[t].vir;
                        Vcorrt = &fr->f_t[t].Vcorr;
                        dvdlt  = &fr->f_t[t].dvdl[efptCOUL];
                        for (i = 0; i < fr->natoms_force; i++)
                        {
                            clear_rvec(fnv[i]);
                        }
                        clear_mat(*vir);
                    }
                    *dvdlt  = 0;
                    *Vcorrt =
                        ewald_LRcorrection(fplog,
                                           fr->excl_load[t], fr->excl_load[t+1],
                                           cr, t, fr,
                                           md->chargeA,
                                           md->nChargePerturbed ? md->chargeB : NULL,
                                           ir->cutoff_scheme != ecutsVERLET,
                                           excl, x, bSB ? boxs : box, mu_tot,
                                           ir->ewald_geometry,
                                           ir->epsilon_surface,
                                           fnv, *vir,
                                           lambda[efptCOUL], dvdlt);
                }
                if (nthreads > 1)
                {
                    reduce_thread_forces(fr->natoms_force, fr->f_novirsum,
                                         fr->vir_el_recip,
                                         &Vcorr, efptCOUL, &dvdl,
                                         nthreads, fr->f_t);
                }

                wallcycle_sub_stop(wcycle, ewcsEWALD_CORRECTION);
            }

            if (fr->n_tpi == 0)
            {
                Vcorr += ewald_charge_correction(cr, fr, lambda[efptCOUL], box,
                                                 &dvdl, fr->vir_el_recip);
            }

            PRINT_SEPDVDL("Ewald excl./charge/dip. corr.", Vcorr, dvdl);
            enerd->dvdl_lin[efptCOUL] += dvdl;
        }

        status = 0;
        Vlr    = 0;
        dvdl   = 0;
        switch (fr->eeltype)
        {
            case eelPME:
            case eelPMESWITCH:
            case eelPMEUSER:
            case eelPMEUSERSWITCH:
            case eelP3M_AD:
                if (cr->duty & DUTY_PME)
                {
                    assert(fr->n_tpi >= 0);
                    if (fr->n_tpi == 0 || (flags & GMX_FORCE_STATECHANGED))
                    {
                        pme_flags = GMX_PME_SPREAD_Q | GMX_PME_SOLVE;
                        if (flags & GMX_FORCE_FORCES)
                        {
                            pme_flags |= GMX_PME_CALC_F;
                        }
                        if (flags & (GMX_FORCE_VIRIAL | GMX_FORCE_ENERGY))
                        {
                            pme_flags |= GMX_PME_CALC_ENER_VIR;
                        }
                        if (fr->n_tpi > 0)
                        {
                            /* We don't calculate f, but we do want the potential */
                            pme_flags |= GMX_PME_CALC_POT;
                        }
                        wallcycle_start(wcycle, ewcPMEMESH);
                        status = gmx_pme_do(fr->pmedata,
                                            md->start, md->homenr - fr->n_tpi,
                                            x, fr->f_novirsum,
                                            md->chargeA, md->chargeB,
                                            bSB ? boxs : box, cr,
                                            DOMAINDECOMP(cr) ? dd_pme_maxshift_x(cr->dd) : 0,
                                            DOMAINDECOMP(cr) ? dd_pme_maxshift_y(cr->dd) : 0,
                                            nrnb, wcycle,
                                            fr->vir_el_recip, fr->ewaldcoeff,
                                            &Vlr, lambda[efptCOUL], &dvdl,
                                            pme_flags);
                        *cycles_pme = wallcycle_stop(wcycle, ewcPMEMESH);

                        /* We should try to do as little computation after
                         * this as possible, because parallel PME synchronizes
                         * the nodes, so we want all load imbalance of the rest
                         * of the force calculation to be before the PME call.
                         * DD load balancing is done on the whole time of
                         * the force call (without PME).
                         */
                    }
                    if (fr->n_tpi > 0)
                    {
                        /* Determine the PME grid energy of the test molecule
                         * with the PME grid potential of the other charges.
                         */
                        gmx_pme_calc_energy(fr->pmedata, fr->n_tpi,
                                            x + md->homenr - fr->n_tpi,
                                            md->chargeA + md->homenr - fr->n_tpi,
                                            &Vlr);
                    }
                    PRINT_SEPDVDL("PME mesh", Vlr, dvdl);
                }
                break;
            case eelEWALD:
                Vlr = do_ewald(fplog, FALSE, ir, x, fr->f_novirsum,
                               md->chargeA, md->chargeB,
                               box_size, cr, md->homenr,
                               fr->vir_el_recip, fr->ewaldcoeff,
                               lambda[efptCOUL], &dvdl, fr->ewald_table);
                PRINT_SEPDVDL("Ewald long-range", Vlr, dvdl);
                break;
            default:
                gmx_fatal(FARGS, "No such electrostatics method implemented %s",
                          eel_names[fr->eeltype]);
        }
        if (status != 0)
        {
            gmx_fatal(FARGS, "Error %d in long range electrostatics routine %s",
                      status, EELTYPE(fr->eeltype));
        }
        /* Note that with separate PME nodes we get the real energies later */
        enerd->dvdl_lin[efptCOUL] += dvdl;
        enerd->term[F_COUL_RECIP]  = Vlr + Vcorr;
        if (debug)
        {
            fprintf(debug, "Vlr = %g, Vcorr = %g, Vlr_corr = %g\n",
                    Vlr, Vcorr, enerd->term[F_COUL_RECIP]);
            pr_rvecs(debug, 0, "vir_el_recip after corr", fr->vir_el_recip, DIM);
            pr_rvecs(debug, 0, "fshift after LR Corrections", fr->fshift, SHIFTS);
        }
    }
    else
    {
        if (EEL_RF(fr->eeltype))
        {
            /* With the Verlet scheme exclusion forces are calculated
             * in the non-bonded kernel.
             */
            if (ir->cutoff_scheme != ecutsVERLET && fr->eeltype != eelRF_NEC)
            {
                dvdl                   = 0;
                enerd->term[F_RF_EXCL] =
                    RF_excl_correction(fplog, fr, graph, md, excl, x, f,
                                       fr->fshift, &pbc, lambda[efptCOUL], &dvdl);
            }

            enerd->dvdl_lin[efptCOUL] += dvdl;
            PRINT_SEPDVDL("RF exclusion correction",
                          enerd->term[F_RF_EXCL], dvdl);
        }
    }
    where();
    debug_gmx();

    if (debug)
    {
        print_nrnb(debug, nrnb);
    }
    debug_gmx();

#ifdef GMX_MPI
    if (TAKETIME)
    {
        t2 = MPI_Wtime();
        MPI_Barrier(cr->mpi_comm_mygroup);
        t3          = MPI_Wtime();
        fr->t_wait += t3-t2;
        if (fr->timesteps == 11)
        {
            fprintf(stderr, "* PP load balancing info: node %d, step %s, rel wait time=%3.0f%% , load string value: %7.2f\n",
                    cr->nodeid, gmx_step_str(fr->timesteps, buf),
                    100*fr->t_wait/(fr->t_wait+fr->t_fnbf),
                    (fr->t_fnbf+fr->t_wait)/fr->t_fnbf);
        }
        fr->timesteps++;
    }
#endif

    if (debug)
    {
        pr_rvecs(debug, 0, "fshift after bondeds", fr->fshift, SHIFTS);
    }

    GMX_MPE_LOG(ev_force_finish);

}
Beispiel #15
0
void
do_force_listed(struct gmx_wallcycle        *wcycle,
                matrix                       box,
                const t_lambda              *fepvals,
                const t_commrec             *cr,
                const gmx_multisim_t        *ms,
                const t_idef                *idef,
                const rvec                   x[],
                history_t                   *hist,
                rvec                        *forceForUseWithShiftForces,
                gmx::ForceWithVirial        *forceWithVirial,
                const t_forcerec            *fr,
                const struct t_pbc          *pbc,
                const struct t_graph        *graph,
                gmx_enerdata_t              *enerd,
                t_nrnb                      *nrnb,
                const real                  *lambda,
                const t_mdatoms             *md,
                t_fcdata                    *fcd,
                int                         *global_atom_index,
                int                          flags)
{
    t_pbc pbc_full; /* Full PBC is needed for position restraints */

    if (!(flags & GMX_FORCE_LISTED))
    {
        return;
    }

    if ((idef->il[F_POSRES].nr > 0) ||
        (idef->il[F_FBPOSRES].nr > 0))
    {
        /* Not enough flops to bother counting */
        set_pbc(&pbc_full, fr->ePBC, box);
    }
    calc_listed(cr, ms, wcycle, idef, x, hist,
                forceForUseWithShiftForces, forceWithVirial,
                fr, pbc, &pbc_full,
                graph, enerd, nrnb, lambda, md, fcd,
                global_atom_index, flags);

    /* Check if we have to determine energy differences
     * at foreign lambda's.
     */
    if (fepvals->n_lambda > 0 && (flags & GMX_FORCE_DHDL))
    {
        posres_wrapper_lambda(wcycle, fepvals, idef, &pbc_full, x, enerd, lambda, fr);

        if (idef->ilsort != ilsortNO_FE)
        {
            wallcycle_sub_start(wcycle, ewcsLISTED_FEP);
            if (idef->ilsort != ilsortFE_SORTED)
            {
                gmx_incons("The bonded interactions are not sorted for free energy");
            }
            for (int i = 0; i < enerd->n_lambda; i++)
            {
                real lam_i[efptNR];

                reset_foreign_enerdata(enerd);
                for (int j = 0; j < efptNR; j++)
                {
                    lam_i[j] = (i == 0 ? lambda[j] : fepvals->all_lambda[j][i-1]);
                }
                calc_listed_lambda(idef, x, fr, pbc, graph, &(enerd->foreign_grpp), enerd->foreign_term, nrnb, lam_i, md,
                                   fcd, global_atom_index);
                sum_epot(&(enerd->foreign_grpp), enerd->foreign_term);
                enerd->enerpart_lambda[i] += enerd->foreign_term[F_EPOT];
            }
            wallcycle_sub_stop(wcycle, ewcsLISTED_FEP);
        }
    }
}
Beispiel #16
0
static void low_set_pbc(t_pbc *pbc,int ePBC,ivec *dd_nc,matrix box)
{
    int  order[5]={0,-1,1,-2,2};
    int  ii,jj,kk,i,j,k,d,dd,jc,kc,npbcdim,shift;
    ivec bPBC;
    real d2old,d2new,d2new_c;
    rvec trial,pos;
    gmx_bool bXY,bUse;
    const char *ptr;

    pbc->ndim_ePBC = ePBC2npbcdim(ePBC);

    copy_mat(box,pbc->box);
    pbc->bLimitDistance = FALSE;
    pbc->max_cutoff2 = 0;
    pbc->dim = -1;

    for(i=0; (i<DIM); i++) {
        pbc->fbox_diag[i]  =  box[i][i];
        pbc->hbox_diag[i]  =  pbc->fbox_diag[i]*0.5;
        pbc->mhbox_diag[i] = -pbc->hbox_diag[i];
    }

    ptr = check_box(ePBC,box);
    if (ePBC == epbcNONE) {
        pbc->ePBCDX = epbcdxNOPBC;
    } else if (ptr) {
        fprintf(stderr,   "Warning: %s\n",ptr);
        pr_rvecs(stderr,0,"         Box",box,DIM);
        fprintf(stderr,   "         Can not fix pbc.\n");
        pbc->ePBCDX = epbcdxUNSUPPORTED;
        pbc->bLimitDistance = TRUE;
        pbc->limit_distance2 = 0;
    } else {
        if (ePBC == epbcSCREW && dd_nc) {
            /* This combinated should never appear here */
            gmx_incons("low_set_pbc called with screw pbc and dd_nc != NULL");
        }

        npbcdim = 0;
        for(i=0; i<DIM; i++) {
            if ((dd_nc && (*dd_nc)[i] > 1) || (ePBC == epbcXY && i == ZZ)) {
                bPBC[i] = 0;
            } else {
                bPBC[i] = 1;
                npbcdim++;
            }
        }
        switch (npbcdim) {
        case 1:
            /* 1D pbc is not an mdp option and it is therefore only used
             * with single shifts.
             */
            pbc->ePBCDX = epbcdx1D_RECT;
            for(i=0; i<DIM; i++)
                if (bPBC[i])
                    pbc->dim = i;
            for(i=0; i<pbc->dim; i++)
                if (pbc->box[pbc->dim][i] != 0)
                    pbc->ePBCDX = epbcdx1D_TRIC;
            break;
        case 2:
            pbc->ePBCDX = epbcdx2D_RECT;
            for(i=0; i<DIM; i++)
                if (!bPBC[i])
                    pbc->dim = i;
            for(i=0; i<DIM; i++)
                if (bPBC[i])
                    for(j=0; j<i; j++)
                        if (pbc->box[i][j] != 0)
                            pbc->ePBCDX = epbcdx2D_TRIC;
            break;
        case 3:
            if (ePBC != epbcSCREW) {
                if (TRICLINIC(box)) {
                    pbc->ePBCDX = epbcdxTRICLINIC;
                } else {
                    pbc->ePBCDX = epbcdxRECTANGULAR;
                }
            } else {
                pbc->ePBCDX = (box[ZZ][YY]==0 ? epbcdxSCREW_RECT : epbcdxSCREW_TRIC);
                if (pbc->ePBCDX == epbcdxSCREW_TRIC) {
                    fprintf(stderr,
                            "Screw pbc is not yet implemented for triclinic boxes.\n"
                            "Can not fix pbc.\n");
                    pbc->ePBCDX = epbcdxUNSUPPORTED;
                }
            }
            break;
        default:
            gmx_fatal(FARGS,"Incorrect number of pbc dimensions with DD: %d",
                      npbcdim);
        }
        pbc->max_cutoff2 = max_cutoff2(ePBC,box);

        if (pbc->ePBCDX == epbcdxTRICLINIC ||
            pbc->ePBCDX == epbcdx2D_TRIC ||
            pbc->ePBCDX == epbcdxSCREW_TRIC) {
            if (debug) {
                pr_rvecs(debug,0,"Box",box,DIM);
                fprintf(debug,"max cutoff %.3f\n",sqrt(pbc->max_cutoff2));
            }
            pbc->ntric_vec = 0;
            /* We will only use single shifts, but we will check a few
             * more shifts to see if there is a limiting distance
             * above which we can not be sure of the correct distance.
             */
            for(kk=0; kk<5; kk++) {
                k = order[kk];
                if (!bPBC[ZZ] && k != 0)
                    continue;
                for(jj=0; jj<5; jj++) {
                    j = order[jj];
                    if (!bPBC[YY] && j != 0)
                        continue;
                    for(ii=0; ii<3; ii++) {
                        i = order[ii];
                        if (!bPBC[XX] && i != 0)
                            continue;
                        /* A shift is only useful when it is trilinic */
                        if (j != 0 || k != 0) {
                            d2old = 0;
                            d2new = 0;
                            for(d=0; d<DIM; d++) {
                                trial[d] = i*box[XX][d] + j*box[YY][d] + k*box[ZZ][d];
                                /* Choose the vector within the brick around 0,0,0 that
                                 * will become the shortest due to shift try.
                                 */
                                if (d == pbc->dim) {
                                    trial[d] = 0;
                                    pos[d] = 0;
                                } else {
                                    if (trial[d] < 0)
                                        pos[d] = min( pbc->hbox_diag[d],-trial[d]);
                                    else
                                        pos[d] = max(-pbc->hbox_diag[d],-trial[d]);
                                }
                                d2old += sqr(pos[d]);
                                d2new += sqr(pos[d] + trial[d]);
                            }
                            if (BOX_MARGIN*d2new < d2old) {
                                if (j < -1 || j > 1 || k < -1 || k > 1) {
                                    /* Check if there is a single shift vector
                                     * that decreases this distance even more.
                                     */
                                    jc = 0;
                                    kc = 0;
                                    if (j < -1 || j > 1)
                                        jc = j/2;
                                    if (k < -1 || k > 1)
                                        kc = k/2;
                                    d2new_c = 0;
                                    for(d=0; d<DIM; d++)
                                        d2new_c += sqr(pos[d] + trial[d] 
                                                                      - jc*box[YY][d] - kc*box[ZZ][d]);
                                    if (d2new_c > BOX_MARGIN*d2new) {
                                        /* Reject this shift vector, as there is no a priori limit
                                         * to the number of shifts that decrease distances.
                                         */
                                        if (!pbc->bLimitDistance || d2new <  pbc->limit_distance2)
                                            pbc->limit_distance2 = d2new;
                                        pbc->bLimitDistance = TRUE;
                                    }
                                } else {
                                    /* Check if shifts with one box vector less do better */
                                    bUse = TRUE;
                                    for(dd=0; dd<DIM; dd++) {
                                        shift = (dd==0 ? i : (dd==1 ? j : k));
                                        if (shift) {
                                            d2new_c = 0;
                                            for(d=0; d<DIM; d++)
                                                d2new_c += sqr(pos[d] + trial[d] - shift*box[dd][d]);
                                            if (d2new_c <= BOX_MARGIN*d2new)
                                                bUse = FALSE;
                                        }
                                    }
                                    if (bUse) {
                                        /* Accept this shift vector. */
                                        if (pbc->ntric_vec >= MAX_NTRICVEC) {
                                            fprintf(stderr,"\nWARNING: Found more than %d triclinic correction vectors, ignoring some.\n"
                                                    "  There is probably something wrong with your box.\n",MAX_NTRICVEC);
                                            pr_rvecs(stderr,0,"         Box",box,DIM);
                                        } else {
                                            copy_rvec(trial,pbc->tric_vec[pbc->ntric_vec]);
                                            pbc->tric_shift[pbc->ntric_vec][XX] = i;
                                            pbc->tric_shift[pbc->ntric_vec][YY] = j;
                                            pbc->tric_shift[pbc->ntric_vec][ZZ] = k;
                                            pbc->ntric_vec++;
                                        }
                                    }
                                }
                                if (debug) {
                                    fprintf(debug,"  tricvec %2d = %2d %2d %2d  %5.2f %5.2f  %5.2f %5.2f %5.2f  %5.2f %5.2f %5.2f\n",
                                            pbc->ntric_vec,i,j,k,
                                            sqrt(d2old),sqrt(d2new),
                                            trial[XX],trial[YY],trial[ZZ],
                                            pos[XX],pos[YY],pos[ZZ]);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
Beispiel #17
0
/* Try to increase nstlist when using the Verlet cut-off scheme */
static void increase_nstlist(FILE *fp, t_commrec *cr,
                             t_inputrec *ir, int nstlist_cmdline,
                             const gmx_mtop_t *mtop, matrix box,
                             gmx_bool bGPU)
{
    float                  listfac_ok, listfac_max;
    int                    nstlist_orig, nstlist_prev;
    verletbuf_list_setup_t ls;
    real                   rlistWithReferenceNstlist, rlist_inc, rlist_ok, rlist_max;
    real                   rlist_new, rlist_prev;
    size_t                 nstlist_ind = 0;
    t_state                state_tmp;
    gmx_bool               bBox, bDD, bCont;
    const char            *nstl_gpu = "\nFor optimal performance with a GPU nstlist (now %d) should be larger.\nThe optimum depends on your CPU and GPU resources.\nYou might want to try several nstlist values.\n";
    const char            *nve_err  = "Can not increase nstlist because an NVE ensemble is used";
    const char            *vbd_err  = "Can not increase nstlist because verlet-buffer-tolerance is not set or used";
    const char            *box_err  = "Can not increase nstlist because the box is too small";
    const char            *dd_err   = "Can not increase nstlist because of domain decomposition limitations";
    char                   buf[STRLEN];
    const float            oneThird = 1.0f / 3.0f;

    if (nstlist_cmdline <= 0)
    {
        if (ir->nstlist == 1)
        {
            /* The user probably set nstlist=1 for a reason,
             * don't mess with the settings.
             */
            return;
        }

        if (fp != NULL && bGPU && ir->nstlist < nstlist_try[0])
        {
            fprintf(fp, nstl_gpu, ir->nstlist);
        }
        nstlist_ind = 0;
        while (nstlist_ind < NNSTL && ir->nstlist >= nstlist_try[nstlist_ind])
        {
            nstlist_ind++;
        }
        if (nstlist_ind == NNSTL)
        {
            /* There are no larger nstlist value to try */
            return;
        }
    }

    if (EI_MD(ir->eI) && ir->etc == etcNO)
    {
        if (MASTER(cr))
        {
            fprintf(stderr, "%s\n", nve_err);
        }
        if (fp != NULL)
        {
            fprintf(fp, "%s\n", nve_err);
        }

        return;
    }

    if (ir->verletbuf_tol == 0 && bGPU)
    {
        gmx_fatal(FARGS, "You are using an old tpr file with a GPU, please generate a new tpr file with an up to date version of grompp");
    }

    if (ir->verletbuf_tol < 0)
    {
        if (MASTER(cr))
        {
            fprintf(stderr, "%s\n", vbd_err);
        }
        if (fp != NULL)
        {
            fprintf(fp, "%s\n", vbd_err);
        }

        return;
    }

    if (bGPU)
    {
        listfac_ok  = nbnxn_gpu_listfac_ok;
        listfac_max = nbnxn_gpu_listfac_max;
    }
    else
    {
        listfac_ok  = nbnxn_cpu_listfac_ok;
        listfac_max = nbnxn_cpu_listfac_max;
    }

    nstlist_orig = ir->nstlist;
    if (nstlist_cmdline > 0)
    {
        if (fp)
        {
            sprintf(buf, "Getting nstlist=%d from command line option",
                    nstlist_cmdline);
        }
        ir->nstlist = nstlist_cmdline;
    }

    verletbuf_get_list_setup(TRUE, bGPU, &ls);

    /* Allow rlist to make the list a given factor larger than the list
     * would be with the reference value for nstlist (10).
     */
    nstlist_prev = ir->nstlist;
    ir->nstlist  = nbnxnReferenceNstlist;
    calc_verlet_buffer_size(mtop, det(box), ir, -1, &ls, NULL,
                            &rlistWithReferenceNstlist);
    ir->nstlist  = nstlist_prev;

    /* Determine the pair list size increase due to zero interactions */
    rlist_inc = nbnxn_get_rlist_effective_inc(ls.cluster_size_j,
                                              mtop->natoms/det(box));
    rlist_ok  = (rlistWithReferenceNstlist + rlist_inc)*pow(listfac_ok, oneThird) - rlist_inc;
    rlist_max = (rlistWithReferenceNstlist + rlist_inc)*pow(listfac_max, oneThird) - rlist_inc;
    if (debug)
    {
        fprintf(debug, "nstlist tuning: rlist_inc %.3f rlist_ok %.3f rlist_max %.3f\n",
                rlist_inc, rlist_ok, rlist_max);
    }

    nstlist_prev = nstlist_orig;
    rlist_prev   = ir->rlist;
    do
    {
        if (nstlist_cmdline <= 0)
        {
            ir->nstlist = nstlist_try[nstlist_ind];
        }

        /* Set the pair-list buffer size in ir */
        calc_verlet_buffer_size(mtop, det(box), ir, -1, &ls, NULL, &rlist_new);

        /* Does rlist fit in the box? */
        bBox = (sqr(rlist_new) < max_cutoff2(ir->ePBC, box));
        bDD  = TRUE;
        if (bBox && DOMAINDECOMP(cr))
        {
            /* Check if rlist fits in the domain decomposition */
            if (inputrec2nboundeddim(ir) < DIM)
            {
                gmx_incons("Changing nstlist with domain decomposition and unbounded dimensions is not implemented yet");
            }
            copy_mat(box, state_tmp.box);
            bDD = change_dd_cutoff(cr, &state_tmp, ir, rlist_new);
        }

        if (debug)
        {
            fprintf(debug, "nstlist %d rlist %.3f bBox %d bDD %d\n",
                    ir->nstlist, rlist_new, bBox, bDD);
        }

        bCont = FALSE;

        if (nstlist_cmdline <= 0)
        {
            if (bBox && bDD && rlist_new <= rlist_max)
            {
                /* Increase nstlist */
                nstlist_prev = ir->nstlist;
                rlist_prev   = rlist_new;
                bCont        = (nstlist_ind+1 < NNSTL && rlist_new < rlist_ok);
            }
            else
            {
                /* Stick with the previous nstlist */
                ir->nstlist = nstlist_prev;
                rlist_new   = rlist_prev;
                bBox        = TRUE;
                bDD         = TRUE;
            }
        }

        nstlist_ind++;
    }
    while (bCont);

    if (!bBox || !bDD)
    {
        gmx_warning(!bBox ? box_err : dd_err);
        if (fp != NULL)
        {
            fprintf(fp, "\n%s\n", bBox ? box_err : dd_err);
        }
        ir->nstlist = nstlist_orig;
    }
    else if (ir->nstlist != nstlist_orig || rlist_new != ir->rlist)
    {
        sprintf(buf, "Changing nstlist from %d to %d, rlist from %g to %g",
                nstlist_orig, ir->nstlist,
                ir->rlist, rlist_new);
        if (MASTER(cr))
        {
            fprintf(stderr, "%s\n\n", buf);
        }
        if (fp != NULL)
        {
            fprintf(fp, "%s\n\n", buf);
        }
        ir->rlist     = rlist_new;
        ir->rlistlong = rlist_new;
    }
}
Beispiel #18
0
static int WndProcET(t_x11 *x11, t_dlgitem *dlgitem, XEvent *event)
{
  t_edittext *et;
  t_windata  *win;
  KeySym     keysym;
  char       c[BUFSIZE+1],*bp;
  char       scrbuf[STRLEN];
  int        i,xp,xtitle,ewidth;
  
  if (dlgitem->type != edlgET)
    gmx_incons("st processing");
  et=&(dlgitem->u.edittext);
  win=&(dlgitem->win);

  /* Copy string part that is visible into screen buffer */
  for(i=0; (i<et->buflen); i++)
    scrbuf[i]=et->buf[i+et->strbegin];
  scrbuf[i]='\0';

  switch(event->type) {
  case Expose:
    XSetForeground(x11->disp,x11->gc,x11->fg);
    xtitle=XTextWidth(x11->font,win->text,strlen(win->text));
    ewidth=win->width-xtitle;
    TextInRect(x11,win->self,win->text,
	       0,0,xtitle-1,win->height,eXLeft,eYCenter);
    XClearArea(x11->disp,win->self,xtitle,0,ewidth+XCARET,win->height,False);
    TextInRect(x11,win->self,scrbuf,
	       xtitle+XCARET,0,ewidth,win->height,eXLeft,eYCenter);
#ifdef DEBUG
    printf("Expose\n");
#endif
    if (win->bFocus)
      ShowCaret(x11,dlgitem);
    break;
  case ButtonPress:
    /* Calculate new position for caret */
    et->pos=strlen(et->buf);
    bp=strdup(et->buf);
    xp=event->xbutton.x-XTextWidth(x11->font,win->text,strlen(win->text))-
      XCARET;
    while ((et->pos > 0) && (XTextWidth(x11->font,bp,strlen(bp)) > xp)) {
      et->pos--;
      bp[et->pos]='\0';
    }
    sfree(bp);
    et->bChanged=TRUE;
    return ETCHANGED;
  case KeyPress:
    /* Check for HelpKey */
    if (HelpPressed(event))
      return DefWndProc(x11,dlgitem,event);
    XLookupString(&(event->xkey),c,BUFSIZE,&keysym,NULL);
#ifdef DEBUG
    printf("Keysym: %x\n",keysym);
#endif
    switch(keysym) {
    case XK_Delete:
      if (my_delete(et->buf,&(et->pos))){
	et->bChanged=TRUE;
	return ETCHANGED;
      }
      else
	XBell(x11->disp,50);
      break;
    case XK_BackSpace:
      if (my_backspace(et->buf,&(et->pos))) {
	et->bChanged=TRUE;
	return ETCHANGED;
      }
      else
	XBell(x11->disp,50);
      break;
    case XK_KP_Enter:
    case XK_Return:
      return ENTERPRESSED;
    case XK_Home:
      et->pos=0;
      et->strbegin=0;
      et->bChanged=TRUE;
      return ETCHANGED;
    case XK_End:
      if (strlen(et->buf) <= et->buflen)
	et->pos=strlen(et->buf);
      else {
	et->pos=et->buflen;
	et->strbegin=strlen(et->buf)-et->buflen;
      }
      et->bChanged=TRUE;
      return ETCHANGED;
    case XK_Left:
      et->pos=max(0,et->pos-1);
      et->strbegin=min(et->strbegin,et->pos);
      et->bChanged=TRUE;
      return ETCHANGED;
    case XK_Right:
      if ((et->pos < et->buflen) && (et->strbegin+et->buflen > strlen(et->buf)))
	et->pos++;
      else if ((et->buflen   < strlen(et->buf)) && 
	       (et->strbegin < strlen(et->buf)-et->buflen))
	et->strbegin++;
      else
	break;
      et->bChanged=TRUE;
      return ETCHANGED;
    default:
      if (keysym < 256) 
	if (insert(et->buf,c[0],&(et->pos))) {
	  et->bChanged=TRUE;
	  return ETCHANGED;
	}
      XBell(x11->disp,50);
      break;
    }
    break;
  case LeaveNotify:
    win->bFocus=FALSE;
    HideCaret(x11,dlgitem);
    if (et->bChanged)
      et->bChanged=FALSE;
    break;
  default:
    return DefWndProc(x11,dlgitem,event);
  }
  return ITEMOK;
}
Beispiel #19
0
void read_stx_conf(char *infile, char *title,t_atoms *atoms, 
		   rvec x[],rvec *v,int *ePBC,matrix box)
{
  FILE       *in;
  char       buf[256];
  gmx_mtop_t *mtop;
  t_topology top;
  t_trxframe fr;
  int        i,ftp,natoms,i1;
  real       d,r1,r2;

  if (atoms->nr == 0)
    fprintf(stderr,"Warning: Number of atoms in %s is 0\n",infile);
  else if (atoms->atom == NULL)
    gmx_mem("Uninitialized array atom");
  
  if (ePBC)
    *ePBC = -1;

  ftp=fn2ftp(infile);
  switch (ftp) {
  case efGRO:
    read_whole_conf(infile, title, atoms, x, v, box);
    break;
  case efG96:
    fr.title = title;
    fr.natoms = atoms->nr;
    fr.atoms = atoms;
    fr.x = x;
    fr.v = v;
    fr.f = NULL;
    in = gmx_fio_fopen(infile,"r");
    read_g96_conf(in, infile, &fr);
    gmx_fio_fclose(in);
    copy_mat(fr.box,box);
    break;
  case efPDB:
  case efBRK:
  case efENT:
    read_pdb_conf(infile, title, atoms, x, ePBC, box, TRUE, NULL);
    break;
  case efESP:
    read_espresso_conf(infile,atoms,x,v,box);
    break;
  case efTPR:
  case efTPB:
  case efTPA: 
    snew(mtop,1);
    i = read_tpx(infile,&i1,&r1,&r2,NULL,box,&natoms,x,v,NULL,mtop);
    if (ePBC)
      *ePBC = i;
    
    strcpy(title,*(mtop->name));
    
    /* Free possibly allocated memory */
    done_atom(atoms);
    
    *atoms = gmx_mtop_global_atoms(mtop);
    top = gmx_mtop_t_to_t_topology(mtop);
    tpx_make_chain_identifiers(atoms,&top.mols);
		
    sfree(mtop);
    done_top(&top);
		  
    break;
  default:
    gmx_incons("Not supported in read_stx_conf");
  }
}
Beispiel #20
0
/*****************************************************************
 *
 *                     EXPORTED SECTION
 *
 *****************************************************************/
t_fileio *gmx_fio_open(const char *fn, const char *mode)
{
    t_fileio *fio = NULL;
    int       i;
    char      newmode[5];
    gmx_bool  bRead, bReadWrite;
    int       xdrid;

    /* sanitize the mode string */
    if (strncmp(mode, "r+", 2) == 0)
    {
        strcpy(newmode, "r+");
    }
    else if (mode[0] == 'r')
    {
        strcpy(newmode, "r");
    }
    else if (strncmp(mode, "w+", 2) == 0)
    {
        strcpy(newmode, "w+");
    }
    else if (mode[0] == 'w')
    {
        strcpy(newmode, "w");
    }
    else if (strncmp(mode, "a+", 2) == 0)
    {
        strcpy(newmode, "a+");
    }
    else if (mode[0] == 'a')
    {
        strcpy(newmode, "a");
    }
    else
    {
        gmx_fatal(FARGS, "DEATH HORROR in gmx_fio_open, mode is '%s'", mode);
    }

    /* Check if it should be opened as a binary file */
    if (strncmp(ftp2ftype(fn2ftp(fn)), "ASCII", 5))
    {
        /* Not ascii, add b to file mode */
        if ((strchr(newmode, 'b') == NULL) && (strchr(newmode, 'B') == NULL))
        {
            strcat(newmode, "b");
        }
    }

    snew(fio, 1);
    tMPI_Lock_init(&(fio->mtx));
    bRead      = (newmode[0] == 'r' && newmode[1] != '+');
    bReadWrite = (newmode[1] == '+');
    fio->fp    = NULL;
    fio->xdr   = NULL;
    if (fn)
    {
        fio->iFTP   = fn2ftp(fn);
        fio->fn     = gmx_strdup(fn);
        fio->bStdio = FALSE;

        /* If this file type is in the list of XDR files, open it like that */
        if (in_ftpset(fio->iFTP, asize(ftpXDR), ftpXDR))
        {
            /* First check whether we have to make a backup,
             * only for writing, not for read or append.
             */
            if (newmode[0] == 'w')
            {
#ifndef GMX_FAHCORE
                /* only make backups for normal gromacs */
                make_backup(fn);
#endif
            }
            else
            {
                /* Check whether file exists */
                if (!gmx_fexist(fn))
                {
                    gmx_open(fn);
                }
            }
            if (fn2ftp(fn) == efTNG)
            {
                gmx_incons("gmx_fio_open may not be used to open TNG files");
            }
            /* Open the file */
            fio->fp = gmx_ffopen(fn, newmode);

            /* determine the XDR direction */
            if (newmode[0] == 'w' || newmode[0] == 'a')
            {
                fio->xdrmode = XDR_ENCODE;
            }
            else
            {
                fio->xdrmode = XDR_DECODE;
            }

            snew(fio->xdr, 1);
            xdrstdio_create(fio->xdr, fio->fp, fio->xdrmode);
        }
        else
        {
            /* If it is not, open it as a regular file */
            fio->fp = gmx_ffopen(fn, newmode);
        }

        /* for appending seek to end of file to make sure ftell gives correct position
         * important for checkpointing */
        if (newmode[0] == 'a')
        {
            gmx_fseek(fio->fp, 0, SEEK_END);
        }
    }
    fio->bRead             = bRead;
    fio->bReadWrite        = bReadWrite;
    fio->bDouble           = (sizeof(real) == sizeof(double));
    fio->bDebug            = FALSE;
    fio->bOpen             = TRUE;

    /* set the reader/writer functions */
    gmx_fio_set_iotype(fio);

    /* and now insert this file into the list of open files. */
    gmx_fio_insert(fio);
    return fio;
}
Beispiel #21
0
static void cmp_eblocks(t_enxframe *fr1,t_enxframe *fr2,real ftol, real abstol)
{
    int i,j,k;
    char buf[64],bs[22];

    cmp_int(stdout,"nblock",-1,fr1->nblock,fr2->nblock);  
    if ((fr1->nblock == fr2->nblock) && (fr1->nblock > 0)) 
    {
        for(j=0; (j<fr1->nblock); j++) 
        {
            t_enxblock *b1, *b2; /* convenience vars */

            b1=&(fr1->block[j]);
            b2=&(fr2->block[j]);

            sprintf(buf,"step %s: block[%d]",gmx_step_str(fr1->step,bs),j);
            cmp_int(stdout,buf,-1,b1->nsub,b2->nsub);
            cmp_int(stdout,buf,-1,b1->id,b2->id);

            if ( (b1->nsub==b2->nsub) && (b1->id==b2->id) )
            {
                for(i=0;i<b1->nsub;i++)
                {
                    t_enxsubblock *s1, *s2;

                    s1=&(b1->sub[i]);
                    s2=&(b2->sub[i]);

                    cmp_int(stdout, buf, -1, (int)s1->type, (int)s2->type);
                    cmp_gmx_large_int(stdout, buf, s1->nr, s2->nr);

                    if ((s1->type == s2->type) && (s1->nr == s2->nr))
                    {
                        switch(s1->type)
                        {
                            case xdr_datatype_float:
                                for(k=0;k<s1->nr;k++)
                                {
                                    cmp_float(stdout, buf, i,
                                             s1->fval[k], s2->fval[k], 
                                             ftol, abstol);
                                }
                                break;
                            case xdr_datatype_double:
                                for(k=0;k<s1->nr;k++)
                                {
                                    cmp_double(stdout, buf, i,
                                             s1->dval[k], s2->dval[k], 
                                             ftol, abstol);
                                }
                                break;
                            case xdr_datatype_int:
                                for(k=0;k<s1->nr;k++)
                                {
                                    cmp_int(stdout, buf, i,
                                            s1->ival[k], s2->ival[k]);
                                }
                                break;
                            case xdr_datatype_large_int:
                                for(k=0;k<s1->nr;k++)
                                {
                                    cmp_gmx_large_int(stdout, buf, 
                                                      s1->lval[k], s2->lval[k]);
                                }
                                break;
                            case xdr_datatype_char:
                                for(k=0;k<s1->nr;k++)
                                {
                                    cmp_uc(stdout, buf, i,
                                           s1->cval[k], s2->cval[k]);
                                }
                                break;
                            case xdr_datatype_string:
                                for(k=0;k<s1->nr;k++)
                                {
                                    cmp_str(stdout, buf, i,
                                            s1->sval[k], s2->sval[k]);
                                }
                                break;
                            default:
                                gmx_incons("Unknown data type!!");
                        }
                    }
                }
            }
        }
    }
}
Beispiel #22
0
/*!
 * \param[in,out] d     Trajectory analysis data structure.
 * \returns    0 on success, a non-zero error code on error.
 *
 * This function should be called first in the analysis program, much in
 * the same way as parse_common_args() in traditional Gromacs analysis
 * programs. It adds some command-line arguments of its own, and uses
 * parse_common_args() to parse the command-line arguments.
 * It also loads topology information if required or if a topology is
 * provided on the command line.
 * Selection handling is also initialized if it is enabled and
 * the user has selected it on the command line.
 *
 * The rest of the parameters are passed on to the Gromacs routine
 * parse_common_args(), and the use of this function should be identical
 * to parse_common_args(), with the exception that for \p pca_flags,
 * \p PCA_CAN_TIME and \p PCA_BE_NICE flags are automatically added.
 * \param      argc
 * \param      argv
 * \param      pca_flags
 * \param      nfile
 * \param      fnm
 * \param      npargs
 * \param      pa
 * \param      ndesc
 * \param      desc
 * \param      nbugs
 * \param      bugs
 */
int
parse_trjana_args(gmx_ana_traj_t *d,
                  int *argc, char *argv[], unsigned long pca_flags,
                  int nfile, t_filenm fnm[], int npargs, t_pargs *pa,
                  int ndesc, const char **desc,
		  int nbugs, const char **bugs)
{
    t_filenm           *all_fnm = NULL;
    int                 max_fnm, nfall;
    int                *fnm_map;
    t_pargs            *all_pa = NULL;
    int                 max_pa, npall;
    size_t              i;
    int                 k;
    int                 rc;

    t_filenm            def_fnm[] = {
        {efTRX, NULL,  NULL,        ffREAD},
        {efTPS, NULL,  NULL,        ffREAD},
        {efDAT, "-sf", "selection", ffOPTRD},
        {efNDX, NULL,  NULL,        ffOPTRD},
    };
    bool                bPBC = TRUE;
    t_pargs             pbc_pa[] = {
        {"-pbc",      FALSE, etBOOL, {&bPBC},
         "Use periodic boundary conditions for distance calculation"},
    };
    bool                bRmPBC = TRUE;
    t_pargs             rmpbc_pa[] = {
        {"-rmpbc",    FALSE, etBOOL, {&bRmPBC},
         "Make molecules whole for each frame"},
    };
    char               *selection = NULL;
    const char        **rpost     = NULL;
    bool                bSelDump  = FALSE;
    t_pargs             sel_pa[] = {
        {"-select",   FALSE, etSTR,  {&selection},
         "Selection string"},
        {"-seldebug", FALSE, etBOOL, {&bSelDump},
         "HIDDENPrint out the parsed and compiled selection trees"},
    };
    t_pargs             dsel_pa[] = {
        {"-selrpos",  FALSE, etENUM, {NULL},
         "Selection reference position"},
    };
    const char        **spost = NULL;
    t_pargs             selpt_pa[] = {
        {"-seltype",  FALSE, etENUM, {NULL},
         "Default analysis positions"},
    };
#define MAX_PA asize(sel_pa)+asize(dsel_pa)+5

    if (d->nrefgrps < 0)
    {
        gmx_incons("number of reference groups is negative");
        return EINVAL;
    }

    if (d->flags & ANA_DEBUG_SELECTION)
    {
        bSelDump = TRUE;
    }

    rpost = gmx_ana_poscalc_create_type_enum(!(d->flags & ANA_REQUIRE_WHOLE));
    if (rpost == NULL)
    {
        return ENOMEM;
    }
    spost = gmx_ana_poscalc_create_type_enum(TRUE);
    if (spost == NULL)
    {
        sfree(rpost);
        return ENOMEM;
    }

    /* Construct the file name argument array */
    max_fnm = nfile + asize(def_fnm);
    snew(all_fnm, max_fnm);
    nfall = 0;
    if (!(d->flags & ANA_REQUIRE_TOP))
    {
        def_fnm[1].flag |= ffOPT;
    }
    snew(fnm_map, nfile);
    for (k = 0; k < nfile; ++k)
    {
        fnm_map[k] = -1;
    }

    for (i = 0; i < asize(def_fnm); ++i)
    {
        for (k = 0; k < nfile; ++k)
        {
            if (fnm_map[k] == -1 && def_fnm[i].opt == NULL &&
                fnm[k].ftp == def_fnm[i].ftp)
            {
                break;
            }
        }
        if (k < nfile)
        {
            fnm_map[k] = nfall;
            nfall = add_fnmarg(nfall, all_fnm, &(fnm[k]));
        }
        else
        {
            nfall = add_fnmarg(nfall, all_fnm, &(def_fnm[i]));
        }
    }

    for (k = 0; k < nfile; ++k)
    {
        if (fnm_map[k] == -1)
        {
            fnm_map[k] = nfall;
            nfall = add_fnmarg(nfall, all_fnm, &(fnm[k]));
        }
    }

    /* Construct the argument array */
    max_pa = npargs + MAX_PA;
    snew(all_pa, max_pa);
    npall = 0;

    if (!(d->flags & ANA_NOUSER_RMPBC))
    {
        for (i = 0; i < asize(rmpbc_pa); ++i)
        {
            npall = add_parg(npall, all_pa, &(rmpbc_pa[i]));
        }
    }
    if (!(d->flags & ANA_NOUSER_PBC))
    {
        for (i = 0; i < asize(pbc_pa); ++i)
        {
            npall = add_parg(npall, all_pa, &(pbc_pa[i]));
        }
    }

    for (i = 0; i < asize(sel_pa); ++i)
    {
        npall = add_parg(npall, all_pa, &(sel_pa[i]));
    }
    if (!(d->flags & ANA_NO_DYNSEL))
    {
        dsel_pa[0].u.c = rpost;
        for (i = 0; i < asize(dsel_pa); ++i)
        {
            npall = add_parg(npall, all_pa, &(dsel_pa[i]));
        }
    }

    if (!(d->flags & ANA_ONLY_ATOMPOS))
    {
        selpt_pa[0].u.c = spost;
        for (i = 0; i < asize(selpt_pa); ++i)
        {
            npall = add_parg(npall, all_pa, &(selpt_pa[i]));
        }
    }

    for (k = 0; k < npargs; ++k)
    {
        npall = add_parg(npall, all_pa, &(pa[k]));
    }

    pca_flags |= PCA_CAN_TIME | PCA_BE_NICE;
    parse_common_args(argc, argv, pca_flags, nfall, all_fnm, npall, all_pa,
                      ndesc, desc, nbugs, bugs);

    /* Copy the results back */
    for (k = 0; k < nfile; ++k)
    {
        memcpy(&(fnm[k]), &(all_fnm[fnm_map[k]]), sizeof(fnm[k]));
    }
    for (i = 0, k = npall - npargs; i < (size_t)npargs; ++i, ++k)
    {
        memcpy(&(pa[i]), &(all_pa[k]), sizeof(pa[i]));
    }

    d->trjfile         = ftp2fn(efTRX, nfall, all_fnm);
    d->topfile         = ftp2fn_null(efTPS, nfall, all_fnm);
    d->topfile_notnull = ftp2fn(efTPS, nfall, all_fnm);
    d->ndxfile         = ftp2fn_null(efNDX, nfall, all_fnm);
    if (!(d->flags & ANA_NOUSER_RMPBC))
    {
        d->bRmPBC      = bRmPBC;
    }
    if (!(d->flags & ANA_NOUSER_PBC))
    {
        d->bPBC        = bPBC;
    }
    d->selection       = selection;
    d->selfile         = opt2fn_null("-sf", nfall, all_fnm);

    sfree(all_fnm);
    sfree(fnm_map);
    sfree(all_pa);

    if (!(d->flags & ANA_NO_DYNSEL))
    {
        gmx_ana_selcollection_set_refpostype(d->sc, rpost[0]);
    }
    else
    {
        gmx_ana_selcollection_set_refpostype(d->sc, rpost[1]);
    }
    sfree(rpost);
    if (bSelDump)
    {
        d->flags |= ANA_DEBUG_SELECTION;
    }
    else
    {
        d->flags &= ~ANA_DEBUG_SELECTION;
    }

    if (!(d->flags & ANA_ONLY_ATOMPOS))
    {
        gmx_ana_selcollection_set_outpostype(d->sc, spost[0], d->flags & ANA_USE_POSMASK);
    }
    else
    {
        gmx_ana_selcollection_set_outpostype(d->sc, spost[1], d->flags & ANA_USE_POSMASK);
    }
    sfree(spost);

    /* Load the topology if so requested. */
    rc = load_topology(d, (d->flags & ANA_REQUIRE_TOP));
    if (rc != 0)
    {
        return rc;
    }

    /* Initialize the selections/index groups */
    if (!(d->flags & ANA_USER_SELINIT))
    {
        rc = gmx_ana_init_selections(d);
    }

    return rc;
}
Beispiel #23
0
t_mdebin *init_mdebin(ener_file_t fp_ene,
                      const gmx_mtop_t *mtop,
                      const t_inputrec *ir,
                      FILE *fp_dhdl)
{
    const char *ener_nm[F_NRE];
    static const char *vir_nm[] = {
        "Vir-XX", "Vir-XY", "Vir-XZ",
        "Vir-YX", "Vir-YY", "Vir-YZ",
        "Vir-ZX", "Vir-ZY", "Vir-ZZ"
    };
    static const char *sv_nm[] = {
        "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ",
        "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ",
        "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ"
    };
    static const char *fv_nm[] = {
        "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ",
        "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ",
        "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ"
    };
    static const char *pres_nm[] = {
        "Pres-XX","Pres-XY","Pres-XZ",
        "Pres-YX","Pres-YY","Pres-YZ",
        "Pres-ZX","Pres-ZY","Pres-ZZ"
    };
    static const char *surft_nm[] = {
        "#Surf*SurfTen"
    };
    static const char *mu_nm[] = {
        "Mu-X", "Mu-Y", "Mu-Z"
    };
    static const char *vcos_nm[] = {
        "2CosZ*Vel-X"
    };
    static const char *visc_nm[] = {
        "1/Viscosity"
    };
    static const char *baro_nm[] = {
        "Barostat"
    };

    char     **grpnms;
    const gmx_groups_t *groups;
    char     **gnm;
    char     buf[256];
    const char     *bufi;
    t_mdebin *md;
    int      i,j,ni,nj,n,nh,k,kk,ncon,nset;
    gmx_bool     bBHAM,bNoseHoover,b14;

    snew(md,1);

    md->bVir=TRUE;
    md->bPress=TRUE;
    md->bSurft=TRUE;
    md->bMu=TRUE;

    if (EI_DYNAMICS(ir->eI))
    {
        md->delta_t = ir->delta_t;
    }
    else
    {
        md->delta_t = 0;
    }

    groups = &mtop->groups;

    bBHAM = (mtop->ffparams.functype[0] == F_BHAM);
    b14   = (gmx_mtop_ftype_count(mtop,F_LJ14) > 0 ||
             gmx_mtop_ftype_count(mtop,F_LJC14_Q) > 0);

    ncon = gmx_mtop_ftype_count(mtop,F_CONSTR);
    nset = gmx_mtop_ftype_count(mtop,F_SETTLE);
    md->bConstr    = (ncon > 0 || nset > 0);
    md->bConstrVir = FALSE;
    if (md->bConstr) {
        if (ncon > 0 && ir->eConstrAlg == econtLINCS) {
            if (ir->eI == eiSD2)
                md->nCrmsd = 2;
            else
                md->nCrmsd = 1;
        }
        md->bConstrVir = (getenv("GMX_CONSTRAINTVIR") != NULL);
    } else {
        md->nCrmsd = 0;
    }

    /* Energy monitoring */
    for(i=0;i<egNR;i++)
    {
        md->bEInd[i]=FALSE;
    }

#ifndef GMX_OPENMM
    for(i=0; i<F_NRE; i++)
    {
        md->bEner[i] = FALSE;
        if (i == F_LJ)
            md->bEner[i] = !bBHAM;
        else if (i == F_BHAM)
            md->bEner[i] = bBHAM;
        else if (i == F_EQM)
            md->bEner[i] = ir->bQMMM;
        else if (i == F_COUL_LR)
            md->bEner[i] = (ir->rcoulomb > ir->rlist);
        else if (i == F_LJ_LR)
            md->bEner[i] = (!bBHAM && ir->rvdw > ir->rlist);
        else if (i == F_BHAM_LR)
            md->bEner[i] = (bBHAM && ir->rvdw > ir->rlist);
        else if (i == F_RF_EXCL)
            md->bEner[i] = (EEL_RF(ir->coulombtype) && ir->coulombtype != eelRF_NEC && ir->cutoff_scheme == ecutsGROUP);
        else if (i == F_COUL_RECIP)
            md->bEner[i] = EEL_FULL(ir->coulombtype);
        else if (i == F_LJ14)
            md->bEner[i] = b14;
        else if (i == F_COUL14)
            md->bEner[i] = b14;
        else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB)
            md->bEner[i] = FALSE;
        else if ((i == F_DVDL_COUL && ir->fepvals->separate_dvdl[efptCOUL]) ||
                 (i == F_DVDL_VDW  && ir->fepvals->separate_dvdl[efptVDW]) ||
                 (i == F_DVDL_BONDED && ir->fepvals->separate_dvdl[efptBONDED]) ||
                 (i == F_DVDL_RESTRAINT && ir->fepvals->separate_dvdl[efptRESTRAINT]) ||
                 (i == F_DKDL && ir->fepvals->separate_dvdl[efptMASS]) ||
                 (i == F_DVDL && ir->fepvals->separate_dvdl[efptFEP]))
            md->bEner[i] = (ir->efep != efepNO);
        else if ((interaction_function[i].flags & IF_VSITE) ||
                 (i == F_CONSTR) || (i == F_CONSTRNC) || (i == F_SETTLE))
            md->bEner[i] = FALSE;
        else if ((i == F_COUL_SR) || (i == F_EPOT) || (i == F_PRES)  || (i==F_EQM))
            md->bEner[i] = TRUE;
        else if ((i == F_GBPOL) && ir->implicit_solvent==eisGBSA)
            md->bEner[i] = TRUE;
        else if ((i == F_NPSOLVATION) && ir->implicit_solvent==eisGBSA && (ir->sa_algorithm != esaNO))
            md->bEner[i] = TRUE;
        else if ((i == F_GB12) || (i == F_GB13) || (i == F_GB14))
            md->bEner[i] = FALSE;
        else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP))
            md->bEner[i] = EI_DYNAMICS(ir->eI);
        else if (i == F_DISPCORR || i == F_PDISPCORR)
            md->bEner[i] = (ir->eDispCorr != edispcNO);
        else if (i == F_DISRESVIOL)
            md->bEner[i] = (gmx_mtop_ftype_count(mtop,F_DISRES) > 0);
        else if (i == F_ORIRESDEV)
            md->bEner[i] = (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0);
        else if (i == F_CONNBONDS)
            md->bEner[i] = FALSE;
        else if (i == F_COM_PULL)
            md->bEner[i] = (ir->ePull == epullUMBRELLA || ir->ePull == epullCONST_F || ir->bRot);
        else if (i == F_ECONSERVED)
            md->bEner[i] = ((ir->etc == etcNOSEHOOVER || ir->etc == etcVRESCALE) &&
                            (ir->epc == epcNO || ir->epc==epcMTTK));
        else
            md->bEner[i] = (gmx_mtop_ftype_count(mtop,i) > 0);
    }
#else
    /* OpenMM always produces only the following 4 energy terms */
    md->bEner[F_EPOT] = TRUE;
    md->bEner[F_EKIN] = TRUE;
    md->bEner[F_ETOT] = TRUE;
    md->bEner[F_TEMP] = TRUE;
#endif

    /* for adress simulations, most energy terms are not meaningfull, and thus disabled*/
    if (ir->bAdress && !debug) {
        for (i = 0; i < F_NRE; i++) {
            md->bEner[i] = FALSE;
            if(i == F_EKIN){ md->bEner[i] = TRUE;}
            if(i == F_TEMP){ md->bEner[i] = TRUE;}
        }
        md->bVir=FALSE;
        md->bPress=FALSE;
        md->bSurft=FALSE;
        md->bMu=FALSE;
    }

    md->f_nre=0;
    for(i=0; i<F_NRE; i++)
    {
        if (md->bEner[i])
        {
            ener_nm[md->f_nre]=interaction_function[i].longname;
            md->f_nre++;
        }
    }

    md->epc = ir->epc;
    md->bDiagPres = !TRICLINIC(ir->ref_p);
    md->ref_p = (ir->ref_p[XX][XX]+ir->ref_p[YY][YY]+ir->ref_p[ZZ][ZZ])/DIM;
    md->bTricl = TRICLINIC(ir->compress) || TRICLINIC(ir->deform);
    md->bDynBox = DYNAMIC_BOX(*ir);
    md->etc = ir->etc;
    md->bNHC_trotter = IR_NVT_TROTTER(ir);
    md->bPrintNHChains = ir-> bPrintNHChains;
    md->bMTTK = (IR_NPT_TROTTER(ir) || IR_NPH_TROTTER(ir));
    md->bMu = NEED_MUTOT(*ir);

    md->ebin  = mk_ebin();
    /* Pass NULL for unit to let get_ebin_space determine the units
     * for interaction_function[i].longname
     */
    md->ie    = get_ebin_space(md->ebin,md->f_nre,ener_nm,NULL);
    if (md->nCrmsd)
    {
        /* This should be called directly after the call for md->ie,
         * such that md->iconrmsd follows directly in the list.
         */
        md->iconrmsd = get_ebin_space(md->ebin,md->nCrmsd,conrmsd_nm,"");
    }
    if (md->bDynBox)
    {
        md->ib    = get_ebin_space(md->ebin,
                                   md->bTricl ? NTRICLBOXS : NBOXS,
                                   md->bTricl ? tricl_boxs_nm : boxs_nm,
                                   unit_length);
        md->ivol  = get_ebin_space(md->ebin, 1, vol_nm,  unit_volume);
        md->idens = get_ebin_space(md->ebin, 1, dens_nm, unit_density_SI);
        if (md->bDiagPres)
        {
            md->ipv   = get_ebin_space(md->ebin, 1, pv_nm,   unit_energy);
            md->ienthalpy = get_ebin_space(md->ebin, 1, enthalpy_nm,   unit_energy);
        }
    }
    if (md->bConstrVir)
    {
        md->isvir = get_ebin_space(md->ebin,asize(sv_nm),sv_nm,unit_energy);
        md->ifvir = get_ebin_space(md->ebin,asize(fv_nm),fv_nm,unit_energy);
    }
    if (md->bVir)
        md->ivir   = get_ebin_space(md->ebin,asize(vir_nm),vir_nm,unit_energy);
    if (md->bPress)
        md->ipres  = get_ebin_space(md->ebin,asize(pres_nm),pres_nm,unit_pres_bar);
    if (md->bSurft)
        md->isurft = get_ebin_space(md->ebin,asize(surft_nm),surft_nm,
                                unit_surft_bar);
    if (md->epc == epcPARRINELLORAHMAN || md->epc == epcMTTK)
    {
        md->ipc = get_ebin_space(md->ebin,md->bTricl ? 6 : 3,
                                 boxvel_nm,unit_vel);
    }
    if (md->bMu)
    {
        md->imu    = get_ebin_space(md->ebin,asize(mu_nm),mu_nm,unit_dipole_D);
    }
    if (ir->cos_accel != 0)
    {
        md->ivcos = get_ebin_space(md->ebin,asize(vcos_nm),vcos_nm,unit_vel);
        md->ivisc = get_ebin_space(md->ebin,asize(visc_nm),visc_nm,
                                   unit_invvisc_SI);
    }

    /* Energy monitoring */
    for(i=0;i<egNR;i++)
    {
        md->bEInd[i] = FALSE;
    }
    md->bEInd[egCOULSR] = TRUE;
    md->bEInd[egLJSR  ] = TRUE;

    if (ir->rcoulomb > ir->rlist)
    {
        md->bEInd[egCOULLR] = TRUE;
    }
    if (!bBHAM)
    {
        if (ir->rvdw > ir->rlist)
        {
            md->bEInd[egLJLR]   = TRUE;
        }
    }
    else
    {
        md->bEInd[egLJSR]   = FALSE;
        md->bEInd[egBHAMSR] = TRUE;
        if (ir->rvdw > ir->rlist)
        {
            md->bEInd[egBHAMLR]   = TRUE;
        }
    }
    if (b14)
    {
        md->bEInd[egLJ14] = TRUE;
        md->bEInd[egCOUL14] = TRUE;
    }
    md->nEc=0;
    for(i=0; (i<egNR); i++)
    {
        if (md->bEInd[i])
        {
            md->nEc++;
        }
    }

    n=groups->grps[egcENER].nr;
    /* for adress simulations, most energy terms are not meaningfull, and thus disabled*/
    if (!ir->bAdress){
        /*standard simulation*/
        md->nEg=n;
        md->nE=(n*(n+1))/2;
    }
    else if (!debug) {
        /*AdResS simulation*/
       md->nU=0;
       md->nEg=0;
       md->nE=0;
       md->nEc=0;
       md->isvir=FALSE;
    }
    snew(md->igrp,md->nE);
    if (md->nE > 1)
    {
        n=0;
        snew(gnm,md->nEc);
        for(k=0; (k<md->nEc); k++)
        {
            snew(gnm[k],STRLEN);
        }
        for(i=0; (i<groups->grps[egcENER].nr); i++)
        {
            ni=groups->grps[egcENER].nm_ind[i];
            for(j=i; (j<groups->grps[egcENER].nr); j++)
            {
                nj=groups->grps[egcENER].nm_ind[j];
                for(k=kk=0; (k<egNR); k++)
                {
                    if (md->bEInd[k])
                    {
                        sprintf(gnm[kk],"%s:%s-%s",egrp_nm[k],
                                *(groups->grpname[ni]),*(groups->grpname[nj]));
                        kk++;
                    }
                }
                md->igrp[n]=get_ebin_space(md->ebin,md->nEc,
                                           (const char **)gnm,unit_energy);
                n++;
            }
        }
        for(k=0; (k<md->nEc); k++)
        {
            sfree(gnm[k]);
        }
        sfree(gnm);

        if (n != md->nE)
        {
            gmx_incons("Number of energy terms wrong");
        }
    }

    md->nTC=groups->grps[egcTC].nr;
    md->nNHC = ir->opts.nhchainlength; /* shorthand for number of NH chains */
    if (md->bMTTK)
    {
        md->nTCP = 1;  /* assume only one possible coupling system for barostat
                          for now */
    }
    else
    {
        md->nTCP = 0;
    }
    if (md->etc == etcNOSEHOOVER)
    {
        if (md->bNHC_trotter)
        {
            md->mde_n = 2*md->nNHC*md->nTC;
        }
        else
        {
            md->mde_n = 2*md->nTC;
        }
        if (md->epc == epcMTTK)
        {
            md->mdeb_n = 2*md->nNHC*md->nTCP;
        }
    } else {
        md->mde_n = md->nTC;
        md->mdeb_n = 0;
    }

    snew(md->tmp_r,md->mde_n);
    snew(md->tmp_v,md->mde_n);
    snew(md->grpnms,md->mde_n);
    grpnms = md->grpnms;

    for(i=0; (i<md->nTC); i++)
    {
        ni=groups->grps[egcTC].nm_ind[i];
        sprintf(buf,"T-%s",*(groups->grpname[ni]));
        grpnms[i]=strdup(buf);
    }
    md->itemp=get_ebin_space(md->ebin,md->nTC,(const char **)grpnms,
                             unit_temp_K);

    if (md->etc == etcNOSEHOOVER)
    {
        if (md->bPrintNHChains)
        {
            if (md->bNHC_trotter)
            {
                for(i=0; (i<md->nTC); i++)
                {
                    ni=groups->grps[egcTC].nm_ind[i];
                    bufi = *(groups->grpname[ni]);
                    for(j=0; (j<md->nNHC); j++)
                    {
                        sprintf(buf,"Xi-%d-%s",j,bufi);
                        grpnms[2*(i*md->nNHC+j)]=strdup(buf);
                        sprintf(buf,"vXi-%d-%s",j,bufi);
                        grpnms[2*(i*md->nNHC+j)+1]=strdup(buf);
                    }
                }
                md->itc=get_ebin_space(md->ebin,md->mde_n,
                                       (const char **)grpnms,unit_invtime);
                if (md->bMTTK)
                {
                    for(i=0; (i<md->nTCP); i++)
                    {
                        bufi = baro_nm[0];  /* All barostat DOF's together for now. */
                        for(j=0; (j<md->nNHC); j++)
                        {
                            sprintf(buf,"Xi-%d-%s",j,bufi);
                            grpnms[2*(i*md->nNHC+j)]=strdup(buf);
                            sprintf(buf,"vXi-%d-%s",j,bufi);
                            grpnms[2*(i*md->nNHC+j)+1]=strdup(buf);
                        }
                    }
                    md->itcb=get_ebin_space(md->ebin,md->mdeb_n,
                                            (const char **)grpnms,unit_invtime);
                }
            }
            else
            {
                for(i=0; (i<md->nTC); i++)
                {
                    ni=groups->grps[egcTC].nm_ind[i];
                    bufi = *(groups->grpname[ni]);
                    sprintf(buf,"Xi-%s",bufi);
                    grpnms[2*i]=strdup(buf);
                    sprintf(buf,"vXi-%s",bufi);
                    grpnms[2*i+1]=strdup(buf);
                }
                md->itc=get_ebin_space(md->ebin,md->mde_n,
                                       (const char **)grpnms,unit_invtime);
            }
        }
    }
    else if (md->etc == etcBERENDSEN || md->etc == etcYES ||
             md->etc == etcVRESCALE)
    {
        for(i=0; (i<md->nTC); i++)
        {
            ni=groups->grps[egcTC].nm_ind[i];
            sprintf(buf,"Lamb-%s",*(groups->grpname[ni]));
            grpnms[i]=strdup(buf);
        }
        md->itc=get_ebin_space(md->ebin,md->mde_n,(const char **)grpnms,"");
    }

    sfree(grpnms);


    md->nU=groups->grps[egcACC].nr;
    if (md->nU > 1)
    {
        snew(grpnms,3*md->nU);
        for(i=0; (i<md->nU); i++)
        {
            ni=groups->grps[egcACC].nm_ind[i];
            sprintf(buf,"Ux-%s",*(groups->grpname[ni]));
            grpnms[3*i+XX]=strdup(buf);
            sprintf(buf,"Uy-%s",*(groups->grpname[ni]));
            grpnms[3*i+YY]=strdup(buf);
            sprintf(buf,"Uz-%s",*(groups->grpname[ni]));
            grpnms[3*i+ZZ]=strdup(buf);
        }
        md->iu=get_ebin_space(md->ebin,3*md->nU,(const char **)grpnms,unit_vel);
        sfree(grpnms);
    }

    if ( fp_ene )
    {
        do_enxnms(fp_ene,&md->ebin->nener,&md->ebin->enm);
    }

    md->print_grpnms=NULL;

    /* check whether we're going to write dh histograms */
    md->dhc=NULL;
    if (ir->fepvals->separate_dhdl_file == esepdhdlfileNO )
    {
        /* Currently dh histograms are only written with dynamics */
        if (EI_DYNAMICS(ir->eI))
        {
            snew(md->dhc, 1);

            mde_delta_h_coll_init(md->dhc, ir);
        }
        md->fp_dhdl = NULL;
    }
    else
    {
        md->fp_dhdl = fp_dhdl;
    }
    if (ir->bSimTemp) {
        int i;
        snew(md->temperatures,ir->fepvals->n_lambda);
        for (i=0;i<ir->fepvals->n_lambda;i++)
        {
            md->temperatures[i] = ir->simtempvals->temperatures[i];
        }
    }
    return md;
}
Beispiel #24
0
t_mdebin *init_mdebin(int fp_ene,
		      const gmx_mtop_t *mtop,
		      const t_inputrec *ir)
{
  char *ener_nm[F_NRE];
  static char *vir_nm[] = {
    "Vir-XX", "Vir-XY", "Vir-XZ",
    "Vir-YX", "Vir-YY", "Vir-YZ",
    "Vir-ZX", "Vir-ZY", "Vir-ZZ"
  };
  static char *sv_nm[] = {
    "ShakeVir-XX", "ShakeVir-XY", "ShakeVir-XZ",
    "ShakeVir-YX", "ShakeVir-YY", "ShakeVir-YZ",
    "ShakeVir-ZX", "ShakeVir-ZY", "ShakeVir-ZZ"
  };
  static char *fv_nm[] = {
    "ForceVir-XX", "ForceVir-XY", "ForceVir-XZ",
    "ForceVir-YX", "ForceVir-YY", "ForceVir-YZ",
    "ForceVir-ZX", "ForceVir-ZY", "ForceVir-ZZ"
  };
  static char *pres_nm[] = {
    "Pres-XX (bar)","Pres-XY (bar)","Pres-XZ (bar)",
    "Pres-YX (bar)","Pres-YY (bar)","Pres-YZ (bar)",
    "Pres-ZX (bar)","Pres-ZY (bar)","Pres-ZZ (bar)"
  };
  static char *surft_nm[] = {
    "#Surf*SurfTen"
  };
  static char *mu_nm[] = {
    "Mu-X", "Mu-Y", "Mu-Z"
  };
  static char *vcos_nm[] = {
    "2CosZ*Vel-X"
  };
  static char *visc_nm[] = {
    "1/Viscosity (SI)"
  };
  static   char   **grpnms;
  const gmx_groups_t *groups;
  char     **gnm;
  char     buf[256];
  t_mdebin *md;
  int      i,j,ni,nj,n,k,kk,ncon,nset;
  bool     bBHAM,b14;
  
  f_nre  = 0; // otherwise, multiple calls to mdrunner_integrate are not possible!NnCrmsd; 
  groups = &mtop->groups;

  bBHAM = (mtop->ffparams.functype[0] == F_BHAM);
  b14   = (gmx_mtop_ftype_count(mtop,F_LJ14) > 0 ||
	   gmx_mtop_ftype_count(mtop,F_LJC14_Q) > 0);

  ncon = gmx_mtop_ftype_count(mtop,F_CONSTR);
  nset = gmx_mtop_ftype_count(mtop,F_SETTLE);
  bConstr    = (ncon > 0 || nset > 0);
  bConstrVir = FALSE;
  if (bConstr) {
    if (ncon > 0 && ir->eConstrAlg == econtLINCS) {
      if (ir->eI == eiSD2)
	nCrmsd = 2;
      else
	nCrmsd = 1;
    }
    bConstrVir = (getenv("GMX_CONSTRAINTVIR") != NULL);
  } else {
    nCrmsd = 0;
  }

  for(i=0; i<F_NRE; i++) {
    bEner[i] = FALSE;
    if (i == F_LJ)
      bEner[i] = !bBHAM;
    else if (i == F_BHAM)
      bEner[i] = bBHAM;
    else if (i == F_EQM)
      bEner[i] = ir->bQMMM;
    else if (i == F_COUL_LR)
      bEner[i] = (ir->rcoulomb > ir->rlist);
    else if (i == F_LJ_LR)
      bEner[i] = (!bBHAM && ir->rvdw > ir->rlist);
    else if (i == F_BHAM_LR)
      bEner[i] = (bBHAM && ir->rvdw > ir->rlist);
    else if (i == F_RF_EXCL)
      bEner[i] = (EEL_RF(ir->coulombtype) && ir->coulombtype != eelRF_NEC);
    else if (i == F_COUL_RECIP)
      bEner[i] = EEL_FULL(ir->coulombtype);
    else if (i == F_LJ14)
      bEner[i] = b14;
    else if (i == F_COUL14)
      bEner[i] = b14;
    else if (i == F_LJC14_Q || i == F_LJC_PAIRS_NB)
      bEner[i] = FALSE;
    else if ((i == F_DVDL) || (i == F_DKDL))
      bEner[i] = (ir->efep != efepNO);
    else if (i == F_DGDL_CON)
      bEner[i] = (ir->efep != efepNO && bConstr);
    else if ((interaction_function[i].flags & IF_VSITE) ||
	     (i == F_CONSTR) || (i == F_SETTLE))
      bEner[i] = FALSE;
    else if ((i == F_COUL_SR) || (i == F_EPOT) || (i == F_PRES)  || (i==F_EQM))
      bEner[i] = TRUE;
    else if ((i == F_ETOT) || (i == F_EKIN) || (i == F_TEMP))
      bEner[i] = EI_DYNAMICS(ir->eI);
    else if (i == F_DISPCORR)
      bEner[i] = (ir->eDispCorr != edispcNO);
    else if (i == F_DISRESVIOL)
      bEner[i] = (gmx_mtop_ftype_count(mtop,F_DISRES) > 0);
    else if (i == F_ORIRESDEV)
      bEner[i] = (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0);
    else if (i == F_CONNBONDS)
      bEner[i] = FALSE;
    else if (i == F_COM_PULL)
      bEner[i] = (ir->ePull == epullUMBRELLA || ir->ePull == epullCONST_F);
    else if (i == F_ECONSERVED)
      bEner[i] = ((ir->etc == etcNOSEHOOVER || ir->etc == etcVRESCALE) &&
		  ir->epc == epcNO);
    else
      bEner[i] = (gmx_mtop_ftype_count(mtop,i) > 0);
  }

  for(i=0; i<F_NRE; i++)
    if (bEner[i]) {
      ener_nm[f_nre]=interaction_function[i].longname;
      f_nre++;
    }

  epc = ir->epc;
  bTricl = TRICLINIC(ir->compress) || TRICLINIC(ir->deform);
  bDynBox = DYNAMIC_BOX(*ir);
  etc = ir->etc;
  
  /* Energy monitoring */
  snew(md,1);
  md->ebin  = mk_ebin();
  md->ie    = get_ebin_space(md->ebin,f_nre,ener_nm);
  if (nCrmsd) {
    /* This should be called directly after the call for md->ie,
     * such that md->iconrmsd follows directly in the list.
     */
    md->iconrmsd = get_ebin_space(md->ebin,nCrmsd,conrmsd_nm);
  }
  if (bDynBox)
    md->ib    = get_ebin_space(md->ebin, bTricl ? NTRICLBOXS :
			       NBOXS, bTricl ? tricl_boxs_nm : boxs_nm);
  if (bConstrVir) {
    md->isvir = get_ebin_space(md->ebin,asize(sv_nm),sv_nm);
    md->ifvir = get_ebin_space(md->ebin,asize(fv_nm),fv_nm);
  }
  md->ivir   = get_ebin_space(md->ebin,asize(vir_nm),vir_nm);
  md->ipres  = get_ebin_space(md->ebin,asize(pres_nm),pres_nm);
  md->isurft = get_ebin_space(md->ebin,asize(surft_nm),surft_nm);
  if (epc == epcPARRINELLORAHMAN) {
    md->ipc  = get_ebin_space(md->ebin,bTricl ? 6 : 3,boxvel_nm);
  }
  md->imu    = get_ebin_space(md->ebin,asize(mu_nm),mu_nm);
  if (ir->cos_accel != 0) {
    md->ivcos = get_ebin_space(md->ebin,asize(vcos_nm),vcos_nm);
    md->ivisc = get_ebin_space(md->ebin,asize(visc_nm),visc_nm);
  }
  if (ir->rcoulomb > ir->rlist) 
    bEInd[egCOULLR] = TRUE;
  if (!bBHAM) {
    if (ir->rvdw > ir->rlist)
      bEInd[egLJLR]   = TRUE;
  } else {
    bEInd[egLJSR]   = FALSE;
    bEInd[egBHAMSR] = TRUE;
    if (ir->rvdw > ir->rlist)
      bEInd[egBHAMLR]   = TRUE;
  }
  if (b14) {
    bEInd[egLJ14] = TRUE;
    bEInd[egCOUL14] = TRUE;
  }
  md->nEc=0;
  for(i=0; (i<egNR); i++)
    if (bEInd[i])
      md->nEc++;
      
  n=groups->grps[egcENER].nr;
  md->nEg=n;
  md->nE=(n*(n+1))/2;
  snew(md->igrp,md->nE);
  if (md->nE > 1) {
    n=0;
    snew(gnm,md->nEc);
    for(k=0; (k<md->nEc); k++)
      snew(gnm[k],STRLEN);
    for(i=0; (i<groups->grps[egcENER].nr); i++) {
      ni=groups->grps[egcENER].nm_ind[i];
      for(j=i; (j<groups->grps[egcENER].nr); j++) {
	nj=groups->grps[egcENER].nm_ind[j];
	for(k=kk=0; (k<egNR); k++) {
	  if (bEInd[k]) {
	    sprintf(gnm[kk],"%s:%s-%s",egrp_nm[k],
		    *(groups->grpname[ni]),*(groups->grpname[nj]));
	    kk++;
	  }
	}
	md->igrp[n]=get_ebin_space(md->ebin,md->nEc,gnm);
	n++;
      }
    }
    for(k=0; (k<md->nEc); k++)
      sfree(gnm[k]);
    sfree(gnm);
    
    if (n != md->nE)
      gmx_incons("Number of energy terms wrong");
  }
  
  md->nTC=groups->grps[egcTC].nr;
  snew(grpnms,md->nTC);
  for(i=0; (i<md->nTC); i++) {
    ni=groups->grps[egcTC].nm_ind[i];
    sprintf(buf,"T-%s",*(groups->grpname[ni]));
    grpnms[i]=strdup(buf);
  }
  md->itemp=get_ebin_space(md->ebin,md->nTC,grpnms);
  sfree(*grpnms);
  if (etc == etcNOSEHOOVER) {
    for(i=0; (i<md->nTC); i++) {
      ni=groups->grps[egcTC].nm_ind[i];
      sprintf(buf,"Xi-%s",*(groups->grpname[ni]));
      grpnms[i]=strdup(buf);
    }
    md->itc=get_ebin_space(md->ebin,md->nTC,grpnms);
    sfree(*grpnms);
  } else  if (etc == etcBERENDSEN || etc == etcYES || etc == etcVRESCALE) {
    for(i=0; (i<md->nTC); i++) {
      ni=groups->grps[egcTC].nm_ind[i];
      sprintf(buf,"Lamb-%s",*(groups->grpname[ni]));
      grpnms[i]=strdup(buf);
    }
    md->itc=get_ebin_space(md->ebin,md->nTC,grpnms);
    sfree(*grpnms);
  }
  sfree(grpnms);
  
  md->nU=groups->grps[egcACC].nr;
  if (md->nU > 1) {
    snew(grpnms,3*md->nU);
    for(i=0; (i<md->nU); i++) {
      ni=groups->grps[egcACC].nm_ind[i];
      sprintf(buf,"Ux-%s",*(groups->grpname[ni]));
      grpnms[3*i+XX]=strdup(buf);
      sprintf(buf,"Uy-%s",*(groups->grpname[ni]));
      grpnms[3*i+YY]=strdup(buf);
      sprintf(buf,"Uz-%s",*(groups->grpname[ni]));
      grpnms[3*i+ZZ]=strdup(buf);
    }
    md->iu=get_ebin_space(md->ebin,3*md->nU,grpnms);
    sfree(*grpnms);
    sfree(grpnms);
  }

  if (fp_ene != -1)
    do_enxnms(fp_ene,&md->ebin->nener,&md->ebin->enm);
  
  return md;
}