// Update the pos of the given virtual particle as defined by the real 
// particles in the same molecule
void update_mol_pos_particle(Particle *p)
{
 // First obtain the real particle responsible for this virtual particle:
 // Find the 1st real particle in the topology for the virtual particle's mol_id
 Particle *p_real = vs_relative_get_real_particle(p);
 // Check, if a real particle was found
 if (!p_real)
 {
   char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE);
   ERROR_SPRINTF(errtxt,"virtual_sites_relative.cpp - update_mol_pos_particle(): No real particle associated with virtual site.\n");
   return;
 }
 
 // Calculate the quaternion defining the orientation of the vecotr connectinhg
 // the virtual site and the real particle
 // This is obtained, by multiplying the quaternion representing the director
 // of the real particle with the quaternion of the virtual particle, which 
 // specifies the relative orientation.
 double q[4];
 multiply_quaternions(p_real->r.quat,p->r.quat,q);
 // Calculate the director resulting from the quaternions
 double director[3];
 convert_quat_to_quatu(q,director);
 // normalize
 double l =sqrt(sqrlen(director));
 // Division comes in the loop below
 
 // Calculate the new position of the virtual sites from
 // position of real particle + director 
 int i;
 double new_pos[3];
 double tmp;
 for (i=0;i<3;i++)
 {
  new_pos[i] =p_real->r.p[i] +director[i]/l*p->p.vs_relative_distance;
  // Handle the case that one of the particles had gone over the periodic
  // boundary and its coordinate has been folded
  #ifdef PARTIAL_PERIODIC
   if (PERIODIC(i)) 
  #endif
  {
    tmp =p->r.p[i] -new_pos[i];
    //printf("%f\n",tmp);
    if (tmp > box_l[i]/2.) {
     //printf("greater than box_l/2 %f\n",tmp);
     p->r.p[i] =new_pos[i] + box_l[i];
    }
    else if (tmp < -box_l[i]/2.) {
     //printf("smaller than box_l/2 %f\n",tmp);
     p->r.p[i] =new_pos[i] - box_l[i];
    }
    else p->r.p[i] =new_pos[i];
   }
   #ifdef PARTIAL_PERIODIC
    else p->r.p[i] =new_pos[i];
   #endif
//   fold_coordinate(p->r.p,p->l.i,i);

 }
}
void rotate_point_axis(point_3D &point, double angle, point_3D axis)
  {
    double q1[4], q2[4], q3[4], q4[4];    // quaternions
    double cos_angle, sin_angle;

    if (angle < 0)
      {
        angle *= -1;
        axis.x *= -1;
        axis.y *= -1;
        axis.z *= -1;
      }

    q1[0] = 0;
    q1[1] = point.x;
    q1[2] = point.y;
    q1[3] = point.z;

    cos_angle = cos(angle / 2.0);
    sin_angle = sin(angle / 2.0);

    q2[0] = cos_angle;
    q2[1] = axis.x * sin_angle;
    q2[2] = axis.y * sin_angle;
    q2[3] = axis.z * sin_angle;

    multiply_quaternions(q2,q1,q3);

    q2[1] *= -1;
    q2[2] *= -1;
    q2[3] *= -1;

    multiply_quaternions(q3,q2,q4);

    point.x = q4[1];
    point.y = q4[2];
    point.z = q4[3];
  }
