예제 #1
0
파일: pdbio.c 프로젝트: yhalcyon/Gromacs
void write_pdbfile_indexed(FILE *out, const char *title,
                           t_atoms *atoms, rvec x[],
                           int ePBC, matrix box, char chainid,
                           int model_nr, atom_id nindex, atom_id index[],
                           gmx_conect conect, gmx_bool bTerSepChains)
{
    gmx_conect_t     *gc = (gmx_conect_t *)conect;
    char              resnm[6], nm[6], pdbform[128], pukestring[100];
    atom_id           i, ii;
    int               resind, resnr, type;
    unsigned char     resic, ch;
    real              occup, bfac;
    gmx_bool          bOccup;
    int               nlongname = 0;
    int               chainnum, lastchainnum;
    int               lastresind, lastchainresind;
    gmx_residuetype_t rt;
    const char       *p_restype;
    const char       *p_lastrestype;

    gmx_residuetype_init(&rt);

    bromacs(pukestring, 99);
    fprintf(out, "TITLE     %s\n", (title && title[0]) ? title : pukestring);
    if (bWideFormat)
    {
        fprintf(out, "REMARK    This file does not adhere to the PDB standard\n");
        fprintf(out, "REMARK    As a result of, some programs may not like it\n");
    }
    if (box && ( norm2(box[XX]) || norm2(box[YY]) || norm2(box[ZZ]) ) )
    {
        gmx_write_pdb_box(out, ePBC, box);
    }
    if (atoms->pdbinfo)
    {
        /* Check whether any occupancies are set, in that case leave it as is,
         * otherwise set them all to one
         */
        bOccup = TRUE;
        for (ii = 0; (ii < nindex) && bOccup; ii++)
        {
            i      = index[ii];
            bOccup = bOccup && (atoms->pdbinfo[i].occup == 0.0);
        }
    }
    else
    {
        bOccup = FALSE;
    }

    fprintf(out, "MODEL %8d\n", model_nr > 0 ? model_nr : 1);

    lastchainresind   = -1;
    lastchainnum      = -1;
    resind            = -1;
    p_restype         = NULL;

    for (ii = 0; ii < nindex; ii++)
    {
        i             = index[ii];
        lastresind    = resind;
        resind        = atoms->atom[i].resind;
        chainnum      = atoms->resinfo[resind].chainnum;
        p_lastrestype = p_restype;
        gmx_residuetype_get_type(rt, *atoms->resinfo[resind].name, &p_restype);

        /* Add a TER record if we changed chain, and if either the previous or this chain is protein/DNA/RNA. */
        if (bTerSepChains && ii > 0 && chainnum != lastchainnum)
        {
            /* Only add TER if the previous chain contained protein/DNA/RNA. */
            if (gmx_residuetype_is_protein(rt, p_lastrestype) || gmx_residuetype_is_dna(rt, p_lastrestype) || gmx_residuetype_is_rna(rt, p_lastrestype))
            {
                fprintf(out, "TER\n");
            }
            lastchainnum    = chainnum;
            lastchainresind = lastresind;
        }

        strncpy(resnm, *atoms->resinfo[resind].name, sizeof(resnm)-1);
        strncpy(nm, *atoms->atomname[i], sizeof(nm)-1);
        /* rename HG12 to 2HG1, etc. */
        xlate_atomname_gmx2pdb(nm);
        resnr = atoms->resinfo[resind].nr;
        resic = atoms->resinfo[resind].ic;
        if (chainid != ' ')
        {
            ch = chainid;
        }
        else
        {
            ch = atoms->resinfo[resind].chainid;

            if (ch == 0)
            {
                ch = ' ';
            }
        }
        if (resnr >= 10000)
        {
            resnr = resnr % 10000;
        }
        if (atoms->pdbinfo)
        {
            type  = atoms->pdbinfo[i].type;
            occup = bOccup ? 1.0 : atoms->pdbinfo[i].occup;
            bfac  = atoms->pdbinfo[i].bfac;
        }
        else
        {
            type  = 0;
            occup = 1.0;
            bfac  = 0.0;
        }
        if (bWideFormat)
        {
            strcpy(pdbform,
                   "%-6s%5u %-4.4s %3.3s %c%4d%c   %10.5f%10.5f%10.5f%8.4f%8.4f    %2s\n");
        }
        else
        {
            /* Check whether atomname is an element name */
            if ((strlen(nm) < 4) && (gmx_strcasecmp(nm, atoms->atom[i].elem) != 0))
            {
                strcpy(pdbform, pdbformat);
            }
            else
            {
                strcpy(pdbform, pdbformat4);
                if (strlen(nm) > 4)
                {
                    int maxwln = 20;
                    if (nlongname < maxwln)
                    {
                        fprintf(stderr, "WARNING: Writing out atom name (%s) longer than 4 characters to .pdb file\n", nm);
                    }
                    else if (nlongname == maxwln)
                    {
                        fprintf(stderr, "WARNING: More than %d long atom names, will not write more warnings\n", maxwln);
                    }
                    nlongname++;
                }
            }
            strcat(pdbform, "%6.2f%6.2f          %2s\n");
        }
        fprintf(out, pdbform, pdbtp[type], (i+1)%100000, nm, resnm, ch, resnr,
                (resic == '\0') ? ' ' : resic,
                10*x[i][XX], 10*x[i][YY], 10*x[i][ZZ], occup, bfac, atoms->atom[i].elem);
        if (atoms->pdbinfo && atoms->pdbinfo[i].bAnisotropic)
        {
            fprintf(out, "ANISOU%5u  %-4.4s%3.3s %c%4d%c %7d%7d%7d%7d%7d%7d\n",
                    (i+1)%100000, nm, resnm, ch, resnr,
                    (resic == '\0') ? ' ' : resic,
                    atoms->pdbinfo[i].uij[0], atoms->pdbinfo[i].uij[1],
                    atoms->pdbinfo[i].uij[2], atoms->pdbinfo[i].uij[3],
                    atoms->pdbinfo[i].uij[4], atoms->pdbinfo[i].uij[5]);
        }
    }

    fprintf(out, "TER\n");
    fprintf(out, "ENDMDL\n");

    if (NULL != gc)
    {
        /* Write conect records */
        for (i = 0; (i < gc->nconect); i++)
        {
            fprintf(out, "CONECT%5d%5d\n", gc->conect[i].ai+1, gc->conect[i].aj+1);
        }
    }

    gmx_residuetype_destroy(rt);
}
예제 #2
0
파일: pack_test.cpp 프로젝트: fwinter/quda
void packTest() {

  float spinorGiB = (float)Vh*spinorSiteSize*param.cuda_prec / (1 << 30);
  printf("\nSpinor mem: %.3f GiB\n", spinorGiB);
  printf("Gauge mem: %.3f GiB\n", param.gaugeGiB);

  printf("Sending fields to GPU...\n"); fflush(stdout);
  
  /*{
    param.gauge_order = QUDA_CPS_WILSON_GAUGE_ORDER;
    
    GaugeFieldParam cpsParam(cpsCpuGauge_p, param);
    cpuGaugeField cpsCpuGauge(cpsParam);
    cpsParam.create = QUDA_NULL_FIELD_CREATE;
    cpsParam.precision = param.cuda_prec;
    cpsParam.reconstruct = param.reconstruct;
    cpsParam.pad = param.ga_pad;
    cpsParam.order = (cpsParam.precision == QUDA_DOUBLE_PRECISION || 
		      cpsParam.reconstruct == QUDA_RECONSTRUCT_NO ) ?
      QUDA_FLOAT2_GAUGE_ORDER : QUDA_FLOAT4_GAUGE_ORDER;
    cudaGaugeField cudaCpsGauge(cpsParam);

    stopwatchStart();
    cudaCpsGauge.loadCPUField(cpsCpuGauge);    
    double cpsGtime = stopwatchReadSeconds();
    printf("CPS Gauge send time = %e seconds\n", cpsGtime);

    stopwatchStart();
    cudaCpsGauge.saveCPUField(cpsCpuGauge);
    double cpsGRtime = stopwatchReadSeconds();
    printf("CPS Gauge restore time = %e seconds\n", cpsGRtime);
  }*/

  {
    param.gauge_order = QUDA_QDP_GAUGE_ORDER;
    
    GaugeFieldParam qdpParam(qdpCpuGauge_p, param);
    cpuGaugeField qdpCpuGauge(qdpParam);
    qdpParam.create = QUDA_NULL_FIELD_CREATE;
    qdpParam.precision = param.cuda_prec;
    qdpParam.reconstruct = param.reconstruct;
    qdpParam.pad = param.ga_pad;
    qdpParam.order = (qdpParam.precision == QUDA_DOUBLE_PRECISION || 
		      qdpParam.reconstruct == QUDA_RECONSTRUCT_NO ) ?
      QUDA_FLOAT2_GAUGE_ORDER : QUDA_FLOAT4_GAUGE_ORDER;
    cudaGaugeField cudaQdpGauge(qdpParam);

    stopwatchStart();
    cudaQdpGauge.loadCPUField(qdpCpuGauge);    
    double qdpGtime = stopwatchReadSeconds();
    printf("QDP Gauge send time = %e seconds\n", qdpGtime);

    stopwatchStart();
    cudaQdpGauge.saveCPUField(qdpCpuGauge);
    double qdpGRtime = stopwatchReadSeconds();
    printf("QDP Gauge restore time = %e seconds\n", qdpGRtime);
  }

  stopwatchStart();
  *cudaSpinor = *spinor;
  double sSendTime = stopwatchReadSeconds();
  printf("Spinor send time = %e seconds\n", sSendTime);

  stopwatchStart();
  *spinor2 = *cudaSpinor;
  double sRecTime = stopwatchReadSeconds();
  printf("Spinor receive time = %e seconds\n", sRecTime);
  
  std::cout << "Norm check: CPU = " << norm2(*spinor) << 
    ", CUDA = " << norm2(*cudaSpinor) << 
    ", CPU =  " << norm2(*spinor2) << std::endl;

  cpuColorSpinorField::Compare(*spinor, *spinor2, 1);

}
예제 #3
0
real
do_nonbonded_listed(int ftype, int nbonds,
                    const t_iatom iatoms[], const t_iparams iparams[],
                    const rvec x[], rvec f[], rvec fshift[],
                    const t_pbc *pbc, const t_graph *g,
                    real *lambda, real *dvdl,
                    const t_mdatoms *md,
                    const t_forcerec *fr, gmx_grppairener_t *grppener,
                    int *global_atom_index)
{
    int              ielec, ivdw;
    real             qq, c6, c12;
    rvec             dx;
    ivec             dt;
    int              i, j, itype, ai, aj, gid;
    int              fshift_index;
    real             r2, rinv;
    real             fscal, velec, vvdw;
    real *           energygrp_elec;
    real *           energygrp_vdw;
    static gmx_bool  warned_rlimit = FALSE;
    /* Free energy stuff */
    gmx_bool         bFreeEnergy;
    real             LFC[2], LFV[2], DLF[2], lfac_coul[2], lfac_vdw[2], dlfac_coul[2], dlfac_vdw[2];
    real             qqB, c6B, c12B, sigma2_def, sigma2_min;


    switch (ftype)
    {
        case F_LJ14:
        case F_LJC14_Q:
            energygrp_elec = grppener->ener[egCOUL14];
            energygrp_vdw  = grppener->ener[egLJ14];
            break;
        case F_LJC_PAIRS_NB:
            energygrp_elec = grppener->ener[egCOULSR];
            energygrp_vdw  = grppener->ener[egLJSR];
            break;
        default:
            energygrp_elec = NULL; /* Keep compiler happy */
            energygrp_vdw  = NULL; /* Keep compiler happy */
            gmx_fatal(FARGS, "Unknown function type %d in do_nonbonded14", ftype);
            break;
    }

    if (fr->efep != efepNO)
    {
        /* Lambda factor for state A=1-lambda and B=lambda */
        LFC[0] = 1.0 - lambda[efptCOUL];
        LFV[0] = 1.0 - lambda[efptVDW];
        LFC[1] = lambda[efptCOUL];
        LFV[1] = lambda[efptVDW];

        /*derivative of the lambda factor for state A and B */
        DLF[0] = -1;
        DLF[1] = 1;

        /* precalculate */
        sigma2_def = pow(fr->sc_sigma6_def, 1.0/3.0);
        sigma2_min = pow(fr->sc_sigma6_min, 1.0/3.0);

        for (i = 0; i < 2; i++)
        {
            lfac_coul[i]  = (fr->sc_power == 2 ? (1-LFC[i])*(1-LFC[i]) : (1-LFC[i]));
            dlfac_coul[i] = DLF[i]*fr->sc_power/fr->sc_r_power*(fr->sc_power == 2 ? (1-LFC[i]) : 1);
            lfac_vdw[i]   = (fr->sc_power == 2 ? (1-LFV[i])*(1-LFV[i]) : (1-LFV[i]));
            dlfac_vdw[i]  = DLF[i]*fr->sc_power/fr->sc_r_power*(fr->sc_power == 2 ? (1-LFV[i]) : 1);
        }
    }
    else
    {
        sigma2_min = sigma2_def = 0;
    }

    bFreeEnergy = FALSE;
    for (i = 0; (i < nbonds); )
    {
        itype = iatoms[i++];
        ai    = iatoms[i++];
        aj    = iatoms[i++];
        gid   = GID(md->cENER[ai], md->cENER[aj], md->nenergrp);

        /* Get parameters */
        switch (ftype)
        {
            case F_LJ14:
                bFreeEnergy =
                    (fr->efep != efepNO &&
                     ((md->nPerturbed && (md->bPerturbed[ai] || md->bPerturbed[aj])) ||
                      iparams[itype].lj14.c6A != iparams[itype].lj14.c6B ||
                      iparams[itype].lj14.c12A != iparams[itype].lj14.c12B));
                qq               = md->chargeA[ai]*md->chargeA[aj]*fr->epsfac*fr->fudgeQQ;
                c6               = iparams[itype].lj14.c6A;
                c12              = iparams[itype].lj14.c12A;
                break;
            case F_LJC14_Q:
                qq               = iparams[itype].ljc14.qi*iparams[itype].ljc14.qj*fr->epsfac*iparams[itype].ljc14.fqq;
                c6               = iparams[itype].ljc14.c6;
                c12              = iparams[itype].ljc14.c12;
                break;
            case F_LJC_PAIRS_NB:
                qq               = iparams[itype].ljcnb.qi*iparams[itype].ljcnb.qj*fr->epsfac;
                c6               = iparams[itype].ljcnb.c6;
                c12              = iparams[itype].ljcnb.c12;
                break;
            default:
                /* Cannot happen since we called gmx_fatal() above in this case */
                qq = c6 = c12 = 0; /* Keep compiler happy */
                break;
        }

        /* To save flops in the optimized kernels, c6/c12 have 6.0/12.0 derivative prefactors
         * included in the general nfbp array now. This means the tables are scaled down by the
         * same factor, so when we use the original c6/c12 parameters from iparams[] they must
         * be scaled up.
         */
        c6  *= 6.0;
        c12 *= 12.0;

        /* Do we need to apply full periodic boundary conditions? */
        if (fr->bMolPBC == TRUE)
        {
            fshift_index = pbc_dx_aiuc(pbc, x[ai], x[aj], dx);
        }
        else
        {
            fshift_index = CENTRAL;
            rvec_sub(x[ai], x[aj], dx);
        }
        r2           = norm2(dx);

        if (r2 >= fr->tab14.r*fr->tab14.r)
        {
            if (warned_rlimit == FALSE)
            {
                nb_listed_warning_rlimit(x, ai, aj, global_atom_index, sqrt(r2), fr->tab14.r);
                warned_rlimit = TRUE;
            }
            continue;
        }

        if (bFreeEnergy)
        {
            /* Currently free energy is only supported for F_LJ14, so no need to check for that if we got here */
            qqB              = md->chargeB[ai]*md->chargeB[aj]*fr->epsfac*fr->fudgeQQ;
            c6B              = iparams[itype].lj14.c6B*6.0;
            c12B             = iparams[itype].lj14.c12B*12.0;

            fscal            = nb_free_energy_evaluate_single(r2, fr->sc_r_power, fr->sc_alphacoul, fr->sc_alphavdw,
                                                              fr->tab14.scale, fr->tab14.data, qq, c6, c12, qqB, c6B, c12B,
                                                              LFC, LFV, DLF, lfac_coul, lfac_vdw, dlfac_coul, dlfac_vdw,
                                                              fr->sc_sigma6_def, fr->sc_sigma6_min, sigma2_def, sigma2_min, &velec, &vvdw, dvdl);
        }
        else
        {
            /* Evaluate tabulated interaction without free energy */
            fscal            = nb_evaluate_single(r2, fr->tab14.scale, fr->tab14.data, qq, c6, c12, &velec, &vvdw);
        }

        energygrp_elec[gid]  += velec;
        energygrp_vdw[gid]   += vvdw;
        svmul(fscal, dx, dx);

        /* Add the forces */
        rvec_inc(f[ai], dx);
        rvec_dec(f[aj], dx);

        if (g)
        {
            /* Correct the shift forces using the graph */
            ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
            fshift_index = IVEC2IS(dt);
        }
        if (fshift_index != CENTRAL)
        {
            rvec_inc(fshift[fshift_index], dx);
            rvec_dec(fshift[CENTRAL], dx);
        }
    }
    return 0.0;
}
예제 #4
0
void write_pdbfile_indexed(FILE *out, const char *title,
                           t_atoms *atoms, rvec x[],
                           int ePBC, matrix box, char chainid,
                           int model_nr, int nindex, const int index[],
                           gmx_conect conect, gmx_bool bTerSepChains)
{
    gmx_conect_t     *gc = (gmx_conect_t *)conect;
    char              resnm[6], nm[6];
    int               i, ii;
    int               resind, resnr;
    enum PDB_record   type;
    unsigned char     resic, ch;
    char              altloc;
    real              occup, bfac;
    gmx_bool          bOccup;
    int               chainnum, lastchainnum;
    gmx_residuetype_t*rt;
    const char       *p_restype;
    const char       *p_lastrestype;

    gmx_residuetype_init(&rt);

    fprintf(out, "TITLE     %s\n", (title && title[0]) ? title : gmx::bromacs().c_str());
    if (box && ( norm2(box[XX]) || norm2(box[YY]) || norm2(box[ZZ]) ) )
    {
        gmx_write_pdb_box(out, ePBC, box);
    }
    if (atoms->pdbinfo)
    {
        /* Check whether any occupancies are set, in that case leave it as is,
         * otherwise set them all to one
         */
        bOccup = TRUE;
        for (ii = 0; (ii < nindex) && bOccup; ii++)
        {
            i      = index[ii];
            bOccup = bOccup && (atoms->pdbinfo[i].occup == 0.0);
        }
    }
    else
    {
        bOccup = FALSE;
    }

    fprintf(out, "MODEL %8d\n", model_nr > 0 ? model_nr : 1);

    lastchainnum      = -1;
    p_restype         = NULL;

    for (ii = 0; ii < nindex; ii++)
    {
        i             = index[ii];
        resind        = atoms->atom[i].resind;
        chainnum      = atoms->resinfo[resind].chainnum;
        p_lastrestype = p_restype;
        gmx_residuetype_get_type(rt, *atoms->resinfo[resind].name, &p_restype);

        /* Add a TER record if we changed chain, and if either the previous or this chain is protein/DNA/RNA. */
        if (bTerSepChains && ii > 0 && chainnum != lastchainnum)
        {
            /* Only add TER if the previous chain contained protein/DNA/RNA. */
            if (gmx_residuetype_is_protein(rt, p_lastrestype) || gmx_residuetype_is_dna(rt, p_lastrestype) || gmx_residuetype_is_rna(rt, p_lastrestype))
            {
                fprintf(out, "TER\n");
            }
            lastchainnum    = chainnum;
        }

        strncpy(resnm, *atoms->resinfo[resind].name, sizeof(resnm)-1);
        resnm[sizeof(resnm)-1] = 0;
        strncpy(nm, *atoms->atomname[i], sizeof(nm)-1);
        nm[sizeof(nm)-1] = 0;

        /* rename HG12 to 2HG1, etc. */
        xlate_atomname_gmx2pdb(nm);
        resnr = atoms->resinfo[resind].nr;
        resic = atoms->resinfo[resind].ic;
        if (chainid != ' ')
        {
            ch = chainid;
        }
        else
        {
            ch = atoms->resinfo[resind].chainid;

            if (ch == 0)
            {
                ch = ' ';
            }
        }
        if (resnr >= 10000)
        {
            resnr = resnr % 10000;
        }
        if (atoms->pdbinfo)
        {
            type   = static_cast<enum PDB_record>(atoms->pdbinfo[i].type);
            altloc = atoms->pdbinfo[i].altloc;
            if (!isalnum(altloc))
            {
                altloc = ' ';
            }
            occup = bOccup ? 1.0 : atoms->pdbinfo[i].occup;
            bfac  = atoms->pdbinfo[i].bfac;
        }
        else
        {
            type   = epdbATOM;
            occup  = 1.0;
            bfac   = 0.0;
            altloc = ' ';
        }

        gmx_fprintf_pdb_atomline(out,
                                 type,
                                 i+1,
                                 nm,
                                 altloc,
                                 resnm,
                                 ch,
                                 resnr,
                                 resic,
                                 10*x[i][XX], 10*x[i][YY], 10*x[i][ZZ],
                                 occup,
                                 bfac,
                                 atoms->atom[i].elem);

        if (atoms->pdbinfo && atoms->pdbinfo[i].bAnisotropic)
        {
            fprintf(out, "ANISOU%5d  %-4.4s%4.4s%c%4d%c %7d%7d%7d%7d%7d%7d\n",
                    (i+1)%100000, nm, resnm, ch, resnr,
                    (resic == '\0') ? ' ' : resic,
                    atoms->pdbinfo[i].uij[0], atoms->pdbinfo[i].uij[1],
                    atoms->pdbinfo[i].uij[2], atoms->pdbinfo[i].uij[3],
                    atoms->pdbinfo[i].uij[4], atoms->pdbinfo[i].uij[5]);
        }
    }

    fprintf(out, "TER\n");
    fprintf(out, "ENDMDL\n");

    if (NULL != gc)
    {
        /* Write conect records */
        for (i = 0; (i < gc->nconect); i++)
        {
            fprintf(out, "CONECT%5d%5d\n", gc->conect[i].ai+1, gc->conect[i].aj+1);
        }
    }

    gmx_residuetype_destroy(rt);
}
예제 #5
0
double norm(const dVector3& a){
  return std::sqrt(norm2(a));
}
예제 #6
0
  void MR::operator()(cudaColorSpinorField &x, cudaColorSpinorField &b)
  {

    globalReduce = false; // use local reductions for DD solver

    if (!init) {
      ColorSpinorParam csParam(x);
      csParam.create = QUDA_ZERO_FIELD_CREATE;
      if (param.preserve_source == QUDA_PRESERVE_SOURCE_YES) {
	rp = new cudaColorSpinorField(x, csParam); 
	allocate_r = true;
      }
      Arp = new cudaColorSpinorField(x);
      tmpp = new cudaColorSpinorField(x, csParam); //temporary for mat-vec

      init = true;
    }
    cudaColorSpinorField &r = 
      (param.preserve_source == QUDA_PRESERVE_SOURCE_YES) ? *rp : b;
    cudaColorSpinorField &Ar = *Arp;
    cudaColorSpinorField &tmp = *tmpp;

    // set initial guess to zero and thus the residual is just the source
    zeroCuda(x);  // can get rid of this for a special first update kernel  
    double b2 = normCuda(b);
    if (&r != &b) copyCuda(r, b);

    // domain-wise normalization of the initial residual to prevent underflow
    double r2=0.0; // if zero source then we will exit immediately doing no work
    if (b2 > 0.0) {
      axCuda(1/sqrt(b2), r); // can merge this with the prior copy
      r2 = 1.0; // by definition by this is now true
    }

    if (param.inv_type_precondition != QUDA_GCR_INVERTER) {
      quda::blas_flops = 0;
      profile.TPSTART(QUDA_PROFILE_COMPUTE);
    }

    double omega = 1.0;

    int k = 0;
    if (getVerbosity() >= QUDA_DEBUG_VERBOSE) {
      double x2 = norm2(x);
      double3 Ar3 = cDotProductNormBCuda(Ar, r);
      printfQuda("MR: %d iterations, r2 = %e, <r|A|r> = (%e, %e), x2 = %e\n", 
		 k, Ar3.z, Ar3.x, Ar3.y, x2);
    }

    while (k < param.maxiter && r2 > 0.0) {
    
      mat(Ar, r, tmp);

      double3 Ar3 = cDotProductNormACuda(Ar, r);
      Complex alpha = Complex(Ar3.x, Ar3.y) / Ar3.z;

      // x += omega*alpha*r, r -= omega*alpha*Ar, r2 = norm2(r)
      //r2 = caxpyXmazNormXCuda(omega*alpha, r, x, Ar);
      caxpyXmazCuda(omega*alpha, r, x, Ar);

      if (getVerbosity() >= QUDA_DEBUG_VERBOSE) {
	double x2 = norm2(x);
	double r2 = norm2(r);
	printfQuda("MR: %d iterations, r2 = %e, <r|A|r> = (%e,%e) x2 = %e\n", 
		   k+1, r2, Ar3.x, Ar3.y, x2);
      } else if (getVerbosity() >= QUDA_VERBOSE) {
	printfQuda("MR: %d iterations, <r|A|r> = (%e, %e)\n", k, Ar3.x, Ar3.y);
      }

      k++;
    }
  
    if (getVerbosity() >= QUDA_VERBOSE) {
      mat(Ar, r, tmp);    
      Complex Ar2 = cDotProductCuda(Ar, r);
      printfQuda("MR: %d iterations, <r|A|r> = (%e, %e)\n", k, real(Ar2), imag(Ar2));
    }

    // Obtain global solution by rescaling
    if (b2 > 0.0) axCuda(sqrt(b2), x);

    if (param.inv_type_precondition != QUDA_GCR_INVERTER) {
        profile.TPSTOP(QUDA_PROFILE_COMPUTE);
        profile.TPSTART(QUDA_PROFILE_EPILOGUE);
	param.secs += profile.Last(QUDA_PROFILE_COMPUTE);
  
	double gflops = (quda::blas_flops + mat.flops())*1e-9;
	reduceDouble(gflops);
	
	param.gflops += gflops;
	param.iter += k;
	
	// this is the relative residual since it has been scaled by b2
	r2 = norm2(r);

	if (param.preserve_source == QUDA_PRESERVE_SOURCE_YES) {
	  // Calculate the true residual
	  mat(r, x);
	  double true_res = xmyNormCuda(b, r);
	  param.true_res = sqrt(true_res / b2);
	  if (getVerbosity() >= QUDA_SUMMARIZE) {
	    printfQuda("MR: Converged after %d iterations, relative residua: iterated = %e, true = %e\n",
		       k, sqrt(r2), param.true_res);
	  }
	} else {
	  if (getVerbosity() >= QUDA_SUMMARIZE) {
	    printfQuda("MR: Converged after %d iterations, relative residua: iterated = %e\n", k, sqrt(r2));
	  }
	}

	// reset the flops counters
	quda::blas_flops = 0;
	mat.flops();
        profile.TPSTOP(QUDA_PROFILE_EPILOGUE);
    }

    globalReduce = true; // renable global reductions for outer solver

    return;
  }
