Пример #1
0
inline void 
calc_non_bonded_pair_force(Particle *p1, Particle *p2, 
                           double d[3], double dist, double dist2, 
                           double force[3]){
  IA_parameters *ia_params = get_ia_param(p1->p.type,p2->p.type);
  calc_non_bonded_pair_force(p1, p2, ia_params, d, dist, dist2, force);
}
Пример #2
0
/** Calculate non bonded energies between a pair of particles.
    @param p1        pointer to particle 1.
    @param p2        pointer to particle 2.
    @param d         vector between p1 and p2.
    @param dist      distance between p1 and p2.
    @param dist2     distance squared between p1 and p2. */
inline void add_non_bonded_pair_virials(Particle *p1, Particle *p2, double d[3],
                                        double dist, double dist2)
{
    int p1molid, p2molid, k, l;
    double force[3] = {0, 0, 0};

    calc_non_bonded_pair_force(p1, p2,d, dist, dist2, force);

    *obsstat_nonbonded(&virials, p1->p.type, p2->p.type) += d[0]*force[0] + d[1]*force[1] + d[2]*force[2];

    /* stress tensor part */
    for(k=0; k<3; k++)
        for(l=0; l<3; l++)
            obsstat_nonbonded(&p_tensor, p1->p.type, p2->p.type)[k*3 + l] += force[k]*d[l];

    p1molid = p1->p.mol_id;
    p2molid = p2->p.mol_id;
    if ( p1molid == p2molid ) {
        *obsstat_nonbonded_intra(&virials_non_bonded, p1->p.type, p2->p.type) += d[0]*force[0] + d[1]*force[1] + d[2]*force[2];

        for(k=0; k<3; k++)
            for(l=0; l<3; l++)
                obsstat_nonbonded_intra(&p_tensor_non_bonded, p1->p.type, p2->p.type)[k*3 + l] += force[k]*d[l];
    }
    if ( p1molid != p2molid ) {
        *obsstat_nonbonded_inter(&virials_non_bonded, p1->p.type, p2->p.type) += d[0]*force[0] + d[1]*force[1] + d[2]*force[2];

        for(k=0; k<3; k++)
            for(l=0; l<3; l++)
                obsstat_nonbonded_inter(&p_tensor_non_bonded, p1->p.type, p2->p.type)[k*3 + l] += force[k]*d[l];
    }

#ifdef ELECTROSTATICS
    /* real space coulomb */
    if (coulomb.method != COULOMB_NONE) {
        switch (coulomb.method) {
#ifdef P3M
        case COULOMB_P3M_GPU:
        case COULOMB_P3M:
            force[0] = 0.0;
            force[1] = 0.0;
            force[2] = 0.0;
            p3m_add_pair_force(p1->p.q*p2->p.q, d, dist2, dist, force);
            virials.coulomb[0] += p3m_pair_energy(p1->p.q*p2->p.q,d,dist2,dist);
            for (k = 0; k<3; k++)
                for (l = 0; l<3; l++)
                    p_tensor.coulomb[k*3 + l] += force[k]*d[l];

            break;
#endif

        /* short range potentials, where we use the virial */
        /***************************************************/
        case COULOMB_DH: {
            double force[3] = {0, 0, 0};

            add_dh_coulomb_pair_force(p1,p2,d,dist, force);
            for(k=0; k<3; k++)
                for(l=0; l<3; l++)
                    p_tensor.coulomb[k*3 + l] += force[k]*d[l];
            virials.coulomb[0] += force[0]*d[0] + force[1]*d[1] + force[2]*d[2];
            break;
        }
        case COULOMB_RF: {
            double force[3] = {0, 0, 0};

            add_rf_coulomb_pair_force(p1,p2,d,dist, force);
            for(k=0; k<3; k++)
                for(l=0; l<3; l++)
                    p_tensor.coulomb[k*3 + l] += force[k]*d[l];
            virials.coulomb[0] += force[0]*d[0] + force[1]*d[1] + force[2]*d[2];
            break;
        }
        case COULOMB_INTER_RF:
            // this is done together with the other short range interactions
            break;
        default:
            fprintf(stderr,"calculating pressure for electrostatics method that doesn't have it implemented\n");
            break;
        }
    }
#endif /*ifdef ELECTROSTATICS */

#ifdef DIPOLES
    /* real space magnetic dipole-dipole */
    if (coulomb.Dmethod != DIPOLAR_NONE) {
        fprintf(stderr,"calculating pressure for magnetostatics which doesn't have it implemented\n");
    }
#endif /*ifdef DIPOLES */
}
Пример #3
0
/** Calculate non bonded forces between a pair of particles.
    @param p1        pointer to particle 1.
    @param p2        pointer to particle 2.
    @param d         vector between p1 and p2. 
    @param dist      distance between p1 and p2.
    @param dist2     distance squared between p1 and p2. */
