// 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; }
// 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; }