예제 #7
0
파일: orires.cpp 프로젝트: rmcgibbo/gromacs
real orires(int nfa, const t_iatom forceatoms[], const t_iparams ip[],
            const rvec x[], rvec f[], rvec fshift[],
            const t_pbc *pbc, const t_graph *g,
            real gmx_unused lambda, real gmx_unused *dvdlambda,
            const t_mdatoms gmx_unused *md, t_fcdata *fcd,
            int gmx_unused *global_atom_index)
{
    atom_id             ai, aj;
    int                 fa, d, i, type, ex, power, ki = CENTRAL;
    ivec                dt;
    real                r2, invr, invr2, fc, smooth_fc, dev, devins, pfac;
    rvec                r, Sr, fij;
    real                vtot;
    const t_oriresdata *od;
    gmx_bool            bTAV;

    vtot = 0;
    od   = &(fcd->orires);

    if (od->fc != 0)
    {
        bTAV = (od->edt != 0);

        smooth_fc = od->fc;
        if (bTAV)
        {
            /* Smoothly switch on the restraining when time averaging is used */
            smooth_fc *= (1.0 - od->exp_min_t_tau);
        }

        d = 0;
        for (fa = 0; fa < nfa; fa += 3)
        {
            type  = forceatoms[fa];
            ai    = forceatoms[fa+1];
            aj    = forceatoms[fa+2];
            if (pbc)
            {
                ki = pbc_dx_aiuc(pbc, x[ai], x[aj], r);
            }
            else
            {
                rvec_sub(x[ai], x[aj], r);
            }
            r2    = norm2(r);
            invr  = gmx_invsqrt(r2);
            invr2 = invr*invr;
            ex    = ip[type].orires.ex;
            power = ip[type].orires.power;
            fc    = smooth_fc*ip[type].orires.kfac;
            dev   = od->otav[d] - ip[type].orires.obs;

            /* NOTE:
             * there is no real potential when time averaging is applied
             */
            vtot += 0.5*fc*sqr(dev);

            if (bTAV)
            {
                /* Calculate the force as the sqrt of tav times instantaneous */
                devins = od->oins[d] - ip[type].orires.obs;
                if (dev*devins <= 0)
                {
                    dev = 0;
                }
                else
                {
                    dev = std::sqrt(dev*devins);
                    if (devins < 0)
                    {
                        dev = -dev;
                    }
                }
            }

            pfac  = fc*ip[type].orires.c*invr2;
            for (i = 0; i < power; i++)
            {
                pfac *= invr;
            }
            mvmul(od->S[ex], r, Sr);
            for (i = 0; i < DIM; i++)
            {
                fij[i] =
                    -pfac*dev*(4*Sr[i] - 2*(2+power)*invr2*iprod(Sr, r)*r[i]);
            }

            if (g)
            {
                ivec_sub(SHIFT_IVEC(g, ai), SHIFT_IVEC(g, aj), dt);
                ki = IVEC2IS(dt);
            }

            for (i = 0; i < DIM; i++)
            {
                f[ai][i]           += fij[i];
                f[aj][i]           -= fij[i];
                fshift[ki][i]      += fij[i];
                fshift[CENTRAL][i] -= fij[i];
            }
            d++;
        }
    }

    return vtot;

    /* Approx. 80*nfa/3 flops */
}
예제 #8
0
 inline value_type norm() const
 {
   return std::sqrt(norm2());
 }
