예제 #1
0
파일: ljcos2.hpp 프로젝트: arnolda/espresso
/** Calculate lj-cos2 force between particle p1 and p2 */
inline void add_ljcos2_pair_force(const Particle * const p1, const Particle * const p2, IA_parameters *ia_params,
                                  double d[3], double dist, double force[3])
{
    int j;
    double r_off, frac2, frac6, fac=0.0;
    if(CUTOFF_CHECK(dist < ia_params->LJCOS2_cut+ia_params->LJCOS2_offset)) {
        r_off = dist - ia_params->LJCOS2_offset;
        /* normal case: resulting force/energy smaller than capping. */
        if(r_off > ia_params->LJCOS2_capradius) {
            if(r_off < ia_params->LJCOS2_rchange) {
                frac2 = SQR(ia_params->LJCOS2_sig/r_off);
                frac6 = frac2*frac2*frac2;
                fac   = 48.0 * ia_params->LJCOS2_eps * frac6*(frac6 - 0.5) / (r_off*dist);
            }
            else if (r_off< ia_params->LJCOS2_rchange + ia_params->LJCOS2_w) {
                fac   = -ia_params->LJCOS2_eps*M_PI/2/ia_params->LJCOS2_w/dist * sin(M_PI*(r_off-ia_params->LJCOS2_rchange)/ia_params->LJCOS2_w);
            }

            for(j=0; j<3; j++)
                force[j] += fac * d[j];

#ifdef LJ_WARN_WHEN_CLOSE
            if(fac*dist > 1000) fprintf(stderr,"%d: LJ-Warning: Pair (%d-%d) force=%f dist=%f\n",
                                            this_node,p1->p.identity,p2->p.identity,fac*dist,dist);
#endif
        }
        /* capped part of lj-cos2 potential. */
        else if(dist > 0.0) {
            frac2 = SQR(ia_params->LJCOS2_sig/ia_params->LJCOS2_capradius);
            frac6 = frac2*frac2*frac2;
            fac   = 48.0 * ia_params->LJCOS2_eps * frac6*(frac6 - 0.5) / (ia_params->LJCOS2_capradius * dist);
            for(j=0; j<3; j++)
                /* vector d is rescaled to length LJCOS2_capradius */
                force[j] += fac * d[j];
        }
        /* this should not happen! */
        else {
            LJ_TRACE(fprintf(stderr, "%d: Lennard-Jones warning: Particles id1=%d id2=%d exactly on top of each other\n",this_node,p1->p.identity,p2->p.identity));

            frac2 = SQR(ia_params->LJCOS2_sig/ia_params->LJCOS2_capradius);
            frac6 = frac2*frac2*frac2;
            fac   = 48.0 * ia_params->LJCOS2_eps * frac6*(frac6 - 0.5) / ia_params->LJCOS2_capradius;

            force[0] += fac * ia_params->LJCOS2_capradius;
        }

        ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: LJ   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,dist,fac));
        ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: LJ   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,dist,fac));

        LJ_TRACE(fprintf(stderr,"%d: LJ: Pair (%d-%d) dist=%.3f: force+-: (%.3e,%.3e,%.3e)\n",
                         this_node,p1->p.identity,p2->p.identity,dist,fac*d[0],fac*d[1],fac*d[2]));
    }