Exemplo n.º 3
0
/** Rotate the particle p around the NORMALIZED axis aSpaceFrame by amount phi */
void rotate_particle(Particle* p, double* aSpaceFrame, double phi)
{
  // Convert rotation axis to body-fixed frame
  double a[3];
  convert_vec_space_to_body(p,aSpaceFrame,a);


  // Apply restrictions from the rotation_per_particle feature
#ifdef ROTATION_PER_PARTICLE
//  printf("%g %g %g - ",a[0],a[1],a[2]);
  // Rotation turned off entirely?
  if (p->p.rotation <2) return;

  // Per coordinate fixing
  if (!(p->p.rotation & 2)) a[0]=0;
  if (!(p->p.rotation & 4)) a[1]=0;
  if (!(p->p.rotation & 8)) a[2]=0;
  // Re-normalize rotation axis
  double l=sqrt(sqrlen(a));
  // Check, if the rotation axis is nonzero
  if (l<1E-10) return;

  for (int i=0;i<3;i++)
    a[i]/=l;
//  printf("%g %g %g\n",a[0],a[1],a[2]);

#endif

  double q[4];
  q[0]=cos(phi/2);
  double tmp=sin(phi/2);
  q[1]=tmp*a[0];
  q[2]=tmp*a[1];
  q[3]=tmp*a[2];
  
  // Normalize
  normalize_quaternion(q);

  // Rotate the particle
  double qn[4]; // Resulting quaternion
  multiply_quaternions(p->r.quat,q,qn);
  for (int k=0; k<4; k++)
    p->r.quat[k]=qn[k];
  convert_quat_to_quatu(p->r.quat, p->r.quatu);
#ifdef DIPOLES
  // When dipoles are enabled, update dipole moment
  convert_quatu_to_dip(p->r.quatu, p->p.dipm, p->r.dip);
#endif
}
// Update the vel of the given virtual particle as defined by the real 
// particles in the same molecule
void update_mol_vel_particle(Particle *p)
{
 // NOT TESTED!
 
 // First obtain the real particle responsible for this virtual particle:
 Particle *p_real = vs_relative_get_real_particle(p);
 // Check, if a real particle was found
 if (!p_real)
 {
   char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE);
   ERROR_SPRINTF(errtxt, "virtual_sites_relative.cpp - update_mol_pos_particle(): No real particle associated with virtual site.\n");
   return;
 }
 
 // Calculate the quaternion defining the orientation of the vecotr connectinhg
 // the virtual site and the real particle
 // This is obtained, by multiplying the quaternion representing the director
 // of the real particle with the quaternion of the virtual particle, which 
 // specifies the relative orientation.
 double q[4];
 multiply_quaternions(p_real->r.quat,p->r.quat,q);
 // Calculate the director resulting from the quaternions
 double director[3];
 convert_quat_to_quatu(q,director);
 // normalize
 double l =sqrt(sqrlen(director));
 // Division comes in the loop below

 // Get omega of real particle in space-fixed frame
 double omega_space_frame[3];
 convert_omega_body_to_space(p_real,omega_space_frame);
 // Obtain velocity from v=v_real particle + omega_real_particle \times director
 vector_product(omega_space_frame,director,p->m.v);

 int i;
 // Add prefactors and add velocity of real particle
 for (i=0;i<3;i++)
 {
  // Scale the velocity by the distance of virtual particle from the real particle
  // Also, espresso stores not velocity but velocity * time_step
  p->m.v[i] *= time_step * p->p.vs_relative_distance/l;
  // Add velocity of real particle
  p->m.v[i] += p_real->m.v[i];
 }
}
// Setup the virtual_sites_relative properties of a particle so that the given virtaul particle will follow the given real particle
int vs_relate_to(int part_num, int relate_to)
{
    // Get the data for the particle we act on and the one we wnat to relate
    // it to.
    Particle  p_current,p_relate_to;
    if ((get_particle_data(relate_to,&p_relate_to)!=ES_OK) || 
        (get_particle_data(part_num,&p_current)!=ES_OK)) {
      char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE);
      ERROR_SPRINTF(errtxt, "Could not retrieve particle data for the given id");
      return ES_ERROR;
    }
    
    // get teh distance between the particles
    double d[3];
    get_mi_vector(d, p_current.r.p,p_relate_to.r.p);
    
    // Set the particle id of the particle we want to relate to and the distnace
    if (set_particle_vs_relative(part_num, relate_to, sqrt(sqrlen(d))) == ES_ERROR) {
      char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE);
      ERROR_SPRINTF(errtxt, "setting the vs_relative attributes failed");
      return ES_ERROR;
    }
    
    
    // Check, if the distance between virtual and non-virtual particles is larger htan minimum global cutoff
    // If so, warn user
    double l=sqrt(sqrlen(d));
    if (l>min_global_cut) {
      char *errtxt = runtime_error(300 + 3*ES_INTEGER_SPACE);
      ERROR_SPRINTF(errtxt, "Warning: The distance between virtual and non-virtual particle (%f) is\nlarger than the minimum global cutoff (%f). This may lead to incorrect simulations\nunder certain conditions. Use \"setmd min_global_cut\" to increase the minimum cutoff.\n",l,min_global_cut);
      return ES_ERROR;
    }

    // Now, calculate the quaternions which specify the angle between 
    // the director of the particel we relate to and the vector
    // (paritlce_we_relate_to - this_particle)
    double quat[4];
    // The vs_relative implemnation later obtains the direcotr by multiplying
    // the quaternions representing the orientation of the real particle
    // with those in the virtual particle. The re quulting quaternion is then
    // converted to a director.
    // Whe have quat_(real particle) *quat_(virtual particle) 
    // = quat_(obtained from desired director)
    // Resolving this for the quat_(virtaul particle)

    //Normalize desired director
    int i;
    for (i=0;i<3;i++)
     d[i]/=l;

    // Obtain quaternions from desired director
    double quat_director[4];
    convert_quatu_to_quat(d, quat_director);

    // Define quat as described above:
    double x=0;
    for (i=0;i<4;i++)
     x+=p_relate_to.r.quat[i]*p_relate_to.r.quat[i];

    quat[0]=0;
    for (i=0;i<4;i++)
     quat[0] +=p_relate_to.r.quat[i]*quat_director[i];
    
    quat[1] =-quat_director[0] *p_relate_to.r.quat[1] 
       +quat_director[1] *p_relate_to.r.quat[0]
       +quat_director[2] *p_relate_to.r.quat[3]
       -quat_director[3] *p_relate_to.r.quat[2];
    quat[2] =p_relate_to.r.quat[1] *quat_director[3] 
      + p_relate_to.r.quat[0] *quat_director[2] 
      - p_relate_to.r.quat[3] *quat_director[1] 
      - p_relate_to.r.quat[2] * quat_director[0];
    quat[3] =quat_director[3] *p_relate_to.r.quat[0]
      - p_relate_to.r.quat[3] *quat_director[0] 
      + p_relate_to.r.quat[2] * quat_director[1] 
      - p_relate_to.r.quat[1] *quat_director[2];
    for (i=0;i<4;i++)
     quat[i]/=x;
   
   
   // Verify result
   double qtemp[4];
   multiply_quaternions(p_relate_to.r.quat,quat,qtemp);
   for (i=0;i<4;i++)
     if (fabs(qtemp[i]-quat_director[i])>1E-9)
       fprintf(stderr, "vs_relate_to: component %d: %f instead of %f\n",
	       i, qtemp[i], quat_director[i]);


   // Save the quaternions in the particle
   if (set_particle_quat(part_num, quat) == ES_ERROR) {
     char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE);
     ERROR_SPRINTF(errtxt, "set particle position first");

     return ES_ERROR;
   }
   
   return ES_OK;
}
Exemplo n.º 6
0
// Setup the virtual_sites_relative properties of a particle so that the given virtaul particle will follow the given real particle
int vs_relate_to(int part_num, int relate_to)
{
    // Get the data for the particle we act on and the one we wnat to relate
    // it to.
    Particle  p_current,p_relate_to;
    if ((get_particle_data(relate_to,&p_relate_to)!=TCL_OK) || 
        (get_particle_data(part_num,&p_current)!=TCL_OK)) {
         printf("Could not retrieve particle data for the given id.\n");
          return TCL_ERROR;
    }
    
    // get teh distance between the particles
    double d[3];
    get_mi_vector(d, p_current.r.p,p_relate_to.r.p);
    
    // Set the particle id of the particle we want to relate to and the distnace
    if (set_particle_vs_relative(part_num, relate_to, sqrt(sqrlen(d))) == TCL_ERROR) {
      printf("setting the vs_relative attributes failed.\n");
      return TCL_ERROR;
    }

    // Now, calculate the quaternions which specify the angle between 
    // the director of the particel we relate to and the vector
    // (paritlce_we_relate_to - this_particle)
    double quat[4];
    // The vs_relative implemnation later obtains the direcotr by multiplying
    // the quaternions representing the orientation of the real particle
    // with those in the virtual particle. The re quulting quaternion is then
    // converted to a director.
    // Whe have quat_(real particle) *quat_(virtual particle) 
    // = quat_(obtained from desired director)
    // Resolving this for the quat_(virtaul particle)

    //Normalize desired director
    double l=sqrt(sqrlen(d));
    int i;
    for (i=0;i<3;i++)
     d[i]/=l;

    // Obtain quaternions from desired director
    double quat_director[4];
    convert_quatu_to_quat(d, quat_director);

    // Define quat as described above:
    double x=0;
    for (i=0;i<4;i++)
     x+=p_relate_to.r.quat[i]*p_relate_to.r.quat[i];

    quat[0]=0;
    for (i=0;i<4;i++)
     quat[0] +=p_relate_to.r.quat[i]*quat_director[i];
    
    quat[1] =-quat_director[0] *p_relate_to.r.quat[1] 
       +quat_director[1] *p_relate_to.r.quat[0]
       +quat_director[2] *p_relate_to.r.quat[3]
       -quat_director[3] *p_relate_to.r.quat[2];
    quat[2] =p_relate_to.r.quat[1] *quat_director[3] 
      + p_relate_to.r.quat[0] *quat_director[2] 
      - p_relate_to.r.quat[3] *quat_director[1] 
      - p_relate_to.r.quat[2] * quat_director[0];
    quat[3] =quat_director[3] *p_relate_to.r.quat[0]
      - p_relate_to.r.quat[3] *quat_director[0] 
      + p_relate_to.r.quat[2] * quat_director[1] 
      - p_relate_to.r.quat[1] *quat_director[2];
    for (i=0;i<4;i++)
     quat[i]/=x;
   
   
   // Verify result
   double qtemp[4];
   multiply_quaternions(p_relate_to.r.quat,quat,qtemp);
   for (i=0;i<4;i++)
    if (fabs(qtemp[i]-quat_director[i])>1E-9)
     printf("Component %d: %f instead of %f\n",i,qtemp[i],quat_director[i]);


   // Save the quaternions in the particle
   if (set_particle_quat(part_num, quat) == TCL_ERROR) {
     printf("set particle position first\n");

     return TCL_ERROR;
   }
   
   return TCL_OK;
}