![]() |
ESPResSo 3.2.0-64-g5125f6e-git
Extensible Simulation Package for Soft Matter Research
|
00001 /* 00002 Copyright (C) 2010,2011,2012,2013 The ESPResSo project 00003 Copyright (C) 2002,2003,2004,2005,2006,2007,2008,2009,2010 00004 Max-Planck-Institute for Polymer Research, Theory Group 00005 00006 This file is part of ESPResSo. 00007 00008 ESPResSo is free software: you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation, either version 3 of the License, or 00011 (at your option) any later version. 00012 00013 ESPResSo is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program. If not, see <http://www.gnu.org/licenses/>. 00020 */ 00021 #ifndef ANGLE_H 00022 #define ANGLE_H 00023 /** \file angle.h 00024 * Routines to calculate the angle energy or/and and force 00025 * for a particle triple. 00026 * \ref forces.c 00027 */ 00028 00029 #include "utils.h" 00030 #include "interaction_data.h" 00031 #include "particle_data.h" 00032 00033 #ifdef BOND_ANGLE_OLD 00034 #include "grid.h" 00035 00036 /** set parameters for the angle potential. 00037 00038 \todo The type of the angle potential 00039 is chosen via config.h and cannot be changed at runtime. 00040 */ 00041 int angle_set_params(int bond_type, double bend, double phi0); 00042 00043 /************************************************************/ 00044 00045 /** Computes the three body angle interaction force and adds this 00046 force to the particle forces (see \ref tclcommand_inter). 00047 @param p_mid Pointer to second/middle particle. 00048 @param p_left Pointer to first/left particle. 00049 @param p_right Pointer to third/right particle. 00050 @param iaparams bond type number of the angle interaction (see \ref tclcommand_inter). 00051 @param force1 returns force of particle 1 00052 @param force2 returns force of particle 2 00053 @return 0 00054 */ 00055 MDINLINE int calc_angle_force(Particle *p_mid, Particle *p_left, Particle *p_right, 00056 Bonded_ia_parameters *iaparams, double force1[3], double force2[3]) 00057 { 00058 double cosine, vec1[3], vec2[3], d1i, d2i, dist2, fac, f1=0.0, f2=0.0; 00059 int j; 00060 00061 cosine=0.0; 00062 /* vector from p_left to p_mid */ 00063 get_mi_vector(vec1, p_mid->r.p, p_left->r.p); 00064 dist2 = sqrlen(vec1); 00065 d1i = 1.0 / sqrt(dist2); 00066 for(j=0;j<3;j++) vec1[j] *= d1i; 00067 /* vector from p_mid to p_right */ 00068 get_mi_vector(vec2, p_right->r.p, p_mid->r.p); 00069 dist2 = sqrlen(vec2); 00070 d2i = 1.0 / sqrt(dist2); 00071 for(j=0;j<3;j++) vec2[j] *= d2i; 00072 /* scalar produvt of vec1 and vec2 */ 00073 cosine = scalar(vec1, vec2); 00074 fac = iaparams->p.angle.bend; 00075 00076 #ifdef BOND_ANGLE_HARMONIC 00077 { 00078 double phi,sinphi; 00079 if ( cosine > TINY_COS_VALUE) cosine = TINY_COS_VALUE; 00080 if ( cosine < -TINY_COS_VALUE) cosine = -TINY_COS_VALUE; 00081 phi = acos(-cosine); 00082 sinphi = sin(phi); 00083 if ( sinphi < TINY_SIN_VALUE ) sinphi = TINY_SIN_VALUE; 00084 fac *= (phi - iaparams->p.angle.phi0)/sinphi; 00085 } 00086 #endif 00087 #ifdef BOND_ANGLE_COSINE 00088 if ( cosine > TINY_COS_VALUE ) cosine = TINY_COS_VALUE; 00089 if ( cosine < -TINY_COS_VALUE) cosine = -TINY_COS_VALUE; 00090 fac *= iaparams->p.angle.sin_phi0 * (cosine/sqrt(1-SQR(cosine))) + iaparams->p.angle.cos_phi0; 00091 #endif 00092 #ifdef BOND_ANGLE_COSSQUARE 00093 fac *= iaparams->p.angle.cos_phi0 + cosine; 00094 #endif 00095 for(j=0;j<3;j++) { 00096 f1 = fac * (cosine * vec1[j] - vec2[j]) * d1i; 00097 f2 = fac * (cosine * vec2[j] - vec1[j]) * d2i; 00098 00099 force1[j] = (f1-f2); 00100 force2[j] = -f1; 00101 } 00102 return 0; 00103 } 00104 00105 /* The force on each particle due to a three-body bonded potential 00106 is computed. */ 00107 MDINLINE void calc_angle_3body_forces(Particle *p_mid, Particle *p_left, 00108 Particle *p_right, Bonded_ia_parameters *iaparams, 00109 double force1[3], double force2[3], double force3[3]) { 00110 00111 int j; 00112 double pot_dep; 00113 double cos_phi; 00114 double sin_phi; 00115 double vec31[3]; 00116 double vec21[3]; 00117 double vec12[3]; // espresso convention 00118 double vec21_sqr; 00119 double vec31_sqr; 00120 double vec21_magn; 00121 double vec31_magn; 00122 double fj[3]; 00123 double fk[3]; 00124 double fac; 00125 00126 get_mi_vector(vec12, p_mid->r.p, p_left->r.p); 00127 for(j = 0; j < 3; j++) 00128 vec21[j] = -vec12[j]; 00129 00130 get_mi_vector(vec31, p_right->r.p, p_mid->r.p); 00131 vec21_sqr = sqrlen(vec21); 00132 vec21_magn = sqrt(vec21_sqr); 00133 vec31_sqr = sqrlen(vec31); 00134 vec31_magn = sqrt(vec31_sqr); 00135 cos_phi = scalar(vec21, vec31) / (vec21_magn * vec31_magn); 00136 sin_phi = sqrt(1.0 - SQR(cos_phi)); 00137 00138 /* uncomment this block if interested in the angle 00139 if(cos_phi < -1.0) cos_phi = -TINY_COS_VALUE; 00140 if(cos_phi > 1.0) cos_phi = TINY_COS_VALUE; 00141 phi = acos(cos_phi); 00142 */ 00143 #ifdef BOND_ANGLE_HARMONIC 00144 { 00145 double K, phi, phi0; 00146 if(cos_phi < -1.0) cos_phi = -TINY_COS_VALUE; 00147 if(cos_phi > 1.0) cos_phi = TINY_COS_VALUE; 00148 phi = acos(cos_phi); 00149 00150 K = iaparams->p.angle.bend; 00151 phi0 = iaparams->p.angle.phi0; 00152 00153 // potential dependent term [dU/dphi = K * (phi - phi0)] 00154 pot_dep = K * (phi - phi0); 00155 } 00156 #endif 00157 #ifdef BOND_ANGLE_COSINE 00158 { 00159 double K, sin_phi0, cos_phi0; 00160 K = iaparams->p.angle.bend; 00161 sin_phi0 = iaparams->p.angle.sin_phi0; 00162 cos_phi0 = iaparams->p.angle.cos_phi0; 00163 00164 // potential dependent term [dU/dphi = K * sin(phi - phi0)] 00165 // trig identity: sin(a - b) = sin(a)cos(b) - cos(a)sin(b) 00166 pot_dep = K * (sin_phi * cos_phi0 - cos_phi * sin_phi0); 00167 } 00168 #endif 00169 #ifdef BOND_ANGLE_COSSQUARE 00170 { 00171 double K, cos_phi0; 00172 K = iaparams->p.angle.bend; 00173 cos_phi0 = iaparams->p.angle.cos_phi0; 00174 00175 // potential dependent term [dU/dphi = K * (sin_phi * cos_phi0 - cos_phi * sin_phi)] 00176 pot_dep = K * (sin_phi * cos_phi0 - cos_phi * sin_phi); 00177 } 00178 #endif 00179 00180 fac = pot_dep / sin_phi; 00181 00182 for(j = 0; j < 3; j++) { 00183 fj[j] = vec31[j] / (vec21_magn * vec31_magn) - cos_phi * vec21[j] / vec21_sqr; 00184 fk[j] = vec21[j] / (vec21_magn * vec31_magn) - cos_phi * vec31[j] / vec31_sqr; 00185 } 00186 00187 // note that F1 = -(F2 + F3) 00188 for(j = 0; j < 3; j++) { 00189 force1[j] = force1[j] - fac * (fj[j] + fk[j]); 00190 force2[j] = force2[j] + fac * fj[j]; 00191 force3[j] = force3[j] + fac * fk[j]; 00192 } 00193 } 00194 00195 00196 /** Computes the three body angle interaction energy (see \ref tclcommand_inter, \ref tclcommand_analyze). 00197 @param p_mid Pointer to first particle. 00198 @param p_left Pointer to second/middle particle. 00199 @param p_right Pointer to third particle. 00200 @param iaparams bond type number of the angle interaction (see \ref tclcommand_inter). 00201 @param _energy return energy pointer. 00202 @return 0. 00203 */ 00204 MDINLINE int angle_energy(Particle *p_mid, Particle *p_left, Particle *p_right, 00205 Bonded_ia_parameters *iaparams, double *_energy) 00206 { 00207 double cosine, vec1[3], vec2[3], d1i, d2i, dist2; 00208 int j; 00209 00210 cosine=0.0; 00211 /* vector from p_mid to p_left */ 00212 get_mi_vector(vec1, p_mid->r.p, p_left->r.p); 00213 dist2 = sqrlen(vec1); 00214 d1i = 1.0 / sqrt(dist2); 00215 for(j=0;j<3;j++) vec1[j] *= d1i; 00216 /* vector from p_right to p_mid */ 00217 get_mi_vector(vec2, p_right->r.p, p_mid->r.p); 00218 dist2 = sqrlen(vec2); 00219 d2i = 1.0 / sqrt(dist2); 00220 for(j=0;j<3;j++) vec2[j] *= d2i; 00221 /* scalar produvt of vec1 and vec2 */ 00222 cosine = scalar(vec1, vec2); 00223 if ( cosine > TINY_COS_VALUE) cosine = TINY_COS_VALUE; 00224 if ( cosine < -TINY_COS_VALUE) cosine = -TINY_COS_VALUE; 00225 /* bond angle energy */ 00226 #ifdef BOND_ANGLE_HARMONIC 00227 { 00228 double phi; 00229 phi = acos(-cosine); 00230 *_energy = 0.5*iaparams->p.angle.bend*SQR(phi - iaparams->p.angle.phi0); 00231 } 00232 #endif 00233 #ifdef BOND_ANGLE_COSINE 00234 *_energy = iaparams->p.angle.bend*(cosine*iaparams->p.angle.cos_phi0 - sqrt(1-SQR(cosine))*iaparams->p.angle.sin_phi0+1); 00235 #endif 00236 #ifdef BOND_ANGLE_COSSQUARE 00237 *_energy = 0.5*iaparams->p.angle.bend*SQR(cosine + iaparams->p.angle.cos_phi0); 00238 #endif 00239 return 0; 00240 } 00241 00242 #endif /* BOND_ANGLE_OLD */ 00243 #endif /* ANGLE_H */
1.7.5.1