Exemplo n.º 1
0
main() {

    double ans, a, b, c;

    a = 2.0;
    b = -5.0;
    c = 7.0;


    printf( "\n\n  Test of utility routines." );

    printf( "\n\n" );

    ans = dsqr( a );
    printf( "\n  a = %lf  ans = dsqr( a ) = %lf", a, ans );

    ans = dcub( a );
    printf( "\n  a = %lf  ans = dcub( a ) = %lf", a, ans );

    ans = dpow4( a );
    printf( "\n  a = %lf  ans = dpow4( a ) = %lf", a, ans );

    ans = dpow5( a );
    printf( "\n  a = %lf  ans = dpow5( a ) = %lf", a, ans );

    ans = dsgn( a );
    printf( "\n  a = %lf  ans = dsgn( a ) = %lf", a, ans );

    ans = dsgn( b );
    printf( "\n  b = %lf  ans = dsgn( b ) = %lf", b, ans );

    ans = dsign( a, b );
    printf( "\n  a = %lf,  b = %lf,  ans = sign( a, b ) = %lf", a, b, ans );

    ans = dpythag( a, b );
    printf( "\n  a = %lf,  b = %lf,  ans = pythag( a, b ) = %lf", a, b, ans );

    ans = dmin( a, b );
    printf( "\n  a = %lf,  b = %lf,  ans = dmin( a, b ) = %lf", a, b, ans );

    ans = dmax( a, b );
    printf( "\n  a = %lf,  b = %lf,  ans = dmax( a, b ) = %lf", a, b, ans );

    ans = dmin3( a, b, c );
    printf( "\n  a = %lf,  b = %lf,  c = %lf,  ans = dmin3( a, b, c ) = %lf", a, b, c, ans );

    ans = dmax3( a, b, c );
    printf( "\n  a = %lf,  b = %lf,  c = %lf,  ans = dmax3( a, b, c ) = %lf", a, b, c, ans );



    printf( "\n\n" );
}
Exemplo n.º 2
0
double dawson( double x ) {

    int i, n0;
    double d1, d2, e1, e2, sum, x2, xp, xx, ans;
    static double c[NMAX+1];
    static int init = 0;

    if ( init == 0 ) {
        init = 1;
        for ( i = 1; i <= NMAX; ++i ) {
            c[i] = exp( -dsqr( ( 2.0*i - 1.0 )*H ) );
        }
    }
    if ( fabs(x) < XMIN ) {
        /*
         *    Use series expansion.
         */
        x2 = x*x;
        ans = x*( 1.0 - (2.0/3.0)*x2*( 1.0 - (2.0/5.0)*x2*( 1.0 - (2.0/7.0)*x2 ) ) );
    } else {
        /*
         *    Use sampling theorem representation.
         */
        xx = fabs(x);
        n0 = 2*( (int)(0.5 + 0.5*xx/H) );
        xp = xx - n0*H;
        e1 = exp(2.0*xp*H);
        e2 = e1*e1;
        d1 = (double) n0 + 1.0;
        d2 = d1 - 2.0;
        sum = 0.0;
        for ( i = 1; i <= NMAX; ++i ) {
            sum += c[i]*( e1/d1 + 1.0/(d2*e1) );
            d1 += 2.0;
            d2 -= 2.0;
            e1 *= e2;
        }
        ans = dsign( exp( -xp*xp ), x )*sum/SQRTPI;
    }
    return ans;
}
Exemplo n.º 3
0
static void make_cyl_refgrps(t_commrec *cr, t_pull *pull, t_mdatoms *md,
                             t_pbc *pbc, double t, rvec *x, rvec *xp)
{
    int           c, i, ii, m, start, end;
    rvec          g_x, dx, dir;
    double        r0_2, sum_a, sum_ap, dr2, mass, weight, wmass, wwmass, inp;
    t_pull_coord *pcrd;
    t_pull_group *pref, *pgrp, *pdyna;
    gmx_ga2la_t   ga2la = NULL;

    if (pull->dbuf_cyl == NULL)
    {
        snew(pull->dbuf_cyl, pull->ncoord*4);
    }

    if (cr && DOMAINDECOMP(cr))
    {
        ga2la = cr->dd->ga2la;
    }

    start = 0;
    end   = md->homenr;

    r0_2 = dsqr(pull->cyl_r0);

    /* loop over all groups to make a reference group for each*/
    for (c = 0; c < pull->ncoord; c++)
    {
        pcrd  = &pull->coord[c];

        /* pref will be the same group for all pull coordinates */
        pref  = &pull->group[pcrd->group[0]];
        pgrp  = &pull->group[pcrd->group[1]];
        pdyna = &pull->dyna[c];
        copy_rvec(pcrd->vec, dir);
        sum_a          = 0;
        sum_ap         = 0;
        wmass          = 0;
        wwmass         = 0;
        pdyna->nat_loc = 0;

        for (m = 0; m < DIM; m++)
        {
            g_x[m] = pgrp->x[m] - pcrd->vec[m]*(pcrd->init + pcrd->rate*t);
        }

        /* loop over all atoms in the main ref group */
        for (i = 0; i < pref->nat; i++)
        {
            ii = pref->ind[i];
            if (ga2la)
            {
                if (!ga2la_get_home(ga2la, pref->ind[i], &ii))
                {
                    ii = -1;
                }
            }
            if (ii >= start && ii < end)
            {
                pbc_dx_aiuc(pbc, x[ii], g_x, dx);
                inp = iprod(dir, dx);
                dr2 = 0;
                for (m = 0; m < DIM; m++)
                {
                    dr2 += dsqr(dx[m] - inp*dir[m]);
                }

                if (dr2 < r0_2)
                {
                    /* add to index, to sum of COM, to weight array */
                    if (pdyna->nat_loc >= pdyna->nalloc_loc)
                    {
                        pdyna->nalloc_loc = over_alloc_large(pdyna->nat_loc+1);
                        srenew(pdyna->ind_loc, pdyna->nalloc_loc);
                        srenew(pdyna->weight_loc, pdyna->nalloc_loc);
                    }
                    pdyna->ind_loc[pdyna->nat_loc] = ii;
                    mass   = md->massT[ii];
                    weight = get_weight(sqrt(dr2), pull->cyl_r1, pull->cyl_r0);
                    pdyna->weight_loc[pdyna->nat_loc] = weight;
                    sum_a += mass*weight*inp;
                    if (xp)
                    {
                        pbc_dx_aiuc(pbc, xp[ii], g_x, dx);
                        inp     = iprod(dir, dx);
                        sum_ap += mass*weight*inp;
                    }
                    wmass  += mass*weight;
                    wwmass += mass*sqr(weight);
                    pdyna->nat_loc++;
                }
            }
        }
        pull->dbuf_cyl[c*4+0] = wmass;
        pull->dbuf_cyl[c*4+1] = wwmass;
        pull->dbuf_cyl[c*4+2] = sum_a;
        pull->dbuf_cyl[c*4+3] = sum_ap;
    }

    if (cr && PAR(cr))
    {
        /* Sum the contributions over the nodes */
        gmx_sumd(pull->ncoord*4, pull->dbuf_cyl, cr);
    }

    for (c = 0; c < pull->ncoord; c++)
    {
        pcrd  = &pull->coord[c];

        pdyna = &pull->dyna[c];
        pgrp  = &pull->group[pcrd->group[1]];

        wmass         = pull->dbuf_cyl[c*4+0];
        wwmass        = pull->dbuf_cyl[c*4+1];
        pdyna->wscale = wmass/wwmass;
        pdyna->invtm  = 1.0/(pdyna->wscale*wmass);

        for (m = 0; m < DIM; m++)
        {
            g_x[m]      = pgrp->x[m] - pcrd->vec[m]*(pcrd->init + pcrd->rate*t);
            pdyna->x[m] = g_x[m] + pcrd->vec[m]*pull->dbuf_cyl[c*4+2]/wmass;
            if (xp)
            {
                pdyna->xp[m] = g_x[m] + pcrd->vec[m]*pull->dbuf_cyl[c*4+3]/wmass;
            }
        }

        if (debug)
        {
            fprintf(debug, "Pull cylinder group %d:%8.3f%8.3f%8.3f m:%8.3f\n",
                    c, pdyna->x[0], pdyna->x[1],
                    pdyna->x[2], 1.0/pdyna->invtm);
        }
    }
}
Exemplo n.º 4
0
double Neuroseg_Ry_P(const Neuroseg *seg, const double *res, 
		     Neuropos_Reference_e ref)
{ 
  return Neuroseg_Ry(seg, ref) * sqrt(dsqr(res[0]) * cos(seg->theta) + 
				      dsqr(res[1]) * sin(seg->theta));
}
Exemplo n.º 5
0
static void convert_full_sums(ener_old_t *ener_old,t_enxframe *fr)
{
    int nstep_all;
    int ne,ns,i;
    double esum_all,eav_all;
    
    if (fr->nsum > 0)
    {
        ne = 0;
        ns = 0;
        for(i=0; i<fr->nre; i++)
        {
            if (fr->ener[i].e    != 0) ne++;
            if (fr->ener[i].esum != 0) ns++;
        }
        if (ne > 0 && ns == 0)
        {
            /* We do not have all energy sums */
            fr->nsum = 0;
        }
    }
    
    /* Convert old full simulation sums to sums between energy frames */
    nstep_all = fr->step - ener_old->first_step + 1;
    if (fr->nsum > 1 && fr->nsum == nstep_all && ener_old->nsum_prev > 0)
    {
        /* Set the new sum length: the frame step difference */
        fr->nsum = fr->step - ener_old->step_prev;
        for(i=0; i<fr->nre; i++)
        {
            esum_all = fr->ener[i].esum;
            eav_all  = fr->ener[i].eav;
            fr->ener[i].esum = esum_all - ener_old->ener_prev[i].esum;
            fr->ener[i].eav  = eav_all  - ener_old->ener_prev[i].eav
                - dsqr(ener_old->ener_prev[i].esum/(nstep_all - fr->nsum)
                       - esum_all/nstep_all)*
                (nstep_all - fr->nsum)*nstep_all/(double)fr->nsum;
            ener_old->ener_prev[i].esum = esum_all;
            ener_old->ener_prev[i].eav  = eav_all;
        }
        ener_old->nsum_prev = nstep_all;
    }
    else if (fr->nsum > 0)
    {
        if (fr->nsum != nstep_all)
        {
            fprintf(stderr,"\nWARNING: something is wrong with the energy sums, will not use exact averages\n");
            ener_old->nsum_prev = 0;
        }
        else
        {
            ener_old->nsum_prev = nstep_all;
        }
        /* Copy all sums to ener_prev */
        for(i=0; i<fr->nre; i++)
        {
            ener_old->ener_prev[i].esum = fr->ener[i].esum;
            ener_old->ener_prev[i].eav  = fr->ener[i].eav;
        }
    }
    
    ener_old->step_prev = fr->step;
}
Exemplo n.º 6
0
static void update_ee_sum(int nre,
                          gmx_int64_t *ee_sum_step,
                          gmx_int64_t *ee_sum_nsteps,
                          gmx_int64_t *ee_sum_nsum,
                          t_energy *ee_sum,
                          t_enxframe *fr, int out_step)
{
    gmx_int64_t     nsteps, nsum, fr_nsum;
    int             i;

    nsteps = *ee_sum_nsteps;
    nsum   = *ee_sum_nsum;

    fr_nsum = fr->nsum;
    if (fr_nsum == 0)
    {
        fr_nsum = 1;
    }

    if (nsteps == 0)
    {
        if (fr_nsum == 1)
        {
            for (i = 0; i < nre; i++)
            {
                ee_sum[i].esum = fr->ener[i].e;
                ee_sum[i].eav  = 0;
            }
        }
        else
        {
            for (i = 0; i < nre; i++)
            {
                ee_sum[i].esum = fr->ener[i].esum;
                ee_sum[i].eav  = fr->ener[i].eav;
            }
        }
        nsteps = fr->nsteps;
        nsum   = fr_nsum;
    }
    else if (out_step + *ee_sum_nsum - *ee_sum_step == nsteps + fr->nsteps)
    {
        if (fr_nsum == 1)
        {
            for (i = 0; i < nre; i++)
            {
                ee_sum[i].eav  +=
                    dsqr(ee_sum[i].esum/nsum
                         - (ee_sum[i].esum + fr->ener[i].e)/(nsum + 1))*nsum*(nsum + 1);
                ee_sum[i].esum += fr->ener[i].e;
            }
        }
        else
        {
            for (i = 0; i < fr->nre; i++)
            {
                ee_sum[i].eav  +=
                    fr->ener[i].eav +
                    dsqr(ee_sum[i].esum/nsum
                         - (ee_sum[i].esum + fr->ener[i].esum)/(nsum + fr->nsum))*
                    nsum*(nsum + fr->nsum)/(double)fr->nsum;
                ee_sum[i].esum += fr->ener[i].esum;
            }
        }
        nsteps += fr->nsteps;
        nsum   += fr_nsum;
    }
    else
    {
        if (fr->nsum != 0)
        {
            fprintf(stderr, "\nWARNING: missing energy sums at time %f\n", fr->t);
        }
        nsteps = 0;
        nsum   = 0;
    }

    *ee_sum_step   = out_step;
    *ee_sum_nsteps = nsteps;
    *ee_sum_nsum   = nsum;
}
Exemplo n.º 7
0
/* Pulling with a harmonic umbrella potential or constant force */
static void do_pull_pot(int ePull,
                        t_pull *pull, t_pbc *pbc, double t, real lambda,
                        real *V, tensor vir, real *dVdl)
{
    int           c, j, m;
    double        dev, ndr, invdr;
    real          k, dkdl;
    t_pull_coord *pcrd;

    /* loop over the pull coordinates */
    *V    = 0;
    *dVdl = 0;
    for (c = 0; c < pull->ncoord; c++)
    {
        pcrd = &pull->coord[c];

        get_pull_coord_distance(pull, c, pbc, t, pcrd->dr, &dev);

        k    = (1.0 - lambda)*pcrd->k + lambda*pcrd->kB;
        dkdl = pcrd->kB - pcrd->k;

        switch (pull->eGeom)
        {
            case epullgDIST:
                ndr   = dnorm(pcrd->dr);
                invdr = 1/ndr;
                if (ePull == epullUMBRELLA)
                {
                    pcrd->f_scal  =       -k*dev;
                    *V           += 0.5*   k*dsqr(dev);
                    *dVdl        += 0.5*dkdl*dsqr(dev);
                }
                else
                {
                    pcrd->f_scal  =   -k;
                    *V           +=    k*ndr;
                    *dVdl        += dkdl*ndr;
                }
                for (m = 0; m < DIM; m++)
                {
                    pcrd->f[m]    = pcrd->f_scal*pcrd->dr[m]*invdr;
                }
                break;
            case epullgDIR:
            case epullgDIRPBC:
            case epullgCYL:
                if (ePull == epullUMBRELLA)
                {
                    pcrd->f_scal  =       -k*dev;
                    *V           += 0.5*   k*dsqr(dev);
                    *dVdl        += 0.5*dkdl*dsqr(dev);
                }
                else
                {
                    ndr = 0;
                    for (m = 0; m < DIM; m++)
                    {
                        ndr += pcrd->vec[m]*pcrd->dr[m];
                    }
                    pcrd->f_scal  =   -k;
                    *V           +=    k*ndr;
                    *dVdl        += dkdl*ndr;
                }
                for (m = 0; m < DIM; m++)
                {
                    pcrd->f[m]    = pcrd->f_scal*pcrd->vec[m];
                }
                break;
        }

        if (vir)
        {
            /* Add the pull contribution to the virial */
            for (j = 0; j < DIM; j++)
            {
                for (m = 0; m < DIM; m++)
                {
                    vir[j][m] -= 0.5*pcrd->f[j]*pcrd->dr[m];
                }
            }
        }
    }
}
Exemplo n.º 8
0
static int gmx_stats_compute(gmx_stats *stats, int weight)
{
    double yy, yx, xx, sx, sy, dy, chi2, chi2aa, d2;
    double ssxx, ssyy, ssxy;
    double w, wtot, yx_nw, sy_nw, sx_nw, yy_nw, xx_nw, dx2, dy2;
    int    i, N;

    N = stats->np;
    if (stats->computed == 0)
    {
        if (N < 1)
        {
            return estatsNO_POINTS;
        }

        xx   = xx_nw = 0;
        yy   = yy_nw = 0;
        yx   = yx_nw = 0;
        sx   = sx_nw = 0;
        sy   = sy_nw = 0;
        wtot = 0;
        d2   = 0;
        for (i = 0; (i < N); i++)
        {
            d2 += dsqr(stats->x[i]-stats->y[i]);
            if ((stats->dy[i]) && (weight == elsqWEIGHT_Y))
            {
                w = 1/dsqr(stats->dy[i]);
            }
            else
            {
                w = 1;
            }

            wtot  += w;

            xx    += w*dsqr(stats->x[i]);
            xx_nw += dsqr(stats->x[i]);

            yy    += w*dsqr(stats->y[i]);
            yy_nw += dsqr(stats->y[i]);

            yx    += w*stats->y[i]*stats->x[i];
            yx_nw += stats->y[i]*stats->x[i];

            sx    += w*stats->x[i];
            sx_nw += stats->x[i];

            sy    += w*stats->y[i];
            sy_nw += stats->y[i];
        }

        /* Compute average, sigma and error */
        stats->aver       = sy_nw/N;
        stats->sigma_aver = sqrt(yy_nw/N - dsqr(sy_nw/N));
        stats->error      = stats->sigma_aver/sqrt(N);

        /* Compute RMSD between x and y */
        stats->rmsd = sqrt(d2/N);

        /* Correlation coefficient for data */
        yx_nw       /= N;
        xx_nw       /= N;
        yy_nw       /= N;
        sx_nw       /= N;
        sy_nw       /= N;
        ssxx         = N*(xx_nw - dsqr(sx_nw));
        ssyy         = N*(yy_nw - dsqr(sy_nw));
        ssxy         = N*(yx_nw - (sx_nw*sy_nw));
        stats->Rdata = sqrt(dsqr(ssxy)/(ssxx*ssyy));

        /* Compute straight line through datapoints, either with intercept
           zero (result in aa) or with intercept variable (results in a
           and b) */
        yx = yx/wtot;
        xx = xx/wtot;
        sx = sx/wtot;
        sy = sy/wtot;

        stats->aa = (yx/xx);
        stats->a  = (yx-sx*sy)/(xx-sx*sx);
        stats->b  = (sy)-(stats->a)*(sx);

        /* Compute chi2, deviation from a line y = ax+b. Also compute
           chi2aa which returns the deviation from a line y = ax. */
        chi2   = 0;
        chi2aa = 0;
        for (i = 0; (i < N); i++)
        {
            if (stats->dy[i] > 0)
            {
                dy = stats->dy[i];
            }
            else
            {
                dy = 1;
            }
            chi2aa += dsqr((stats->y[i]-(stats->aa*stats->x[i]))/dy);
            chi2   += dsqr((stats->y[i]-(stats->a*stats->x[i]+stats->b))/dy);
        }
        if (N > 2)
        {
            stats->chi2   = sqrt(chi2/(N-2));
            stats->chi2aa = sqrt(chi2aa/(N-2));

            /* Look up equations! */
            dx2            = (xx-sx*sx);
            dy2            = (yy-sy*sy);
            stats->sigma_a = sqrt(stats->chi2/((N-2)*dx2));
            stats->sigma_b = stats->sigma_a*sqrt(xx);
            stats->Rfit    = fabs(ssxy)/sqrt(ssxx*ssyy);
            /*stats->a*sqrt(dx2/dy2);*/
            stats->Rfitaa  = stats->aa*sqrt(dx2/dy2);
        }
        else
        {
            stats->chi2    = 0;
            stats->chi2aa  = 0;
            stats->sigma_a = 0;
            stats->sigma_b = 0;
            stats->Rfit    = 0;
            stats->Rfitaa  = 0;
        }

        stats->computed = 1;
    }

    return estatsOK;
}
Exemplo n.º 9
0
/* Apply constraint using SHAKE */
static void do_constraint(t_pull *pull, t_pbc *pbc,
                          rvec *x, rvec *v,
                          gmx_bool bMaster, tensor vir,
                          double dt, double t)
{

    dvec      *r_ij;   /* x[i] com of i in prev. step. Obeys constr. -> r_ij[i] */
    dvec       unc_ij; /* xp[i] com of i this step, before constr.   -> unc_ij  */
    dvec      *rnew;  /* current 'new' positions of the groups */
    double    *dr_tot; /* the total update of the coords */
    double     ref;
    dvec       vec;
    double     d0, inpr;
    double     lambda, rm, mass, invdt = 0;
    gmx_bool   bConverged_all, bConverged = FALSE;
    int        niter = 0, g, c, ii, j, m, max_iter = 100;
    double     a;
    dvec       f;          /* the pull force */
    dvec       tmp, tmp3;
    t_pull_group *pdyna, *pgrp0, *pgrp1;
    t_pull_coord *pcrd;

    snew(r_ij,   pull->ncoord);
    snew(dr_tot, pull->ncoord);

    snew(rnew, pull->ngroup);

    /* copy the current unconstrained positions for use in iterations. We
       iterate until rinew[i] and rjnew[j] obey the constraints. Then
       rinew - pull.x_unc[i] is the correction dr to group i */
    for (g = 0; g < pull->ngroup; g++)
    {
        copy_dvec(pull->group[g].xp, rnew[g]);
    }
    if (PULL_CYL(pull))
    {
        /* There is only one pull coordinate and reference group */
        copy_dvec(pull->dyna[0].xp, rnew[pull->coord[0].group[0]]);
    }

    /* Determine the constraint directions from the old positions */
    for (c = 0; c < pull->ncoord; c++)
    {
        get_pull_coord_dr(pull, c, pbc, t, r_ij[c]);
        /* Store the difference vector at time t for printing */
        copy_dvec(r_ij[c], pull->coord[c].dr);
        if (debug)
        {
            fprintf(debug, "Pull coord %d dr %f %f %f\n",
                    c, r_ij[c][XX], r_ij[c][YY], r_ij[c][ZZ]);
        }

        if (pull->eGeom == epullgDIR || pull->eGeom == epullgDIRPBC)
        {
            /* Select the component along vec */
            a = 0;
            for (m = 0; m < DIM; m++)
            {
                a += pull->coord[c].vec[m]*r_ij[c][m];
            }
            for (m = 0; m < DIM; m++)
            {
                r_ij[c][m] = a*pull->coord[c].vec[m];
            }
        }
    }

    bConverged_all = FALSE;
    while (!bConverged_all && niter < max_iter)
    {
        bConverged_all = TRUE;

        /* loop over all constraints */
        for (c = 0; c < pull->ncoord; c++)
        {
            dvec dr0, dr1;

            pcrd  = &pull->coord[c];
            pgrp0 = &pull->group[pcrd->group[0]];
            pgrp1 = &pull->group[pcrd->group[1]];

            /* Get the current difference vector */
            low_get_pull_coord_dr(pull, pcrd, pbc, t,
                                  rnew[pcrd->group[1]],
                                  rnew[pcrd->group[0]],
                                  -1, unc_ij);

            ref = pcrd->init + pcrd->rate*t;

            if (debug)
            {
                fprintf(debug, "Pull coord %d, iteration %d\n", c, niter);
            }

            rm = 1.0/(pgrp0->invtm + pgrp1->invtm);

            switch (pull->eGeom)
            {
                case epullgDIST:
                    if (ref <= 0)
                    {
                        gmx_fatal(FARGS, "The pull constraint reference distance for group %d is <= 0 (%f)", c, ref);
                    }

                    {
                        double q, c_a, c_b, c_c;

                        c_a = diprod(r_ij[c], r_ij[c]);
                        c_b = diprod(unc_ij, r_ij[c])*2;
                        c_c = diprod(unc_ij, unc_ij) - dsqr(ref);

                        if (c_b < 0)
                        {
                            q      = -0.5*(c_b - sqrt(c_b*c_b - 4*c_a*c_c));
                            lambda = -q/c_a;
                        }
                        else
                        {
                            q      = -0.5*(c_b + sqrt(c_b*c_b - 4*c_a*c_c));
                            lambda = -c_c/q;
                        }

                        if (debug)
                        {
                            fprintf(debug,
                                    "Pull ax^2+bx+c=0: a=%e b=%e c=%e lambda=%e\n",
                                    c_a, c_b, c_c, lambda);
                        }
                    }

                    /* The position corrections dr due to the constraints */
                    dsvmul(-lambda*rm*pgrp1->invtm, r_ij[c], dr1);
                    dsvmul( lambda*rm*pgrp0->invtm, r_ij[c], dr0);
                    dr_tot[c] += -lambda*dnorm(r_ij[c]);
                    break;
                case epullgDIR:
                case epullgDIRPBC:
                case epullgCYL:
                    /* A 1-dimensional constraint along a vector */
                    a = 0;
                    for (m = 0; m < DIM; m++)
                    {
                        vec[m] = pcrd->vec[m];
                        a     += unc_ij[m]*vec[m];
                    }
                    /* Select only the component along the vector */
                    dsvmul(a, vec, unc_ij);
                    lambda = a - ref;
                    if (debug)
                    {
                        fprintf(debug, "Pull inpr %e lambda: %e\n", a, lambda);
                    }

                    /* The position corrections dr due to the constraints */
                    dsvmul(-lambda*rm*pgrp1->invtm, vec, dr1);
                    dsvmul( lambda*rm*pgrp0->invtm, vec, dr0);
                    dr_tot[c] += -lambda;
                    break;
            }

            /* DEBUG */
            if (debug)
            {
                int g0, g1;

                g0 = pcrd->group[0];
                g1 = pcrd->group[1];
                low_get_pull_coord_dr(pull, pcrd, pbc, t, rnew[g1], rnew[g0], -1, tmp);
                low_get_pull_coord_dr(pull, pcrd, pbc, t, dr1, dr0, -1, tmp3);
                fprintf(debug,
                        "Pull cur %8.5f %8.5f %8.5f j:%8.5f %8.5f %8.5f d: %8.5f\n",
                        rnew[g0][0], rnew[g0][1], rnew[g0][2],
                        rnew[g1][0], rnew[g1][1], rnew[g1][2], dnorm(tmp));
                fprintf(debug,
                        "Pull ref %8s %8s %8s   %8s %8s %8s d: %8.5f\n",
                        "", "", "", "", "", "", ref);
                fprintf(debug,
                        "Pull cor %8.5f %8.5f %8.5f j:%8.5f %8.5f %8.5f d: %8.5f\n",
                        dr0[0], dr0[1], dr0[2],
                        dr1[0], dr1[1], dr1[2],
                        dnorm(tmp3));
            } /* END DEBUG */

            /* Update the COMs with dr */
            dvec_inc(rnew[pcrd->group[1]], dr1);
            dvec_inc(rnew[pcrd->group[0]], dr0);
        }

        /* Check if all constraints are fullfilled now */
        for (c = 0; c < pull->ncoord; c++)
        {
            pcrd = &pull->coord[c];

            low_get_pull_coord_dr(pull, pcrd, pbc, t,
                                  rnew[pcrd->group[1]],
                                  rnew[pcrd->group[0]],
                                  -1, unc_ij);

            switch (pull->eGeom)
            {
                case epullgDIST:
                    bConverged = fabs(dnorm(unc_ij) - ref) < pull->constr_tol;
                    break;
                case epullgDIR:
                case epullgDIRPBC:
                case epullgCYL:
                    for (m = 0; m < DIM; m++)
                    {
                        vec[m] = pcrd->vec[m];
                    }
                    inpr = diprod(unc_ij, vec);
                    dsvmul(inpr, vec, unc_ij);
                    bConverged =
                        fabs(diprod(unc_ij, vec) - ref) < pull->constr_tol;
                    break;
            }

            if (!bConverged)
            {
                if (debug)
                {
                    fprintf(debug, "NOT CONVERGED YET: Group %d:"
                            "d_ref = %f, current d = %f\n",
                            g, ref, dnorm(unc_ij));
                }

                bConverged_all = FALSE;
            }
        }

        niter++;
        /* if after all constraints are dealt with and bConverged is still TRUE
           we're finished, if not we do another iteration */
    }
    if (niter > max_iter)
    {
        gmx_fatal(FARGS, "Too many iterations for constraint run: %d", niter);
    }

    /* DONE ITERATING, NOW UPDATE COORDINATES AND CALC. CONSTRAINT FORCES */

    if (v)
    {
        invdt = 1/dt;
    }

    /* update atoms in the groups */
    for (g = 0; g < pull->ngroup; g++)
    {
        const t_pull_group *pgrp;
        dvec                dr;

        if (PULL_CYL(pull) && g == pull->coord[0].group[0])
        {
            pgrp = &pull->dyna[0];
        }
        else
        {
            pgrp = &pull->group[g];
        }

        /* get the final constraint displacement dr for group g */
        dvec_sub(rnew[g], pgrp->xp, dr);
        /* select components of dr */
        for (m = 0; m < DIM; m++)
        {
            dr[m] *= pull->dim[m];
        }

        /* update the atom positions */
        copy_dvec(dr, tmp);
        for (j = 0; j < pgrp->nat_loc; j++)
        {
            ii = pgrp->ind_loc[j];
            if (pgrp->weight_loc)
            {
                dsvmul(pgrp->wscale*pgrp->weight_loc[j], dr, tmp);
            }
            for (m = 0; m < DIM; m++)
            {
                x[ii][m] += tmp[m];
            }
            if (v)
            {
                for (m = 0; m < DIM; m++)
                {
                    v[ii][m] += invdt*tmp[m];
                }
            }
        }
    }

    /* calculate the constraint forces, used for output and virial only */
    for (c = 0; c < pull->ncoord; c++)
    {
        pcrd         = &pull->coord[c];
        pcrd->f_scal = dr_tot[c]/((pull->group[pcrd->group[0]].invtm + pull->group[pcrd->group[1]].invtm)*dt*dt);

        if (vir && bMaster)
        {
            double f_invr;

            /* Add the pull contribution to the virial */
            f_invr = pcrd->f_scal/dnorm(r_ij[c]);

            for (j = 0; j < DIM; j++)
            {
                for (m = 0; m < DIM; m++)
                {
                    vir[j][m] -= 0.5*f_invr*r_ij[c][j]*r_ij[c][m];
                }
            }
        }
    }

    /* finished! I hope. Give back some memory */
    sfree(r_ij);
    sfree(dr_tot);
    sfree(rnew);
}
Exemplo n.º 10
0
/* Pulling with a harmonic umbrella potential or constant force */
static void do_pull_pot(int ePull,
                        t_pull *pull, t_pbc *pbc, double t, real lambda,
                        real *V, tensor vir, real *dVdl)
{
    int       g,j,m;
    dvec      dev;
    double    ndr,invdr;
    real      k,dkdl;
    t_pullgrp *pgrp;
    
    /* loop over the groups that are being pulled */
    *V    = 0;
    *dVdl = 0;
    for(g=1; g<1+pull->ngrp; g++)
    {
        pgrp = &pull->grp[g];
        get_pullgrp_distance(pull,pbc,g,t,pgrp->dr,dev);
        
        k    = (1.0 - lambda)*pgrp->k + lambda*pgrp->kB;
        dkdl = pgrp->kB - pgrp->k;
        
        switch (pull->eGeom)
        {
        case epullgDIST:
            ndr   = dnorm(pgrp->dr);
            invdr = 1/ndr;
            if (ePull == epullUMBRELLA)
            {
                pgrp->f_scal  =       -k*dev[0];
                *V           += 0.5*   k*dsqr(dev[0]);
                *dVdl        += 0.5*dkdl*dsqr(dev[0]);
            }
            else
            {
                pgrp->f_scal  =   -k;
                *V           +=    k*ndr;
                *dVdl        += dkdl*ndr;
            }
            for(m=0; m<DIM; m++)
            {
                pgrp->f[m]    = pgrp->f_scal*pgrp->dr[m]*invdr;
            }
            break;
        case epullgDIR:
        case epullgDIRPBC:
        case epullgCYL:
            if (ePull == epullUMBRELLA)
            {
                pgrp->f_scal  =       -k*dev[0];
                *V           += 0.5*   k*dsqr(dev[0]);
                *dVdl        += 0.5*dkdl*dsqr(dev[0]);
            }
            else
            {
                ndr = 0;
                for(m=0; m<DIM; m++)
                {
                    ndr += pgrp->vec[m]*pgrp->dr[m];
                }
                pgrp->f_scal  =   -k;
                *V           +=    k*ndr;
                *dVdl        += dkdl*ndr;
            }
            for(m=0; m<DIM; m++)
            {
                pgrp->f[m]    = pgrp->f_scal*pgrp->vec[m];
            }
            break;
        case epullgPOS:
            for(m=0; m<DIM; m++)
            {
                if (ePull == epullUMBRELLA)
                {
                    pgrp->f[m]  =       -k*dev[m];
                    *V         += 0.5*   k*dsqr(dev[m]);
                    *dVdl      += 0.5*dkdl*dsqr(dev[m]);
                }
                else
                {
                    pgrp->f[m]  =   -k*pull->dim[m];
                    *V         +=    k*pgrp->dr[m]*pull->dim[m];
                    *dVdl      += dkdl*pgrp->dr[m]*pull->dim[m];
                }
            }
            break;
        }
        
        if (vir)
        {
            /* Add the pull contribution to the virial */
            for(j=0; j<DIM; j++)
            {
                for(m=0;m<DIM;m++)
                {
                    vir[j][m] -= 0.5*pgrp->f[j]*pgrp->dr[m];
                }
            }
        }
    }
}
Exemplo n.º 11
0
/* Apply constraint using SHAKE */
static void do_constraint(t_pull *pull, t_mdatoms *md, t_pbc *pbc,
                          rvec *x, rvec *v,
                          gmx_bool bMaster, tensor vir,
                          double dt, double t) 
{

    dvec *r_ij;  /* x[i] com of i in prev. step. Obeys constr. -> r_ij[i] */
    dvec unc_ij; /* xp[i] com of i this step, before constr.   -> unc_ij  */

    dvec *rinew;           /* current 'new' position of group i */
    dvec *rjnew;           /* current 'new' position of group j */
    dvec  ref,vec;
    double d0,inpr;
    double lambda, rm, mass, invdt=0;
    gmx_bool bConverged_all,bConverged=FALSE;
    int niter=0,g,ii,j,m,max_iter=100;
    double q,a,b,c;  /* for solving the quadratic equation, 
                        see Num. Recipes in C ed 2 p. 184 */
    dvec *dr;        /* correction for group i */
    dvec ref_dr;     /* correction for group j */
    dvec f;          /* the pull force */
    dvec tmp,tmp3;
    t_pullgrp *pdyna,*pgrp,*pref;
    
    snew(r_ij,pull->ngrp+1);
    if (PULL_CYL(pull))
    {
        snew(rjnew,pull->ngrp+1);
    }
    else
    {
        snew(rjnew,1);
    }
    snew(dr,pull->ngrp+1);
    snew(rinew,pull->ngrp+1);
    
    /* copy the current unconstrained positions for use in iterations. We 
       iterate until rinew[i] and rjnew[j] obey the constraints. Then
       rinew - pull.x_unc[i] is the correction dr to group i */
    for(g=1; g<1+pull->ngrp; g++)
    {
        copy_dvec(pull->grp[g].xp,rinew[g]);
    }
    if (PULL_CYL(pull))
    {
        for(g=1; g<1+pull->ngrp; g++)
        {
            copy_dvec(pull->dyna[g].xp,rjnew[g]);
        }
    }
    else
    {
        copy_dvec(pull->grp[0].xp,rjnew[0]);
    }
    
    /* Determine the constraint directions from the old positions */
    for(g=1; g<1+pull->ngrp; g++)
    {
        get_pullgrp_dr(pull,pbc,g,t,r_ij[g]);
        /* Store the difference vector at time t for printing */
        copy_dvec(r_ij[g],pull->grp[g].dr);
        if (debug)
        {
            fprintf(debug,"Pull group %d dr %f %f %f\n",
                    g,r_ij[g][XX],r_ij[g][YY],r_ij[g][ZZ]);
        }
        
        if (pull->eGeom == epullgDIR || pull->eGeom == epullgDIRPBC)
        {
            /* Select the component along vec */
            a = 0;
            for(m=0; m<DIM; m++)
            {
                a += pull->grp[g].vec[m]*r_ij[g][m];
            }
            for(m=0; m<DIM; m++)
            {
                r_ij[g][m] = a*pull->grp[g].vec[m];
            }
        }
    }
    
    bConverged_all = FALSE;
    while (!bConverged_all && niter < max_iter)
    {
        bConverged_all = TRUE;

        /* loop over all constraints */
        for(g=1; g<1+pull->ngrp; g++)
        {
            pgrp = &pull->grp[g];
            if (PULL_CYL(pull))
                pref = &pull->dyna[g];
            else
                pref = &pull->grp[0];

            /* Get the current difference vector */
            get_pullgrps_dr(pull,pbc,g,t,rinew[g],rjnew[PULL_CYL(pull) ? g : 0],
                            -1,unc_ij);

            if (pull->eGeom == epullgPOS)
            {
                for(m=0; m<DIM; m++)
                {
                    ref[m] = pgrp->init[m] + pgrp->rate*t*pgrp->vec[m];
                }
            }
            else
            {
                ref[0] = pgrp->init[0] + pgrp->rate*t;
                /* Keep the compiler happy */
                ref[1] = 0;
                ref[2] = 0;
            }
            
            if (debug)
            {
                fprintf(debug,"Pull group %d, iteration %d\n",g,niter);
            }
            
            rm = 1.0/(pull->grp[g].invtm + pref->invtm);
            
            switch (pull->eGeom)
            {
            case epullgDIST:
                if (ref[0] <= 0)
                {
                    gmx_fatal(FARGS,"The pull constraint reference distance for group %d is <= 0 (%f)",g,ref[0]);
                }
                
                a = diprod(r_ij[g],r_ij[g]); 
                b = diprod(unc_ij,r_ij[g])*2;
                c = diprod(unc_ij,unc_ij) - dsqr(ref[0]);
                
                if (b < 0)
                {
                    q = -0.5*(b - sqrt(b*b - 4*a*c));
                    lambda = -q/a;
                }
                else
                {
                    q = -0.5*(b + sqrt(b*b - 4*a*c));
                    lambda = -c/q;
                }
                
                if (debug)
                {
                    fprintf(debug,
                            "Pull ax^2+bx+c=0: a=%e b=%e c=%e lambda=%e\n",
                            a,b,c,lambda);
                }
                
                /* The position corrections dr due to the constraints */
                dsvmul(-lambda*rm*pgrp->invtm, r_ij[g],  dr[g]);
                dsvmul( lambda*rm*pref->invtm, r_ij[g], ref_dr);
                break;
            case epullgDIR:
            case epullgDIRPBC:
            case epullgCYL:
                /* A 1-dimensional constraint along a vector */
                a = 0;
                for(m=0; m<DIM; m++)
                {
                    vec[m] = pgrp->vec[m];
                    a += unc_ij[m]*vec[m];
                }
                /* Select only the component along the vector */
                dsvmul(a,vec,unc_ij);
                lambda = a - ref[0];
                if (debug)
                {
                    fprintf(debug,"Pull inpr %e lambda: %e\n",a,lambda);
                }
                
                /* The position corrections dr due to the constraints */
                dsvmul(-lambda*rm*pull->grp[g].invtm, vec, dr[g]);
                dsvmul( lambda*rm*       pref->invtm, vec,ref_dr);
                break;
            case epullgPOS:
                for(m=0; m<DIM; m++)
                {
                    if (pull->dim[m])
                    {
                        lambda = r_ij[g][m] - ref[m];
                        /* The position corrections dr due to the constraints */
                        dr[g][m]  = -lambda*rm*pull->grp[g].invtm;
                        ref_dr[m] =  lambda*rm*pref->invtm;
                    }
                    else
                    {
                        dr[g][m]  = 0;
                        ref_dr[m] = 0;
                    }
                }
                break;
            }
            
            /* DEBUG */
            if (debug)
            {
                j = (PULL_CYL(pull) ? g : 0);
                get_pullgrps_dr(pull,pbc,g,t,rinew[g],rjnew[j],-1,tmp);
                get_pullgrps_dr(pull,pbc,g,t,dr[g]   ,ref_dr  ,-1,tmp3);
                fprintf(debug,
                        "Pull cur %8.5f %8.5f %8.5f j:%8.5f %8.5f %8.5f d: %8.5f\n",
                        rinew[g][0],rinew[g][1],rinew[g][2], 
                        rjnew[j][0],rjnew[j][1],rjnew[j][2], dnorm(tmp));
                if (pull->eGeom == epullgPOS)
                {
                    fprintf(debug,
                            "Pull ref %8.5f %8.5f %8.5f\n",
                            pgrp->vec[0],pgrp->vec[1],pgrp->vec[2]);
                }
                else
                {
                    fprintf(debug,
                            "Pull ref %8s %8s %8s   %8s %8s %8s d: %8.5f %8.5f %8.5f\n",
                            "","","","","","",ref[0],ref[1],ref[2]);
                }
                fprintf(debug,
                        "Pull cor %8.5f %8.5f %8.5f j:%8.5f %8.5f %8.5f d: %8.5f\n",
                        dr[g][0],dr[g][1],dr[g][2],
                        ref_dr[0],ref_dr[1],ref_dr[2],
                        dnorm(tmp3));
                fprintf(debug,
                        "Pull cor %10.7f %10.7f %10.7f\n",
                        dr[g][0],dr[g][1],dr[g][2]);
            } /* END DEBUG */
            
            /* Update the COMs with dr */
            dvec_inc(rinew[g],                     dr[g]);
            dvec_inc(rjnew[PULL_CYL(pull) ? g : 0],ref_dr);
        }
        
        /* Check if all constraints are fullfilled now */
        for(g=1; g<1+pull->ngrp; g++)
        {
            pgrp = &pull->grp[g];
            
            get_pullgrps_dr(pull,pbc,g,t,rinew[g],rjnew[PULL_CYL(pull) ? g : 0],
                            -1,unc_ij);
            
            switch (pull->eGeom)
            {
            case epullgDIST:
                bConverged = fabs(dnorm(unc_ij) - ref[0]) < pull->constr_tol;
                break;
            case epullgDIR:
            case epullgDIRPBC:
            case epullgCYL:
                for(m=0; m<DIM; m++)
                {
                    vec[m] = pgrp->vec[m];
                }
                inpr = diprod(unc_ij,vec);
                dsvmul(inpr,vec,unc_ij);
                bConverged =
                    fabs(diprod(unc_ij,vec) - ref[0]) < pull->constr_tol;
                break;
            case epullgPOS:
                bConverged = TRUE;
                for(m=0; m<DIM; m++)
                {
                    if (pull->dim[m] && 
                        fabs(unc_ij[m] - ref[m]) >= pull->constr_tol)
                    {
                        bConverged = FALSE;
                    }
                }
                break;
            }
            
            if (!bConverged)
            {
                if (debug)
                {
                    fprintf(debug,"NOT CONVERGED YET: Group %d:"
                            "d_ref = %f %f %f, current d = %f\n",
                            g,ref[0],ref[1],ref[2],dnorm(unc_ij));
                }

                bConverged_all = FALSE;
            }
        }
        
        niter++;
        /* if after all constraints are dealt with and bConverged is still TRUE
           we're finished, if not we do another iteration */
    }
    if (niter > max_iter)
    {
        gmx_fatal(FARGS,"Too many iterations for constraint run: %d",niter);
    }
    
    /* DONE ITERATING, NOW UPDATE COORDINATES AND CALC. CONSTRAINT FORCES */
    
    if (v)
    {
        invdt = 1/dt;
    }
    
    /* update the normal groups */
    for(g=1; g<1+pull->ngrp; g++)
    {
        pgrp = &pull->grp[g];
        /* get the final dr and constraint force for group i */
        dvec_sub(rinew[g],pgrp->xp,dr[g]);
        /* select components of dr */
        for(m=0; m<DIM; m++)
        {
            dr[g][m] *= pull->dim[m];
        }
        dsvmul(1.0/(pgrp->invtm*dt*dt),dr[g],f);
        dvec_inc(pgrp->f,f);
        switch (pull->eGeom)
        {
        case epullgDIST:
            for(m=0; m<DIM; m++)
            {
                pgrp->f_scal += r_ij[g][m]*f[m]/dnorm(r_ij[g]);
            }
            break;
        case epullgDIR:
        case epullgDIRPBC:
        case epullgCYL:
            for(m=0; m<DIM; m++)
            {
                pgrp->f_scal += pgrp->vec[m]*f[m];
            }
            break;
        case epullgPOS:
            break;
        }
        
        if (vir && bMaster) {
            /* Add the pull contribution to the virial */
            for(j=0; j<DIM; j++)
            {
                for(m=0; m<DIM; m++)
                {
                    vir[j][m] -= 0.5*f[j]*r_ij[g][m];
                }
            }
        }
        
        /* update the atom positions */
        copy_dvec(dr[g],tmp);
        for(j=0;j<pgrp->nat_loc;j++)
        {
            ii = pgrp->ind_loc[j];
            if (pgrp->weight_loc)
            {
                dsvmul(pgrp->wscale*pgrp->weight_loc[j],dr[g],tmp); 
            }
            for(m=0; m<DIM; m++)
            {
                x[ii][m] += tmp[m];
            }
            if (v)
            {
                for(m=0; m<DIM; m++)
                {
                    v[ii][m] += invdt*tmp[m];
                }
            }
        }
    }
    
    /* update the reference groups */
    if (PULL_CYL(pull))
    {
        /* update the dynamic reference groups */
        for(g=1; g<1+pull->ngrp; g++)
        {
            pdyna = &pull->dyna[g];
            dvec_sub(rjnew[g],pdyna->xp,ref_dr);
            /* select components of ref_dr */
            for(m=0; m<DIM; m++)
            {
                ref_dr[m] *= pull->dim[m];
            }
            
            for(j=0;j<pdyna->nat_loc;j++)
            {
                /* reset the atoms with dr, weighted by w_i */
                dsvmul(pdyna->wscale*pdyna->weight_loc[j],ref_dr,tmp); 
                ii = pdyna->ind_loc[j];
                for(m=0; m<DIM; m++)
                {
                    x[ii][m] += tmp[m];
                }
                if (v)
                {
                    for(m=0; m<DIM; m++)
                    {
                        v[ii][m] += invdt*tmp[m];
                    }
                }
            }
        }
    }
    else
    {
        pgrp = &pull->grp[0];
        /* update the reference group */
        dvec_sub(rjnew[0],pgrp->xp, ref_dr); 
        /* select components of ref_dr */
        for(m=0;m<DIM;m++)
        {
            ref_dr[m] *= pull->dim[m];
        }
        
        copy_dvec(ref_dr,tmp);
        for(j=0; j<pgrp->nat_loc;j++)
        {
            ii = pgrp->ind_loc[j];
            if (pgrp->weight_loc)
            {
                dsvmul(pgrp->wscale*pgrp->weight_loc[j],ref_dr,tmp); 
            }
            for(m=0; m<DIM; m++)
            {
                x[ii][m] += tmp[m];
            }
            if (v)
            {
                for(m=0; m<DIM; m++)
                {
                    v[ii][m] += invdt*tmp[m];
                }
            }
        }
    }
    
    /* finished! I hope. Give back some memory */
    sfree(r_ij);
    sfree(rinew);
    sfree(rjnew);
    sfree(dr);
}
Exemplo n.º 12
0
static void make_cyl_refgrps(t_commrec *cr, struct pull_t *pull, t_mdatoms *md,
                             t_pbc *pbc, double t, rvec *x)
{
    /* The size and stride per coord for the reduction buffer */
    const int     stride = 9;
    int           c, i, ii, m, start, end;
    rvec          g_x, dx, dir;
    double        inv_cyl_r2;
    pull_comm_t  *comm;
    gmx_ga2la_t   ga2la = NULL;

    comm = &pull->comm;

    if (comm->dbuf_cyl == NULL)
    {
        snew(comm->dbuf_cyl, pull->ncoord*stride);
    }

    if (cr && DOMAINDECOMP(cr))
    {
        ga2la = cr->dd->ga2la;
    }

    start = 0;
    end   = md->homenr;

    inv_cyl_r2 = 1/dsqr(pull->params.cylinder_r);

    /* loop over all groups to make a reference group for each*/
    for (c = 0; c < pull->ncoord; c++)
    {
        pull_coord_work_t *pcrd;
        double             sum_a, wmass, wwmass;
        dvec               radf_fac0, radf_fac1;

        pcrd   = &pull->coord[c];

        sum_a  = 0;
        wmass  = 0;
        wwmass = 0;
        clear_dvec(radf_fac0);
        clear_dvec(radf_fac1);

        if (pcrd->params.eGeom == epullgCYL)
        {
            pull_group_work_t *pref, *pgrp, *pdyna;

            /* pref will be the same group for all pull coordinates */
            pref  = &pull->group[pcrd->params.group[0]];
            pgrp  = &pull->group[pcrd->params.group[1]];
            pdyna = &pull->dyna[c];
            copy_rvec(pcrd->vec, dir);
            pdyna->nat_loc = 0;

            /* We calculate distances with respect to the reference location
             * of this cylinder group (g_x), which we already have now since
             * we reduced the other group COM over the ranks. This resolves
             * any PBC issues and we don't need to use a PBC-atom here.
             */
            if (pcrd->params.rate != 0)
            {
                /* With rate=0, value_ref is set initially */
                pcrd->value_ref = pcrd->params.init + pcrd->params.rate*t;
            }
            for (m = 0; m < DIM; m++)
            {
                g_x[m] = pgrp->x[m] - pcrd->vec[m]*pcrd->value_ref;
            }

            /* loop over all atoms in the main ref group */
            for (i = 0; i < pref->params.nat; i++)
            {
                ii = pref->params.ind[i];
                if (ga2la)
                {
                    if (!ga2la_get_home(ga2la, pref->params.ind[i], &ii))
                    {
                        ii = -1;
                    }
                }
                if (ii >= start && ii < end)
                {
                    double dr2, dr2_rel, inp;
                    dvec   dr;

                    pbc_dx_aiuc(pbc, x[ii], g_x, dx);
                    inp = iprod(dir, dx);
                    dr2 = 0;
                    for (m = 0; m < DIM; m++)
                    {
                        /* Determine the radial components */
                        dr[m] = dx[m] - inp*dir[m];
                        dr2  += dr[m]*dr[m];
                    }
                    dr2_rel = dr2*inv_cyl_r2;

                    if (dr2_rel < 1)
                    {
                        double mass, weight, dweight_r;
                        dvec   mdw;

                        /* add to index, to sum of COM, to weight array */
                        if (pdyna->nat_loc >= pdyna->nalloc_loc)
                        {
                            pdyna->nalloc_loc = over_alloc_large(pdyna->nat_loc+1);
                            srenew(pdyna->ind_loc,    pdyna->nalloc_loc);
                            srenew(pdyna->weight_loc, pdyna->nalloc_loc);
                            srenew(pdyna->mdw,        pdyna->nalloc_loc);
                            srenew(pdyna->dv,         pdyna->nalloc_loc);
                        }
                        pdyna->ind_loc[pdyna->nat_loc] = ii;

                        mass      = md->massT[ii];
                        /* The radial weight function is 1-2x^2+x^4,
                         * where x=r/cylinder_r. Since this function depends
                         * on the radial component, we also get radial forces
                         * on both groups.
                         */
                        weight    = 1 + (-2 + dr2_rel)*dr2_rel;
                        dweight_r = (-4 + 4*dr2_rel)*inv_cyl_r2;
                        pdyna->weight_loc[pdyna->nat_loc] = weight;
                        sum_a    += mass*weight*inp;
                        wmass    += mass*weight;
                        wwmass   += mass*weight*weight;
                        dsvmul(mass*dweight_r, dr, mdw);
                        copy_dvec(mdw, pdyna->mdw[pdyna->nat_loc]);
                        /* Currently we only have the axial component of the
                         * distance (inp) up to an unkown offset. We add this
                         * offset after the reduction needs to determine the
                         * COM of the cylinder group.
                         */
                        pdyna->dv[pdyna->nat_loc] = inp;
                        for (m = 0; m < DIM; m++)
                        {
                            radf_fac0[m] += mdw[m];
                            radf_fac1[m] += mdw[m]*inp;
                        }
                        pdyna->nat_loc++;
                    }
                }
            }
        }
        comm->dbuf_cyl[c*stride+0] = wmass;
        comm->dbuf_cyl[c*stride+1] = wwmass;
        comm->dbuf_cyl[c*stride+2] = sum_a;
        comm->dbuf_cyl[c*stride+3] = radf_fac0[XX];
        comm->dbuf_cyl[c*stride+4] = radf_fac0[YY];
        comm->dbuf_cyl[c*stride+5] = radf_fac0[ZZ];
        comm->dbuf_cyl[c*stride+6] = radf_fac1[XX];
        comm->dbuf_cyl[c*stride+7] = radf_fac1[YY];
        comm->dbuf_cyl[c*stride+8] = radf_fac1[ZZ];
    }

    if (cr != NULL && PAR(cr))
    {
        /* Sum the contributions over the ranks */
        pull_reduce_double(cr, comm, pull->ncoord*stride, comm->dbuf_cyl);
    }

    for (c = 0; c < pull->ncoord; c++)
    {
        pull_coord_work_t *pcrd;

        pcrd  = &pull->coord[c];

        if (pcrd->params.eGeom == epullgCYL)
        {
            pull_group_work_t *pdyna, *pgrp;
            double             wmass, wwmass, dist;

            pdyna = &pull->dyna[c];
            pgrp  = &pull->group[pcrd->params.group[1]];

            wmass          = comm->dbuf_cyl[c*stride+0];
            wwmass         = comm->dbuf_cyl[c*stride+1];
            pdyna->mwscale = 1.0/wmass;
            /* Cylinder pulling can't be used with constraints, but we set
             * wscale and invtm anyhow, in case someone would like to use them.
             */
            pdyna->wscale  = wmass/wwmass;
            pdyna->invtm   = wwmass/(wmass*wmass);

            /* We store the deviation of the COM from the reference location
             * used above, since we need it when we apply the radial forces
             * to the atoms in the cylinder group.
             */
            pcrd->cyl_dev  = 0;
            for (m = 0; m < DIM; m++)
            {
                g_x[m]         = pgrp->x[m] - pcrd->vec[m]*pcrd->value_ref;
                dist           = -pcrd->vec[m]*comm->dbuf_cyl[c*stride+2]*pdyna->mwscale;
                pdyna->x[m]    = g_x[m] - dist;
                pcrd->cyl_dev += dist;
            }
            /* Now we know the exact COM of the cylinder reference group,
             * we can determine the radial force factor (ffrad) that when
             * multiplied with the axial pull force will give the radial
             * force on the pulled (non-cylinder) group.
             */
            for (m = 0; m < DIM; m++)
            {
                pcrd->ffrad[m] = (comm->dbuf_cyl[c*stride+6+m] +
                                  comm->dbuf_cyl[c*stride+3+m]*pcrd->cyl_dev)/wmass;
            }

            if (debug)
            {
                fprintf(debug, "Pull cylinder group %d:%8.3f%8.3f%8.3f m:%8.3f\n",
                        c, pdyna->x[0], pdyna->x[1],
                        pdyna->x[2], 1.0/pdyna->invtm);
                fprintf(debug, "ffrad %8.3f %8.3f %8.3f\n",
                        pcrd->ffrad[XX], pcrd->ffrad[YY], pcrd->ffrad[ZZ]);
            }
        }
    }
}
Exemplo n.º 13
0
 /** 
  * Calculate approximate squared (flat projected) distance between this point
  * and another
  * 
  * @param tp Point to calculate distance to
  * 
  * @return Approximate squared distance
  */
 gcc_pure
 unsigned approx_sq_dist(const TracePoint& tp) const {
   return dsqr(get_flatLocation().Longitude-tp.get_flatLocation().Longitude)+
     dsqr(get_flatLocation().Latitude-tp.get_flatLocation().Latitude);
 }