// 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)
 {
  printf(stderr,"virtual_sites_relative.c - 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


 }
}
Beispiel #2
0
/** propagate angular velocities and quaternions \todo implement for
       fixed_coord_flag */
void propagate_omega_quat()
{
  Particle *p;
  Cell *cell;
  int c,i,j, np;
  double lambda, dt2, dt4, dtdt, dtdt2;

  dt2 = time_step*0.5;
  dt4 = time_step*0.25;
  dtdt = time_step*time_step;
  dtdt2 = dtdt*0.5;

  INTEG_TRACE(fprintf(stderr,"%d: propagate_omega_quat:\n",this_node));

  for (c = 0; c < local_cells.n; c++) {
    cell = local_cells.cell[c];
    p  = cell->part;
    np = cell->n;
    for(i = 0; i < np; i++) {
	  double Qd[4], Qdd[4], S[3], Wd[3];
	  
	  #ifdef VIRTUAL_SITES
	   // Virtual sites are not propagated in the integration step
	   if (ifParticleIsVirtual(&p[i]))
	    continue;
	  #endif

	  define_Qdd(&p[i], Qd, Qdd, S, Wd);
	  
	  lambda = 1 - S[0]*dtdt2 - sqrt(1 - dtdt*(S[0] + time_step*(S[1] + dt4*(S[2]-S[0]*S[0]))));

	  for(j=0; j < 3; j++){
	    p[i].m.omega[j]+= dt2*Wd[j];
	  }
	  ONEPART_TRACE(if(p[i].p.identity==check_id) fprintf(stderr,"%d: OPT: PV_1 v_new = (%.3e,%.3e,%.3e)\n",this_node,p[i].m.v[0],p[i].m.v[1],p[i].m.v[2]));

	  p[i].r.quat[0]+= time_step*(Qd[0] + dt2*Qdd[0]) - lambda*p[i].r.quat[0];
	  p[i].r.quat[1]+= time_step*(Qd[1] + dt2*Qdd[1]) - lambda*p[i].r.quat[1];
	  p[i].r.quat[2]+= time_step*(Qd[2] + dt2*Qdd[2]) - lambda*p[i].r.quat[2];
	  p[i].r.quat[3]+= time_step*(Qd[3] + dt2*Qdd[3]) - lambda*p[i].r.quat[3];
	  // Update the director
	  convert_quat_to_quatu(p[i].r.quat, p[i].r.quatu);
#ifdef DIPOLES
	  // When dipoles are enabled, update dipole moment
	  convert_quatu_to_dip(p[i].r.quatu, p[i].p.dipm, p[i].r.dip);
#endif
	

      ONEPART_TRACE(if(p[i].p.identity==check_id) fprintf(stderr,"%d: OPT: PPOS p = (%.3f,%.3f,%.3f)\n",this_node,p[i].r.p[0],p[i].r.p[1],p[i].r.p[2]));
    }
  }
}
Beispiel #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];
 }
}