예제 #9
0
int gmx_dist(int argc,char *argv[])
{
  const char *desc[] = {
    "g_dist can calculate the distance between the centers of mass of two",
    "groups of atoms as a function of time. The total distance and its",
    "x, y and z components are plotted.[PAR]",
    "Or when [TT]-dist[tt] is set, print all the atoms in group 2 that are",
    "closer than a certain distance to the center of mass of group 1.[PAR]",
    "With options [TT]-lt[tt] and [TT]-dist[tt] the number of contacts",
    "of all atoms in group 2 that are closer than a certain distance",
    "to the center of mass of group 1 are plotted as a function of the time",
    "that the contact was continously present.[PAR]",
    "Other programs that calculate distances are [TT]g_mindist[tt]",
    "and [TT]g_bond[tt]."
  };
  
  t_topology *top=NULL;
  int  ePBC;
  real t,t0,cut2,dist2;
  rvec *x=NULL,*v=NULL,dx;
  matrix box;
  t_trxstatus *status;
  int natoms;

  int g,d,i,j,res,teller=0;
  atom_id aid;

  int     ngrps;     /* the number of index groups */
  atom_id **index,max;   /* the index for the atom numbers */
  int     *isize;    /* the size of each group */
  char    **grpname; /* the name of each group */
  rvec    *com;
  real    *mass;
  FILE    *fp=NULL,*fplt=NULL;
  gmx_bool    bCutoff,bPrintDist,bLifeTime;
  t_pbc   *pbc;
  int     *contact_time=NULL,*ccount=NULL,ccount_nalloc=0,sum;
  char    buf[STRLEN];
  output_env_t oenv;
  gmx_rmpbc_t  gpbc=NULL;
  
  const char *leg[4] = { "|d|","d\\sx\\N","d\\sy\\N","d\\sz\\N" };

  static real cut=0;
  
  static t_pargs pa[] = {
    { "-dist",      FALSE, etREAL, {&cut},
      "Print all atoms in group 2 closer than dist to the center of mass of group 1" }
  };
#define NPA asize(pa)

  t_filenm fnm[] = {
    { efTRX, "-f", NULL, ffREAD },
    { efTPX, NULL, NULL, ffREAD },
    { efNDX, NULL, NULL, ffOPTRD },
    { efXVG, NULL, "dist", ffOPTWR },
    { efXVG, "-lt", "lifetime", ffOPTWR },
  };
#define NFILE asize(fnm)


  CopyRight(stderr,argv[0]);

  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE,
		    NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL,&oenv);
  
  bCutoff = opt2parg_bSet("-dist",NPA,pa);
  cut2 = cut*cut;
  bLifeTime = opt2bSet("-lt",NFILE,fnm);
  bPrintDist = (bCutoff && !bLifeTime);
  
  top=read_top(ftp2fn(efTPX,NFILE,fnm),&ePBC);
  
  /* read index files */
  ngrps = 2;
  snew(com,ngrps);
  snew(grpname,ngrps);
  snew(index,ngrps);
  snew(isize,ngrps);
  get_index(&top->atoms,ftp2fn(efNDX,NFILE,fnm),ngrps,isize,index,grpname);
  
  /* calculate mass */
  max=0;
  snew(mass,ngrps);
  for(g=0;(g<ngrps);g++) {
    mass[g]=0;
    for(i=0;(i<isize[g]);i++) {
      if (index[g][i]>max)
	max=index[g][i];
      if (index[g][i] >= top->atoms.nr)
	gmx_fatal(FARGS,"Atom number %d, item %d of group %d, is larger than number of atoms in the topolgy (%d)\n",index[g][i]+1,i+1,g+1,top->atoms.nr+1);
      mass[g]+=top->atoms.atom[index[g][i]].m;
    }
  }

  natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
  t0 = t;

  if (max>=natoms)
    gmx_fatal(FARGS,"Atom number %d in an index group is larger than number of atoms in the trajectory (%d)\n",(int)max+1,natoms);

  if (!bCutoff) {
    /* open output file */
    fp = xvgropen(ftp2fn(efXVG,NFILE,fnm),
		  "Distance","Time (ps)","Distance (nm)",oenv);
    xvgr_legend(fp,4,leg,oenv);
  } else {
    ngrps = 1;
    if (bLifeTime)
      snew(contact_time,isize[1]);
  }
  if (ePBC != epbcNONE)
    snew(pbc,1);
  else
    pbc = NULL;
    
  gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
  do {
    /* initialisation for correct distance calculations */
    if (pbc) {
      set_pbc(pbc,ePBC,box);
      /* make molecules whole again */
      gmx_rmpbc(gpbc,natoms,box,x);
    }
    /* calculate center of masses */
    for(g=0;(g<ngrps);g++) {
      if (isize[g] == 1) {
	copy_rvec(x[index[g][0]],com[g]);
      } else {
	for(d=0;(d<DIM);d++) {
	  com[g][d]=0;
	  for(i=0;(i<isize[g]);i++) {
	    com[g][d] += x[index[g][i]][d] * top->atoms.atom[index[g][i]].m;
	  }
	  com[g][d] /= mass[g];
	}
      }
    }
    
    if (!bCutoff) {
      /* write to output */
      fprintf(fp,"%12.7f ",t);
      for(g=0;(g<ngrps/2);g++) {
	if (pbc)
	  pbc_dx(pbc,com[2*g],com[2*g+1],dx);
	else
	  rvec_sub(com[2*g],com[2*g+1],dx);
	
	fprintf(fp,"%12.7f %12.7f %12.7f %12.7f",
		norm(dx),dx[XX],dx[YY],dx[ZZ]);
      }
      fprintf(fp,"\n");
    } else {
      for(i=0;(i<isize[1]);i++) { 
	j=index[1][i];
	if (pbc)
	  pbc_dx(pbc,x[j],com[0],dx);
	else
	  rvec_sub(x[j],com[0],dx);
	
	dist2 = norm2(dx);
	if (dist2<cut2) {
	  if (bPrintDist) {
	    res=top->atoms.atom[j].resind;
	    fprintf(stdout,"\rt: %g  %d %s %d %s  %g (nm)\n",
		    t,top->atoms.resinfo[res].nr,*top->atoms.resinfo[res].name,
		    j+1,*top->atoms.atomname[j],sqrt(dist2));
	  }
	  if (bLifeTime)
	    contact_time[i]++;
	} else {
	  if (bLifeTime) {
	    if (contact_time[i]) {
	      add_contact_time(&ccount,&ccount_nalloc,contact_time[i]-1);
	      contact_time[i] = 0;
	    }
	  }
	}
      }
    }
    
    teller++;
  } while (read_next_x(oenv,status,&t,natoms,x,box));
  gmx_rmpbc_done(gpbc);

  if (!bCutoff)
    ffclose(fp);

  close_trj(status);
  
  if (bCutoff && bLifeTime) {
    /* Add the contacts still present in the last frame */
    for(i=0; i<isize[1]; i++)
      if (contact_time[i])
	add_contact_time(&ccount,&ccount_nalloc,contact_time[i]-1);

    sprintf(buf,"%s - %s within %g nm",
	    grpname[0],grpname[1],cut);
    fp = xvgropen(opt2fn("-lt",NFILE,fnm),
		  buf,"Time (ps)","Number of contacts",oenv);
    for(i=0; i<min(ccount_nalloc,teller-1); i++) {
      /* Account for all subintervals of longer intervals */
      sum = 0;
      for(j=i; j<ccount_nalloc; j++)
	sum += (j-i+1)*ccount[j];

      fprintf(fp,"%10.3f %10.3f\n",i*(t-t0)/(teller-1),sum/(double)(teller-i));
    }
    ffclose(fp);
  }
  
  thanx(stderr);
  return 0;
}
예제 #10
0
파일: Roads.cpp 프로젝트: kamalsirsa/vtp
void NodeGeom::ComputeIntersectionVertices()
{
	FPoint3 v, v_next, v_prev;
	FPoint3 pn0, pn1;
	float w;			// link width

	SortLinksByAngle();

	// how many links meet here?
	if (NumLinks() == 0)
	{
		; // bogus case (put a breakpoint here)
	}
	else if (NumLinks() == 1)
	{
		// dead end: only need 2 vertices for this node
		m_iVerts = 2;
		m_v.SetSize(2);

		// get info about the link
		LinkGeom *r = GetLink(0);
		w = (r->m_fLeftWidth + r->m_fRightWidth) / 2;

		pn1 = GetAdjacentRoadpoint(0);
		v = CreateRoadVector(m_p3, pn1, w);

		m_v[0].Set(m_p3.x + v.z, m_p3.y, m_p3.z - v.x);
		m_v[1].Set(m_p3.x - v.z, m_p3.y, m_p3.z + v.x);

		one++;
	}
	else if (NumLinks() == 2)
	{
		// only need 2 vertices for this node; no intersection
		m_iVerts = 2;
		m_v.SetSize(2);

		// get info about the links
		w = (GetLink(0)->m_fLeftWidth + GetLink(1)->m_fRightWidth) / 2.0f;

		pn0 = GetAdjacentRoadpoint(0);
		pn1 = GetAdjacentRoadpoint(1);

		v = CreateRoadVector(pn0, pn1, w);

		m_v[0].Set(m_p3.x + v.z, m_p3.y, m_p3.z - v.x);
		m_v[1].Set(m_p3.x - v.z, m_p3.y, m_p3.z + v.x);

		two++;
	}
	else
	{
		// intersection: need 2 vertices for each link meeting here
		m_iVerts = 2 * NumLinks();
		m_v.SetSize(m_iVerts);

		// For each pairs of links, find the places where the link edges
		//  intersect as they approach this node.

		// The following is an array of float triples, used as follows:
		//  x = minimum distance which avoids intersection with next link
		//  y = minimum distance which avoids intersection with previous link
		//  z = greater of x or y.
		FLine3 distance_to_intersection(NumLinks());

		// Go through the links once, collecting the minimum distances
		for (int i = 0; i < NumLinks(); i++)
		{
			// indices of the next and previous links
			const int i_next = (i == NumLinks()-1) ? 0 : i+1;

			const TLink *pL = GetLink(i);
			const TLink *pL_next = GetLink(i_next);

			const float width1 = pL->m_fLeftWidth;
			const float width2 = pL_next->m_fRightWidth;

			const FPoint3 linkv1 = GetUnitLinkVector(i);
			const FPoint3 linkv2 = GetUnitLinkVector(i_next);

			// Use 2D vectors for the following math
			// Compute two vectors: left road edge of this link, right road
			//  edge of the following link, compute where they intersect, in
			//  terms of the ua and ub factors, which are the distance along
			//  each input vector to the intersection point.
			const FPoint2 v1(linkv1.x, linkv1.z);
			const FPoint2 v2(linkv2.x, linkv2.z);

			const float denom = v2.y*v1.x - v2.x*v1.y;
			if (fabs(denom) < 0.01)
			{
				// too parallel, pick a safety value
				distance_to_intersection[i].x = 1.0f;
				distance_to_intersection[i_next].y = 1.0f;
			}
			else
			{
				FPoint2 norm1(linkv1.z, -linkv1.x);
				FPoint2 norm2(linkv2.z, -linkv2.x);
				norm1.Normalize();
				norm2.Normalize();

				const FPoint2 center(m_p3.x, m_p3.z);
				const FPoint2 p1 = center + norm1 * width1;
				const FPoint2 p2 = center - norm2 * width2;

				const float ua = (v2.x*(p1.y - p2.y) - v2.y*(p1.x - p2.x)) / denom;
				const float ub = (v1.x*(p1.y - p2.y) - v1.y*(p1.x - p2.x)) / denom;

				distance_to_intersection[i].x = ua;
				distance_to_intersection[i_next].y = ub;
			}
		}
		// Go through the links again, picking the largest minimum
		for (int i = 0; i < NumLinks(); i++)
		{
			distance_to_intersection[i].z = std::max(distance_to_intersection[i].x,
				distance_to_intersection[i].y);
		}
		// Now we can finally set the two points where this link meets the
		//  intersection without overlapping with the other links
		for (int i = 0; i < NumLinks(); i++)
		{
			const TLink *pL = GetLink(i);
			v = GetUnitLinkVector(i);

			FPoint3 norm(v.z, 0, -v.x);
			norm.Normalize();
			norm *= pL->m_fLeftWidth;

			const float dist = distance_to_intersection[i].z;
			m_v[i * 2 + 0] = m_p3 + norm + (v * dist);
			m_v[i * 2 + 1] = m_p3 - norm + (v * dist);
		}
		many++;
	}
}
예제 #11
0
void test_solver(BfmSolver solver)
{

  g5dParams parms;

  int Ls=16;
  double M5=1.8;
  double mq=0.0001;
  double wilson_lo = 0.05;
  double wilson_hi = 6.8;
  double shamir_lo = 0.025;
  double shamir_hi = 1.7;
  double ht_scale=1.7;
  double hw_scale=1.0;

  if ( solver != DWF ) { 
    exit(0);
    Printf("Should be testing HtCayleyTanh aka DWF\n");
  }
  parms.pDWF(mq,M5,Ls);

  multi1d<LatticeColorMatrix> u(4);
  HotSt(u);
  //  ArchivGauge_t Header ; readArchiv(Header,u,"ckpoint_lat.3000");  

  multi1d<LatticeFermion> src(Ls);

/* Rudy calculate some eigenvectors */


  BfmWrapperParams BWP;
  BWP.BfmInverter = BfmInv_CG; 
  BWP.BfmMatrix   = BfmMat_M;
  BWP.BfmPrecision= Bfm64bit;
  BWP.MaxIter     = 10000;
  BWP.RsdTarget.resize(1);
  BWP.RsdTarget[0]= 1.0e-9;
  BWP.Delta = 1.0e-4;
  BWP.BAP = parms;
  BfmWrapper bfm(BWP);

    bfmarg bfma;
#if defined(QDP_USE_OMP_THREADS)
    bfma.Threads(omp_get_max_threads());
#else
    bfma.Threads(16);
#endif
    bfma.Verbose(0);

    //Physics parameters
    bfmActionParams *bfmap = (bfmActionParams *) &bfma;
    *bfmap = bfm.invParam.BAP;
    
    // Algorithm & code control
    bfma.time_report_iter=-100;
    bfma.max_iter     = bfm.invParam.MaxIter;
    bfma.residual     = toDouble(bfm.invParam.RsdTarget[0]);

  int lx = QDP::Layout::subgridLattSize()[0];
  int ly = QDP::Layout::subgridLattSize()[1];
  int lz = QDP::Layout::subgridLattSize()[2];
  int lt = QDP::Layout::subgridLattSize()[3];
    //Geometry
    bfma.node_latt[0] = lx;
    bfma.node_latt[1] = ly;
    bfma.node_latt[2] = lz;
    bfma.node_latt[3] = lt;
    
    multi1d<int> procs = QDP::Layout::logicalSize();
    for(int mu=0;mu<4;mu++){
      if (procs[mu]>1) bfma.local_comm[mu] = 0;
      else             bfma.local_comm[mu] = 1;
    }
    
    // Bfm object
    bfm_qdp<double> bfm_eig; 
    bfm_eig.init(bfma);

    //Gauge field import
    bfm_eig.importGauge(u);

    //Subspace
#define NumberGaussian (1)
  Fermion_t subspace[NumberGaussian];
  Fermion_t check;
  Fermion_t mp;
  Fermion_t mmp;
  Fermion_t tmp_t;
  check = bfm_eig.allocFermion();
     mp = bfm_eig.allocFermion();
    mmp = bfm_eig.allocFermion();
  tmp_t = bfm_eig.allocFermion();
  bfm_eig.importFermion(src,check,1);

  QDPIO::cout << "Ls = "<<Ls<<endl;
  for(int g=0;g<NumberGaussian;g++){
    for(int s=0;s<Ls;s++){
      gaussian(src[s]);
    }
    subspace[g]=bfm_eig.allocFermion();
    bfm_eig.importFermion(src,subspace[g],1); // Half parity gaussian
    if ( g==0) {
      bfm_eig.importFermion(src,check,1);
    }
    for(int s=0;s<Ls;s++){
      src[s]=zero;
    }
    bfm_eig.exportFermion(src,subspace[g],1);
    QDPIO::cout << "Subspace norm " << norm2(src)<<endl;
  }
  for(int s=0;s<Ls;s++){
    gaussian(src[s]);
  }
  QDPIO::cout << "Got here " << endl;

  //  Handle< LinearOperatorArray<T> > linop =GetLinOp(u, parms);
  int block[5];
  for(int i=0;i<5;i++) block[i]=4;

  QDPIO::cout << "Initialised dirac op"<<endl;
  BfmLittleDiracOperator ldop(Ls,NumberGaussian,block,subspace,&bfm_eig);

  int ns = ldop.SubspaceDimension();
  QDPIO::cout << "subspace dimension is "<< ns<<endl;
  ns = ldop.SubspaceLocalDimension();
  QDPIO::cout << "subspace dimension per node is "<< ns<<endl;

  std::vector<std::complex<double> > decomp(ns);
  ldop.ProjectToSubspace(check,decomp);
  if (QMP_is_primary_node()){
    FILE * fp = fopen("coeff.dat","w");
    for(int s=0;s<ns;s++){
      fprintf(fp,"coeff %d %le %le\n",s,real(decomp[s]),imag(decomp[s]));
    }
    fclose(fp);
  }
  for(int s=0;s<ns;s++){
    QDPIO::cout << "coeff "<<s<<" " << real(decomp[s]) << " " << imag(decomp[s])<<endl;
  }
  ldop.PromoteFromSubspace(decomp,mp);
  double n;
#pragma omp parallel 
  {
    omp_set_num_threads(bfm_eig.nthread);
#pragma omp for 
    for(int t=0;t<bfm_eig.nthread;t++) {
      bfm_eig.axpy(check,mp,check,-1);
      n = bfm_eig.norm(check);
    }
  }
  QDPIO::cout << "project/promote n2diff "<< n<<endl;
  QMP_barrier();

QDPIO::cout << "Computing little dirac matrix"<<endl;
  ldop.ComputeLittleMatrixColored();

  QDPIO::cout << "Done"<<endl;

  std::vector<std::complex<double> > Aphi(ns);
  //        phi^dag DdagD phi = |Dphi|^2 with phi a subspace vector
  //        should be equal to Project/Apply/Promote + inner product

#pragma omp parallel 
  {
#pragma omp for 
    for(int t=0;t<bfm_eig.nthread;t++) {
      bfm_eig.Mprec(subspace[0],mp,tmp_t,0);
    }
  }

  QDPIO::cout << "Applied BFM matrix "<<endl;

  double n2;
#pragma omp parallel 
  {
    omp_set_num_threads(bfm_eig.nthread);
#pragma omp for 
    for(int t=0;t<bfm_eig.nthread;t++) {
      n2 = bfm_eig.norm(mp);
    }
  }

  QDPIO::cout << "Applied BFM matrix "<<n2<<endl;

  ldop.ProjectToSubspace(subspace[0],decomp);
  QDPIO::cout << "Projected to subspace "<<endl;
  ldop.Apply(decomp,Aphi);
  QDPIO::cout << "Applied A "<<endl;
  ldop.PromoteFromSubspace(Aphi,check);
  QDPIO::cout << "Promoted "<<endl;

  complex<double> inn;
#pragma omp parallel 
  {
#pragma omp for 
    for(int t=0;t<bfm_eig.nthread;t++) {
      inn = bfm_eig.inner(subspace[0],check);
    }
  }

  QDPIO::cout << "phi^dag Ddag D phi check " << n2 << " " <<real(inn) << imag(inn) <<endl;

  std::vector<std::complex<double> > AinvAphi(ns);
  ldop.ProjectToSubspace(subspace[0],decomp);
  ldop.Apply(decomp,Aphi);
  for(int s=0;s<ns;s++){
    QDPIO::cout << "Aphi "<<s<<" " << real(Aphi[s]) <<" " << imag(Aphi[s])<<endl;
  }
  ldop.PromoteFromSubspace(Aphi,check);

#pragma omp parallel 
  {
#pragma omp for 
    for(int t=0;t<bfm_eig.nthread;t++) {
      bfm_eig.Mprec(subspace[0],mp,tmp_t,0);
      bfm_eig.Mprec(mp,mmp,tmp_t,1);
    }
  }
  ldop.ProjectToSubspace(mmp,decomp);
  ldop.PromoteFromSubspace(decomp,mmp);
#pragma omp parallel 
  {
#pragma omp for 
    for(int t=0;t<bfm_eig.nthread;t++) {
      bfm_eig.axpy(check,mmp,check,-1.0);
      n2 = bfm_eig.norm(check);
    }
  }
  QDPIO::cout << "PMdagMP check n2diff "<< n2<<endl;


  QMP_barrier();
  QDPIO::cout << "Applying inverse"<<endl;
  ldop.ApplyInverse(Aphi,AinvAphi);
  QMP_barrier();
  for(int s=0;s<ns;s++){
    QDPIO::cout << "AinvAphi "<<s<<" " << real(AinvAphi[s]) << " " << imag(AinvAphi[s])<<endl;
  }
  ldop.PromoteFromSubspace(AinvAphi,check);

#pragma omp parallel 
  {
#pragma omp for 
    for(int t=0;t<bfm_eig.nthread;t++) {
      bfm_eig.axpy(check,subspace[0],check,-1.0);
      n2 = bfm_eig.norm(check);
    }
  }
  QDPIO::cout << "AinvA check n2diff "<< n2<<endl;
  

}
예제 #12
0
파일: tpi.c 프로젝트: TTarenzi/MMCG-HAdResS
double do_tpi(FILE *fplog,t_commrec *cr,
              int nfile, const t_filenm fnm[],
              const output_env_t oenv, gmx_bool bVerbose,gmx_bool bCompact,
              int nstglobalcomm,
              gmx_vsite_t *vsite,gmx_constr_t constr,
              int stepout,
              t_inputrec *inputrec,
              gmx_mtop_t *top_global,t_fcdata *fcd,
              t_state *state,
              t_mdatoms *mdatoms,
              t_nrnb *nrnb,gmx_wallcycle_t wcycle,
              gmx_edsam_t ed,
              t_forcerec *fr,
              int repl_ex_nst,int repl_ex_seed,
              real cpt_period,real max_hours,
              const char *deviceOptions,
              unsigned long Flags,
              gmx_runtime_t *runtime)
{
  const char *TPI="Test Particle Insertion"; 
  gmx_localtop_t *top;
  gmx_groups_t *groups;
  gmx_enerdata_t *enerd;
  rvec   *f;
  real   lambda,t,temp,beta,drmax,epot;
  double embU,sum_embU,*sum_UgembU,V,V_all,VembU_all;
  t_trxstatus   *status;
  t_trxframe rerun_fr;
  gmx_bool   bDispCorr,bCharge,bRFExcl,bNotLastFrame,bStateChanged,bNS,bOurStep;
  tensor force_vir,shake_vir,vir,pres;
  int    cg_tp,a_tp0,a_tp1,ngid,gid_tp,nener,e;
  rvec   *x_mol;
  rvec   mu_tot,x_init,dx,x_tp;
  int    nnodes,frame,nsteps,step;
  int    i,start,end;
  gmx_rng_t tpi_rand;
  FILE   *fp_tpi=NULL;
  char   *ptr,*dump_pdb,**leg,str[STRLEN],str2[STRLEN];
  double dbl,dump_ener;
  gmx_bool   bCavity;
  int    nat_cavity=0,d;
  real   *mass_cavity=NULL,mass_tot;
  int    nbin;
  double invbinw,*bin,refvolshift,logV,bUlogV;
  real dvdl,prescorr,enercorr,dvdlcorr;
  gmx_bool bEnergyOutOfBounds;
  const char *tpid_leg[2]={"direct","reweighted"};

  /* Since there is no upper limit to the insertion energies,
   * we need to set an upper limit for the distribution output.
   */
  real bU_bin_limit      = 50;
  real bU_logV_bin_limit = bU_bin_limit + 10;

  nnodes = cr->nnodes;

  top = gmx_mtop_generate_local_top(top_global,inputrec);

  groups = &top_global->groups;

  bCavity = (inputrec->eI == eiTPIC);
  if (bCavity) {
    ptr = getenv("GMX_TPIC_MASSES");
    if (ptr == NULL) {
      nat_cavity = 1;
    } else {
      /* Read (multiple) masses from env var GMX_TPIC_MASSES,
       * The center of mass of the last atoms is then used for TPIC.
       */
      nat_cavity = 0;
      while (sscanf(ptr,"%lf%n",&dbl,&i) > 0) {
	srenew(mass_cavity,nat_cavity+1);
	mass_cavity[nat_cavity] = dbl;
	fprintf(fplog,"mass[%d] = %f\n",
		nat_cavity+1,mass_cavity[nat_cavity]);
	nat_cavity++;
	ptr += i;
      }
      if (nat_cavity == 0)
	gmx_fatal(FARGS,"Found %d masses in GMX_TPIC_MASSES",nat_cavity);
    }
  }

  /*
  init_em(fplog,TPI,inputrec,&lambda,nrnb,mu_tot,
  state->box,fr,mdatoms,top,cr,nfile,fnm,NULL,NULL);*/
  /* We never need full pbc for TPI */
  fr->ePBC = epbcXYZ;
  /* Determine the temperature for the Boltzmann weighting */
  temp = inputrec->opts.ref_t[0];
  if (fplog) {
    for(i=1; (i<inputrec->opts.ngtc); i++) {
      if (inputrec->opts.ref_t[i] != 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");
      }
    }
    fprintf(fplog,
	    "\n  The temperature for test particle insertion is %.3f K\n\n",
	    temp);
  }
  beta = 1.0/(BOLTZ*temp);

  /* Number of insertions per frame */
  nsteps = inputrec->nsteps; 

  /* Use the same neighborlist with more insertions points
   * in a sphere of radius drmax around the initial point
   */
  /* This should be a proper mdp parameter */
  drmax = inputrec->rtpi;

  /* An environment variable can be set to dump all configurations
   * to pdb with an insertion energy <= this value.
   */
  dump_pdb = getenv("GMX_TPI_DUMP");
  dump_ener = 0;
  if (dump_pdb)
    sscanf(dump_pdb,"%lf",&dump_ener);

  atoms2md(top_global,inputrec,0,NULL,0,top_global->natoms,mdatoms);
  update_mdatoms(mdatoms,inputrec->init_lambda);

  snew(enerd,1);
  init_enerdata(groups->grps[egcENER].nr,inputrec->n_flambda,enerd);
  snew(f,top_global->natoms);

  /* Print to log file  */
  runtime_start(runtime);
  print_date_and_time(fplog,cr->nodeid,
                      "Started Test Particle Insertion",runtime); 
  wallcycle_start(wcycle,ewcRUN);

  /* The last charge group is the group to be inserted */
  cg_tp = top->cgs.nr - 1;
  a_tp0 = top->cgs.index[cg_tp];
  a_tp1 = top->cgs.index[cg_tp+1];
  if (debug)
    fprintf(debug,"TPI cg %d, atoms %d-%d\n",cg_tp,a_tp0,a_tp1);
  if (a_tp1 - a_tp0 > 1 &&
      (inputrec->rlist < inputrec->rcoulomb ||
       inputrec->rlist < inputrec->rvdw))
    gmx_fatal(FARGS,"Can not do TPI for multi-atom molecule with a twin-range cut-off");
  snew(x_mol,a_tp1-a_tp0);

  bDispCorr = (inputrec->eDispCorr != edispcNO);
  bCharge = FALSE;
  for(i=a_tp0; i<a_tp1; i++) {
    /* Copy the coordinates of the molecule to be insterted */
    copy_rvec(state->x[i],x_mol[i-a_tp0]);
    /* Check if we need to print electrostatic energies */
    bCharge |= (mdatoms->chargeA[i] != 0 ||
		(mdatoms->chargeB && mdatoms->chargeB[i] != 0));
  }
  bRFExcl = (bCharge && EEL_RF(fr->eeltype) && fr->eeltype!=eelRF_NEC);

  calc_cgcm(fplog,cg_tp,cg_tp+1,&(top->cgs),state->x,fr->cg_cm);
  if (bCavity) {
    if (norm(fr->cg_cm[cg_tp]) > 0.5*inputrec->rlist && fplog) {
      fprintf(fplog, "WARNING: Your TPI molecule is not centered at 0,0,0\n");
      fprintf(stderr,"WARNING: Your TPI molecule is not centered at 0,0,0\n");
    }
  } else {
    /* Center the molecule to be inserted at zero */
     for(i=0; i<a_tp1-a_tp0; i++)
      rvec_dec(x_mol[i],fr->cg_cm[cg_tp]);
  }

  if (fplog) {
    fprintf(fplog,"\nWill insert %d atoms %s partial charges\n",
	    a_tp1-a_tp0,bCharge ? "with" : "without");
    
    fprintf(fplog,"\nWill insert %d times in each frame of %s\n",
	    nsteps,opt2fn("-rerun",nfile,fnm));
  }
  
    if (!bCavity)
    {
        if (inputrec->nstlist > 1)
        {
            if (drmax==0 && a_tp1-a_tp0==1)
            {
                gmx_fatal(FARGS,"Re-using the neighborlist %d times for insertions of a single atom in a sphere of radius %f does not make sense",inputrec->nstlist,drmax);
            }
            if (fplog)
            {
                fprintf(fplog,"Will use the same neighborlist for %d insertions in a sphere of radius %f\n",inputrec->nstlist,drmax);
            }
        }
    }
    else
    {
        if (fplog)
        {
            fprintf(fplog,"Will insert randomly in a sphere of radius %f around the center of the cavity\n",drmax);
        }
    }

  ngid = groups->grps[egcENER].nr;
  gid_tp = GET_CGINFO_GID(fr->cginfo[cg_tp]);
  nener = 1 + ngid;
  if (bDispCorr)
    nener += 1;
  if (bCharge) {
    nener += ngid;
    if (bRFExcl)
      nener += 1;
    if (EEL_FULL(fr->eeltype))
      nener += 1;
  }
  snew(sum_UgembU,nener);

  /* Initialize random generator */
  tpi_rand = gmx_rng_init(inputrec->ld_seed);

  if (MASTER(cr)) {
    fp_tpi = xvgropen(opt2fn("-tpi",nfile,fnm),
		      "TPI energies","Time (ps)",
		      "(kJ mol\\S-1\\N) / (nm\\S3\\N)",oenv);
    xvgr_subtitle(fp_tpi,"f. are averages over one frame",oenv);
    snew(leg,4+nener);
    e = 0;
    sprintf(str,"-kT log(<Ve\\S-\\betaU\\N>/<V>)");
    leg[e++] = strdup(str);
    sprintf(str,"f. -kT log<e\\S-\\betaU\\N>");
    leg[e++] = strdup(str);
    sprintf(str,"f. <e\\S-\\betaU\\N>");
    leg[e++] = strdup(str);
    sprintf(str,"f. V");
    leg[e++] = strdup(str);
    sprintf(str,"f. <Ue\\S-\\betaU\\N>");
    leg[e++] = strdup(str);
    for(i=0; i<ngid; i++) {
      sprintf(str,"f. <U\\sVdW %s\\Ne\\S-\\betaU\\N>",
	      *(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
      leg[e++] = strdup(str);
    }
    if (bDispCorr) {
      sprintf(str,"f. <U\\sdisp c\\Ne\\S-\\betaU\\N>");
      leg[e++] = strdup(str);
    }
    if (bCharge) {
      for(i=0; i<ngid; i++) {
	sprintf(str,"f. <U\\sCoul %s\\Ne\\S-\\betaU\\N>",
		*(groups->grpname[groups->grps[egcENER].nm_ind[i]]));
	leg[e++] = strdup(str);
      }
      if (bRFExcl) {
	sprintf(str,"f. <U\\sRF excl\\Ne\\S-\\betaU\\N>");
	leg[e++] = strdup(str);
      }
      if (EEL_FULL(fr->eeltype)) {
	sprintf(str,"f. <U\\sCoul recip\\Ne\\S-\\betaU\\N>");
	leg[e++] = strdup(str);
      }
    }
    xvgr_legend(fp_tpi,4+nener,(const char**)leg,oenv);
    for(i=0; i<4+nener; i++)
      sfree(leg[i]);
    sfree(leg);
  }
  clear_rvec(x_init);
  V_all = 0;
  VembU_all = 0;

  invbinw = 10;
  nbin = 10;
  snew(bin,nbin);

  bNotLastFrame = read_first_frame(oenv,&status,opt2fn("-rerun",nfile,fnm),
				   &rerun_fr,TRX_NEED_X);
  frame = 0;

  if (rerun_fr.natoms - (bCavity ? nat_cavity : 0) !=
      mdatoms->nr - (a_tp1 - a_tp0))
    gmx_fatal(FARGS,"Number of atoms in trajectory (%d)%s "
	      "is not equal the number in the run input file (%d) "
	      "minus the number of atoms to insert (%d)\n",
	      rerun_fr.natoms,bCavity ? " minus one" : "",
	      mdatoms->nr,a_tp1-a_tp0);

  refvolshift = log(det(rerun_fr.box));

#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) )
    /* Make sure we don't detect SSE overflow generated before this point */
    gmx_mm_check_and_reset_overflow();
#endif

    while (bNotLastFrame)
    {
        lambda = rerun_fr.lambda;
        t = rerun_fr.time;
        
        sum_embU = 0;
        for(e=0; e<nener; e++)
        {
            sum_UgembU[e] = 0;
        }
        
        /* Copy the coordinates from the input trajectory */
        for(i=0; i<rerun_fr.natoms; i++)
        {
            copy_rvec(rerun_fr.x[i],state->x[i]);
        }
        
        V = det(rerun_fr.box);
        logV = log(V);
        
        bStateChanged = TRUE;
        bNS = TRUE;
        for(step=0; step<nsteps; step++)
        {
            /* In parallel all nodes generate all random configurations.
             * In that way the result is identical to a single cpu tpi run.
             */
            if (!bCavity)
            {
                /* Random insertion in the whole volume */
                bNS = (step % inputrec->nstlist == 0);
                if (bNS)
                {
                    /* Generate a random position in the box */
                    x_init[XX] = gmx_rng_uniform_real(tpi_rand)*state->box[XX][XX];
                    x_init[YY] = gmx_rng_uniform_real(tpi_rand)*state->box[YY][YY];
                    x_init[ZZ] = gmx_rng_uniform_real(tpi_rand)*state->box[ZZ][ZZ];
                }
                if (inputrec->nstlist == 1)
                {
                    copy_rvec(x_init,x_tp);
                }
                else
                {
                    /* Generate coordinates within |dx|=drmax of x_init */
                    do
                    {
                        dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                        dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                        dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                    }
                    while (norm2(dx) > drmax*drmax);
                    rvec_add(x_init,dx,x_tp);
                }
            }
            else
            {
                /* Random insertion around a cavity location
                 * given by the last coordinate of the trajectory.
                 */
                if (step == 0)
                {
                    if (nat_cavity == 1)
                    {
                        /* Copy the location of the cavity */
                        copy_rvec(rerun_fr.x[rerun_fr.natoms-1],x_init);
                    }
                    else
                    {
                        /* Determine the center of mass of the last molecule */
                        clear_rvec(x_init);
                        mass_tot = 0;
                        for(i=0; i<nat_cavity; i++)
                        {
                            for(d=0; d<DIM; d++)
                            {
                                x_init[d] +=
                                    mass_cavity[i]*rerun_fr.x[rerun_fr.natoms-nat_cavity+i][d];
                            }
                            mass_tot += mass_cavity[i];
                        }
                        for(d=0; d<DIM; d++)
                        {
                            x_init[d] /= mass_tot;
                        }
                    }
                }
                /* Generate coordinates within |dx|=drmax of x_init */
                do
                {
                    dx[XX] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                    dx[YY] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                    dx[ZZ] = (2*gmx_rng_uniform_real(tpi_rand) - 1)*drmax;
                }
                while (norm2(dx) > drmax*drmax);
                rvec_add(x_init,dx,x_tp);
            }
            
            if (a_tp1 - a_tp0 == 1)
            {
                /* Insert a single atom, just copy the insertion location */
	copy_rvec(x_tp,state->x[a_tp0]);
            }
            else
            {
                /* Copy the coordinates from the top file */
                for(i=a_tp0; i<a_tp1; i++)
                {
                    copy_rvec(x_mol[i-a_tp0],state->x[i]);
                }
                /* Rotate the molecule randomly */
                rotate_conf(a_tp1-a_tp0,state->x+a_tp0,NULL,
                            2*M_PI*gmx_rng_uniform_real(tpi_rand),
                            2*M_PI*gmx_rng_uniform_real(tpi_rand),
                            2*M_PI*gmx_rng_uniform_real(tpi_rand));
                /* Shift to the insertion location */
                for(i=a_tp0; i<a_tp1; i++)
                {
                    rvec_inc(state->x[i],x_tp);
                }
            }
            
            /* Check if this insertion belongs to this node */
            bOurStep = TRUE;
            if (PAR(cr))
            {
                switch (inputrec->eI)
                {
                case eiTPI:
                    bOurStep = ((step / inputrec->nstlist) % nnodes == cr->nodeid);
                    break;
                case eiTPIC:
                    bOurStep = (step % nnodes == cr->nodeid);
                    break;
                default:
                    gmx_fatal(FARGS,"Unknown integrator %s",ei_names[inputrec->eI]);
                }
            }
            if (bOurStep)
            {
                /* Clear some matrix variables  */
                clear_mat(force_vir); 
                clear_mat(shake_vir);
                clear_mat(vir);
                clear_mat(pres);
                
                /* Set the charge group center of mass of the test particle */
                copy_rvec(x_init,fr->cg_cm[top->cgs.nr-1]);
                
                /* Calc energy (no forces) on new positions.
                 * Since we only need the intermolecular energy
                 * and the RF exclusion terms of the inserted molecule occur
                 * within a single charge group we can pass NULL for the graph.
                 * This also avoids shifts that would move charge groups
                 * out of the box.
                 *
                 * Some checks above ensure than we can not have
                 * twin-range interactions together with nstlist > 1,
                 * therefore we do not need to remember the LR energies.
                 */
                /* Make do_force do a single node force calculation */
                cr->nnodes = 1;
                do_force(fplog,cr,inputrec,
                         step,nrnb,wcycle,top,top_global,&top_global->groups,
                         rerun_fr.box,state->x,&state->hist,
                         f,force_vir,mdatoms,enerd,fcd,
                         lambda,NULL,fr,NULL,mu_tot,t,NULL,NULL,FALSE,
                         GMX_FORCE_NONBONDED |
                         (bNS ? GMX_FORCE_NS | GMX_FORCE_DOLR : 0) |
                         (bStateChanged ? GMX_FORCE_STATECHANGED : 0)); 
                cr->nnodes = nnodes;
                bStateChanged = FALSE;
                bNS = FALSE;
                
                /* Calculate long range corrections to pressure and energy */
                calc_dispcorr(fplog,inputrec,fr,step,top_global->natoms,rerun_fr.box,
                              lambda,pres,vir,&prescorr,&enercorr,&dvdlcorr);
                /* figure out how to rearrange the next 4 lines MRS 8/4/2009 */
                enerd->term[F_DISPCORR] = enercorr;
                enerd->term[F_EPOT] += enercorr;
                enerd->term[F_PRES] += prescorr;
                enerd->term[F_DVDL] += dvdlcorr;

                epot = enerd->term[F_EPOT];
                bEnergyOutOfBounds = FALSE;
#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) )
                /* With SSE the energy can overflow, check for this */
                if (gmx_mm_check_and_reset_overflow())
                {
                    if (debug)
                    {
                        fprintf(debug,"Found an SSE overflow, assuming the energy is out of bounds\n");
                    }
                    bEnergyOutOfBounds = TRUE;
                }
#endif
                /* If the compiler doesn't optimize this check away
                 * we catch the NAN energies.
                 * The epot>GMX_REAL_MAX check catches inf values,
                 * which should nicely result in embU=0 through the exp below,
                 * but it does not hurt to check anyhow.
                 */
                /* Non-bonded Interaction usually diverge at r=0.
                 * With tabulated interaction functions the first few entries
                 * should be capped in a consistent fashion between
                 * repulsion, dispersion and Coulomb to avoid accidental
                 * negative values in the total energy.
                 * The table generation code in tables.c does this.
                 * With user tbales the user should take care of this.
                 */
                if (epot != epot || epot > GMX_REAL_MAX)
                {
                    bEnergyOutOfBounds = TRUE;
                }
                if (bEnergyOutOfBounds)
                {
                    if (debug)
                    {
                        fprintf(debug,"\n  time %.3f, step %d: non-finite energy %f, using exp(-bU)=0\n",t,step,epot);
                    }
                    embU = 0;
                }
                else
                {
                    embU = exp(-beta*epot);
                    sum_embU += embU;
                    /* Determine the weighted energy contributions of each energy group */
                    e = 0;
                    sum_UgembU[e++] += epot*embU;
                    if (fr->bBHAM)
                    {
                        for(i=0; i<ngid; i++)
                        {
                            sum_UgembU[e++] +=
                                (enerd->grpp.ener[egBHAMSR][GID(i,gid_tp,ngid)] +
                                 enerd->grpp.ener[egBHAMLR][GID(i,gid_tp,ngid)])*embU;
                        }
                    }
                    else
                    {
                        for(i=0; i<ngid; i++)
                        {
                            sum_UgembU[e++] +=
                                (enerd->grpp.ener[egLJSR][GID(i,gid_tp,ngid)] +
                                 enerd->grpp.ener[egLJLR][GID(i,gid_tp,ngid)])*embU;
                        }
                    }
                    if (bDispCorr)
                    {
                        sum_UgembU[e++] += enerd->term[F_DISPCORR]*embU;
                    }
                    if (bCharge)
                    {
                        for(i=0; i<ngid; i++)
                        {
                            sum_UgembU[e++] +=
                                (enerd->grpp.ener[egCOULSR][GID(i,gid_tp,ngid)] +
                                 enerd->grpp.ener[egCOULLR][GID(i,gid_tp,ngid)])*embU;
                        }
                        if (bRFExcl)
                        {
                            sum_UgembU[e++] += enerd->term[F_RF_EXCL]*embU;
                        }
                        if (EEL_FULL(fr->eeltype))
                        {
                            sum_UgembU[e++] += enerd->term[F_COUL_RECIP]*embU;
                        }
                    }
                }
                
                if (embU == 0 || beta*epot > bU_bin_limit)
                {
                    bin[0]++;
                }
                else
                {
                    i = (int)((bU_logV_bin_limit
                               - (beta*epot - logV + refvolshift))*invbinw
                              + 0.5);
                    if (i < 0)
                    {
                        i = 0;
                    }
                    if (i >= nbin)
                    {
                        realloc_bins(&bin,&nbin,i+10);
                    }
                    bin[i]++;
                }

                if(fr->adress_do_drift ||fr->adress_icor == eAdressICThermoForce ){
                    sum_UgembU[e++] += enerd->term[F_ADR_DELTU]*embU;
                }

                if (debug)
                {
                    fprintf(debug,"TPI %7d %12.5e %12.5f %12.5f %12.5f\n",
                            step,epot,x_tp[XX],x_tp[YY],x_tp[ZZ]);
                }

                if (dump_pdb && epot <= dump_ener)
                {
                    sprintf(str,"t%g_step%d.pdb",t,step);
                    sprintf(str2,"t: %f step %d ener: %f",t,step,epot);
                    write_sto_conf_mtop(str,str2,top_global,state->x,state->v,
                                        inputrec->ePBC,state->box);
                }
            }
        }
        
        if (PAR(cr))
        {
            /* When running in parallel sum the energies over the processes */
            gmx_sumd(1,    &sum_embU, cr);
            gmx_sumd(nener,sum_UgembU,cr);
        }

        frame++;
        V_all += V;
        VembU_all += V*sum_embU/nsteps;
        
        if (fp_tpi)
        {
            if (bVerbose || frame%10==0 || frame<10)
            {
                fprintf(stderr,"mu %10.3e <mu> %10.3e\n",
                        -log(sum_embU/nsteps)/beta,-log(VembU_all/V_all)/beta);
            }
            
            fprintf(fp_tpi,"%10.3f %12.5e %12.5e %12.5e %12.5e",
                    t,
                    VembU_all==0 ? 20/beta : -log(VembU_all/V_all)/beta,
                    sum_embU==0  ? 20/beta : -log(sum_embU/nsteps)/beta,
                    sum_embU/nsteps,V);
            for(e=0; e<nener; e++)
            {
                fprintf(fp_tpi," %12.5e",sum_UgembU[e]/nsteps);
            }
            fprintf(fp_tpi,"\n");
            fflush(fp_tpi);
        }
        
        bNotLastFrame = read_next_frame(oenv, status,&rerun_fr);
    } /* End of the loop  */
    runtime_end(runtime);

    close_trj(status);

    if (fp_tpi != NULL)
    {
        gmx_fio_fclose(fp_tpi);
    }

    if (fplog != NULL)
    {
        fprintf(fplog,"\n");
        fprintf(fplog,"  <V>  = %12.5e nm^3\n",V_all/frame);
        fprintf(fplog,"  <mu> = %12.5e kJ/mol\n",-log(VembU_all/V_all)/beta);
    }
  
    /* Write the Boltzmann factor histogram */
    if (PAR(cr))
    {
        /* When running in parallel sum the bins over the processes */
        i = nbin;
        global_max(cr,&i);
        realloc_bins(&bin,&nbin,i);
        gmx_sumd(nbin,bin,cr);
    }
    if (MASTER(cr))
    {
        fp_tpi = xvgropen(opt2fn("-tpid",nfile,fnm),
                          "TPI energy distribution",
                          "\\betaU - log(V/<V>)","count",oenv);
        sprintf(str,"number \\betaU > %g: %9.3e",bU_bin_limit,bin[0]);
        xvgr_subtitle(fp_tpi,str,oenv);
        xvgr_legend(fp_tpi,2,(const char **)tpid_leg,oenv);
        for(i=nbin-1; i>0; i--)
        {
            bUlogV = -i/invbinw + bU_logV_bin_limit - refvolshift + log(V_all/frame);
            fprintf(fp_tpi,"%6.2f %10d %12.5e\n",
                    bUlogV,
                    (int)(bin[i]+0.5),
                    bin[i]*exp(-bUlogV)*V_all/VembU_all);
        }
        gmx_fio_fclose(fp_tpi);
    }
    sfree(bin);

    sfree(sum_UgembU);

    runtime->nsteps_done = frame*inputrec->nsteps;

    return 0;
}
inline void callFunction(mxArray* plhs[], const mxArray*prhs[],const long nrhs,
      const long nlhs) {
   if (nrhs==3) {
      if (!mexCheckType<T>(prhs[0])) 
         mexErrMsgTxt("type of argument 1 is not consistent");
      if (mxIsSparse(prhs[0])) 
         mexErrMsgTxt("argument 1 should be full");
      if (!mexCheckType<T>(prhs[1])) 
         mexErrMsgTxt("type of argument 2 is not consistent");
      if (mxIsSparse(prhs[1])) 
         mexErrMsgTxt("argument 2 should be full");
      if (!mxIsStruct(prhs[2])) 
         mexErrMsgTxt("argument 3 should be struct");

      T* prX = reinterpret_cast<T*>(mxGetPr(prhs[0]));
      const mwSize* dimsX=mxGetDimensions(prhs[0]);
      long n=static_cast<long>(dimsX[0]);
      long M=static_cast<long>(dimsX[1]);

      T* prD = reinterpret_cast<T*>(mxGetPr(prhs[1]));
      const mwSize* dimsD=mxGetDimensions(prhs[1]);
      long nD=static_cast<long>(dimsD[0]);
      long K=static_cast<long>(dimsD[1]);
      if (n != nD) mexErrMsgTxt("argument sizes are not consistent");
      T lambda = getScalarStruct<T>(prhs[2],"lambda");
      T lambda2 = getScalarStructDef<T>(prhs[2],"lambda2",0);
      long L = getScalarStructDef<long>(prhs[2],"L",K);
      long length_path = MAX(2,getScalarStructDef<long>(prhs[2],"length_path",4*L));
      long numThreads = getScalarStructDef<long>(prhs[2],"numThreads",-1);
      bool pos = getScalarStructDef<bool>(prhs[2],"pos",false);
      bool verbose = getScalarStructDef<bool>(prhs[2],"verbose",false);
      bool ols = getScalarStructDef<bool>(prhs[2],"ols",false);
      bool cholesky = ols || getScalarStructDef<bool>(prhs[2],"cholesky",false);
      constraint_type mode = (constraint_type)getScalarStructDef<long>(prhs[2],"mode",PENALTY);
      if (L > n && !(mode == PENALTY && isZero(lambda) && !pos && lambda2 > 0)) {
//         if (verbose)
//            printf("L is changed to %ld\n",n);
         L=n;
      }
      if (L > K) {
//         if (verbose)
//            printf("L is changed to %ld\n",K);
         L=K;
      }
      Matrix<T> X(prX,n,M);
      Matrix<T> D(prD,n,K);
      SpMatrix<T> alpha;

      if (nlhs == 2) {
         Matrix<T> norm(K,length_path);
         norm.setZeros();
         if (cholesky) {
            lasso<T>(X,D,alpha,L,lambda,lambda2,mode,pos,ols,numThreads,&norm,length_path);
         } else {
            lasso2<T>(X,D,alpha,L,lambda,lambda2,mode,pos,numThreads,&norm,length_path);
         }
         Vector<T> norms_col;
         norm.norm_2_cols(norms_col);
         long length=1;
         for (long i = 1; i<norms_col.n(); ++i)
            if (norms_col[i]) ++length;
         plhs[1]=createMatrix<T>(K,length);
         T* pr_norm=reinterpret_cast<T*>(mxGetPr(plhs[1]));
         Matrix<T> norm2(pr_norm,K,length);
         Vector<T> col;
         for (long i = 0; i<length; ++i) {
            norm2.refCol(i,col);
            norm.copyCol(i,col);
         }
      } else {
         if (cholesky) {
            lasso<T>(X,D,alpha,L,lambda,lambda2,mode,pos,ols,numThreads,NULL,length_path);
         } else {
            lasso2<T>(X,D,alpha,L,lambda,lambda2,mode,pos,numThreads,NULL,length_path);
         }
      }
      convertSpMatrix(plhs[0],alpha.m(),alpha.n(),alpha.n(),
            alpha.nzmax(),alpha.v(),alpha.r(),alpha.pB());
   } else {
      if (!mexCheckType<T>(prhs[0])) 
         mexErrMsgTxt("type of argument 1 is not consistent");
      if (mxIsSparse(prhs[0])) 
         mexErrMsgTxt("argument 1 should be full");
      if (!mexCheckType<T>(prhs[1])) 
         mexErrMsgTxt("type of argument 2 is not consistent");
      if (mxIsSparse(prhs[1])) 
         mexErrMsgTxt("argument 2 should be full");
      if (!mexCheckType<T>(prhs[2])) 
         mexErrMsgTxt("type of argument 3 is not consistent");
      if (mxIsSparse(prhs[2])) 
         mexErrMsgTxt("argument 3 should be full");
      if (!mxIsStruct(prhs[3])) 
         mexErrMsgTxt("argument 4 should be struct");

      T* prX = reinterpret_cast<T*>(mxGetPr(prhs[0]));
      const mwSize* dimsX=mxGetDimensions(prhs[0]);
      long n=static_cast<long>(dimsX[0]);
      long M=static_cast<long>(dimsX[1]);

      T* prG = reinterpret_cast<T*>(mxGetPr(prhs[1]));
      const mwSize* dimsD=mxGetDimensions(prhs[1]);
      long K1=static_cast<long>(dimsD[0]);
      long K2=static_cast<long>(dimsD[1]);
      if (K1 != K2) mexErrMsgTxt("argument sizes are not consistent");
      long K=K1;

      T* prDtR = reinterpret_cast<T*>(mxGetPr(prhs[2]));
      const mwSize* dimsDtR=mxGetDimensions(prhs[2]);
      long K3=static_cast<long>(dimsDtR[0]);
      long M2=static_cast<long>(dimsDtR[1]);
      if (K1 != K3) mexErrMsgTxt("argument sizes are not consistent");
      if (M != M2) mexErrMsgTxt("argument sizes are not consistent");

      T lambda = getScalarStruct<T>(prhs[3],"lambda");
      T lambda2 = getScalarStructDef<T>(prhs[3],"lambda2",0);
      long L = getScalarStructDef<long>(prhs[3],"L",K1);
      long length_path = getScalarStructDef<long>(prhs[3],"length_path",4*L);
      long numThreads = getScalarStructDef<long>(prhs[3],"numThreads",-1);
      bool pos = getScalarStructDef<bool>(prhs[3],"pos",false);
      bool verbose = getScalarStructDef<bool>(prhs[3],"verbose",true);
      bool ols = getScalarStructDef<bool>(prhs[3],"ols",false);
      bool cholesky = ols || getScalarStructDef<bool>(prhs[3],"cholesky",false);
      constraint_type mode = (constraint_type)getScalarStructDef<long>(prhs[3],"mode",PENALTY);
      if (L > n && !(mode == PENALTY && isZero(lambda) && !pos && lambda2 > 0)) {
//         if (verbose)
//            printf("L is changed to %ld\n",n);
         L=n;
      }
      if (L > K) {
//         if (verbose)
//            printf("L is changed to %ld\n",K);
         L=K;
      }
      Matrix<T> X(prX,n,M);
      Matrix<T> G(prG,K,K);
      Matrix<T> DtR(prDtR,K,M);
      SpMatrix<T> alpha;

      if (nlhs == 2) {
         Matrix<T> norm(K,length_path);
         norm.setZeros();
         if (cholesky) {
            lasso<T>(X,G,DtR,alpha,L,lambda,mode,pos,ols,numThreads,&norm,length_path);
         } else {
            lasso2<T>(X,G,DtR,alpha,L,lambda,mode,pos,numThreads,&norm,length_path);
         }
         Vector<T> norms_col;
         norm.norm_2_cols(norms_col);
         long length=1;
         for (long i = 1; i<norms_col.n(); ++i)
            if (norms_col[i]) ++length;
         plhs[1]=createMatrix<T>(K,length);
         T* pr_norm=reinterpret_cast<T*>(mxGetPr(plhs[1]));
         Matrix<T> norm2(pr_norm,K,length);
         Vector<T> col;
         for (long i = 0; i<length; ++i) {
            norm2.refCol(i,col);
            norm.copyCol(i,col);
         }
      } else {
         if (cholesky) {
            lasso<T>(X,G,DtR,alpha,L,lambda,mode,pos,ols,numThreads,NULL,length_path);
         } else {
            lasso2<T>(X,G,DtR,alpha,L,lambda,mode,pos,numThreads,NULL,length_path);
         }
      }
      convertSpMatrix(plhs[0],alpha.m(),alpha.n(),alpha.n(),
            alpha.nzmax(),alpha.v(),alpha.r(),alpha.pB());
   }
}
예제 #14
0
/* Estimate the reciprocal space part error of the SPME Ewald sum. */
static real estimate_reciprocal(
        t_inputinfo *info, 
        rvec x[],           /* array of particles */
        real q[],           /* array of charges */
        int nr,             /* number of charges = size of the charge array */
        FILE *fp_out,
        t_commrec *cr)
{
    real e_rec=0;   /* reciprocal error estimate */
    real e_rec1=0;  /* Error estimate term 1*/
    real e_rec2=0;  /* Error estimate term 2*/
    real e_rec3=0;  /* Error estimate term 3 */
    real e_rec3x=0; /* part of Error estimate term 3 in x */
    real e_rec3y=0; /* part of Error estimate term 3 in y */
    real e_rec3z=0; /* part of Error estimate term 3 in z */
    int i,ci;
    int nx,ny,nz;   /* grid coordinates */
    real q2_all=0;  /* sum of squared charges */
    rvec gridpx;    /* reciprocal grid point in x direction*/
    rvec gridpxy;   /* reciprocal grid point in x and y direction*/
    rvec gridp;     /* complete reciprocal grid point in 3 directions*/
    rvec tmpvec;    /* template to create points from basis vectors */
    rvec tmpvec2;   /* template to create points from basis vectors */
    real coeff=0;   /* variable to compute coefficients of the error estimate */
    real coeff2=0;   /* variable to compute coefficients of the error estimate */
    real tmp=0;     /* variables to compute different factors from vectors */
    real tmp1=0;
    real tmp2=0;
    real xtmp=0;
    real ytmp=0;
    real ztmp=0;
    double ewald_error;
    
    /* Random number generator */
    
    gmx_rng_t rng=NULL;
    /*rng=gmx_rng_init(gmx_rng_make_seed());  */

    /* Index variables for parallel work distribution */
    int startglobal,stopglobal;
    int startlocal, stoplocal;
    int x_per_core;
    int nrsamples;
    real xtot;    

/* #define TAKETIME */
#ifdef TAKETIME
    double t0=0.0;
    double t1=0.0;
    double t2=0.0;
#endif

    rng=gmx_rng_init(cr->nodeid);

    clear_rvec(gridpx);
    clear_rvec(gridpxy);
    clear_rvec(gridp);
    clear_rvec(tmpvec);
    clear_rvec(tmpvec2);

    for(i=0;i<nr;i++)
    {
        q2_all += q[i]*q[i];
    }
    
    /* Calculate indices for work distribution */
    startglobal=-info->nkx[0]/2;
    stopglobal = info->nkx[0]/2;
    xtot = stopglobal*2+1;
    if (PAR(cr))
    {
        x_per_core = ceil(xtot / cr->nnodes);
        startlocal = startglobal + x_per_core*cr->nodeid;
        stoplocal = startlocal + x_per_core -1;
        if (stoplocal > stopglobal)
             stoplocal = stopglobal;
    }
    else
    {
        startlocal = startglobal;
        stoplocal  = stopglobal;
        x_per_core = xtot;
    }
/*     
#ifdef GMX_MPI
    MPI_Barrier(MPI_COMM_WORLD);
#endif
*/

#ifdef TAKETIME
    if (MASTER(cr))
        t0 = MPI_Wtime();
#endif
    
    if (MASTER(cr)){
                         
        fprintf(stderr, "Calculating reciprocal error part 1 ...");
        
    }

    for(nx=startlocal; nx<=stoplocal; nx++)
    {   
        svmul(nx,info->recipbox[XX],gridpx);
        for(ny=-info->nky[0]/2; ny<info->nky[0]/2+1; ny++)
        {
            svmul(ny,info->recipbox[YY],tmpvec);
            rvec_add(gridpx,tmpvec,gridpxy);
            for(nz=-info->nkz[0]/2; nz<info->nkz[0]/2+1; nz++)
            {
                if (  0 == nx &&  0 == ny &&  0 == nz )
                    continue;
                svmul(nz,info->recipbox[ZZ],tmpvec);
                rvec_add(gridpxy,tmpvec,gridp);
                tmp=norm2(gridp);
                coeff=exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] ) ;
                coeff/= 2.0 * M_PI * info->volume * tmp;
                coeff2=tmp ;
                
                
                tmp=eps_poly2(nx,info->nkx[0],info->pme_order[0]);
                tmp+=eps_poly2(ny,info->nkx[0],info->pme_order[0]);
                tmp+=eps_poly2(nz,info->nkx[0],info->pme_order[0]);
                
                tmp1=eps_poly1(nx,info->nkx[0],info->pme_order[0]);
                tmp2=eps_poly1(ny,info->nky[0],info->pme_order[0]);
                
                tmp+=2.0 * tmp1 * tmp2;
                
                tmp1=eps_poly1(nz,info->nkz[0],info->pme_order[0]);
                tmp2=eps_poly1(ny,info->nky[0],info->pme_order[0]);
                
                tmp+=2.0 * tmp1 * tmp2;
                
                tmp1=eps_poly1(nz,info->nkz[0],info->pme_order[0]);
                tmp2=eps_poly1(nx,info->nkx[0],info->pme_order[0]);
                
                tmp+=2.0 * tmp1 * tmp2;
                
                tmp1=eps_poly1(nx,info->nkx[0],info->pme_order[0]);
                tmp1+=eps_poly1(ny,info->nky[0],info->pme_order[0]);
                tmp1+=eps_poly1(nz,info->nkz[0],info->pme_order[0]);
                
                tmp+= tmp1 * tmp1;
                
                e_rec1+= 32.0 * M_PI * M_PI * coeff * coeff * coeff2 * tmp  * q2_all * q2_all / nr ;

                tmp1=eps_poly3(nx,info->nkx[0],info->pme_order[0]);
                tmp1*=info->nkx[0];
                tmp2=iprod(gridp,info->recipbox[XX]);
                
                tmp=tmp1*tmp2;
                
                tmp1=eps_poly3(ny,info->nky[0],info->pme_order[0]);
                tmp1*=info->nky[0];
                tmp2=iprod(gridp,info->recipbox[YY]);
                
                tmp+=tmp1*tmp2;
                
                tmp1=eps_poly3(nz,info->nkz[0],info->pme_order[0]);
                tmp1*=info->nkz[0];
                tmp2=iprod(gridp,info->recipbox[ZZ]);
                
                tmp+=tmp1*tmp2;
                
                tmp*=4.0 * M_PI;
                
                tmp1=eps_poly4(nx,info->nkx[0],info->pme_order[0]);
                tmp1*=norm2(info->recipbox[XX]);
                tmp1*=info->nkx[0] * info->nkx[0];
                
                tmp+=tmp1;
                
                tmp1=eps_poly4(ny,info->nky[0],info->pme_order[0]);
                tmp1*=norm2(info->recipbox[YY]);
                tmp1*=info->nky[0] * info->nky[0];
                
                tmp+=tmp1;
                
                tmp1=eps_poly4(nz,info->nkz[0],info->pme_order[0]);
                tmp1*=norm2(info->recipbox[ZZ]);
                tmp1*=info->nkz[0] * info->nkz[0];
                
                tmp+=tmp1;
                
                e_rec2+= 4.0 * coeff * coeff * tmp * q2_all * q2_all / nr ;
                
            }
        }
        if (MASTER(cr))
            fprintf(stderr, "\rCalculating reciprocal error part 1 ... %3.0f%%", 100.0*(nx-startlocal+1)/(x_per_core));
        
    }

/* 
#ifdef GMX_MPI
    MPI_Barrier(MPI_COMM_WORLD);
#endif
*/

    if (MASTER(cr))
        fprintf(stderr, "\n");
    if (info->fracself>0)
    {
        nrsamples=ceil(info->fracself*nr);
    }
    else
    {
        nrsamples=nr;
    }
    
    
    xtot=nrsamples;


    startglobal=0;
    stopglobal=nr;

    if(PAR(cr))
    {
        x_per_core=ceil(xtot/cr->nnodes);
        startlocal=startglobal+x_per_core*cr->nodeid;
        stoplocal=startglobal+x_per_core*(cr->nodeid+1);
        if (stoplocal>stopglobal)
            stoplocal=stopglobal;
    }
    else
    {
        startlocal=startglobal;
        stoplocal=stopglobal;
        x_per_core=xtot;
    }



    for(i=startlocal;i<stoplocal;i++)
    {
        e_rec3x=0;
        e_rec3y=0;
        e_rec3z=0;

        if (info->fracself<0) {
            ci=i;
        }else {
            ci=floor(gmx_rng_uniform_real(rng) * nr );
            if (ci==nr)
            {
                ci=nr-1;
            }
        }

        /* for(nx=startlocal; nx<=stoplocal; nx++)*/
        for(nx=-info->nkx[0]/2; nx<info->nkx[0]/2+1; nx++) 
        {   
            svmul(nx,info->recipbox[XX],gridpx);
            for(ny=-info->nky[0]/2; ny<info->nky[0]/2+1; ny++)
            {
                svmul(ny,info->recipbox[YY],tmpvec);
                rvec_add(gridpx,tmpvec,gridpxy);
                for(nz=-info->nkz[0]/2; nz<info->nkz[0]/2+1; nz++)
                {
                    
                    if (  0 == nx && 0 == ny && 0 == nz)
                        continue;
                    
                    svmul(nz,info->recipbox[ZZ],tmpvec);
                    rvec_add(gridpxy,tmpvec,gridp);
                    tmp=norm2(gridp);
                    coeff=exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] );
                    coeff/= tmp ;
                    e_rec3x+=coeff*eps_self(nx,info->nkx[0],info->recipbox[XX],info->pme_order[0],x[ci]);
                    e_rec3y+=coeff*eps_self(ny,info->nky[0],info->recipbox[YY],info->pme_order[0],x[ci]);
                    e_rec3z+=coeff*eps_self(nz,info->nkz[0],info->recipbox[ZZ],info->pme_order[0],x[ci]);

                }
            }
        }

        clear_rvec(tmpvec2);

        svmul(e_rec3x,info->recipbox[XX],tmpvec);
        rvec_inc(tmpvec2,tmpvec);
        svmul(e_rec3y,info->recipbox[YY],tmpvec);
        rvec_inc(tmpvec2,tmpvec);
        svmul(e_rec3z,info->recipbox[ZZ],tmpvec);
        rvec_inc(tmpvec2,tmpvec);

        e_rec3 += q[ci]*q[ci]*q[ci]*q[ci]*norm2(tmpvec2) / ( nrsamples * M_PI * info->volume * M_PI * info->volume); 
        if (MASTER(cr)){
            fprintf(stderr, "\rCalculating reciprocal error part 2 ... %3.0f%%",
                    100.0*(i+1)/stoplocal);

        }
       
    }

    if (MASTER(cr))
        fprintf(stderr, "\n");


