![]() |
ESPResSo 3.2.0-11-g9950804-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 /** \file endangledist.c 00022 * 00023 * Implementation of \ref endangledist.h 00024 */ 00025 #include "utils.h" 00026 #include "interaction_data.h" 00027 #include "communication.h" 00028 #include "constraint.h" 00029 #include "grid.h" 00030 00031 #ifdef BOND_ENDANGLEDIST 00032 00033 int endangledist_set_params(int bond_type, double bend, double phi0 ,double distmin, double distmax) 00034 { 00035 if(bond_type < 0) 00036 return ES_ERROR; 00037 00038 make_bond_type_exist(bond_type); 00039 00040 bonded_ia_params[bond_type].p.endangledist.bend = bend; 00041 bonded_ia_params[bond_type].p.endangledist.phi0 = phi0; 00042 bonded_ia_params[bond_type].p.endangledist.distmin = distmin; 00043 bonded_ia_params[bond_type].p.endangledist.distmax = distmax; 00044 00045 bonded_ia_params[bond_type].type = BONDED_IA_ENDANGLEDIST; 00046 /* Normally LENGTH=1 ANGLE=2 DIHEDRAL=3 00047 * Here angle only requires one particle (other reference is wall constraint) 00048 */ 00049 bonded_ia_params[bond_type].num = 1; 00050 00051 /* broadcast interaction parameters */ 00052 mpi_bcast_ia_params(bond_type, -1); 00053 00054 return ES_OK; 00055 } 00056 00057 #ifdef CONSTRAINTS 00058 /// Calculates the minimum distance between a particle to any wall constraint 00059 static double calc_pwdist(Particle *p1, Bonded_ia_parameters *iaparams, int *clconstr) 00060 { 00061 int j,k,img[3]; 00062 double distwallmin=0.0, normal=0.0; 00063 double folded_pos_p1[3]; 00064 double pwdist[n_constraints]; 00065 Constraint_wall wall; 00066 00067 /*fprintf(stdout," Entering calc_pwdist:\n");*/ 00068 00069 /* folds coordinates of p_left into original box */ 00070 memcpy(folded_pos_p1, p1->r.p, 3*sizeof(double)); 00071 memcpy(img, p1->l.i, 3*sizeof(int)); 00072 fold_position(folded_pos_p1, img); 00073 /*fprintf(stdout," p1= %9.6f %9.6f %9.6f\n",p1->r.p[0],p1->r.p[1],p1->r.p[2]);*/ 00074 00075 /* Gets and tests wall data */ 00076 for(k=0;k<n_constraints;k++) { 00077 switch(constraints[k].type) { 00078 case CONSTRAINT_WAL: 00079 wall=constraints[k].c.wal; 00080 /* check that constraint wall normal is normalised */ 00081 for(j=0;j<3;j++) normal += wall.n[j] * wall.n[j]; 00082 if (sqrt(normal) != 1.0) { 00083 for(j=0;j<3;j++) wall.n[j]=wall.n[j]/normal; 00084 } 00085 break; 00086 } 00087 } 00088 00089 /* Calculate distance of end particle from closest wall */ 00090 for(k=0;k<n_constraints;k++) { 00091 switch(constraints[k].type) { 00092 case CONSTRAINT_WAL: 00093 wall=constraints[k].c.wal; 00094 /* distwallmin is distance of closest wall from p1 */ 00095 pwdist[k]=-1.0 * wall.d; 00096 for(j=0;j<3;j++) { 00097 pwdist[k] += folded_pos_p1[j] * wall.n[j]; 00098 } 00099 if (k==0) { 00100 distwallmin=pwdist[k]; 00101 } else { 00102 if (pwdist[k] < distwallmin) { 00103 distwallmin = pwdist[k]; 00104 *clconstr = k; 00105 } 00106 } 00107 /*fprintf(stdout," k=%d clconstr=%d\n",k,*clconstr);*/ 00108 break; 00109 } 00110 } 00111 /* 00112 if (distwallmin <= iaparams->p.endangledist.distmax) { 00113 fprintf(stdout," clconstr=%d distwallmin=%f distmx=%f\n",*clconstr,distwallmin,distmx); 00114 } 00115 */ 00116 return distwallmin; 00117 } 00118 00119 /// Calculate angle that p1--p2 makes with wall constraint 00120 static double calc_pwangle(Particle *p1, Particle *p2, Bonded_ia_parameters *iaparams, int *constr) 00121 { 00122 int j; 00123 double dist,di,cosine,phi; 00124 double vec[3]; 00125 00126 /* vector from p1 to p2 */ 00127 get_mi_vector(vec, p2->r.p, p1->r.p); 00128 dist = sqrlen(vec); 00129 di = 1.0/sqrt(dist); 00130 for(j=0;j<3;j++) vec[j] *= di; 00131 /* 00132 fprintf(stdout,"Normalised: p1= %9.6f %9.6f %9.6f p1= %9.6f %9.6f %9.6f vec= %9.6f %9.6f %9.6f\n",p1->r.p[0],p1->r.p[1],p1->r.p[2],p2->r.p[0],p2->r.p[1],p2->r.p[2],vec[0],vec[1],vec[2]); 00133 */ 00134 /* vectors are normalised so cosine is just cos(angle_between_vec1_and_vec2) 00135 * Wall is closest wall to particle 00136 */ 00137 00138 cosine = scalar(vec, constraints[*constr].c.wal.n); 00139 if ( cosine > TINY_COS_VALUE) cosine = TINY_COS_VALUE; 00140 if ( cosine < -TINY_COS_VALUE) cosine = -TINY_COS_VALUE; 00141 phi=acos(cosine); 00142 00143 /* 00144 fprintf(stdout,"Angle with wall 0=%f ",(acos(scalar(vec, constraints[0].c.wal.n)))*180.0/PI); 00145 fprintf(stdout,"Angle with wall 1=%f ",(acos(scalar(vec, constraints[1].c.wal.n)))*180.0/PI); 00146 fprintf(stdout,"dxy=%f dz=%f angle=%f\n",sqrt(vec[0]*vec[0]+vec[1]*vec[1]),vec[2],atan(sqrt(vec[0]*vec[0]+vec[1]*vec[1])/vec[2])*180.0/PI); 00147 fprintf(stdout,"Angle with closest wall %d=%f ",*constr,(acos(scalar(vec, constraints[*constr].c.wal.n)))*180.0/PI); 00148 */ 00149 return phi; 00150 } 00151 #endif 00152 00153 /// 00154 int calc_endangledist_pair_force(Particle *p1, Particle *p2, Bonded_ia_parameters *iaparams, double dx[3], double force1[3], double force2[3]) 00155 { 00156 00157 int i=0; 00158 int clconstr=0; 00159 // double distwallmin=0.0, distmx, distmn; 00160 double bend=0.0,phieq=0.0,phi=0.0,distwallmin=0.0, distmx, distmn, dist, di; 00161 double smooth, sinphi, cosphi, fac_a, fac_b, gradharm1, gradharm2; 00162 double vec[3],dsmooth[3],f1a[3],f1b[3],f2a[3]; 00163 00164 /*fprintf(stdout,"\nEntering calc_endangledist_pair_force:\n");*/ 00165 00166 distwallmin = calc_pwdist(p1, iaparams, &clconstr); 00167 distmx = iaparams->p.endangledist.distmax; 00168 distmn = iaparams->p.endangledist.distmin; 00169 00170 if (distwallmin < distmx) { 00171 /* function which goes smoothly from 0 to 1 as z goes from distmax to distmin */ 00172 if (distwallmin < distmn) { 00173 smooth = 1.0; 00174 for(i=0;i<3;i++) { 00175 dsmooth[i] = 0.0; 00176 } 00177 } else { 00178 smooth = 0.5*(cos((distwallmin-distmn)/(distmx-distmn)*PI)+1.0); 00179 for(i=0;i<3;i++) { 00180 dsmooth[i] = -0.5*PI/(distmx-distmn)*sin((distwallmin-distmn)/(distmx-distmn)*PI)*constraints[clconstr].c.wal.n[i]; 00181 } 00182 } 00183 /* Get vector from particle 1 to particle 2 */ 00184 get_mi_vector(vec, p2->r.p, p1->r.p); 00185 dist = sqrlen(vec); 00186 di = 1.0/sqrt(dist); 00187 /* 00188 for(j=0;j<3;j++) vec[j] *= di; 00189 */ 00190 /* Calculate angle that p1-p2 makes with wall */ 00191 phi = calc_pwangle(p1, p2, iaparams, &clconstr); 00192 00193 sinphi = sin(phi); 00194 cosphi = cos(phi); 00195 bend = iaparams->p.endangledist.bend; 00196 phieq = iaparams->p.endangledist.phi0; 00197 00198 /* 00199 fprintf(stdout," Bead %4d: Cl.wall=%2d distwallmin=%9.6f \n",p1->p.identity,clconstr,distwallmin); 00200 fprintf(stdout," vector=(%f %f %f)\n",vec[0],vec[1],vec[2]); 00201 fprintf(stdout,"pos1=(%f %f %f) pos2=(%f %f %f) distwallmin=%9.6f angle=%9.6f\n",p1->r.p[0],p1->r.p[1],p1->r.p[2],p2->r.p[0],p2->r.p[1],p2->r.p[2],distwallmin,phi*180.0/PI); 00202 */ 00203 00204 #ifdef BOND_ENDANGLEDIST_HARMONIC 00205 /* Force = -dU/dr_i= k*smooth*(phi-phi0)/sin(phi)(cosphi*vec + n)/|vec| */ 00206 fac_a = bend*(phi-phieq)/sinphi; 00207 fac_b = 0.5*bend*SQR(phi-phieq); 00208 for(i=0;i<3;i++) { 00209 gradharm1 = -1.0*fac_a*(cosphi*vec[i]-constraints[clconstr].c.wal.n[i])*di; 00210 gradharm2 = -1.0*gradharm1; 00211 f1a[i] = smooth*gradharm1; 00212 f1b[i] = dsmooth[i]*fac_b; 00213 f2a[i] = smooth*gradharm2; 00214 force1[i] = -1.0*(f1a[i]+f1b[i]); 00215 force2[i] = -1.0*f2a[i]; 00216 } 00217 /* 00218 fprintf(stdout," f1=(% 9.6f % 9.6f % 9.6f) ",f1[0],f1[1],f1[2]); 00219 fprintf(stdout," f2=(% 9.6f % 9.6f % 9.6f)\n",f2[0],f2[1],f2[2]); 00220 fprintf(stdout," force=(% 9.6f % 9.6f % 9.6f) ",force1[0],force1[1],force1[2]); 00221 fprintf(stdout," force2=(% 9.6f % 9.6f % 9.6f)\n",force2[0],force2[1],force2[2]); 00222 */ 00223 } else if (distwallmin >= distmx) { 00224 for(i=0;i<3;i++) { 00225 force1[i] = 0.0; 00226 force2[i] = 0.0; 00227 } 00228 } 00229 #endif 00230 00231 ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: ENDANGLEDIST f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,dist2,fac)); 00232 ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: ENDANGLEDIST f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,dist2,fac)); 00233 00234 return 0; 00235 } 00236 00237 int endangledist_pair_energy(Particle *p1, Particle *p2, Bonded_ia_parameters *iaparams, double dx[3], double *_energy) 00238 { 00239 int clconstr=0; 00240 double bend=0.0,phieq=0.0,phi=0.0; 00241 double distwallmin=0.0, distmx, distmn, smooth; 00242 00243 /*fprintf(stdout,"Entering endangledist_pair_energy\n");*/ 00244 00245 distwallmin = calc_pwdist(p1, iaparams, &clconstr); 00246 /* fprintf(stdout,"clconstr=%d\n",clconstr);*/ 00247 /* fprintf(stdout,"Minimum particle-wall distance=%f\n",distwallmin);*/ 00248 distmx = iaparams->p.endangledist.distmax; 00249 distmn = iaparams->p.endangledist.distmin; 00250 00251 #ifdef BOND_ENDANGLEDIST_HARMONIC 00252 if (distwallmin < distmx) { 00253 /* function which goes smoothly from 0 to 1 as z goes from distmax to distmin */ 00254 if (distwallmin < distmn) { 00255 smooth = 1.0; 00256 } else { 00257 smooth = 0.5*(cos((distwallmin-distmn)/(distmx-distmn)*PI)+1); 00258 } 00259 /* Calculate angle that p1-p2 makes with wall */ 00260 phi = calc_pwangle(p1, p2, iaparams, &clconstr); 00261 /*fprintf(stdout,"clconstr=%d smooth=%f\n",clconstr,smooth);*/ 00262 bend = iaparams->p.endangledist.bend; 00263 phieq = iaparams->p.endangledist.phi0; 00264 *_energy = 0.5*bend*smooth*SQR(phi - phieq); 00265 } else if (distwallmin >= distmx) { 00266 *_energy = 0.0; 00267 } 00268 #endif 00269 00270 return 0; 00271 } 00272 00273 #endif 00274
1.7.5.1