예제 #2
0
inline void add_ljcos_pair_force(const Particle * const p1, const Particle * const p2, IA_parameters *ia_params,
				   double d[3], double dist, double force[3])
{
  int j;
  double r_off, frac2, frac6, fac=0.0;

  if(CUTOFF_CHECK(dist < ia_params->LJCOS_cut+ia_params->LJCOS_offset)) {
    r_off = dist - ia_params->LJCOS_offset;
    /* cos part of ljcos potential. */
    if(dist > ia_params->LJCOS_rmin+ia_params->LJCOS_offset) {
      fac   = (r_off/dist) * ia_params->LJCOS_alfa * ia_params->LJCOS_eps * (sin(ia_params->LJCOS_alfa * SQR(r_off) + ia_params->LJCOS_beta));
      for(j=0;j<3;j++)
	force[j] += fac * d[j];
    }
    /* lennard-jones part of the potential. */
    else if(dist > 0) {
      frac2 = SQR(ia_params->LJCOS_sig/r_off);
      frac6 = frac2*frac2*frac2;
      fac   = 48.0 * ia_params->LJCOS_eps * frac6*(frac6 - 0.5) / (r_off * dist);

      for(j=0;j<3;j++)
	force[j] += fac * d[j];

#ifdef LJ_WARN_WHEN_CLOSE
      if(fac*dist > 1000) fprintf(stderr,"%d: LJCOS-Warning: Pair (%d-%d) force=%f dist=%f\n",
				  this_node,p1->p.identity,p2->p.identity,fac*dist,dist);
#endif
    }
    /* this should not happen! */
    else {
      LJ_TRACE(fprintf(stderr, "%d: Lennard-Jones warning: Particles id1=%d id2=%d exactly on top of each other\n",this_node,p1->p.identity,p2->p.identity));

      frac2 = SQR(ia_params->LJ_sig/ia_params->LJ_capradius);
      frac6 = frac2*frac2*frac2;
      fac   = 48.0 * ia_params->LJ_eps * frac6*(frac6 - 0.5) / ia_params->LJ_capradius;

      force[0] += fac * ia_params->LJ_capradius;
    }

    ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: LJ   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,dist,fac));
    ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: LJ   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,dist,fac));

    LJ_TRACE(fprintf(stderr,"%d: LJ: Pair (%d-%d) dist=%.3f: force+-: (%.3e,%.3e,%.3e)\n",
		     this_node,p1->p.identity,p2->p.identity,dist,fac*d[0],fac*d[1],fac*d[2]));
  }
예제 #3
0
/** Calculate lennard Jones force between particle p1 and p2 */
inline void add_ljgen_pair_force(Particle *p1, Particle *p2, IA_parameters *ia_params,
				   double d[3], double dist, double force[3])
{
  if (CUTOFF_CHECK(dist < ia_params->LJGEN_cut+ia_params->LJGEN_offset)) {
    int j;
    double r_off, frac, fac=0.0;
    r_off = dist - ia_params->LJGEN_offset;
#ifdef LJGEN_SOFTCORE
    r_off *= r_off;
    r_off += pow(ia_params->LJGEN_sig,2) * (1.0-ia_params->LJGEN_lambda)
             * ia_params->LJGEN_softrad;
    /* Taking a square root is not optimal, but we can't prevent the user from
       using an odd m, n coefficient. */
    r_off  = sqrt(r_off);
#endif
    /* normal case: resulting force/energy smaller than capping. */
    if(r_off > ia_params->LJGEN_capradius) {
      frac = ia_params->LJGEN_sig/r_off;
      fac   = ia_params->LJGEN_eps 
#ifdef LJGEN_SOFTCORE
        * ia_params->LJGEN_lambda
#endif
	      * (ia_params->LJGEN_b1 * ia_params->LJGEN_a1 * pow(frac, ia_params->LJGEN_a1) 
	   - ia_params->LJGEN_b2 * ia_params->LJGEN_a2 * pow(frac, ia_params->LJGEN_a2))
	/ (r_off * dist);
      for(j=0;j<3;j++)
	force[j] += fac * d[j];
      
#ifdef LJ_WARN_WHEN_CLOSE
      if(fac*dist > 1000) fprintf(stderr,"%d: LJ-Gen-Warning: Pair (%d-%d) force=%f dist=%f\n",
				  this_node,p1->p.identity,p2->p.identity,fac*dist,dist);
#endif
    }
    /* capped part of lj potential. */
    else if(dist > 0.0) {
      frac = ia_params->LJGEN_sig/ia_params->LJGEN_capradius;
      fac   = ia_params->LJGEN_eps 
	* (ia_params->LJGEN_b1 * ia_params->LJGEN_a1 * pow(frac, ia_params->LJGEN_a1) 
	   - ia_params->LJGEN_b2 * ia_params->LJGEN_a2 * pow(frac, ia_params->LJGEN_a2))
	/ (ia_params->LJGEN_capradius * dist);
      for(j=0;j<3;j++)
	/* vector d is rescaled to length LJGEN_capradius */
	force[j] += fac * d[j];
    }
    /* this should not happen! */
    else {
      LJ_TRACE(fprintf(stderr, "%d: Lennard-Jones-Generic warning: Particles id1=%d id2=%d exactly on top of each other\n",this_node,p1->p.identity,p2->p.identity));
      
      frac = ia_params->LJGEN_sig/ia_params->LJGEN_capradius;
      fac   = ia_params->LJGEN_eps 
#ifdef LJGEN_SOFTCORE
        * ia_params->LJGEN_lambda
#endif
        * (ia_params->LJGEN_b1 * ia_params->LJGEN_a1 * pow(frac, ia_params->LJGEN_a1) 
	   - ia_params->LJGEN_b2 * ia_params->LJGEN_a2 * pow(frac, ia_params->LJGEN_a2))
	/ ia_params->LJGEN_capradius;
      
      force[0] += fac * ia_params->LJGEN_capradius;
    }
    
    ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: LJGEN   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,dist,fac));
    ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: LJGEN   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,dist,fac));
    
    LJ_TRACE(fprintf(stderr,"%d: LJGEN: Pair (%d-%d) dist=%.3f: force+-: (%.3e,%.3e,%.3e)\n",
		     this_node,p1->p.identity,p2->p.identity,dist,fac*d[0],fac*d[1],fac*d[2]));
  }