#ifdef TAKETIME
    if (MASTER(cr))
    {
        t1= MPI_Wtime() - t0;
        fprintf(fp_out, "Recip. err. est. took   : %lf s\n", t1);
    }
#endif
   
#ifdef DEBUG
    if (PAR(cr))
    {
        fprintf(stderr, "Node %3d: nx=[%3d...%3d]  e_rec3=%e\n", 
                cr->nodeid, startlocal, stoplocal, e_rec3);
    }
#endif
   

/*
#ifdef GMX_MPI
    MPI_Barrier(MPI_COMM_WORLD);
#endif
  */ 

#ifdef TAKETIME
    if (MASTER(cr))
    {
        t2= MPI_Wtime() - t0;
        fprintf(fp_out, "barrier   : %lf s\n", t2-t1);
    }
#endif

    if (PAR(cr))
    {
        gmx_sum(1,&e_rec1,cr);
        gmx_sum(1,&e_rec2,cr);
        gmx_sum(1,&e_rec3,cr);
    }
    
#ifdef TAKETIME
    if (MASTER(cr))
        fprintf(fp_out, "final reduce : %lf s\n", MPI_Wtime() - t0-t2);
#endif
    /* e_rec1*=8.0 * q2_all / info->volume / info->volume / nr ;
       e_rec2*=  q2_all / M_PI / M_PI / info->volume / info->volume / nr ;
       e_rec3/= M_PI * M_PI * info->volume * info->volume * nr ; 
     */
    e_rec=sqrt(e_rec1+e_rec2+e_rec3);
    
    
    return ONE_4PI_EPS0 * e_rec;
}
예제 #15
0
파일: qvvector.cpp 프로젝트: dehabu/QSL
QVVector QVVector::normalize()	const
	{
	return operator/(norm2());
	}