inline void add_non_bonded_pair_force(Particle *p1, Particle *p2, 
					double d[3], double dist, double dist2)
{
  IA_parameters *ia_params = get_ia_param(p1->p.type,p2->p.type);
  double force[3] = { 0., 0., 0. };
  double torque1[3] = { 0., 0., 0. };
  double torque2[3] = { 0., 0., 0. };
  int j;

  /***********************************************/
  /* bond creation and breaking                  */
  /***********************************************/

#ifdef COLLISION_DETECTION
  if (collision_params.mode > 0)
    detect_collision(p1,p2);
#endif

  /*affinity potential*/
#ifdef AFFINITY
  add_affinity_pair_force(p1,p2,ia_params,d,dist,force);
#endif
  
  FORCE_TRACE(fprintf(stderr, "%d: interaction %d<->%d dist %f\n", this_node, p1->p.identity, p2->p.identity, dist));

  /***********************************************/
  /* thermostat                                  */
  /***********************************************/

#ifdef DPD
  /* DPD thermostat forces */
  if ( thermo_switch & THERMO_DPD ) add_dpd_thermo_pair_force(p1,p2,d,dist,dist2);
#endif

  /** The inter dpd force should not be part of the virial
      
#ifdef INTER_DPD
  add_inter_dpd_pair_force(p1,p2,ia_params,d,dist,dist2);
#endif
  
  /***********************************************/
  /* non bonded pair potentials                  */
  /***********************************************/

   calc_non_bonded_pair_force(p1,p2,ia_params,d,dist,dist2,force,torque1,torque2);
   
  /***********************************************/
  /* short range electrostatics                  */
  /***********************************************/

#ifdef ELECTROSTATICS
  if (coulomb.method == COULOMB_DH)
    add_dh_coulomb_pair_force(p1,p2,d,dist,force);
  
  if (coulomb.method == COULOMB_RF)
    add_rf_coulomb_pair_force(p1,p2,d,dist,force);
#endif

  /*********************************************************************/
  /* everything before this contributes to the virial pressure in NpT, */
  /* but nothing afterwards                                            */
  /*********************************************************************/
#ifdef NPT
  for (j = 0; j < 3; j++)
    if(integ_switch == INTEG_METHOD_NPT_ISO)
      nptiso.p_vir[j] += force[j] * d[j];
#endif

  /***********************************************/
  /* semi-bonded multi-body potentials            */
  /***********************************************/
  
   /* Directional LJ */
#ifdef LJ_ANGLE
   /* This is a multi-body forces that changes the forces of 6 particles */
   add_ljangle_force(p1, p2, ia_params, d, dist);
#endif
  
  /***********************************************/
  /* long range electrostatics                   */
  /***********************************************/

#ifdef ELECTROSTATICS

  /* real space coulomb */
  double q1q2 = p1->p.q*p2->p.q;
  switch (coulomb.method) {
#ifdef P3M
  case COULOMB_ELC_P3M: {
	  if (q1q2) {
		  p3m_add_pair_force(q1q2,d,dist2,dist,force);

		  // forces from the virtual charges
		  // they go directly onto the particles, since they are not pairwise forces
		  if (elc_params.dielectric_contrast_on)
			  ELC_P3M_dielectric_layers_force_contribution(p1, p2, p1->f.f, p2->f.f);
	  }
	  break;
  }
  case COULOMB_P3M_GPU:
  case COULOMB_P3M: {
#ifdef NPT
	  if (q1q2) {
		  double eng = p3m_add_pair_force(q1q2,d,dist2,dist,force);
		  if(integ_switch == INTEG_METHOD_NPT_ISO)
			  nptiso.p_vir[0] += eng;
	  }
#else
	  if (q1q2) p3m_add_pair_force(q1q2,d,dist2,dist,force);
#endif
	  break;
  }
#endif
  case COULOMB_MMM1D:
	  if (q1q2) add_mmm1d_coulomb_pair_force(q1q2,d,dist2,dist,force);
	  break;
  case COULOMB_MMM2D:
	  if (q1q2) add_mmm2d_coulomb_pair_force(q1q2,d,dist2,dist,force);
	  break;
#ifdef EWALD_GPU
  case COULOMB_EWALD_GPU:
	  if (q1q2) add_ewald_gpu_coulomb_pair_force(p1,p2,d,dist,force);
	  break;
#endif
  default:
	  break;
  }

#endif /*ifdef ELECTROSTATICS */


  /***********************************************/
  /* long range magnetostatics                   */
  /***********************************************/


#ifdef DIPOLES
  /* real space magnetic dipole-dipole */
  switch (coulomb.Dmethod) {
#ifdef DP3M
  case  DIPOLAR_MDLC_P3M: 
   //fall trough 
  case DIPOLAR_P3M: {
#ifdef NPT
    double eng = dp3m_add_pair_force(p1,p2,d,dist2,dist,force);
    if(integ_switch == INTEG_METHOD_NPT_ISO)
      nptiso.p_vir[0] += eng;
#else
    dp3m_add_pair_force(p1,p2,d,dist2,dist,force);
#endif
    break;
  }
#endif /*ifdef DP3M */
  default:
      break;
  }  
#endif /* ifdef DIPOLES */
  
  /***********************************************/
  /* add total nonbonded forces to particle      */
  /***********************************************/

  for (j = 0; j < 3; j++) {
    p1->f.f[j] += force[j];
    p2->f.f[j] -= force[j];
#ifdef ROTATION
    p1->f.torque[j] += torque1[j];
    p2->f.torque[j] += torque2[j];
#endif
  }
}