예제 #4
0
/** Calculate lj-angle force between particle p1 and p2
    Involves 6 particles total */
inline void add_ljangle_force(Particle *p1, Particle *p2, IA_parameters *ia_params,
                              double d[3], double dist)
{
    if(!CUTOFF_CHECK(dist < ia_params->LJANGLE_cut))
        return;
    int j;
    double frac2=0.0, frac10=0.0, rad=0.0, radprime=0.0;
    double r31[3], r41[3], r52[3], r62[3], rij[3], rik[3], rkn[3];
    double l_rij, l_rik, l_rkn, l_rij2, l_rik2, l_rkn2;
    double cos_jik, cos_ikn;
    double angular_jik, angular_ikn, angular_jik_prime, angular_ikn_prime;
    /* Recreate angular dependence of potential by including 6 particles instead of 2. */
    Particle *p3=NULL, *p4=NULL, *p5=NULL, *p6=NULL;
    int part1p, part1n, part2p, part2n;
    /* Optional 2nd environment */
    double effective_eps=ia_params->LJANGLE_eps, z1, z2, z_middle, z_ref, z_ref5,
           localz0=ia_params->LJANGLE_z0, localdz2=ia_params->LJANGLE_dz/2.,
           localkappa6=pow(1/ia_params->LJANGLE_kappa,6);



    /* Retrieve the bonded partners from parsing */
    if (ia_params->LJANGLE_bonded1type == p1->p.type) {
        part1p = p1->p.identity + ia_params->LJANGLE_bonded1pos;
        part1n = p1->p.identity + ia_params->LJANGLE_bonded1neg;
        part2p = p2->p.identity + ia_params->LJANGLE_bonded2pos;
        part2n = p2->p.identity + ia_params->LJANGLE_bonded2neg;
    } else {
        part1p = p1->p.identity + ia_params->LJANGLE_bonded2pos;
        part1n = p1->p.identity + ia_params->LJANGLE_bonded2neg;
        part2p = p2->p.identity + ia_params->LJANGLE_bonded1pos;
        part2n = p2->p.identity + ia_params->LJANGLE_bonded1neg;
    }

    if (part1p >= 0 && part1p < n_part &&
            part1n >= 0 && part1n < n_part &&
            part2p >= 0 && part2p < n_part &&
            part2n >= 0 && part2n < n_part     ) {

        p3 = local_particles[part1p];
        p4 = local_particles[part1n];
        p5 = local_particles[part2p];
        p6 = local_particles[part2n];

        /* Check whether pointers have been allocated.
         * Otherwise, there's a communication error (verlet skin too small).
         */
        if (p3==NULL ||p4==NULL ||p5==NULL ||p6==NULL)
            fprintf(stderr, "LJANGLE - Communication error, all particles cannot be reached locally.\n");



        get_mi_vector(r31, p1->r.p, p3->r.p);
        get_mi_vector(r41, p1->r.p, p4->r.p);
        get_mi_vector(r52, p2->r.p, p5->r.p);
        get_mi_vector(r62, p2->r.p, p6->r.p);


        /* Bead i represents the central particle of monomer 1.
         * Bead j is the virtual particle that gives the orientation of monomer 1.
         * Bead k represents the central particle of monomer 2.
         * Bead n is the virtual particle that gives the orientation of monomer 2.
         */
        for(j=0; j<3; ++j) {
            rij[j] = r31[j] + r41[j];
            rik[j] = -d[j]; /* At this point, rik[3] has length dist */
            rkn[j] = r52[j] + r62[j];
        }

        l_rij2 = sqrlen(rij);
        l_rik2 = dist*dist;
        l_rkn2 = sqrlen(rkn);
        l_rij  = sqrt(l_rij2);
        l_rik  = dist;
        l_rkn  = sqrt(l_rkn2);

        cos_jik = scalar(rij,rik)/(l_rij*l_rik);
        cos_ikn = -scalar(rik,rkn)/(l_rik*l_rkn);

        if(cos_jik>0. && cos_ikn>0.) {
            angular_jik       = pow(cos_jik,2);
            angular_ikn       = pow(cos_ikn,2);
            angular_jik_prime = -2*cos_jik;
            angular_ikn_prime = -2*cos_ikn;

            /* Optional 2nd environment */
            if (localdz2 > 0.) {
                /* calculate center position of the interaction (calculate minimal distance) */
                z1  = p1->r.p[2];
                z2  = p2->r.p[2];
                z_middle  = z1 + z2;
                z_middle /= 2.;
                if (PERIODIC(2))
                    if (z_middle > box_l[2] || z_middle < 0.)
                        z_middle -= dround(z_middle *box_l_i[2])*box_l[2];

                /* If we're in the environment #2 region, calculate the new interaction strength */
                if (z_middle > localz0 - localdz2 && z_middle <= localz0) {
                    z_ref = z_middle - localz0 + localdz2;
                    z_ref5 = pow(z_ref,5);
                    effective_eps += (ia_params->LJANGLE_epsprime - ia_params->LJANGLE_eps) *
                                     localkappa6*z_ref5*fabs(z_ref) /
                                     (1 + localkappa6*z_ref5*z_ref);
                } else if (z_middle > localz0 && z_middle < localz0 + localdz2) {
                    z_ref = z_middle - localz0 - localdz2;
                    z_ref5 = pow(z_ref,5);
                    effective_eps -= (ia_params->LJANGLE_epsprime - ia_params->LJANGLE_eps) *
                                     localkappa6*z_ref5*fabs(z_ref) /
                                     (1 + localkappa6*z_ref5*z_ref);
                }
            }

            /* normal case: resulting force/energy smaller than capping. */
            if(dist > ia_params->LJANGLE_capradius) {
                frac2 = SQR(ia_params->LJANGLE_sig/dist);
                frac10 = frac2*frac2*frac2*frac2*frac2;
                rad        = effective_eps * frac10*(5.0 * frac2 - 6.0);
                radprime   = 60.0 * effective_eps * frac10*(1.0 - frac2) / dist;

#ifdef LJ_WARN_WHEN_CLOSE
                if(radprime > 1000) fprintf(stderr,"%d: LJANGLE-Warning: Pair (%d-%d) force=%f dist=%f\n",
                                                this_node,p1->p.identity,p2->p.identity,radprime,dist);
#endif
            }
            /* capped part of lj-angle potential. */
            else if(dist > 0.0) {
                /* set the length of rik to capradius */
                for (j=0; j<3; ++j)
                    rik[j] *= ia_params->LJANGLE_capradius/dist;

                l_rik = ia_params->LJANGLE_capradius;

                frac2 = SQR(ia_params->LJANGLE_sig/ia_params->LJANGLE_capradius);
                frac10 = frac2*frac2*frac2*frac2*frac2;

                rad        = effective_eps * frac10*(5.0 * frac2 - 6.0);
                radprime   = 60.0 * effective_eps * frac10*(1.0 - frac2) / (ia_params->LJANGLE_capradius);
            }

            /* Regroup the last two cases in one */
            /* Propagate all forces in this function rather than in the forces.hpp file */
            if (dist > 0.0) {
                for(j=0; j<3; ++j) {
                    p1->f.f[j] += angular_jik * angular_ikn * rik[j]/l_rik *radprime
                                  + angular_ikn * rad * angular_jik_prime
                                  * ( ( 2*rik[j]-rij[j] )/( l_rij*l_rik )
                                      - cos_jik*( 2*rij[j]/l_rij2 - rik[j]/l_rik2 ) )
                                  + angular_jik * rad * angular_ikn_prime
                                  * ( rkn[j]/( l_rik*l_rkn )
                                      + cos_ikn*rik[j]/l_rik2 );
                    p2->f.f[j] += -angular_jik * angular_ikn * rik[j]/l_rik *radprime
                                  + angular_ikn * rad * angular_jik_prime
                                  * ( rij[j]/( l_rij*l_rik )
                                      - cos_jik*rik[j]/l_rik2 )
                                  + angular_jik * rad * angular_ikn_prime
                                  * ( -(2*rik[j]+rkn[j])/(l_rik*l_rkn)
                                      - cos_ikn*( 2*rkn[j]/l_rkn2 + rik[j]/l_rik2 ) );
                    p3->f.f[j] += angular_ikn * rad * angular_jik_prime
                                  * ( -rik[j]/(l_rij*l_rik)
                                      + cos_jik*rij[j]/l_rij2 );
                    p4->f.f[j] += angular_ikn * rad * angular_jik_prime
                                  * ( -rik[j]/(l_rij*l_rik)
                                      + cos_jik*rij[j]/l_rij2 );
                    p5->f.f[j] += angular_jik * rad * angular_ikn_prime
                                  * ( rik[j]/(l_rik*l_rkn)
                                      + cos_ikn*rkn[j]/l_rkn2 );
                    p6->f.f[j] += angular_jik * rad * angular_ikn_prime
                                  * ( rik[j]/(l_rik*l_rkn)
                                      + cos_ikn*rkn[j]/l_rkn2 );
                }
            }


            /* this should not happen! In this case consider only radial potential*/
            else {
                LJ_TRACE(fprintf(stderr, "%d: LJ-angle warning: Particles id1=%d id2=%d exactly on top of each other\n",this_node,p1->p.identity,p2->p.identity));

                frac2 = SQR(ia_params->LJANGLE_sig/ia_params->LJANGLE_capradius);
                frac10 = frac2*frac2*frac2*frac2*frac2;
                rad   = effective_eps * frac10*(5.0 * frac2 - 6.0) / ia_params->LJANGLE_capradius;

                p1->f.f[0] += rad * ia_params->LJANGLE_capradius;
            }


            ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: LJANGLE   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,dist,radprime));
            ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: LJANGLE   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,dist,radprime));

            LJ_TRACE(fprintf(stderr,"%d: LJANGLE: Pair (%d-%d) dist=%.3f: force+-: (%.3e,%.3e,%.3e)\n",
                             this_node,p1->p.identity,p2->p.identity,dist,rad*d[0],rad*d[1],rad*d[2]));
        }