예제 #16
0
파일: mydist.c 프로젝트: graceli/labwork
int main(int argc,char *argv[])
{
  static char *desc[] = {
	"g_mydist is g_dist with periodic boundary conditions disabled completely.",
	"g_mydist does not output the dx,dy,dz components of the coordinate displacement vector.",
	"see g_dist -h for other usage"
  };
  
  t_topology *top=NULL;
  real t,cut2,dist2;
  rvec *x=NULL,*v=NULL,dx;
  matrix box;
  int status;
  int natoms;

  int g,d,i,j,res,teller=0;
  atom_id aid;

  int     ngrps;     /* the number of index groups */
  atom_id **index,max;   /* the index for the atom numbers */
  int     *isize;    /* the size of each group */
  char    **grpname; /* the name of each group */
  rvec    *com;
  real    *mass;
  FILE    *fp=NULL;
  bool    bCutoff;
  t_pbc   pbc;

  char    *leg[4] = { "|d|","d\\sx\\N","d\\sy\\N","d\\sz\\N" };

  static real cut=0;

  static t_pargs pa[] = {
    { "-dist",      FALSE, etREAL, {&cut},
      "Print all atoms in group 2 closer than dist to the center of mass of group 1" },
  };
#define NPA asize(pa)

  t_filenm fnm[] = {
    { efTRX, "-f", NULL, ffREAD },
    { efTPX, NULL, NULL, ffREAD },
    { efNDX, NULL, NULL, ffOPTRD },
    { efXVG, NULL, "dist", ffOPTWR },
  };
#define NFILE asize(fnm)


  CopyRight(stderr,argv[0]);

  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE,
		    NFILE,fnm,NPA,pa,asize(desc),desc,0,NULL);
  
  bCutoff=opt2parg_bSet("-dist",NPA,pa);
  cut2=cut*cut;
  
  top=read_top(ftp2fn(efTPX,NFILE,fnm));
  
  /* read index files */
  ngrps = 2;
  snew(com,ngrps);
  snew(grpname,ngrps);
  snew(index,ngrps);
  snew(isize,ngrps);
  get_index(&top->atoms,ftp2fn(efNDX,NFILE,fnm),ngrps,isize,index,grpname);
  
  /* calculate mass */
  max=0;
  snew(mass,ngrps);
  for(g=0;(g<ngrps);g++) {
    mass[g]=0;
    for(i=0;(i<isize[g]);i++) {
      if (index[g][i]>max)
	max=index[g][i];
      if (index[g][i] >= top->atoms.nr)
	gmx_fatal(FARGS,"Atom number %d, item %d of group %d, is larger than number of atoms in the topolgy (%d)\n",index[g][i]+1,i+1,g+1,top->atoms.nr+1);
      mass[g]+=top->atoms.atom[index[g][i]].m;
    }
  }

  natoms=read_first_x(&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);

  if (max>=natoms)
    gmx_fatal(FARGS,"Atom number %d in an index group is larger than number of atoms in the trajectory (%d)\n",(int)max+1,natoms);

  if (!bCutoff) {
    /* open output file */
    fp = xvgropen(ftp2fn(efXVG,NFILE,fnm),
		  "Distance","Time (ps)","Distance (nm)");
    xvgr_legend(fp,4,leg);
  } else
    ngrps=1;
  
  do {
    /* initialisation for correct distance calculations */

   /* GL : set box diagonal to zero to avoid pbc distance calculations 
 	* note that set_pbc do not use pbc to calc. distances if one of 
 	* the diagonal entries for box is 0	
 	*/

 /* GL: comment out this line to get PBC back */ 

    box[XX][XX]=box[YY][YY]=box[ZZ][ZZ]=0;
/* end comment */

    set_pbc(&pbc,box);

    /* make molecules whole again */
	/*GL: rm_pbc transforms the molecules' coordinates to make them whole.  
 	* Not sure if rm_pbc needs to be called here..but I think it was put here 
 	* in case a user used an input trajectory with non-whole molecule(s)
 	*/

    rm_pbc(&top->idef,natoms,box,x,x);

    /* calculate center of masses */
    for(g=0;(g<ngrps);g++) {
      for(d=0;(d<DIM);d++) {
	com[g][d]=0;
	for(i=0;(i<isize[g]);i++) {
	  com[g][d] += x[index[g][i]][d] * top->atoms.atom[index[g][i]].m;
	}
	com[g][d] /= mass[g];
      }
    }
    
    if (!bCutoff) {
      /* write to output */
      fprintf(fp,"%12.7f ",t);
      for(g=0;(g<ngrps/2);g++) {
	pbc_dx(&pbc,com[2*g],com[2*g+1],dx);
	/*fprintf(fp,"%12.7f %12.7f %12.7f %12.7f",
		norm(dx),dx[XX],dx[YY],dx[ZZ]);*/
	/*GL: prints only the distance*/
	fprintf(fp,"%12.7f",norm(dx));
      }
      fprintf(fp,"\n");
    } else {
      for(i=0;(i<isize[1]);i++) { 
	j=index[1][i];
	pbc_dx(&pbc,x[j],com[0],dx);
	dist2 = norm2(dx);
	if (dist2<cut2) {
	  res=top->atoms.atom[j].resnr;
	  fprintf(stdout,"\rt: %g  %d %s %d %s  %g (nm)\n",
		  t,res+1,*top->atoms.resname[res],
		  j+1,*top->atoms.atomname[j],sqrt(dist2));     
	} 
      }
    }
    
    teller++;
  } while (read_next_x(status,&t,natoms,x,box));

  if (!bCutoff)
    fclose(fp);

  close_trj(status);
  
  thanx(stderr);
  return 0;
}
예제 #17
0
Float32
Vector2D::norm () const
{
  return sqrt (norm2 ());
}
예제 #18
0
int local(Trial &T, TBox &box, TBox &domain, double eps_cl, double *mgr,
          Global &glob, int axis, RCRVector x_av
#ifdef NLOPT_UTIL_H
      , nlopt_stopping *stop
#endif
      ) {

  int n=box.GetDim();
  RVector x(n);
  double tmp, f;

  x=T.xvals ;

#ifdef LS_DEBUG
  cout << "Local Search, x=" << x << endl;
#endif

  if (box.OutsideBox(x, domain) != 0) {
    cout << "Starting point is not inside the boundary. Exiting...\n" ;
    exit(1) ;
    return LS_Out ;
  }

  // Check if we are close to a stationary point located previously
  if (box.CloseToMin(x, &tmp, eps_cl)) {
#ifdef LS_DEBUG
     cout << "Close to a previously located stationary point, exiting" << endl;
#endif
     T.objval=tmp;
     return LS_Old ;
   }

#if 0

  if (axis != -1) {
    cout << "NLopt code only works with axis == -1, exiting...\n" ;
    exit(EXIT_FAILURE);
  }
  f_local_data data;
  data.glob = &glob;
  data.maxgrad = *mgr;
  data.stop = stop;
  nlopt_result ret = nlopt_minimize(NLOPT_LOCAL_LBFGS, n, f_local, &data,
                    box.lb.raw_data(), box.ub.raw_data(),
                    x.raw_data(), &f,
                    stop->minf_max,
                    stop->ftol_rel, stop->ftol_abs,
                    stop->xtol_rel, stop->xtol_abs,
                    stop->maxeval - stop->nevals,
                    stop->maxtime - stop->start);
  *mgr = data.maxgrad;
  T.xvals=x ; T.objval=f ;
  if (ret == NLOPT_MAXEVAL_REACHED || ret == NLOPT_MAXTIME_REACHED)
    return LS_MaxEvalTime;
  else if (ret > 0)
    return LS_New;
  else
    return LS_Out; // failure

#else /* not using NLopt local optimizer ... use original STOgo BFGS code */

  int k_max, info, outside = 0;
  int k, i, good_enough, iTmp ;

  double maxgrad, delta, f_new;
  double alpha, gamma, beta, d2, s2, nom, den, ro ;
  double nrm_sd, nrm_hn, snrm_hn, nrm_dl ;
  RVector g(n), h_sd(n), h_dl(n), h_n(n), x_new(n), g_new(n) ;
  RVector s(n),y(n),z(n),w(n) ; // Temporary vectors
  RMatrix B(n), H(n) ;          // Hessian and it's inverse

  k_max = max_iter*n ;

  // Initially B and H are equal to the identity matrix
  B=0 ; H=0 ;
  for (i=0 ; i<n ; i++) {
    B(i,i)=1 ;
    H(i,i)=1 ;
  }

  RVector g_av(x_av.GetLength());
  if (axis==-1) {
    f=glob.ObjectiveGradient(x,g,OBJECTIVE_AND_GRADIENT);
  }
  else {
    x_av(axis)=x(0);
    f=glob.ObjectiveGradient(x_av,g_av,OBJECTIVE_AND_GRADIENT);
    g(0)=g_av(axis);
  }
  IF_NLOPT_CHECK_EVALS;
  FC++;GC++;

  if (axis == -1) {
    // Skipping AV
#ifdef INI3
    // Elaborate scheme to initalize delta
    delta=delta_coef*norm2(g) ;
    copy(g,z) ;
    axpy(1.0,x,z) ;
    if (!box.InsideBox(z)) {
      if (box.Intersection(x,g,z)==TRUE) {
    axpy(-1.0,x,z) ;
    delta=min(delta,delta_coef*norm2(z)) ;
      }
      else {
    // Algorithm broke down, use INI1
        delta = (1.0/7)*box.ShortestSide(&iTmp) ;
      }
    }
#endif
#ifdef INI2
    // Use INI2 scheme
    delta = box.ClosestSide(x)*delta_coef ;
    if (delta<MacEpsilon)
      // Patch to avoid trust region with radius close to zero
      delta = (1.0/7)*box.ShortestSide(&iTmp) ;
#endif
#ifdef INI1
    delta = delta_coef*box.ShortestSide(&iTmp) ;
#endif
  }
  else {
    // Use a simple scheme for the 1D minimization (INI1)
    delta = (1.0/7.0)*box.ShortestSide(&iTmp) ;
  }

  k=0 ; good_enough = 0 ; info=LS_New ; outside=0 ;
  maxgrad=*mgr ;
  while (good_enough == 0) {
    k++ ;
    if (k>k_max) {
#ifdef LS_DEBUG
      cout << "Maximum number of iterations reached\n" ;
#endif
      info=LS_MaxIter ;
      break ;
    }

    // Update maximal gradient value
    maxgrad=max(maxgrad,normInf(g)) ;

    // Steepest descent, h_sd = -g
    copy(g,h_sd) ;
    scal(-1.0,h_sd) ;
    nrm_sd=norm2(h_sd) ;

    if (nrm_sd < epsilon) {
      // Stop criterion (gradient) fullfilled
#ifdef LS_DEBUG
      cout << "Gradient small enough" << endl ;
#endif
      good_enough = 1 ;
      break ;
    }

    // Compute Newton step, h_n = -H*g
    gemv('N',-1.0, H, g, 0.0, h_n) ;
    nrm_hn = norm2(h_n) ;

    if (nrm_hn < delta) {
      // Pure Newton step
      copy(h_n, h_dl) ;
#ifdef LS_DEBUG
      cout << "[Newton step]      " ;
#endif
    }
    else {
      gemv('N',1.0,B,g,0.0,z) ;
      tmp=dot(g,z) ;
      if (tmp==0) {
    info = LS_Unstable ;
    break ;
      }
      alpha=(nrm_sd*nrm_sd)/tmp ; // Normalization (N38,eq. 3.30)
      scal(alpha,h_sd) ;
      nrm_sd=fabs(alpha)*nrm_sd ;

      if (nrm_sd >= delta) {
    gamma = delta/nrm_sd ; // Normalization (N38, eq. 3.33)
    copy(h_sd,h_dl) ;
    scal(gamma,h_dl) ;
#ifdef LS_DEBUG
    cout << "[Steepest descent]  " ;
#endif
      }
      else {
    // Combination of Newton and SD steps
    d2 = delta*delta ;
    copy(h_sd,s) ;
    s2=nrm_sd*nrm_sd ;
    nom = d2 - s2 ;
    snrm_hn=nrm_hn*nrm_hn ;
    tmp = dot(h_n,s) ;
        den = tmp-s2 + sqrt((tmp-d2)*(tmp-d2)+(snrm_hn-d2)*(d2-s2)) ;
    if (den==0) {
      info = LS_Unstable ;
      break ;
    }
    // Normalization (N38, eq. 3.31)
    beta = nom/den ;
    copy(h_n,h_dl) ;
    scal(beta,h_dl) ;
    axpy((1-beta),h_sd,h_dl) ;
#ifdef LS_DEBUG
    cout << "[Mixed step]        " ;
#endif
      }
    }
    nrm_dl=norm2(h_dl) ;

    //x_new = x+h_dl ;
    copy(x,x_new) ;
    axpy(1.0,h_dl,x_new) ;

    // Check if x_new is inside the box
    iTmp=box.OutsideBox(x_new, domain) ;
    if (iTmp == 1) {
#ifdef LS_DEBUG
      cout << "x_new is outside the box " << endl ;
#endif
      outside++ ;
      if (outside>max_outside_steps) {
    // Previous point was also outside, exit
    break ;
      }
    }
    else if (iTmp == 2) {
#ifdef LS_DEBUG
      cout << " x_new is outside the domain" << endl ;
#endif
      info=LS_Out ;
      break ;
    }
    else {
      outside=0 ;
    }

    // Compute the gain
    if (axis==-1)
      f_new=glob.ObjectiveGradient(x_new,g_new,OBJECTIVE_AND_GRADIENT);
    else {
      x_av(axis)=x_new(0);
      f_new=glob.ObjectiveGradient(x_av,g_av,OBJECTIVE_AND_GRADIENT);
    }
    IF_NLOPT_CHECK_EVALS;
    FC++; GC++;
    gemv('N',0.5,B,h_dl,0.0,z);
    ro = (f_new-f) / (dot(g,h_dl) + dot(h_dl,z)); // Quadratic model
    if (ro > 0.75) {
      delta = delta*2;
    }
    if (ro < 0.25) {
      delta = delta/3;
    }
    if (ro > 0) {
      // Update the Hessian and it's inverse using the BFGS formula
#if 0 // changed by SGJ to compute OBJECTIVE_AND_GRADIENT above
      if (axis==-1)
    glob.ObjectiveGradient(x_new,g_new,GRADIENT_ONLY);
      else {
    x_av(axis)=x_new(0);
    glob.ObjectiveGradient(x_av,g_av,GRADIENT_ONLY);
    g_new(0)=g_av(axis);
      }
      GC++;
      IF_NLOPT_CHECK_EVALS;
#else
      if (axis != -1)
    g_new(0)=g_av(axis);
#endif

      // y=g_new-g
      copy(g_new,y);
      axpy(-1.0,g,y);

      // Check curvature condition
      alpha=dot(y,h_dl);
      if (alpha <= sqrt(MacEpsilon)*nrm_dl*norm2(y)) {
#ifdef LS_DEBUG
    cout << "Curvature condition violated " ;
#endif
      }
      else {
    // Update Hessian
    gemv('N',1.0,B,h_dl,0.0,z) ; // z=Bh_dl
    beta=-1/dot(h_dl,z) ;
    ger(1/alpha,y,y,B) ;
    ger(beta,z,z,B) ;

        // Update Hessian inverse
        gemv('N',1.0,H,y,0.0,z) ; // z=H*y
        gemv('T',1.0,H,y,0.0,w) ; // w=y'*H
    beta=dot(y,z) ;
    beta=(1+beta/alpha)/alpha ;

    // It should be possible to do this updating more efficiently, by
    // exploiting the fact that (h_dl*y'*H) = transpose(H*y*h_dl')
    ger(beta,h_dl,h_dl,H) ;
    ger(-1/alpha,z,h_dl,H) ;
    ger(-1/alpha,h_dl,w,H) ;
      }

      if (nrm_dl < norm2(x)*epsilon) {
    // Stop criterion (iteration progress) fullfilled
#ifdef LS_DEBUG
    cout << "Progress is marginal" ;
#endif
    good_enough = 1 ;
      }

      // Check if we are close to a stationary point located previously
      if (box.CloseToMin(x_new, &f_new, eps_cl)) {
    // Note that x_new and f_new may be overwritten on exit from CloseToMin
#ifdef LS_DEBUG
    cout << "Close to a previously located stationary point, exiting" << endl;
#endif
    info = LS_Old ;
    good_enough = 1 ;
      }

      // Update x, g and f
      copy(x_new,x) ; copy(g_new,g) ; f=f_new ;

#ifdef LS_DEBUG
      cout << " x=" << x << endl ;
#endif

    }
    else {
#ifdef LS_DEBUG
      cout << "Step is no good, ro=" << ro << " delta=" << delta << endl ;
#endif
    }

  } // wend

  // Make sure the routine returns correctly...
  // Check if last iterate is outside the boundary
  if (box.OutsideBox(x, domain) != 0) {
    info=LS_Out; f=DBL_MAX;
  }

  if (info == LS_Unstable) {
    cout << "Local search became unstable. No big deal but exiting anyway\n" ;
    exit(1);
  }

  *mgr=maxgrad ;

  T.xvals=x ; T.objval=f ;
  if (outside>0)
    return LS_Out ;
  else
    return info ;

#endif
}
예제 #19
0
파일: orires.cpp 프로젝트: rmcgibbo/gromacs
real calc_orires_dev(const gmx_multisim_t *ms,
                     int nfa, const t_iatom forceatoms[], const t_iparams ip[],
                     const t_mdatoms *md, const rvec x[], const t_pbc *pbc,
                     t_fcdata *fcd, history_t *hist)
{
    int              fa, d, i, j, type, ex, nref;
    real             edt, edt_1, invn, pfac, r2, invr, corrfac, weight, wsv2, sw, dev;
    tensor          *S, R, TMP;
    rvec5           *Dinsl, *Dins, *Dtav, *rhs;
    real            *mref, ***T;
    double           mtot;
    rvec            *xref, *xtmp, com, r_unrot, r;
    t_oriresdata    *od;
    gmx_bool         bTAV;
    const real       two_thr = 2.0/3.0;

    od = &(fcd->orires);

    if (od->nr == 0)
    {
        /* This means that this is not the master node */
        gmx_fatal(FARGS, "Orientation restraints are only supported on the master rank, use fewer ranks");
    }

    bTAV  = (od->edt != 0);
    edt   = od->edt;
    edt_1 = od->edt_1;
    S     = od->S;
    Dinsl = od->Dinsl;
    Dins  = od->Dins;
    Dtav  = od->Dtav;
    T     = od->TMP;
    rhs   = od->tmp;
    nref  = od->nref;
    mref  = od->mref;
    xref  = od->xref;
    xtmp  = od->xtmp;

    if (bTAV)
    {
        od->exp_min_t_tau = hist->orire_initf*edt;

        /* Correction factor to correct for the lack of history
         * at short times.
         */
        corrfac = 1.0/(1.0 - od->exp_min_t_tau);
    }
    else
    {
        corrfac = 1.0;
    }

    if (ms)
    {
        invn = 1.0/ms->nsim;
    }
    else
    {
        invn = 1.0;
    }

    clear_rvec(com);
    mtot = 0;
    j    = 0;
    for (i = 0; i < md->nr; i++)
    {
        if (md->cORF[i] == 0)
        {
            copy_rvec(x[i], xtmp[j]);
            mref[j] = md->massT[i];
            for (d = 0; d < DIM; d++)
            {
                com[d] += mref[j]*xref[j][d];
            }
            mtot += mref[j];
            j++;
        }
    }
    svmul(1.0/mtot, com, com);
    for (j = 0; j < nref; j++)
    {
        rvec_dec(xtmp[j], com);
    }
    /* Calculate the rotation matrix to rotate x to the reference orientation */
    calc_fit_R(DIM, nref, mref, xref, xtmp, R);
    copy_mat(R, od->R);

    d = 0;
    for (fa = 0; fa < nfa; fa += 3)
    {
        type = forceatoms[fa];
        if (pbc)
        {
            pbc_dx_aiuc(pbc, x[forceatoms[fa+1]], x[forceatoms[fa+2]], r_unrot);
        }
        else
        {
            rvec_sub(x[forceatoms[fa+1]], x[forceatoms[fa+2]], r_unrot);
        }
        mvmul(R, r_unrot, r);
        r2   = norm2(r);
        invr = gmx_invsqrt(r2);
        /* Calculate the prefactor for the D tensor, this includes the factor 3! */
        pfac = ip[type].orires.c*invr*invr*3;
        for (i = 0; i < ip[type].orires.power; i++)
        {
            pfac *= invr;
        }
        Dinsl[d][0] = pfac*(2*r[0]*r[0] + r[1]*r[1] - r2);
        Dinsl[d][1] = pfac*(2*r[0]*r[1]);
        Dinsl[d][2] = pfac*(2*r[0]*r[2]);
        Dinsl[d][3] = pfac*(2*r[1]*r[1] + r[0]*r[0] - r2);
        Dinsl[d][4] = pfac*(2*r[1]*r[2]);

        if (ms)
        {
            for (i = 0; i < 5; i++)
            {
                Dins[d][i] = Dinsl[d][i]*invn;
            }
        }

        d++;
    }

    if (ms)
    {
        gmx_sum_sim(5*od->nr, Dins[0], ms);
    }

    /* Calculate the order tensor S for each experiment via optimization */
    for (ex = 0; ex < od->nex; ex++)
    {
        for (i = 0; i < 5; i++)
        {
            rhs[ex][i] = 0;
            for (j = 0; j <= i; j++)
            {
                T[ex][i][j] = 0;
            }
        }
    }
    d = 0;
    for (fa = 0; fa < nfa; fa += 3)
    {
        if (bTAV)
        {
            /* Here we update Dtav in t_fcdata using the data in history_t.
             * Thus the results stay correct when this routine
             * is called multiple times.
             */
            for (i = 0; i < 5; i++)
            {
                Dtav[d][i] = edt*hist->orire_Dtav[d*5+i] + edt_1*Dins[d][i];
            }
        }

        type   = forceatoms[fa];
        ex     = ip[type].orires.ex;
        weight = ip[type].orires.kfac;
        /* Calculate the vector rhs and half the matrix T for the 5 equations */
        for (i = 0; i < 5; i++)
        {
            rhs[ex][i] += Dtav[d][i]*ip[type].orires.obs*weight;
            for (j = 0; j <= i; j++)
            {
                T[ex][i][j] += Dtav[d][i]*Dtav[d][j]*weight;
            }
        }
        d++;
    }
    /* Now we have all the data we can calculate S */
    for (ex = 0; ex < od->nex; ex++)
    {
        /* Correct corrfac and copy one half of T to the other half */
        for (i = 0; i < 5; i++)
        {
            rhs[ex][i]  *= corrfac;
            T[ex][i][i] *= sqr(corrfac);
            for (j = 0; j < i; j++)
            {
                T[ex][i][j] *= sqr(corrfac);
                T[ex][j][i]  = T[ex][i][j];
            }
        }
        m_inv_gen(T[ex], 5, T[ex]);
        /* Calculate the orientation tensor S for this experiment */
        S[ex][0][0] = 0;
        S[ex][0][1] = 0;
        S[ex][0][2] = 0;
        S[ex][1][1] = 0;
        S[ex][1][2] = 0;
        for (i = 0; i < 5; i++)
        {
            S[ex][0][0] += 1.5*T[ex][0][i]*rhs[ex][i];
            S[ex][0][1] += 1.5*T[ex][1][i]*rhs[ex][i];
            S[ex][0][2] += 1.5*T[ex][2][i]*rhs[ex][i];
            S[ex][1][1] += 1.5*T[ex][3][i]*rhs[ex][i];
            S[ex][1][2] += 1.5*T[ex][4][i]*rhs[ex][i];
        }
        S[ex][1][0] = S[ex][0][1];
        S[ex][2][0] = S[ex][0][2];
        S[ex][2][1] = S[ex][1][2];
        S[ex][2][2] = -S[ex][0][0] - S[ex][1][1];
    }

    wsv2 = 0;
    sw   = 0;

    d = 0;
    for (fa = 0; fa < nfa; fa += 3)
    {
        type = forceatoms[fa];
        ex   = ip[type].orires.ex;

        od->otav[d] = two_thr*
            corrfac*(S[ex][0][0]*Dtav[d][0] + S[ex][0][1]*Dtav[d][1] +
                     S[ex][0][2]*Dtav[d][2] + S[ex][1][1]*Dtav[d][3] +
                     S[ex][1][2]*Dtav[d][4]);
        if (bTAV)
        {
            od->oins[d] = two_thr*(S[ex][0][0]*Dins[d][0] + S[ex][0][1]*Dins[d][1] +
                                   S[ex][0][2]*Dins[d][2] + S[ex][1][1]*Dins[d][3] +
                                   S[ex][1][2]*Dins[d][4]);
        }
        if (ms)
        {
            /* When ensemble averaging is used recalculate the local orientation
             * for output to the energy file.
             */
            od->oinsl[d] = two_thr*
                (S[ex][0][0]*Dinsl[d][0] + S[ex][0][1]*Dinsl[d][1] +
                 S[ex][0][2]*Dinsl[d][2] + S[ex][1][1]*Dinsl[d][3] +
                 S[ex][1][2]*Dinsl[d][4]);
        }

        dev = od->otav[d] - ip[type].orires.obs;

        wsv2 += ip[type].orires.kfac*sqr(dev);
        sw   += ip[type].orires.kfac;

        d++;
    }
    od->rmsdev = std::sqrt(wsv2/sw);

    /* Rotate the S matrices back, so we get the correct grad(tr(S D)) */
    for (ex = 0; ex < od->nex; ex++)
    {
        tmmul(R, S[ex], TMP);
        mmul(TMP, R, S[ex]);
    }

    return od->rmsdev;

    /* Approx. 120*nfa/3 flops */
}
double norm(quaternion m)
{
  return sqrt(norm2(m));
}
예제 #21
0
void PREFIX position_restraint(int i_c, struct mtd_data_s *mtd_data)
{
  int  i, j, iat;
  int  dir;
  rvec v0, v1;
  rvec pos2;
  real l0, l1, l2;
  int i1, i2, i3;

  for(iat=0;iat<colvar.natoms[i_c];iat++)
    colvar.myder[i_c][iat][0] = colvar.myder[i_c][iat][1] = colvar.myder[i_c][iat][2] = 0.;

  if(colvar.intpar[i_c][0]<3){
    iat = colvar.cvatoms[i_c][0];
    dir = colvar.intpar[i_c][0];
    colvar.ss0[i_c] = 0.;
    for(i=0;i<colvar.natoms[i_c];i++){
      iat = colvar.cvatoms[i_c][i];
      colvar.ss0[i_c] +=  mtd_data->pos[iat][dir]/colvar.natoms[i_c];
      colvar.myder[i_c][i][dir] = 1./colvar.natoms[i_c];
    }

  } else if(colvar.intpar[i_c][0]==3) {
    i1=colvar.intpar[i_c][1];
    i2=colvar.intpar[i_c][2];
    i3=colvar.intpar[i_c][3];
    pos2[0]=pos2[1]=pos2[2]=0.;
    v0[0]=v0[1]=v0[2]=0.;
    v1[0]=v1[1]=v1[2]=0.;
    for(i=0;i<colvar.natoms[i_c];i++){
      iat = colvar.cvatoms[i_c][i];
      for(dir=i1;dir<i2;dir+=i3)pos2[dir]+=mtd_data->pos[iat][dir]/colvar.natoms[i_c];
    }

    for(dir=i1;dir<i2;dir+=i3)v0[dir]=colvar.vecpar[i_c][1][dir]-colvar.vecpar[i_c][0][dir];
    for(dir=i1;dir<i2;dir+=i3)v1[dir]=                 pos2[dir]-colvar.vecpar[i_c][0][dir];
    l0=norm(v0);
    colvar.ss0[i_c]=iprod(v0,v1)/l0;
    for(i=0;i<colvar.natoms[i_c];i++)
      for(dir=i1;dir<i2;dir+=i3)
        colvar.myder[i_c][i][dir]=v0[dir]/colvar.natoms[i_c]/l0;

  } else if(colvar.intpar[i_c][0]==4) {
    i1=colvar.intpar[i_c][1];
    i2=colvar.intpar[i_c][2];
    i3=colvar.intpar[i_c][3];
    pos2[0]=pos2[1]=pos2[2]=0.;
    v0[0]=v0[1]=v0[2]=0.;
    v1[0]=v1[1]=v1[2]=0.;
    for(i=0;i<colvar.natoms[i_c];i++){
      iat = colvar.cvatoms[i_c][i];
      for(dir=i1;dir<i2;dir+=i3)pos2[dir]+=mtd_data->pos[iat][dir]/colvar.natoms[i_c];
    }

    for(dir=i1;dir<i2;dir+=i3)v0[dir]=colvar.vecpar[i_c][1][dir]-colvar.vecpar[i_c][0][dir];
    for(dir=i1;dir<i2;dir+=i3)v1[dir]=                 pos2[dir]-colvar.vecpar[i_c][0][dir];
    l0=norm(v0);
    l1=norm2(v1);
    l2=iprod(v0,v1)/l0;
    colvar.ss0[i_c]=sqrt(l1-l2*l2);
    for(i=0;i<colvar.natoms[i_c];i++)
      for(dir=i1;dir<i2;dir+=i3)
        colvar.myder[i_c][i][dir]=(v1[dir]-l2*v0[dir]/l0)/colvar.natoms[i_c]/colvar.ss0[i_c];

  }
}
quaternion reciprocal(quaternion m)
{
  quaternion out;
  out = rmult(1/norm2(m),conjugate(m));
  return out;
}
예제 #23
0
double norm(double x1, double y1, double x2, double y2) {
    return sqrt(norm2(x1, y1, x2, y2));
}
예제 #24
0
void add_conf(t_atoms *atoms, rvec **x, rvec **v, real **r, gmx_bool bSrenew,
              int ePBC, matrix box, gmx_bool bInsert,
              t_atoms *atoms_solvt, rvec *x_solvt, rvec *v_solvt, real *r_solvt,
              gmx_bool bVerbose, real rshell, int max_sol, const output_env_t oenv)
{
    t_nblist       *nlist;
    t_atoms        *atoms_all;
    real            max_vdw, *r_prot, *r_all, n2, r2, ib1, ib2;
    int             natoms_prot, natoms_solvt;
    int             i, j, jj, m, j0, j1, jjj, jnres, jnr, inr, iprot, is1, is2;
    int             prev, resnr, nresadd, d, k, ncells, maxincell;
    int             dx0, dx1, dy0, dy1, dz0, dz1;
    int             ntest, nremove, nkeep;
    rvec            dx, xi, xj, xpp, *x_all, *v_all;
    gmx_bool       *remove, *keep;
    int             bSolSol;

    natoms_prot  = atoms->nr;
    natoms_solvt = atoms_solvt->nr;
    if (natoms_solvt <= 0)
    {
        fprintf(stderr, "WARNING: Nothing to add\n");
        return;
    }

    if (ePBC == epbcSCREW)
    {
        gmx_fatal(FARGS, "Sorry, %s pbc is not yet supported", epbc_names[ePBC]);
    }

    if (bVerbose)
    {
        fprintf(stderr, "Calculating Overlap...\n");
    }

    /* Set margin around box edges to largest solvent dimension.
     * The maximum distance between atoms in a solvent molecule should
     * be calculated. At the moment a fudge factor of 3 is used.
     */
    r_prot     = *r;
    box_margin = 3*find_max_real(natoms_solvt, r_solvt);
    max_vdw    = max(3*find_max_real(natoms_prot, r_prot), box_margin);
    fprintf(stderr, "box_margin = %g\n", box_margin);

    snew(remove, natoms_solvt);

    nremove = 0;
    if (!bInsert)
    {
        for (i = 0; i < atoms_solvt->nr; i++)
        {
            if (outside_box_plus_margin(x_solvt[i], box) )
            {
                i = mark_res(i, remove, atoms_solvt->nr, atoms_solvt->atom, &nremove);
            }
        }
        fprintf(stderr, "Removed %d atoms that were outside the box\n", nremove);
    }

    /* Define grid stuff */
    /* Largest VDW radius */
    snew(r_all, natoms_prot+natoms_solvt);
    for (i = j = 0; i < natoms_prot; i++, j++)
    {
        r_all[j] = r_prot[i];
    }
    for (i = 0; i < natoms_solvt; i++, j++)
    {
        r_all[j] = r_solvt[i];
    }

    /* Combine arrays */
    combine_atoms(atoms, atoms_solvt, *x, v ? *v : NULL, x_solvt, v_solvt,
                  &atoms_all, &x_all, &v_all);

    /* Do neighboursearching step */
    do_nsgrid(stdout, bVerbose, box, x_all, atoms_all, max_vdw, oenv);

    /* check solvent with solute */
    nlist = &(fr->nblists[0].nlist_sr[eNL_VDW]);
    fprintf(stderr, "nri = %d, nrj = %d\n", nlist->nri, nlist->nrj);
    for (bSolSol = 0; (bSolSol <= (bInsert ? 0 : 1)); bSolSol++)
    {
        ntest = nremove = 0;
        fprintf(stderr, "Checking %s-Solvent overlap:",
                bSolSol ? "Solvent" : "Protein");
        for (i = 0; (i < nlist->nri && nremove < natoms_solvt); i++)
        {
            inr = nlist->iinr[i];
            j0  = nlist->jindex[i];
            j1  = nlist->jindex[i+1];
            rvec_add(x_all[inr], fr->shift_vec[nlist->shift[i]], xi);

            for (j = j0; (j < j1 && nremove < natoms_solvt); j++)
            {
                jnr = nlist->jjnr[j];
                copy_rvec(x_all[jnr], xj);

                /* Check solvent-protein and solvent-solvent */
                is1 = inr-natoms_prot;
                is2 = jnr-natoms_prot;

                /* Check if at least one of the atoms is a solvent that is not yet
                 * listed for removal, and if both are solvent, that they are not in the
                 * same residue.
                 */
                if ((!bSolSol &&
                     bXor((is1 >= 0), (is2 >= 0)) && /* One atom is protein */
                     ((is1 < 0) || ((is1 >= 0) && !remove[is1])) &&
                     ((is2 < 0) || ((is2 >= 0) && !remove[is2]))) ||

                    (bSolSol  &&
                     (is1 >= 0) && (!remove[is1]) &&                   /* is1 is solvent */
                     (is2 >= 0) && (!remove[is2]) &&                   /* is2 is solvent */
                     (bInsert ||                                       /* when inserting also check inside the box */
                      (outside_box_minus_margin2(x_solvt[is1], box) && /* is1 on edge */
                       outside_box_minus_margin2(x_solvt[is2], box))   /* is2 on edge */
                     ) &&
                     (atoms_solvt->atom[is1].resind !=                 /* Not the same residue */
                      atoms_solvt->atom[is2].resind)))
                {

                    ntest++;
                    rvec_sub(xi, xj, dx);
                    n2 = norm2(dx);
                    r2 = sqr(r_all[inr]+r_all[jnr]);
                    if (n2 < r2)
                    {
                        if (bInsert)
                        {
                            nremove = natoms_solvt;
                            for (k = 0; k < nremove; k++)
                            {
                                remove[k] = TRUE;
                            }
                        }
                        /* Need only remove one of the solvents... */
                        if (is2 >= 0)
                        {
                            (void) mark_res(is2, remove, natoms_solvt, atoms_solvt->atom,
                                            &nremove);
                        }
                        else if (is1 >= 0)
                        {
                            (void) mark_res(is1, remove, natoms_solvt, atoms_solvt->atom,
                                            &nremove);
                        }
                        else
                        {
                            fprintf(stderr, "Neither atom is solvent%d %d\n", is1, is2);
                        }
                    }
                }
            }
        }
        if (!bInsert)
        {
            fprintf(stderr, " tested %d pairs, removed %d atoms.\n", ntest, nremove);
        }
    }
    if (debug)
    {
        for (i = 0; i < natoms_solvt; i++)
        {
            fprintf(debug, "remove[%5d] = %s\n", i, bool_names[remove[i]]);
        }
    }

    /* Search again, now with another cut-off */
    if (rshell > 0)
    {
        do_nsgrid(stdout, bVerbose, box, x_all, atoms_all, rshell, oenv);
        nlist = &(fr->nblists[0].nlist_sr[eNL_VDW]);
        fprintf(stderr, "nri = %d, nrj = %d\n", nlist->nri, nlist->nrj);
        nkeep = 0;
        snew(keep, natoms_solvt);
        for (i = 0; i < nlist->nri; i++)
        {
            inr = nlist->iinr[i];
            j0  = nlist->jindex[i];
            j1  = nlist->jindex[i+1];

            for (j = j0; j < j1; j++)
            {
                jnr = nlist->jjnr[j];

                /* Check solvent-protein and solvent-solvent */
                is1 = inr-natoms_prot;
                is2 = jnr-natoms_prot;

                /* Check if at least one of the atoms is a solvent that is not yet
                 * listed for removal, and if both are solvent, that they are not in the
                 * same residue.
                 */
                if (is1 >= 0 && is2 < 0)
                {
                    mark_res(is1, keep, natoms_solvt, atoms_solvt->atom, &nkeep);
                }
                else if (is1 < 0 && is2 >= 0)
                {
                    mark_res(is2, keep, natoms_solvt, atoms_solvt->atom, &nkeep);
                }
            }
        }
        fprintf(stderr, "Keeping %d solvent atoms after proximity check\n",
                nkeep);
        for (i = 0; i < natoms_solvt; i++)
        {
            remove[i] = remove[i] || !keep[i];
        }
        sfree(keep);
    }
    /* count how many atoms and residues will be added and make space */
    if (bInsert)
    {
        j     = atoms_solvt->nr;
        jnres = atoms_solvt->nres;
    }
    else
    {
        j     = 0;
        jnres = 0;
        for (i = 0; ((i < atoms_solvt->nr) &&
                     ((max_sol == 0) || (jnres < max_sol))); i++)
        {
            if (!remove[i])
            {
                j++;
                if ((i == 0) ||
                    (atoms_solvt->atom[i].resind != atoms_solvt->atom[i-1].resind))
                {
                    jnres++;
                }
            }
        }
    }
    if (debug)
    {
        fprintf(debug, "Will add %d atoms in %d residues\n", j, jnres);
    }
    if (!bInsert)
    {
        /* Flag the remaing solvent atoms to be removed */
        jjj = atoms_solvt->atom[i-1].resind;
        for (; (i < atoms_solvt->nr); i++)
        {
            if (atoms_solvt->atom[i].resind > jjj)
            {
                remove[i] = TRUE;
            }
            else
            {
                j++;
            }
        }
    }

    if (bSrenew)
    {
        srenew(atoms->resinfo,  atoms->nres+jnres);
        srenew(atoms->atomname, atoms->nr+j);
        srenew(atoms->atom,     atoms->nr+j);
        srenew(*x,              atoms->nr+j);
        if (v)
        {
            srenew(*v,       atoms->nr+j);
        }
        srenew(*r,              atoms->nr+j);
    }

    /* add the selected atoms_solvt to atoms */
    if (atoms->nr > 0)
    {
        resnr = atoms->resinfo[atoms->atom[atoms->nr-1].resind].nr;
    }
    else
    {
        resnr = 0;
    }
    prev    = -1;
    nresadd = 0;
    for (i = 0; i < atoms_solvt->nr; i++)
    {
        if (!remove[i])
        {
            if (prev == -1 ||
                atoms_solvt->atom[i].resind != atoms_solvt->atom[prev].resind)
            {
                nresadd++;
                atoms->nres++;
                resnr++;
                atoms->resinfo[atoms->nres-1] =
                    atoms_solvt->resinfo[atoms_solvt->atom[i].resind];
                atoms->resinfo[atoms->nres-1].nr = resnr;
                /* calculate shift of the solvent molecule using the first atom */
                copy_rvec(x_solvt[i], dx);
                put_atoms_in_box(ePBC, box, 1, &dx);
                rvec_dec(dx, x_solvt[i]);
            }
            atoms->atom[atoms->nr]     = atoms_solvt->atom[i];
            atoms->atomname[atoms->nr] = atoms_solvt->atomname[i];
            rvec_add(x_solvt[i], dx, (*x)[atoms->nr]);
            if (v)
            {
                copy_rvec(v_solvt[i], (*v)[atoms->nr]);
            }
            (*r)[atoms->nr]               = r_solvt[i];
            atoms->atom[atoms->nr].resind = atoms->nres-1;
            atoms->nr++;
            prev = i;
        }
    }
    if (bSrenew)
    {
        srenew(atoms->resinfo,  atoms->nres+nresadd);
    }

    if (bVerbose)
    {
        fprintf(stderr, "Added %d molecules\n", nresadd);
    }

    sfree(remove);
    done_atom(atoms_all);
    sfree(x_all);
    sfree(v_all);
}
예제 #25
0
real 
do_listed_vdw_q(int ftype,int nbonds,
                const t_iatom iatoms[],const t_iparams iparams[],
                const rvec x[],rvec f[],rvec fshift[],
                const t_pbc *pbc,const t_graph *g,
                real lambda,real *dvdlambda,
                const t_mdatoms *md,
                const t_forcerec *fr,gmx_grppairener_t *grppener,
                int *global_atom_index)
{
    static    gmx_bool bWarn=FALSE;
    real      eps,r2,*tab,rtab2=0;
    rvec      dx,x14[2],f14[2];
    int       i,ai,aj,itype;
    int       typeA[2]={0,0},typeB[2]={0,1};
    real      chargeA[2]={0,0},chargeB[2];
    int       gid,shift_vir,shift_f;
    int       j_index[] = { 0, 1 };
    int       i0=0,i1=1,i2=2;
    ivec      dt;
    int       outeriter,inneriter;
    int       nthreads = 1;
    int       count;
    real      krf,crf,tabscale;
    int       ntype=0;
    real      *nbfp=NULL;
    real      *egnb=NULL,*egcoul=NULL;
    t_nblist  tmplist;
    int       icoul,ivdw;
    gmx_bool      bMolPBC,bFreeEnergy;
    
    gmx_bool      bCG; /* AdResS*/
    real      wf14[2]={0,0}; /* AdResS*/
   
#if GMX_THREAD_SHM_FDECOMP
    pthread_mutex_t mtx;
#else
    void *    mtx = NULL;
#endif

    
#if GMX_THREAD_SHM_FDECOMP
    pthread_mutex_initialize(&mtx);
#endif

    bMolPBC = fr->bMolPBC;

    switch (ftype) {
    case F_LJ14:
    case F_LJC14_Q:
        eps = fr->epsfac*fr->fudgeQQ;
        ntype  = 1;
        egnb   = grppener->ener[egLJ14];
        egcoul = grppener->ener[egCOUL14];
        break;
    case F_LJC_PAIRS_NB:
        eps = fr->epsfac;
        ntype  = 1;
        egnb   = grppener->ener[egLJSR];
        egcoul = grppener->ener[egCOULSR];
        break;
    default:
        gmx_fatal(FARGS,"Unknown function type %d in do_nonbonded14",
                  ftype);
    }
    tab = fr->tab14.tab;
    rtab2 = sqr(fr->tab14.r);
    tabscale = fr->tab14.scale;

    krf = fr->k_rf;
    crf = fr->c_rf;

    /* Determine the values for icoul/ivdw. */
    if (fr->bEwald) {
        icoul = 1;
    } 
    else if(fr->bcoultab)
    {
        icoul = 3;
    }
    else if(fr->eeltype == eelRF_NEC)
    {
        icoul = 2;
    }
    else 
    {
        icoul = 1;
    }
    
    if(fr->bvdwtab)
    {
        ivdw = 3;
    }
    else if(fr->bBHAM)
    {
        ivdw = 2;
    }
    else 
    {
        ivdw = 1;
    }
    
    
    bCG = FALSE; /*Adres*/
    /* We don't do SSE or altivec here, due to large overhead for 4-fold 
     * unrolling on short lists 
     */
    
    bFreeEnergy = FALSE;
    for(i=0; (i<nbonds); ) 
    {
        itype = iatoms[i++];
        ai    = iatoms[i++];
        aj    = iatoms[i++];
        gid   = GID(md->cENER[ai],md->cENER[aj],md->nenergrp);
        
        if (!fr->adress_type == eAdressOff) {
            if (fr->adress_group_explicit[md->cENER[ai]] != fr->adress_group_explicit[md->cENER[aj]]){
                /*exclude cg-ex interaction*/
                continue;
            }           
            bCG = !fr->adress_group_explicit[md->cENER[ai]];
            wf14[0] = md->wf[ai];
            wf14[1] = md->wf[aj];
        }
        switch (ftype) {
        case F_LJ14:
            bFreeEnergy =
                (fr->efep != efepNO &&
                 ((md->nPerturbed && (md->bPerturbed[ai] || md->bPerturbed[aj])) ||
                  iparams[itype].lj14.c6A != iparams[itype].lj14.c6B ||
                  iparams[itype].lj14.c12A != iparams[itype].lj14.c12B));
            chargeA[0] = md->chargeA[ai];
            chargeA[1] = md->chargeA[aj];
            nbfp = (real *)&(iparams[itype].lj14.c6A);
            break;
        case F_LJC14_Q:
            eps = fr->epsfac*iparams[itype].ljc14.fqq;
            chargeA[0] = iparams[itype].ljc14.qi;
            chargeA[1] = iparams[itype].ljc14.qj;
            nbfp = (real *)&(iparams[itype].ljc14.c6);
            break;
        case F_LJC_PAIRS_NB:
            chargeA[0] = iparams[itype].ljcnb.qi;
            chargeA[1] = iparams[itype].ljcnb.qj;
            nbfp = (real *)&(iparams[itype].ljcnb.c6);
            break;
        }
        
        if (!bMolPBC) 
        {
            /* This is a bonded interaction, atoms are in the same box */
            shift_f = CENTRAL;
            r2 = distance2(x[ai],x[aj]);
        }
        else 
        {
            /* Apply full periodic boundary conditions */
            shift_f = pbc_dx_aiuc(pbc,x[ai],x[aj],dx);
            r2 = norm2(dx);
        }

        if (r2 >= rtab2) 
        {
            if (!bWarn) 
            {
                fprintf(stderr,"Warning: 1-4 interaction between %d and %d "
                        "at distance %.3f which is larger than the 1-4 table size %.3f nm\n", 
			glatnr(global_atom_index,ai),
			glatnr(global_atom_index,aj),
			sqrt(r2), sqrt(rtab2));
                fprintf(stderr,"These are ignored for the rest of the simulation\n");
                fprintf(stderr,"This usually means your system is exploding,\n"
                        "if not, you should increase table-extension in your mdp file\n"
                        "or with user tables increase the table size\n");
                bWarn = TRUE;
            }
            if (debug) 
	      fprintf(debug,"%8f %8f %8f\n%8f %8f %8f\n1-4 (%d,%d) interaction not within cut-off! r=%g. Ignored\n",
		      x[ai][XX],x[ai][YY],x[ai][ZZ],
		      x[aj][XX],x[aj][YY],x[aj][ZZ],
		      glatnr(global_atom_index,ai),
		      glatnr(global_atom_index,aj),
		      sqrt(r2));
        }
        else 
        {
            copy_rvec(x[ai],x14[0]);
            copy_rvec(x[aj],x14[1]);
            clear_rvec(f14[0]);
            clear_rvec(f14[1]);
#ifdef DEBUG
            fprintf(debug,"LJ14: grp-i=%2d, grp-j=%2d, ngrp=%2d, GID=%d\n",
                    md->cENER[ai],md->cENER[aj],md->nenergrp,gid);
#endif
            
	    outeriter = inneriter = count = 0;
	    if (bFreeEnergy)
        {
            chargeB[0] = md->chargeB[ai];
            chargeB[1] = md->chargeB[aj];
            /* We pass &(iparams[itype].lj14.c6A) as LJ parameter matrix
             * to the innerloops.
             * Here we use that the LJ-14 parameters are stored in iparams
             * as c6A,c12A,c6B,c12B, which are referenced correctly
             * in the innerloops if we assign type combinations 0-0 and 0-1
             * to atom pair ai-aj in topologies A and B respectively.
             */
            if(ivdw==2)
            {
                gmx_fatal(FARGS,"Cannot do free energy Buckingham interactions.");
            }
            count = 0;
            gmx_nb_free_energy_kernel(icoul,
                                      ivdw,
                                      i1,
                                      &i0,
                                      j_index,
                                      &i1,
                                      &shift_f,
                                      fr->shift_vec[0],
                                      fshift[0],
                                      &gid,
                                      x14[0],
                                      f14[0],
                                      chargeA,
                                      chargeB,
                                      eps,
                                      krf,
                                      crf,
                                      fr->ewaldcoeff,
                                      egcoul,
                                      typeA,
                                      typeB,
                                      ntype,
                                      nbfp,
                                      egnb,
                                      tabscale,
                                      tab,
                                      lambda,
                                      dvdlambda,
                                      fr->sc_alpha,
                                      fr->sc_power,
                                      fr->sc_sigma6_def,
                                      fr->sc_sigma6_min,
                                      TRUE,
                                      &outeriter,
                                      &inneriter);
        }
        else 
        { 
          if (fr->adress_type==eAdressOff || !fr->adress_do_hybridpairs){
            /* Not perturbed - call kernel 330 */
            nb_kernel330
                ( &i1,
                  &i0,
                  j_index,
                  &i1,
                  &shift_f,
                  fr->shift_vec[0],
                  fshift[0],
                  &gid,
                  x14[0],
                  f14[0],
                  chargeA,
                  &eps,
                  &krf,
                  &crf,
                  egcoul,
                  typeA,
                  &ntype,
                  nbfp,
                  egnb,
                  &tabscale,
                  tab,
                  NULL,
                  NULL,
                  NULL,
                  NULL,
                  &nthreads,
                  &count,
                  (void *)&mtx,
                  &outeriter,
                  &inneriter,
                  NULL);                
                } else {
                    if (bCG) {
                        nb_kernel330_adress_cg(&i1,
                                &i0,
                                j_index,
                                &i1,
                                &shift_f,
                                fr->shift_vec[0],
                                fshift[0],
                                &gid,
                                x14[0],
                                f14[0],
                                chargeA,
                                &eps,
                                &krf,
                                &crf,
                                egcoul,
                                typeA,
                                &ntype,
                                nbfp,
                                egnb,
                                &tabscale,
                                tab,
                                NULL,
                                NULL,
                                NULL,
                                NULL,
                                &nthreads,
                                &count,
                                (void *) &mtx,
                                &outeriter,
                                &inneriter,
                                fr->adress_ex_forcecap,
                                wf14);
                    } else {
                        nb_kernel330_adress_ex(&i1,
                                &i0,
                                j_index,
                                &i1,
                                &shift_f,
                                fr->shift_vec[0],
                                fshift[0],
                                &gid,
                                x14[0],
                                f14[0],
                                chargeA,
                                &eps,
                                &krf,
                                &crf,
                                egcoul,
                                typeA,
                                &ntype,
                                nbfp,
                                egnb,
                                &tabscale,
                                tab,
                                NULL,
                                NULL,
                                NULL,
                                NULL,
                                &nthreads,
                                &count,
                                (void *) &mtx,
                                &outeriter,
                                &inneriter,
                                fr->adress_ex_forcecap,
                                wf14);
                    }

                }
            }
        
        /* Add the forces */
        rvec_inc(f[ai],f14[0]);
        rvec_dec(f[aj],f14[0]);
        
        if (g) 
        {
            /* Correct the shift forces using the graph */
            ivec_sub(SHIFT_IVEC(g,ai),SHIFT_IVEC(g,aj),dt);    
            shift_vir = IVEC2IS(dt);
            rvec_inc(fshift[shift_vir],f14[0]);
            rvec_dec(fshift[CENTRAL],f14[0]);
        }
        
	    /* flops: eNR_KERNEL_OUTER + eNR_KERNEL330 + 12 */
        }
    }
    return 0.0;
}
예제 #26
0
int gmx_trjorder(int argc, char *argv[])
{
    const char       *desc[] = {
        "[THISMODULE] orders molecules according to the smallest distance",
        "to atoms in a reference group",
        "or on z-coordinate (with option [TT]-z[tt]).",
        "With distance ordering, it will ask for a group of reference",
        "atoms and a group of molecules. For each frame of the trajectory",
        "the selected molecules will be reordered according to the shortest",
        "distance between atom number [TT]-da[tt] in the molecule and all the",
        "atoms in the reference group. The center of mass of the molecules can",
        "be used instead of a reference atom by setting [TT]-da[tt] to 0.",
        "All atoms in the trajectory are written",
        "to the output trajectory.[PAR]",
        "[THISMODULE] can be useful for e.g. analyzing the n waters closest to a",
        "protein.",
        "In that case the reference group would be the protein and the group",
        "of molecules would consist of all the water atoms. When an index group",
        "of the first n waters is made, the ordered trajectory can be used",
        "with any GROMACS program to analyze the n closest waters.",
        "[PAR]",
        "If the output file is a [REF].pdb[ref] file, the distance to the reference target",
        "will be stored in the B-factor field in order to color with e.g. Rasmol.",
        "[PAR]",
        "With option [TT]-nshell[tt] the number of molecules within a shell",
        "of radius [TT]-r[tt] around the reference group are printed."
    };
    static int        na   = 3, ref_a = 1;
    static real       rcut = 0;
    static gmx_bool   bCOM = FALSE, bZ = FALSE;
    t_pargs           pa[] = {
        { "-na", FALSE, etINT,  {&na},
          "Number of atoms in a molecule" },
        { "-da", FALSE, etINT,  {&ref_a},
          "Atom used for the distance calculation, 0 is COM" },
        { "-com", FALSE, etBOOL, {&bCOM},
          "Use the distance to the center of mass of the reference group" },
        { "-r",  FALSE, etREAL, {&rcut},
          "Cutoff used for the distance calculation when computing the number of molecules in a shell around e.g. a protein" },
        { "-z", FALSE, etBOOL, {&bZ},
          "Order molecules on z-coordinate" }
    };
    FILE             *fp;
    t_trxstatus      *out;
    t_trxstatus      *status;
    gmx_bool          bNShell, bPDBout;
    t_topology        top;
    int               ePBC;
    rvec             *x, *xsol, xcom, dx;
    matrix            box;
    t_pbc             pbc;
    gmx_rmpbc_t       gpbc;
    real              t, totmass, mass, rcut2 = 0, n2;
    int               natoms, nwat, ncut;
    char            **grpname;
    int               i, j, d, *isize, isize_ref = 0, isize_sol;
    int               sa, sr, *swi, **index, *ind_ref = nullptr, *ind_sol;
    gmx_output_env_t *oenv;
    t_filenm          fnm[] = {
        { efTRX, "-f", nullptr, ffREAD  },
        { efTPS, nullptr, nullptr, ffREAD  },
        { efNDX, nullptr, nullptr, ffOPTRD },
        { efTRO, "-o", "ordered", ffOPTWR },
        { efXVG, "-nshell", "nshell", ffOPTWR }
    };
#define NFILE asize(fnm)

    if (!parse_common_args(&argc, argv, PCA_CAN_TIME,
                           NFILE, fnm, asize(pa), pa, asize(desc), desc, 0, nullptr, &oenv))
    {
        return 0;
    }

    read_tps_conf(ftp2fn(efTPS, NFILE, fnm), &top, &ePBC, &x, nullptr, box, TRUE);
    sfree(x);

    /* get index groups */
    printf("Select %sa group of molecules to be ordered:\n",
           bZ ? "" : "a group of reference atoms and ");
    snew(grpname, 2);
    snew(index, 2);
    snew(isize, 2);
    get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), bZ ? 1 : 2,
              isize, index, grpname);

    if (!bZ)
    {
        isize_ref = isize[0];
        isize_sol = isize[1];
        ind_ref   = index[0];
        ind_sol   = index[1];
    }
    else
    {
        isize_sol = isize[0];
        ind_sol   = index[0];
    }

    natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);
    if (natoms > top.atoms.nr)
    {
        gmx_fatal(FARGS, "Number of atoms in the run input file is larger than in the trjactory");
    }
    for (i = 0; (i < 2); i++)
    {
        for (j = 0; (j < isize[i]); j++)
        {
            if (index[i][j] > natoms)
            {
                gmx_fatal(FARGS, "An atom number in group %s is larger than the number of atoms in the trajectory", grpname[i]);
            }
        }
    }

    if ((isize_sol % na) != 0)
    {
        gmx_fatal(FARGS, "Number of atoms in the molecule group (%d) is not a multiple of na (%d)",
                  isize[1], na);
    }

    nwat = isize_sol/na;
    if (ref_a > na)
    {
        gmx_fatal(FARGS, "The reference atom can not be larger than the number of atoms in a molecule");
    }
    ref_a--;
    snew(xsol, nwat);
    snew(order, nwat);
    snew(swi, natoms);
    for (i = 0; (i < natoms); i++)
    {
        swi[i] = i;
    }

    out     = nullptr;
    fp      = nullptr;
    bNShell = ((opt2bSet("-nshell", NFILE, fnm)) ||
               (opt2parg_bSet("-r", asize(pa), pa)));
    bPDBout = FALSE;
    if (bNShell)
    {
        rcut2   = rcut*rcut;
        fp      = xvgropen(opt2fn("-nshell", NFILE, fnm), "Number of molecules",
                           "Time (ps)", "N", oenv);
        printf("Will compute the number of molecules within a radius of %g\n",
               rcut);
    }
    if (!bNShell || opt2bSet("-o", NFILE, fnm))
    {
        bPDBout = (fn2ftp(opt2fn("-o", NFILE, fnm)) == efPDB);
        if (bPDBout && !top.atoms.pdbinfo)
        {
            fprintf(stderr, "Creating pdbfino records\n");
            snew(top.atoms.pdbinfo, top.atoms.nr);
        }
        out = open_trx(opt2fn("-o", NFILE, fnm), "w");
    }
    gpbc = gmx_rmpbc_init(&top.idef, ePBC, natoms);
    do
    {
        gmx_rmpbc(gpbc, natoms, box, x);
        set_pbc(&pbc, ePBC, box);

        if (ref_a == -1)
        {
            /* Calculate the COM of all solvent molecules */
            for (i = 0; i < nwat; i++)
            {
                totmass = 0;
                clear_rvec(xsol[i]);
                for (j = 0; j < na; j++)
                {
                    sa       = ind_sol[i*na+j];
                    mass     = top.atoms.atom[sa].m;
                    totmass += mass;
                    for (d = 0; d < DIM; d++)
                    {
                        xsol[i][d] += mass*x[sa][d];
                    }
                }
                svmul(1.0/totmass, xsol[i], xsol[i]);
            }
        }
        else
        {
            /* Copy the reference atom of all solvent molecules */
            for (i = 0; i < nwat; i++)
            {
                copy_rvec(x[ind_sol[i*na+ref_a]], xsol[i]);
            }
        }

        if (bZ)
        {
            for (i = 0; (i < nwat); i++)
            {
                sa           = ind_sol[na*i];
                order[i].i   = sa;
                order[i].d2  = xsol[i][ZZ];
            }
        }
        else if (bCOM)
        {
            totmass = 0;
            clear_rvec(xcom);
            for (i = 0; i < isize_ref; i++)
            {
                mass     = top.atoms.atom[ind_ref[i]].m;
                totmass += mass;
                for (j = 0; j < DIM; j++)
                {
                    xcom[j] += mass*x[ind_ref[i]][j];
                }
            }
            svmul(1/totmass, xcom, xcom);
            for (i = 0; (i < nwat); i++)
            {
                sa = ind_sol[na*i];
                pbc_dx(&pbc, xcom, xsol[i], dx);
                order[i].i   = sa;
                order[i].d2  = norm2(dx);
            }
        }
        else
        {
            /* Set distance to first atom */
            for (i = 0; (i < nwat); i++)
            {
                sa = ind_sol[na*i];
                pbc_dx(&pbc, x[ind_ref[0]], xsol[i], dx);
                order[i].i   = sa;
                order[i].d2  = norm2(dx);
            }
            for (j = 1; (j < isize_ref); j++)
            {
                sr = ind_ref[j];
                for (i = 0; (i < nwat); i++)
                {
                    pbc_dx(&pbc, x[sr], xsol[i], dx);
                    n2 = norm2(dx);
                    if (n2 < order[i].d2)
                    {
                        order[i].d2  = n2;
                    }
                }
            }
        }

        if (bNShell)
        {
            ncut = 0;
            for (i = 0; (i < nwat); i++)
            {
                if (order[i].d2 <= rcut2)
                {
                    ncut++;
                }
            }
            fprintf(fp, "%10.3f  %8d\n", t, ncut);
        }
        if (out)
        {
            qsort(order, nwat, sizeof(*order), ocomp);
            for (i = 0; (i < nwat); i++)
            {
                for (j = 0; (j < na); j++)
                {
                    swi[ind_sol[na*i]+j] = order[i].i+j;
                }
            }

            /* Store the distance as the B-factor */
            if (bPDBout)
            {
                for (i = 0; (i < nwat); i++)
                {
                    for (j = 0; (j < na); j++)
                    {
                        top.atoms.pdbinfo[order[i].i+j].bfac = std::sqrt(order[i].d2);
                    }
                }
            }
            write_trx(out, natoms, swi, &top.atoms, 0, t, box, x, nullptr, nullptr);
        }
    }
    while (read_next_x(oenv, status, &t, x, box));
    close_trx(status);
    if (out)
    {
        close_trx(out);
    }
    if (fp)
    {
        xvgrclose(fp);
    }
    gmx_rmpbc_done(gpbc);

    return 0;
}
예제 #27
0
void calc_order(const char *fn, atom_id *index, atom_id *a, rvec **order,
                real ***slOrder, real *slWidth, int nslices, gmx_bool bSliced,
                gmx_bool bUnsat, t_topology *top, int ePBC, int ngrps, int axis,
                gmx_bool permolecule, gmx_bool radial, gmx_bool distcalc, const char *radfn,
                real ***distvals,
                const output_env_t oenv)
{
    /* if permolecule = TRUE, order parameters will be calculed per molecule
     * and stored in slOrder with #slices = # molecules */
    rvec *x0,                                    /* coordinates with pbc                           */
    *x1,                                         /* coordinates without pbc                        */
          dist;                                  /* vector between two atoms                       */
    matrix       box;                            /* box (3x3)                                      */
    t_trxstatus *status;
    rvec         cossum,                         /* sum of vector angles for three axes            */
                 Sx, Sy, Sz,                     /* the three molecular axes                       */
                 tmp1, tmp2,                     /* temp. rvecs for calculating dot products       */
                 frameorder;                     /* order parameters for one frame                 */
    real *slFrameorder;                          /* order parameter for one frame, per slice      */
    real  length,                                /* total distance between two atoms               */
          t,                                     /* time from trajectory                           */
          z_ave, z1, z2;                         /* average z, used to det. which slice atom is in */
    int natoms,                                  /* nr. atoms in trj                               */
        nr_tails,                                /* nr tails, to check if index file is correct    */
        size = 0,                                /* nr. of atoms in group. same as nr_tails        */
        i, j, m, k, l, teller = 0,
        slice,                                   /* current slice number                           */
        nr_frames = 0;
    int         *slCount;                        /* nr. of atoms in one slice                      */
    real         dbangle                = 0,     /* angle between double bond and  axis            */
                 sdbangle               = 0;     /* sum of these angles                            */
    gmx_bool     use_unitvector         = FALSE; /* use a specified unit vector instead of axis to specify unit normal*/
    rvec         direction, com, dref, dvec;
    int          comsize, distsize;
    atom_id     *comidx  = NULL, *distidx = NULL;
    char        *grpname = NULL;
    t_pbc        pbc;
    real         arcdist, tmpdist;
    gmx_rmpbc_t  gpbc = NULL;

    /* PBC added for center-of-mass vector*/
    /* Initiate the pbc structure */
    memset(&pbc, 0, sizeof(pbc));

    if ((natoms = read_first_x(oenv, &status, fn, &t, &x0, box)) == 0)
    {
        gmx_fatal(FARGS, "Could not read coordinates from statusfile\n");
    }

    nr_tails = index[1] - index[0];
    fprintf(stderr, "Number of elements in first group: %d\n", nr_tails);
    /* take first group as standard. Not rocksolid, but might catch error in index*/

    if (permolecule)
    {
        nslices = nr_tails;
        bSliced = FALSE; /*force slices off */
        fprintf(stderr, "Calculating order parameters for each of %d molecules\n",
                nslices);
    }

    if (radial)
    {
        use_unitvector = TRUE;
        fprintf(stderr, "Select an index group to calculate the radial membrane normal\n");
        get_index(&top->atoms, radfn, 1, &comsize, &comidx, &grpname);
    }
    if (distcalc)
    {
        if (grpname != NULL)
        {
            sfree(grpname);
        }
        fprintf(stderr, "Select an index group to use as distance reference\n");
        get_index(&top->atoms, radfn, 1, &distsize, &distidx, &grpname);
        bSliced = FALSE; /*force slices off*/
    }

    if (use_unitvector && bSliced)
    {
        fprintf(stderr, "Warning:  slicing and specified unit vectors are not currently compatible\n");
    }

    snew(slCount, nslices);
    snew(*slOrder, nslices);
    for (i = 0; i < nslices; i++)
    {
        snew((*slOrder)[i], ngrps);
    }
    if (distcalc)
    {
        snew(*distvals, nslices);
        for (i = 0; i < nslices; i++)
        {
            snew((*distvals)[i], ngrps);
        }
    }
    snew(*order, ngrps);
    snew(slFrameorder, nslices);
    snew(x1, natoms);

    if (bSliced)
    {
        *slWidth = box[axis][axis]/nslices;
        fprintf(stderr, "Box divided in %d slices. Initial width of slice: %f\n",
                nslices, *slWidth);
    }


#if 0
    nr_tails = index[1] - index[0];
    fprintf(stderr, "Number of elements in first group: %d\n", nr_tails);
    /* take first group as standard. Not rocksolid, but might catch error
       in index*/
#endif

    teller = 0;

    gpbc = gmx_rmpbc_init(&top->idef, ePBC, natoms);
    /*********** Start processing trajectory ***********/
    do
    {
        if (bSliced)
        {
            *slWidth = box[axis][axis]/nslices;
        }
        teller++;

        set_pbc(&pbc, ePBC, box);
        gmx_rmpbc_copy(gpbc, natoms, box, x0, x1);

        /* Now loop over all groups. There are ngrps groups, the order parameter can
           be calculated for grp 1 to grp ngrps - 1. For each group, loop over all
           atoms in group, which is index[i] to (index[i+1] - 1) See block.h. Of
           course, in this case index[i+1] -index[i] has to be the same for all
           groups, namely the number of tails. i just runs over all atoms in a tail,
           so for DPPC ngrps = 16 and i runs from 1 to 14, including 14
         */


        if (radial)
        {
            /*center-of-mass determination*/
            com[XX] = 0.0; com[YY] = 0.0; com[ZZ] = 0.0;
            for (j = 0; j < comsize; j++)
            {
                rvec_inc(com, x1[comidx[j]]);
            }
            svmul(1.0/comsize, com, com);
        }
        if (distcalc)
        {
            dref[XX] = 0.0; dref[YY] = 0.0; dref[ZZ] = 0.0;
            for (j = 0; j < distsize; j++)
            {
                rvec_inc(dist, x1[distidx[j]]);
            }
            svmul(1.0/distsize, dref, dref);
            if (radial)
            {
                pbc_dx(&pbc, dref, com, dvec);
                unitv(dvec, dvec);
            }
        }

        for (i = 1; i < ngrps - 1; i++)
        {
            clear_rvec(frameorder);

            size = index[i+1] - index[i];
            if (size != nr_tails)
            {
                gmx_fatal(FARGS, "grp %d does not have same number of"
                          " elements as grp 1\n", i);
            }

            for (j = 0; j < size; j++)
            {
                if (radial)
                /*create unit vector*/
                {
                    pbc_dx(&pbc, x1[a[index[i]+j]], com, direction);
                    unitv(direction, direction);
                    /*DEBUG*/
                    /*if (j==0)
                        fprintf(stderr,"X %f %f %f\tcom %f %f %f\tdirection %f %f %f\n",x1[a[index[i]+j]][0],x1[a[index[i]+j]][1],x1[a[index[i]+j]][2],com[0],com[1],com[2],
                            direction[0],direction[1],direction[2]);*/
                }

                if (bUnsat)
                {
                    /* Using convention for unsaturated carbons */
                    /* first get Sz, the vector from Cn to Cn+1 */
                    rvec_sub(x1[a[index[i+1]+j]], x1[a[index[i]+j]], dist);
                    length = norm(dist);
                    check_length(length, a[index[i]+j], a[index[i+1]+j]);
                    svmul(1/length, dist, Sz);

                    /* this is actually the cosine of the angle between the double bond
                       and axis, because Sz is normalized and the two other components of
                       the axis on the bilayer are zero */
                    if (use_unitvector)
                    {
                        sdbangle += gmx_angle(direction, Sz); /*this can probably be optimized*/
                    }
                    else
                    {
                        sdbangle += acos(Sz[axis]);
                    }
                }
                else
                {
                    /* get vector dist(Cn-1,Cn+1) for tail atoms */
                    rvec_sub(x1[a[index[i+1]+j]], x1[a[index[i-1]+j]], dist);
                    length = norm(dist); /* determine distance between two atoms */
                    check_length(length, a[index[i-1]+j], a[index[i+1]+j]);

                    svmul(1/length, dist, Sz);
                    /* Sz is now the molecular axis Sz, normalized and all that */
                }

                /* now get Sx. Sx is normal to the plane of Cn-1, Cn and Cn+1 so
                   we can use the outer product of Cn-1->Cn and Cn+1->Cn, I hope */
                rvec_sub(x1[a[index[i+1]+j]], x1[a[index[i]+j]], tmp1);
                rvec_sub(x1[a[index[i-1]+j]], x1[a[index[i]+j]], tmp2);
                cprod(tmp1, tmp2, Sx);
                svmul(1/norm(Sx), Sx, Sx);

                /* now we can get Sy from the outer product of Sx and Sz   */
                cprod(Sz, Sx, Sy);
                svmul(1/norm(Sy), Sy, Sy);

                /* the square of cosine of the angle between dist and the axis.
                   Using the innerproduct, but two of the three elements are zero
                   Determine the sum of the orderparameter of all atoms in group
                 */
                if (use_unitvector)
                {
                    cossum[XX] = sqr(iprod(Sx, direction)); /* this is allowed, since Sa is normalized */
                    cossum[YY] = sqr(iprod(Sy, direction));
                    cossum[ZZ] = sqr(iprod(Sz, direction));
                }
                else
                {
                    cossum[XX] = sqr(Sx[axis]); /* this is allowed, since Sa is normalized */
                    cossum[YY] = sqr(Sy[axis]);
                    cossum[ZZ] = sqr(Sz[axis]);
                }

                for (m = 0; m < DIM; m++)
                {
                    frameorder[m] += 0.5 * (3 * cossum[m] - 1);
                }

                if (bSliced)
                {
                    /* get average coordinate in box length for slicing,
                       determine which slice atom is in, increase count for that
                       slice. slFrameorder and slOrder are reals, not
                       rvecs. Only the component [axis] of the order tensor is
                       kept, until I find it necessary to know the others too
                     */

                    z1    = x1[a[index[i-1]+j]][axis];
                    z2    = x1[a[index[i+1]+j]][axis];
                    z_ave = 0.5 * (z1 + z2);
                    if (z_ave < 0)
                    {
                        z_ave += box[axis][axis];
                    }
                    if (z_ave > box[axis][axis])
                    {
                        z_ave -= box[axis][axis];
                    }

                    slice  = (int)(0.5 + (z_ave / (*slWidth))) - 1;
                    slCount[slice]++;     /* determine slice, increase count */

                    slFrameorder[slice] += 0.5 * (3 * cossum[axis] - 1);
                }
                else if (permolecule)
                {
                    /*  store per-molecule order parameter
                     *  To just track single-axis order: (*slOrder)[j][i] += 0.5 * (3 * iprod(cossum,direction) - 1);
                     *  following is for Scd order: */
                    (*slOrder)[j][i] += -1* (0.3333 * (3 * cossum[XX] - 1) + 0.3333 * 0.5 * (3 * cossum[YY] - 1));
                }
                if (distcalc)
                {
                    if (radial)
                    {
                        /* bin order parameter by arc distance from reference group*/
                        arcdist            = gmx_angle(dvec, direction);
                        (*distvals)[j][i] += arcdist;
                    }
                    else if (i == 1)
                    {
                        /* Want minimum lateral distance to first group calculated */
                        tmpdist = trace(box);  /* should be max value */
                        for (k = 0; k < distsize; k++)
                        {
                            pbc_dx(&pbc, x1[distidx[k]], x1[a[index[i]+j]], dvec);
                            /* at the moment, just remove dvec[axis] */
                            dvec[axis] = 0;
                            tmpdist    = min(tmpdist, norm2(dvec));
                        }
                        //fprintf(stderr, "Min dist %f; trace %f\n", tmpdist, trace(box));
                        (*distvals)[j][i] += sqrt(tmpdist);
                    }
                }
            } /* end loop j, over all atoms in group */

            for (m = 0; m < DIM; m++)
            {
                (*order)[i][m] += (frameorder[m]/size);
            }

            if (!permolecule)
            {   /*Skip following if doing per-molecule*/
                for (k = 0; k < nslices; k++)
                {
                    if (slCount[k]) /* if no elements, nothing has to be added */
                    {
                        (*slOrder)[k][i] += slFrameorder[k]/slCount[k];
                        slFrameorder[k]   = 0; slCount[k] = 0;
                    }
                }
            } /* end loop i, over all groups in indexfile */
        }
        nr_frames++;

    }
    while (read_next_x(oenv, status, &t, x0, box));
    /*********** done with status file **********/

    fprintf(stderr, "\nRead trajectory. Printing parameters to file\n");
    gmx_rmpbc_done(gpbc);

    /* average over frames */
    for (i = 1; i < ngrps - 1; i++)
    {
        svmul(1.0/nr_frames, (*order)[i], (*order)[i]);
        fprintf(stderr, "Atom %d Tensor: x=%g , y=%g, z=%g\n", i, (*order)[i][XX],
                (*order)[i][YY], (*order)[i][ZZ]);
        if (bSliced || permolecule)
        {
            for (k = 0; k < nslices; k++)
            {
                (*slOrder)[k][i] /= nr_frames;
            }
        }
        if (distcalc)
        {
            for (k = 0; k < nslices; k++)
            {
                (*distvals)[k][i] /= nr_frames;
            }
        }
    }

    if (bUnsat)
    {
        fprintf(stderr, "Average angle between double bond and normal: %f\n",
                180*sdbangle/(nr_frames * size*M_PI));
    }

    sfree(x0); /* free memory used by coordinate arrays */
    sfree(x1);
    if (comidx != NULL)
    {
        sfree(comidx);
    }
    if (distidx != NULL)
    {
        sfree(distidx);
    }
    if (grpname != NULL)
    {
        sfree(grpname);
    }
}
예제 #28
0
int gmx_densmap(int argc, char *argv[])
{
    const char        *desc[] = {
        "[TT]g_densmap[tt] computes 2D number-density maps.",
        "It can make planar and axial-radial density maps.",
        "The output [TT].xpm[tt] file can be visualized with for instance xv",
        "and can be converted to postscript with [TT]xpm2ps[tt].",
        "Optionally, output can be in text form to a [TT].dat[tt] file with [TT]-od[tt], instead of the usual [TT].xpm[tt] file with [TT]-o[tt].",
        "[PAR]",
        "The default analysis is a 2-D number-density map for a selected",
        "group of atoms in the x-y plane.",
        "The averaging direction can be changed with the option [TT]-aver[tt].",
        "When [TT]-xmin[tt] and/or [TT]-xmax[tt] are set only atoms that are",
        "within the limit(s) in the averaging direction are taken into account.",
        "The grid spacing is set with the option [TT]-bin[tt].",
        "When [TT]-n1[tt] or [TT]-n2[tt] is non-zero, the grid",
        "size is set by this option.",
        "Box size fluctuations are properly taken into account.",
        "[PAR]",
        "When options [TT]-amax[tt] and [TT]-rmax[tt] are set, an axial-radial",
        "number-density map is made. Three groups should be supplied, the centers",
        "of mass of the first two groups define the axis, the third defines the",
        "analysis group. The axial direction goes from -amax to +amax, where",
        "the center is defined as the midpoint between the centers of mass and",
        "the positive direction goes from the first to the second center of mass.",
        "The radial direction goes from 0 to rmax or from -rmax to +rmax",
        "when the [TT]-mirror[tt] option has been set.",
        "[PAR]",
        "The normalization of the output is set with the [TT]-unit[tt] option.",
        "The default produces a true number density. Unit [TT]nm-2[tt] leaves out",
        "the normalization for the averaging or the angular direction.",
        "Option [TT]count[tt] produces the count for each grid cell.",
        "When you do not want the scale in the output to go",
        "from zero to the maximum density, you can set the maximum",
        "with the option [TT]-dmax[tt]."
    };
    static int         n1      = 0, n2 = 0;
    static real        xmin    = -1, xmax = -1, bin = 0.02, dmin = 0, dmax = 0, amax = 0, rmax = 0;
    static gmx_bool    bMirror = FALSE, bSums = FALSE;
    static const char *eaver[] = { NULL, "z", "y", "x", NULL };
    static const char *eunit[] = { NULL, "nm-3", "nm-2", "count", NULL };

    t_pargs            pa[] = {
        { "-bin", FALSE, etREAL, {&bin},
          "Grid size (nm)" },
        { "-aver", FALSE, etENUM, {eaver},
          "The direction to average over" },
        { "-xmin", FALSE, etREAL, {&xmin},
          "Minimum coordinate for averaging" },
        { "-xmax", FALSE, etREAL, {&xmax},
          "Maximum coordinate for averaging" },
        { "-n1", FALSE, etINT, {&n1},
          "Number of grid cells in the first direction" },
        { "-n2", FALSE, etINT, {&n2},
          "Number of grid cells in the second direction" },
        { "-amax", FALSE, etREAL, {&amax},
          "Maximum axial distance from the center"},
        { "-rmax", FALSE, etREAL, {&rmax},
          "Maximum radial distance" },
        { "-mirror", FALSE, etBOOL, {&bMirror},
          "Add the mirror image below the axial axis" },
        { "-sums", FALSE, etBOOL, {&bSums},
          "Print density sums (1D map) to stdout" },
        { "-unit", FALSE, etENUM, {eunit},
          "Unit for the output" },
        { "-dmin", FALSE, etREAL, {&dmin},
          "Minimum density in output"},
        { "-dmax", FALSE, etREAL, {&dmax},
          "Maximum density in output (0 means calculate it)"},
    };
    gmx_bool           bXmin, bXmax, bRadial;
    FILE              *fp;
    t_trxstatus       *status;
    t_topology         top;
    int                ePBC = -1;
    rvec              *x, xcom[2], direction, center, dx;
    matrix             box;
    real               t, m, mtot;
    t_pbc              pbc;
    int                cav = 0, c1 = 0, c2 = 0, natoms;
    char             **grpname, title[256], buf[STRLEN];
    const char        *unit;
    int                i, j, k, l, ngrps, anagrp, *gnx = NULL, nindex, nradial = 0, nfr, nmpower;
    atom_id          **ind = NULL, *index;
    real             **grid, maxgrid, m1, m2, box1, box2, *tickx, *tickz, invcellvol;
    real               invspa = 0, invspz = 0, axial, r, vol_old, vol, rowsum;
    int                nlev   = 51;
    t_rgb              rlo    = {1, 1, 1}, rhi = {0, 0, 0};
    output_env_t       oenv;
    const char        *label[] = { "x (nm)", "y (nm)", "z (nm)" };
    t_filenm           fnm[]   = {
        { efTRX, "-f",   NULL,       ffREAD },
        { efTPS, NULL,   NULL,       ffOPTRD },
        { efNDX, NULL,   NULL,       ffOPTRD },
        { efDAT, "-od",  "densmap",   ffOPTWR },
        { efXPM, "-o",   "densmap",   ffWRITE }
    };
#define NFILE asize(fnm)
    int                npargs;

    CopyRight(stderr, argv[0]);
    npargs = asize(pa);

    parse_common_args(&argc, argv, PCA_CAN_TIME | PCA_CAN_VIEW | PCA_BE_NICE,
                      NFILE, fnm, npargs, pa, asize(desc), desc, 0, NULL, &oenv);

    bXmin   = opt2parg_bSet("-xmin", npargs, pa);
    bXmax   = opt2parg_bSet("-xmax", npargs, pa);
    bRadial = (amax > 0 || rmax > 0);
    if (bRadial)
    {
        if (amax <= 0 || rmax <= 0)
        {
            gmx_fatal(FARGS, "Both amax and rmax should be larger than zero");
        }
    }

    if (strcmp(eunit[0], "nm-3") == 0)
    {
        nmpower = -3;
        unit    = "(nm^-3)";
    }
    else if (strcmp(eunit[0], "nm-2") == 0)
    {
        nmpower = -2;
        unit    = "(nm^-2)";
    }
    else
    {
        nmpower = 0;
        unit    = "count";
    }

    if (ftp2bSet(efTPS, NFILE, fnm) || !ftp2bSet(efNDX, NFILE, fnm))
    {
        read_tps_conf(ftp2fn(efTPS, NFILE, fnm), title, &top, &ePBC, &x, NULL, box,
                      bRadial);
    }
    if (!bRadial)
    {
        ngrps = 1;
        fprintf(stderr, "\nSelect an analysis group\n");
    }
    else
    {
        ngrps = 3;
        fprintf(stderr,
                "\nSelect two groups to define the axis and an analysis group\n");
    }
    snew(gnx, ngrps);
    snew(grpname, ngrps);
    snew(ind, ngrps);
    get_index(&top.atoms, ftp2fn_null(efNDX, NFILE, fnm), ngrps, gnx, ind, grpname);
    anagrp = ngrps - 1;
    nindex = gnx[anagrp];
    index  = ind[anagrp];
    if (bRadial)
    {
        if ((gnx[0] > 1 || gnx[1] > 1) && !ftp2bSet(efTPS, NFILE, fnm))
        {
            gmx_fatal(FARGS, "No run input file was supplied (option -s), this is required for the center of mass calculation");
        }
    }

    switch (eaver[0][0])
    {
        case 'x': cav = XX; c1 = YY; c2 = ZZ; break;
        case 'y': cav = YY; c1 = XX; c2 = ZZ; break;
        case 'z': cav = ZZ; c1 = XX; c2 = YY; break;
    }

    natoms = read_first_x(oenv, &status, ftp2fn(efTRX, NFILE, fnm), &t, &x, box);

    if (!bRadial)
    {
        if (n1 == 0)
        {
            n1 = (int)(box[c1][c1]/bin + 0.5);
        }
        if (n2 == 0)
        {
            n2 = (int)(box[c2][c2]/bin + 0.5);
        }
    }
    else
    {
        n1      = (int)(2*amax/bin + 0.5);
        nradial = (int)(rmax/bin + 0.5);
        invspa  = n1/(2*amax);
        invspz  = nradial/rmax;
        if (bMirror)
        {
            n2 = 2*nradial;
        }
        else
        {
            n2 = nradial;
        }
    }

    snew(grid, n1);
    for (i = 0; i < n1; i++)
    {
        snew(grid[i], n2);
    }

    box1 = 0;
    box2 = 0;
    nfr  = 0;
    do
    {
        if (!bRadial)
        {
            box1      += box[c1][c1];
            box2      += box[c2][c2];
            invcellvol = n1*n2;
            if (nmpower == -3)
            {
                invcellvol /= det(box);
            }
            else if (nmpower == -2)
            {
                invcellvol /= box[c1][c1]*box[c2][c2];
            }
            for (i = 0; i < nindex; i++)
            {
                j = index[i];
                if ((!bXmin || x[j][cav] >= xmin) &&
                    (!bXmax || x[j][cav] <= xmax))
                {
                    m1 = x[j][c1]/box[c1][c1];
                    if (m1 >= 1)
                    {
                        m1 -= 1;
                    }
                    if (m1 < 0)
                    {
                        m1 += 1;
                    }
                    m2 = x[j][c2]/box[c2][c2];
                    if (m2 >= 1)
                    {
                        m2 -= 1;
                    }
                    if (m2 < 0)
                    {
                        m2 += 1;
                    }
                    grid[(int)(m1*n1)][(int)(m2*n2)] += invcellvol;
                }
            }
        }
        else
        {
            set_pbc(&pbc, ePBC, box);
            for (i = 0; i < 2; i++)
            {
                if (gnx[i] == 1)
                {
                    /* One atom, just copy the coordinates */
                    copy_rvec(x[ind[i][0]], xcom[i]);
                }
                else
                {
                    /* Calculate the center of mass */
                    clear_rvec(xcom[i]);
                    mtot = 0;
                    for (j = 0; j < gnx[i]; j++)
                    {
                        k = ind[i][j];
                        m = top.atoms.atom[k].m;
                        for (l = 0; l < DIM; l++)
                        {
                            xcom[i][l] += m*x[k][l];
                        }
                        mtot += m;
                    }
                    svmul(1/mtot, xcom[i], xcom[i]);
                }
            }
            pbc_dx(&pbc, xcom[1], xcom[0], direction);
            for (i = 0; i < DIM; i++)
            {
                center[i] = xcom[0][i] + 0.5*direction[i];
            }
            unitv(direction, direction);
            for (i = 0; i < nindex; i++)
            {
                j = index[i];
                pbc_dx(&pbc, x[j], center, dx);
                axial = iprod(dx, direction);
                r     = sqrt(norm2(dx) - axial*axial);
                if (axial >= -amax && axial < amax && r < rmax)
                {
                    if (bMirror)
                    {
                        r += rmax;
                    }
                    grid[(int)((axial + amax)*invspa)][(int)(r*invspz)] += 1;
                }
            }
        }
        nfr++;
    }
    while (read_next_x(oenv, status, &t, natoms, x, box));
    close_trj(status);

    /* normalize gridpoints */
    maxgrid = 0;
    if (!bRadial)
    {
        for (i = 0; i < n1; i++)
        {
            for (j = 0; j < n2; j++)
            {
                grid[i][j] /= nfr;
                if (grid[i][j] > maxgrid)
                {
                    maxgrid = grid[i][j];
                }
            }
        }
    }
    else
    {
        for (i = 0; i < n1; i++)
        {
            vol_old = 0;
            for (j = 0; j < nradial; j++)
            {
                switch (nmpower)
                {
                    case -3: vol = M_PI*(j+1)*(j+1)/(invspz*invspz*invspa); break;
                    case -2: vol =            (j+1)/(invspz*invspa);        break;
                    default: vol =             j+1;                         break;
                }
                if (bMirror)
                {
                    k = j + nradial;
                }
                else
                {
                    k = j;
                }
                grid[i][k] /= nfr*(vol - vol_old);
                if (bMirror)
                {
                    grid[i][nradial-1-j] = grid[i][k];
                }
                vol_old = vol;
                if (grid[i][k] > maxgrid)
                {
                    maxgrid = grid[i][k];
                }
            }
        }
    }
    fprintf(stdout, "\n  The maximum density is %f %s\n", maxgrid, unit);
    if (dmax > 0)
    {
        maxgrid = dmax;
    }

    snew(tickx, n1+1);
    snew(tickz, n2+1);
    if (!bRadial)
    {
        /* normalize box-axes */
        box1 /= nfr;
        box2 /= nfr;
        for (i = 0; i <= n1; i++)
        {
            tickx[i] = i*box1/n1;
        }
        for (i = 0; i <= n2; i++)
        {
            tickz[i] = i*box2/n2;
        }
    }
    else
    {
        for (i = 0; i <= n1; i++)
        {
            tickx[i] = i/invspa - amax;
        }
        if (bMirror)
        {
            for (i = 0; i <= n2; i++)
            {
                tickz[i] = i/invspz - rmax;
            }
        }
        else
        {
            for (i = 0; i <= n2; i++)
            {
                tickz[i] = i/invspz;
            }
        }
    }

    if (bSums)
    {
        for (i = 0; i < n1; ++i)
        {
            fprintf(stdout, "Density sums:\n");
            rowsum = 0;
            for (j = 0; j < n2; ++j)
            {
                rowsum += grid[i][j];
            }
            fprintf(stdout, "%g\t", rowsum);
        }
        fprintf(stdout, "\n");
    }

    sprintf(buf, "%s number density", grpname[anagrp]);
    if (!bRadial && (bXmin || bXmax))
    {
        if (!bXmax)
        {
            sprintf(buf+strlen(buf), ", %c > %g nm", eaver[0][0], xmin);
        }
        else if (!bXmin)
        {
            sprintf(buf+strlen(buf), ", %c < %g nm", eaver[0][0], xmax);
        }
        else
        {
            sprintf(buf+strlen(buf), ", %c: %g - %g nm", eaver[0][0], xmin, xmax);
        }
    }
    if (ftp2bSet(efDAT, NFILE, fnm))
    {
        fp = ffopen(ftp2fn(efDAT, NFILE, fnm), "w");
        /*optional text form output:  first row is tickz; first col is tickx */
        fprintf(fp, "0\t");
        for (j = 0; j < n2; ++j)
        {
            fprintf(fp, "%g\t", tickz[j]);
        }
        fprintf(fp, "\n");

        for (i = 0; i < n1; ++i)
        {
            fprintf(fp, "%g\t", tickx[i]);
            for (j = 0; j < n2; ++j)
            {
                fprintf(fp, "%g\t", grid[i][j]);
            }
            fprintf(fp, "\n");
        }
        ffclose(fp);
    }
    else
    {
        fp = ffopen(ftp2fn(efXPM, NFILE, fnm), "w");
        write_xpm(fp, MAT_SPATIAL_X | MAT_SPATIAL_Y, buf, unit,
                  bRadial ? "axial (nm)" : label[c1], bRadial ? "r (nm)" : label[c2],
                  n1, n2, tickx, tickz, grid, dmin, maxgrid, rlo, rhi, &nlev);
        ffclose(fp);
    }

    thanx(stderr);

    do_view(oenv, opt2fn("-o", NFILE, fnm), NULL);

    return 0;
}
예제 #29
0
/* Estimate the reciprocal space part error of the SPME Ewald sum. */
static real estimate_reciprocal(
        t_inputinfo       *info,
        rvec               x[], /* array of particles */
        real               q[], /* array of charges */
        int                nr,  /* number of charges = size of the charge array */
        FILE  gmx_unused  *fp_out,
        gmx_bool           bVerbose,
        unsigned int       seed,     /* The seed for the random number generator */
        int               *nsamples, /* Return the number of samples used if Monte Carlo
                                      * algorithm is used for self energy error estimate */
        t_commrec         *cr)
{
    real     e_rec   = 0; /* reciprocal error estimate */
    real     e_rec1  = 0; /* Error estimate term 1*/
    real     e_rec2  = 0; /* Error estimate term 2*/
    real     e_rec3  = 0; /* Error estimate term 3 */
    real     e_rec3x = 0; /* part of Error estimate term 3 in x */
    real     e_rec3y = 0; /* part of Error estimate term 3 in y */
    real     e_rec3z = 0; /* part of Error estimate term 3 in z */
    int      i, ci;
    int      nx, ny, nz;  /* grid coordinates */
    real     q2_all = 0;  /* sum of squared charges */
    rvec     gridpx;      /* reciprocal grid point in x direction*/
    rvec     gridpxy;     /* reciprocal grid point in x and y direction*/
    rvec     gridp;       /* complete reciprocal grid point in 3 directions*/
    rvec     tmpvec;      /* template to create points from basis vectors */
    rvec     tmpvec2;     /* template to create points from basis vectors */
    real     coeff  = 0;  /* variable to compute coefficients of the error estimate */
    real     coeff2 = 0;  /* variable to compute coefficients of the error estimate */
    real     tmp    = 0;  /* variables to compute different factors from vectors */
    real     tmp1   = 0;
    real     tmp2   = 0;
    gmx_bool bFraction;

    /* Random number generator */
    gmx_rng_t rng     = NULL;
    int      *numbers = NULL;

    /* Index variables for parallel work distribution */
    int startglobal, stopglobal;
    int startlocal, stoplocal;
    int x_per_core;
    int xtot;

#ifdef TAKETIME
    double t0 = 0.0;
    double t1 = 0.0;
#endif

    rng = gmx_rng_init(seed);

    clear_rvec(gridpx);
    clear_rvec(gridpxy);
    clear_rvec(gridp);
    clear_rvec(tmpvec);
    clear_rvec(tmpvec2);

    for (i = 0; i < nr; i++)
    {
        q2_all += q[i]*q[i];
    }

    /* Calculate indices for work distribution */
    startglobal = -info->nkx[0]/2;
    stopglobal  = info->nkx[0]/2;
    xtot        = stopglobal*2+1;
    if (PAR(cr))
    {
        x_per_core = static_cast<int>(ceil(static_cast<real>(xtot) / cr->nnodes));
        startlocal = startglobal + x_per_core*cr->nodeid;
        stoplocal  = startlocal + x_per_core -1;
        if (stoplocal > stopglobal)
        {
            stoplocal = stopglobal;
        }
    }
    else
    {
        startlocal = startglobal;
        stoplocal  = stopglobal;
        x_per_core = xtot;
    }
/*
   #ifdef GMX_LIB_MPI
    MPI_Barrier(MPI_COMM_WORLD);
   #endif
 */

#ifdef GMX_LIB_MPI
#ifdef TAKETIME
    if (MASTER(cr))
    {
        t0 = MPI_Wtime();
    }
#endif
#endif

    if (MASTER(cr))
    {

        fprintf(stderr, "Calculating reciprocal error part 1 ...");

    }

    for (nx = startlocal; nx <= stoplocal; nx++)
    {
        svmul(nx, info->recipbox[XX], gridpx);
        for (ny = -info->nky[0]/2; ny < info->nky[0]/2+1; ny++)
        {
            svmul(ny, info->recipbox[YY], tmpvec);
            rvec_add(gridpx, tmpvec, gridpxy);
            for (nz = -info->nkz[0]/2; nz < info->nkz[0]/2+1; nz++)
            {
                if (0 == nx &&  0 == ny &&  0 == nz)
                {
                    continue;
                }
                svmul(nz, info->recipbox[ZZ], tmpvec);
                rvec_add(gridpxy, tmpvec, gridp);
                tmp    = norm2(gridp);
                coeff  = exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] );
                coeff /= 2.0 * M_PI * info->volume * tmp;
                coeff2 = tmp;


                tmp  = eps_poly2(nx, info->nkx[0], info->pme_order[0]);
                tmp += eps_poly2(ny, info->nkx[0], info->pme_order[0]);
                tmp += eps_poly2(nz, info->nkx[0], info->pme_order[0]);

                tmp1 = eps_poly1(nx, info->nkx[0], info->pme_order[0]);
                tmp2 = eps_poly1(ny, info->nky[0], info->pme_order[0]);

                tmp += 2.0 * tmp1 * tmp2;

                tmp1 = eps_poly1(nz, info->nkz[0], info->pme_order[0]);
                tmp2 = eps_poly1(ny, info->nky[0], info->pme_order[0]);

                tmp += 2.0 * tmp1 * tmp2;

                tmp1 = eps_poly1(nz, info->nkz[0], info->pme_order[0]);
                tmp2 = eps_poly1(nx, info->nkx[0], info->pme_order[0]);

                tmp += 2.0 * tmp1 * tmp2;

                tmp1  = eps_poly1(nx, info->nkx[0], info->pme_order[0]);
                tmp1 += eps_poly1(ny, info->nky[0], info->pme_order[0]);
                tmp1 += eps_poly1(nz, info->nkz[0], info->pme_order[0]);

                tmp += tmp1 * tmp1;

                e_rec1 += 32.0 * M_PI * M_PI * coeff * coeff * coeff2 * tmp  * q2_all * q2_all / nr;

                tmp1  = eps_poly3(nx, info->nkx[0], info->pme_order[0]);
                tmp1 *= info->nkx[0];
                tmp2  = iprod(gridp, info->recipbox[XX]);

                tmp = tmp1*tmp2;

                tmp1  = eps_poly3(ny, info->nky[0], info->pme_order[0]);
                tmp1 *= info->nky[0];
                tmp2  = iprod(gridp, info->recipbox[YY]);

                tmp += tmp1*tmp2;

                tmp1  = eps_poly3(nz, info->nkz[0], info->pme_order[0]);
                tmp1 *= info->nkz[0];
                tmp2  = iprod(gridp, info->recipbox[ZZ]);

                tmp += tmp1*tmp2;

                tmp *= 4.0 * M_PI;

                tmp1  = eps_poly4(nx, info->nkx[0], info->pme_order[0]);
                tmp1 *= norm2(info->recipbox[XX]);
                tmp1 *= info->nkx[0] * info->nkx[0];

                tmp += tmp1;

                tmp1  = eps_poly4(ny, info->nky[0], info->pme_order[0]);
                tmp1 *= norm2(info->recipbox[YY]);
                tmp1 *= info->nky[0] * info->nky[0];

                tmp += tmp1;

                tmp1  = eps_poly4(nz, info->nkz[0], info->pme_order[0]);
                tmp1 *= norm2(info->recipbox[ZZ]);
                tmp1 *= info->nkz[0] * info->nkz[0];

                tmp += tmp1;

                e_rec2 += 4.0 * coeff * coeff * tmp * q2_all * q2_all / nr;

            }
        }
        if (MASTER(cr))
        {
            fprintf(stderr, "\rCalculating reciprocal error part 1 ... %3.0f%%", 100.0*(nx-startlocal+1)/(x_per_core));
        }

    }

    if (MASTER(cr))
    {
        fprintf(stderr, "\n");
    }

    /* Use just a fraction of all charges to estimate the self energy error term? */
    bFraction =  (info->fracself > 0.0) && (info->fracself < 1.0);

    if (bFraction)
    {
        /* Here xtot is the number of samples taken for the Monte Carlo calculation
         * of the average of term IV of equation 35 in Wang2010. Round up to a
         * number of samples that is divisible by the number of nodes */
        x_per_core  = static_cast<int>(ceil(info->fracself * nr / cr->nnodes));
        xtot        = x_per_core * cr->nnodes;
    }
    else
    {
        /* In this case we use all nr particle positions */
        xtot       = nr;
        x_per_core = static_cast<int>(ceil(static_cast<real>(xtot) / cr->nnodes));
    }

    startlocal = x_per_core *  cr->nodeid;
    stoplocal  = std::min(startlocal + x_per_core, xtot);  /* min needed if xtot == nr */

    if (bFraction)
    {
        /* Make shure we get identical results in serial and parallel. Therefore,
         * take the sample indices from a single, global random number array that
         * is constructed on the master node and that only depends on the seed */
        snew(numbers, xtot);
        if (MASTER(cr))
        {
            for (i = 0; i < xtot; i++)
            {
                numbers[i] = static_cast<int>(floor(gmx_rng_uniform_real(rng) * nr));
            }
        }
        /* Broadcast the random number array to the other nodes */
        if (PAR(cr))
        {
            nblock_bc(cr, xtot, numbers);
        }

        if (bVerbose && MASTER(cr))
        {
            fprintf(stdout, "Using %d sample%s to approximate the self interaction error term",
                    xtot, xtot == 1 ? "" : "s");
            if (PAR(cr))
            {
                fprintf(stdout, " (%d sample%s per node)", x_per_core, x_per_core == 1 ? "" : "s");
            }
            fprintf(stdout, ".\n");
        }
    }

    /* Return the number of positions used for the Monte Carlo algorithm */
    *nsamples = xtot;

    for (i = startlocal; i < stoplocal; i++)
    {
        e_rec3x = 0;
        e_rec3y = 0;
        e_rec3z = 0;

        if (bFraction)
        {
            /* Randomly pick a charge */
            ci = numbers[i];
        }
        else
        {
            /* Use all charges */
            ci = i;
        }

        /* for(nx=startlocal; nx<=stoplocal; nx++)*/
        for (nx = -info->nkx[0]/2; nx < info->nkx[0]/2+1; nx++)
        {
            svmul(nx, info->recipbox[XX], gridpx);
            for (ny = -info->nky[0]/2; ny < info->nky[0]/2+1; ny++)
            {
                svmul(ny, info->recipbox[YY], tmpvec);
                rvec_add(gridpx, tmpvec, gridpxy);
                for (nz = -info->nkz[0]/2; nz < info->nkz[0]/2+1; nz++)
                {

                    if (0 == nx && 0 == ny && 0 == nz)
                    {
                        continue;
                    }

                    svmul(nz, info->recipbox[ZZ], tmpvec);
                    rvec_add(gridpxy, tmpvec, gridp);
                    tmp      = norm2(gridp);
                    coeff    = exp(-1.0 * M_PI * M_PI * tmp / info->ewald_beta[0] / info->ewald_beta[0] );
                    coeff   /= tmp;
                    e_rec3x += coeff*eps_self(nx, info->nkx[0], info->recipbox[XX], info->pme_order[0], x[ci]);
                    e_rec3y += coeff*eps_self(ny, info->nky[0], info->recipbox[YY], info->pme_order[0], x[ci]);
                    e_rec3z += coeff*eps_self(nz, info->nkz[0], info->recipbox[ZZ], info->pme_order[0], x[ci]);

                }
            }
        }

        clear_rvec(tmpvec2);

        svmul(e_rec3x, info->recipbox[XX], tmpvec);
        rvec_inc(tmpvec2, tmpvec);
        svmul(e_rec3y, info->recipbox[YY], tmpvec);
        rvec_inc(tmpvec2, tmpvec);
        svmul(e_rec3z, info->recipbox[ZZ], tmpvec);
        rvec_inc(tmpvec2, tmpvec);

        e_rec3 += q[ci]*q[ci]*q[ci]*q[ci]*norm2(tmpvec2) / ( xtot * M_PI * info->volume * M_PI * info->volume);
        if (MASTER(cr))
        {
            fprintf(stderr, "\rCalculating reciprocal error part 2 ... %3.0f%%",
                    100.0*(i+1)/stoplocal);

        }
    }

    if (MASTER(cr))
    {
        fprintf(stderr, "\n");
    }

#ifdef GMX_LIB_MPI
#ifdef TAKETIME
    if (MASTER(cr))
    {
        t1 = MPI_Wtime() - t0;
        fprintf(fp_out, "Recip. err. est. took   : %lf s\n", t1);
    }
#endif
#endif

#ifdef DEBUG
    if (PAR(cr))
    {
        fprintf(stderr, "Node %3d: nx=[%3d...%3d]  e_rec3=%e\n",
                cr->nodeid, startlocal, stoplocal, e_rec3);
    }
#endif

    if (PAR(cr))
    {
        gmx_sum(1, &e_rec1, cr);
        gmx_sum(1, &e_rec2, cr);
        gmx_sum(1, &e_rec3, cr);
    }

    /* e_rec1*=8.0 * q2_all / info->volume / info->volume / nr ;
       e_rec2*=  q2_all / M_PI / M_PI / info->volume / info->volume / nr ;
       e_rec3/= M_PI * M_PI * info->volume * info->volume * nr ;
     */
    e_rec = sqrt(e_rec1+e_rec2+e_rec3);


    return ONE_4PI_EPS0 * e_rec;
}
예제 #30
0
 double Quaternion::norm()
 {
   return sqrt(norm2());
 }