![]() |
ESPResSo 3.2.0-167-g2c9ead1-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 constraint.c 00022 Implementation of \ref constraint.h "constraint.h", here it's just the parsing stuff. 00023 */ 00024 00025 #include "constraint.h" 00026 #include "energy.h" 00027 #include "forces.h" 00028 #include "tunable_slip.h" 00029 00030 // for the charged rod "constraint" 00031 #define C_GAMMA 0.57721566490153286060651209008 00032 00033 int reflection_happened; 00034 00035 #ifdef CONSTRAINTS 00036 00037 int n_constraints = 0; 00038 Constraint *constraints = NULL; 00039 00040 Constraint *generate_constraint() 00041 { 00042 n_constraints++; 00043 constraints = realloc(constraints,n_constraints*sizeof(Constraint)); 00044 constraints[n_constraints-1].type = CONSTRAINT_NONE; 00045 constraints[n_constraints-1].part_rep.p.identity = -n_constraints; 00046 00047 return &constraints[n_constraints-1]; 00048 } 00049 00050 void init_constraint_forces() 00051 { 00052 int n, i; 00053 00054 for (n = 0; n < n_constraints; n++) 00055 for (i = 0; i < 3; i++) 00056 constraints[n].part_rep.f.f[i] = 0; 00057 } 00058 00059 00060 static double sign(double x) { 00061 if (x > 0) 00062 return 1.; 00063 else 00064 return -1; 00065 } 00066 00067 static double max(double x1, double x2) { 00068 return x1>x2?x1:x2; 00069 } 00070 00071 void calculate_wall_dist(Particle *p1, double ppos[3], Particle *c_p, Constraint_wall *c, double *dist, double *vec) 00072 { 00073 int i; 00074 00075 *dist = -c->d; 00076 for(i=0;i<3;i++) *dist += ppos[i]*c->n[i]; 00077 00078 for(i=0;i<3;i++) vec[i] = c->n[i] * *dist; 00079 00080 } 00081 00082 00083 void calculate_sphere_dist(Particle *p1, double ppos[3], Particle *c_p, Constraint_sphere *c, double *dist, double *vec) 00084 { 00085 int i; 00086 double fac, c_dist; 00087 00088 c_dist=0.0; 00089 for(i=0;i<3;i++) { 00090 vec[i] = c->pos[i] - ppos[i]; 00091 c_dist += SQR(vec[i]); 00092 } 00093 c_dist = sqrt(c_dist); 00094 00095 if ( c->direction == -1 ) { 00096 /* apply force towards inside the sphere */ 00097 *dist = c->rad - c_dist; 00098 fac = *dist / c_dist; 00099 for(i=0;i<3;i++) vec[i] *= fac; 00100 } else { 00101 /* apply force towards outside the sphere */ 00102 *dist = c_dist - c->rad; 00103 fac = *dist / c_dist; 00104 for(i=0;i<3;i++) vec[i] *= -fac; 00105 } 00106 } 00107 00108 00109 void calculate_maze_dist(Particle *p1, double ppos[3], Particle *c_p, Constraint_maze *c, double *dist, double *vec) 00110 { 00111 int i,min_axis,cursph[3],dim; 00112 double diasph,fac,c_dist,sph_dist,cyl_dist,temp_dis; 00113 double sph_vec[3],cyl_vec[3]; 00114 00115 dim=(int) c->dim; 00116 diasph = box_l[0]/c->nsphere; 00117 00118 /* First determine the distance to the sphere */ 00119 c_dist=0.0; 00120 for(i=0;i<3;i++) { 00121 cursph[i] = (int) (ppos[i]/diasph); 00122 sph_vec[i] = (cursph[i]+0.5) * diasph - (ppos[i]); 00123 c_dist += SQR(sph_vec[i]); 00124 } 00125 c_dist = sqrt(c_dist); 00126 sph_dist = c->sphrad - c_dist; 00127 fac = sph_dist / c_dist; 00128 for(i=0;i<3;i++) cyl_vec[i] = sph_vec[i]; 00129 for(i=0;i<3;i++) sph_vec[i] *= fac; 00130 00131 /* Now calculate the cylinder stuff */ 00132 /* have to check all 3 cylinders */ 00133 min_axis=2; 00134 cyl_dist=sqrt(cyl_vec[0]*cyl_vec[0]+cyl_vec[1]*cyl_vec[1]); 00135 00136 if(dim > 0 ){ 00137 temp_dis=sqrt(cyl_vec[0]*cyl_vec[0]+cyl_vec[2]*cyl_vec[2]); 00138 if ( temp_dis < cyl_dist) { 00139 min_axis=1; 00140 cyl_dist=temp_dis; 00141 } 00142 00143 if(dim > 1 ){ 00144 temp_dis=sqrt(cyl_vec[1]*cyl_vec[1]+cyl_vec[2]*cyl_vec[2]); 00145 if ( temp_dis < cyl_dist) { 00146 min_axis=0; 00147 cyl_dist=temp_dis; 00148 } 00149 } 00150 } 00151 cyl_vec[min_axis]=0.; 00152 00153 c_dist=cyl_dist; 00154 cyl_dist = c->cylrad - c_dist; 00155 fac = cyl_dist / c_dist; 00156 for(i=0;i<3;i++) cyl_vec[i] *= fac; 00157 00158 /* Now decide between cylinder and sphere */ 00159 if ( sph_dist > 0 ) { 00160 if ( sph_dist>cyl_dist ) { 00161 *dist = sph_dist; 00162 for(i=0;i<3;i++) vec[i] = sph_vec[i]; 00163 } else { 00164 *dist = cyl_dist; 00165 for(i=0;i<3;i++) vec[i] = cyl_vec[i]; 00166 } 00167 } else { 00168 *dist = cyl_dist; 00169 for(i=0;i<3;i++) vec[i] = cyl_vec[i]; 00170 } 00171 } 00172 00173 void calculate_cylinder_dist(Particle *p1, double ppos[3], Particle *c_p, Constraint_cylinder *c, double *dist, double *vec) 00174 { 00175 int i; 00176 double d_per,d_par,d_real,d_per_vec[3],d_par_vec[3],d_real_vec[3]; 00177 00178 d_real = 0.0; 00179 for(i=0;i<3;i++) { 00180 d_real_vec[i] = ppos[i] - c->pos[i]; 00181 d_real += SQR(d_real_vec[i]); 00182 } 00183 d_real = sqrt(d_real); 00184 00185 d_par=0.; 00186 for(i=0;i<3;i++) { 00187 d_par += (d_real_vec[i] * c->axis[i]); 00188 } 00189 00190 for(i=0;i<3;i++) { 00191 d_par_vec[i] = d_par * c->axis[i] ; 00192 d_per_vec[i] = ppos[i] - (c->pos[i] + d_par_vec[i]) ; 00193 } 00194 00195 d_per=sqrt(SQR(d_real)-SQR(d_par)); 00196 d_par = fabs(d_par) ; 00197 00198 if ( c->direction == -1 ) { 00199 /*apply force towards inside cylinder */ 00200 d_per = c->rad - d_per ; 00201 d_par = c->length - d_par; 00202 if (d_per < d_par ) { 00203 *dist = d_per ; 00204 for (i=0; i<3;i++) { 00205 vec[i]= -d_per_vec[i] * d_per / (c->rad - d_per) ; 00206 } 00207 } else { 00208 *dist = d_par ; 00209 for (i=0; i<3;i++) { 00210 vec[i]= -d_par_vec[i] * d_par / (c->length - d_par) ; 00211 } 00212 } 00213 } else { 00214 /*apply force towards outside cylinder */ 00215 d_per = d_per - c->rad ; 00216 d_par = d_par - c->length ; 00217 if (d_par < 0 ) { 00218 *dist = d_per ; 00219 for (i=0; i<3;i++) { 00220 vec[i]= d_per_vec[i] * d_per / (d_per + c->rad) ; 00221 } 00222 } else if ( d_per < 0) { 00223 *dist = d_par ; 00224 for (i=0; i<3;i++) { 00225 vec[i]= d_par_vec[i] * d_par / (d_par + c->length) ; 00226 } 00227 } else { 00228 *dist = sqrt( SQR(d_par) + SQR(d_per)) ; 00229 for (i=0; i<3;i++) { 00230 vec[i]= 00231 d_per_vec[i] * d_per / (d_per + c->rad) + 00232 d_par_vec[i] * d_par / (d_par + c->length) ; 00233 } 00234 } 00235 } 00236 } 00237 00238 void calculate_rhomboid_dist(Particle *p1, double ppos[3], Particle *c_p, Constraint_rhomboid *c, double *dist, double *vec) 00239 { 00240 double axb[3], bxc[3], axc[3]; 00241 double A, B, C; 00242 double a_dot_bxc, b_dot_axc, c_dot_axb; 00243 double tmp; 00244 double d; 00245 00246 //calculate a couple of vectors and scalars that are going to be used frequently 00247 00248 axb[0] = c->a[1]*c->b[2] - c->a[2]*c->b[1]; 00249 axb[1] = c->a[2]*c->b[0] - c->a[0]*c->b[2]; 00250 axb[2] = c->a[0]*c->b[1] - c->a[1]*c->b[0]; 00251 00252 bxc[0] = c->b[1]*c->c[2] - c->b[2]*c->c[1]; 00253 bxc[1] = c->b[2]*c->c[0] - c->b[0]*c->c[2]; 00254 bxc[2] = c->b[0]*c->c[1] - c->b[1]*c->c[0]; 00255 00256 axc[0] = c->a[1]*c->c[2] - c->a[2]*c->c[1]; 00257 axc[1] = c->a[2]*c->c[0] - c->a[0]*c->c[2]; 00258 axc[2] = c->a[0]*c->c[1] - c->a[1]*c->c[0]; 00259 00260 a_dot_bxc = c->a[0]*bxc[0] + c->a[1]*bxc[1] + c->a[2]*bxc[2]; 00261 b_dot_axc = c->b[0]*axc[0] + c->b[1]*axc[1] + c->b[2]*axc[2]; 00262 c_dot_axb = c->c[0]*axb[0] + c->c[1]*axb[1] + c->c[2]*axb[2]; 00263 00264 //represent the distance from pos to ppos as a linear combination of the edge vectors. 00265 00266 A = (ppos[0]-c->pos[0])*bxc[0] + (ppos[1]-c->pos[1])*bxc[1] + (ppos[2]-c->pos[2])*bxc[2]; 00267 A /= a_dot_bxc; 00268 B = (ppos[0]-c->pos[0])*axc[0] + (ppos[1]-c->pos[1])*axc[1] + (ppos[2]-c->pos[2])*axc[2]; 00269 B /= b_dot_axc; 00270 C = (ppos[0]-c->pos[0])*axb[0] + (ppos[1]-c->pos[1])*axb[1] + (ppos[2]-c->pos[2])*axb[2]; 00271 C /= c_dot_axb; 00272 00273 //the coefficients tell whether ppos lies within the cone defined by pos and the adjacent edges 00274 00275 if(A <= 0 && B <= 0 && C <= 0) 00276 { 00277 vec[0] = ppos[0]-c->pos[0]; 00278 vec[1] = ppos[1]-c->pos[1]; 00279 vec[2] = ppos[2]-c->pos[2]; 00280 00281 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00282 00283 return; 00284 } 00285 00286 //check for cone at pos+a 00287 00288 A = (ppos[0]-c->pos[0]-c->a[0])*bxc[0] + (ppos[1]-c->pos[1]-c->a[1])*bxc[1] + (ppos[2]-c->pos[2]-c->a[2])*bxc[2]; 00289 A /= a_dot_bxc; 00290 B = (ppos[0]-c->pos[0]-c->a[0])*axc[0] + (ppos[1]-c->pos[1]-c->a[1])*axc[1] + (ppos[2]-c->pos[2]-c->a[2])*axc[2]; 00291 B /= b_dot_axc; 00292 C = (ppos[0]-c->pos[0]-c->a[0])*axb[0] + (ppos[1]-c->pos[1]-c->a[1])*axb[1] + (ppos[2]-c->pos[2]-c->a[2])*axb[2]; 00293 C /= c_dot_axb; 00294 00295 if(A >= 0 && B <= 0 && C <= 0) 00296 { 00297 vec[0] = ppos[0]-c->pos[0]-c->a[0]; 00298 vec[1] = ppos[1]-c->pos[1]-c->a[1]; 00299 vec[2] = ppos[2]-c->pos[2]-c->a[2]; 00300 00301 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00302 00303 return; 00304 } 00305 00306 //check for cone at pos+b 00307 00308 A = (ppos[0]-c->pos[0]-c->b[0])*bxc[0] + (ppos[1]-c->pos[1]-c->b[1])*bxc[1] + (ppos[2]-c->pos[2]-c->b[2])*bxc[2]; 00309 A /= a_dot_bxc; 00310 B = (ppos[0]-c->pos[0]-c->b[0])*axc[0] + (ppos[1]-c->pos[1]-c->b[1])*axc[1] + (ppos[2]-c->pos[2]-c->b[2])*axc[2]; 00311 B /= b_dot_axc; 00312 C = (ppos[0]-c->pos[0]-c->b[0])*axb[0] + (ppos[1]-c->pos[1]-c->b[1])*axb[1] + (ppos[2]-c->pos[2]-c->b[2])*axb[2]; 00313 C /= c_dot_axb; 00314 00315 if(A <= 0 && B >= 0 && C <= 0) 00316 { 00317 vec[0] = ppos[0]-c->pos[0]-c->b[0]; 00318 vec[1] = ppos[1]-c->pos[1]-c->b[1]; 00319 vec[2] = ppos[2]-c->pos[2]-c->b[2]; 00320 00321 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00322 00323 return; 00324 } 00325 00326 //check for cone at pos+c 00327 00328 A = (ppos[0]-c->pos[0]-c->c[0])*bxc[0] + (ppos[1]-c->pos[1]-c->c[1])*bxc[1] + (ppos[2]-c->pos[2]-c->c[2])*bxc[2]; 00329 A /= a_dot_bxc; 00330 B = (ppos[0]-c->pos[0]-c->c[0])*axc[0] + (ppos[1]-c->pos[1]-c->c[1])*axc[1] + (ppos[2]-c->pos[2]-c->c[2])*axc[2]; 00331 B /= b_dot_axc; 00332 C = (ppos[0]-c->pos[0]-c->c[0])*axb[0] + (ppos[1]-c->pos[1]-c->c[1])*axb[1] + (ppos[2]-c->pos[2]-c->c[2])*axb[2]; 00333 C /= c_dot_axb; 00334 00335 if(A <= 0 && B <= 0 && C >= 0) 00336 { 00337 vec[0] = ppos[0]-c->pos[0]-c->c[0]; 00338 vec[1] = ppos[1]-c->pos[1]-c->c[1]; 00339 vec[2] = ppos[2]-c->pos[2]-c->c[2]; 00340 00341 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00342 00343 return; 00344 } 00345 00346 //check for cone at pos+a+b 00347 00348 A = (ppos[0]-c->pos[0]-c->a[0]-c->b[0])*bxc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1])*bxc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2])*bxc[2]; 00349 A /= a_dot_bxc; 00350 B = (ppos[0]-c->pos[0]-c->a[0]-c->b[0])*axc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1])*axc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2])*axc[2]; 00351 B /= b_dot_axc; 00352 C = (ppos[0]-c->pos[0]-c->a[0]-c->b[0])*axb[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1])*axb[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2])*axb[2]; 00353 C /= c_dot_axb; 00354 00355 if(A >= 0 && B >= 0 && C <= 0) 00356 { 00357 vec[0] = ppos[0]-c->pos[0]-c->a[0]-c->b[0]; 00358 vec[1] = ppos[1]-c->pos[1]-c->a[1]-c->b[1]; 00359 vec[2] = ppos[2]-c->pos[2]-c->a[2]-c->b[2]; 00360 00361 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00362 00363 return; 00364 } 00365 00366 //check for cone at pos+a+c 00367 00368 A = (ppos[0]-c->pos[0]-c->a[0]-c->c[0])*bxc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->c[1])*bxc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->c[2])*bxc[2]; 00369 A /= a_dot_bxc; 00370 B = (ppos[0]-c->pos[0]-c->a[0]-c->c[0])*axc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->c[1])*axc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->c[2])*axc[2]; 00371 B /= b_dot_axc; 00372 C = (ppos[0]-c->pos[0]-c->a[0]-c->c[0])*axb[0] + (ppos[1]-c->pos[1]-c->a[1]-c->c[1])*axb[1] + (ppos[2]-c->pos[2]-c->a[2]-c->c[2])*axb[2]; 00373 C /= c_dot_axb; 00374 00375 if(A >= 0 && B <= 0 && C >= 0) 00376 { 00377 vec[0] = ppos[0]-c->pos[0]-c->a[0]-c->c[0]; 00378 vec[1] = ppos[1]-c->pos[1]-c->a[1]-c->c[1]; 00379 vec[2] = ppos[2]-c->pos[2]-c->a[2]-c->c[2]; 00380 00381 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00382 00383 return; 00384 } 00385 00386 //check for cone at pos+a+c 00387 00388 A = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*bxc[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*bxc[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*bxc[2]; 00389 A /= a_dot_bxc; 00390 B = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*axc[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*axc[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*axc[2]; 00391 B /= b_dot_axc; 00392 C = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*axb[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*axb[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*axb[2]; 00393 C /= c_dot_axb; 00394 00395 if(A <= 0 && B >= 0 && C >= 0) 00396 { 00397 vec[0] = ppos[0]-c->pos[0]-c->b[0]-c->c[0]; 00398 vec[1] = ppos[1]-c->pos[1]-c->b[1]-c->c[1]; 00399 vec[2] = ppos[2]-c->pos[2]-c->b[2]-c->c[2]; 00400 00401 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00402 00403 return; 00404 } 00405 00406 //check for cone at pos+a+b+c 00407 00408 A = (ppos[0]-c->pos[0]-c->a[0]-c->b[0]-c->c[0])*bxc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1]-c->c[1])*bxc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2]-c->c[2])*bxc[2]; 00409 A /= a_dot_bxc; 00410 B = (ppos[0]-c->pos[0]-c->a[0]-c->b[0]-c->c[0])*axc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1]-c->c[1])*axc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2]-c->c[2])*axc[2]; 00411 B /= b_dot_axc; 00412 C = (ppos[0]-c->pos[0]-c->a[0]-c->b[0]-c->c[0])*axb[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1]-c->c[1])*axb[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2]-c->c[2])*axb[2]; 00413 C /= c_dot_axb; 00414 00415 if(A >= 0 && B >= 0 && C >= 0) 00416 { 00417 vec[0] = ppos[0]-c->pos[0]-c->a[0]-c->b[0]-c->c[0]; 00418 vec[1] = ppos[1]-c->pos[1]-c->a[1]-c->b[1]-c->c[1]; 00419 vec[2] = ppos[2]-c->pos[2]-c->a[2]-c->b[2]-c->c[2]; 00420 00421 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00422 00423 return; 00424 } 00425 00426 //check for prism at edge pos, a 00427 00428 B = (ppos[0]-c->pos[0])*axc[0] + (ppos[1]-c->pos[1])*axc[1] + (ppos[2]-c->pos[2])*axc[2]; 00429 B /= b_dot_axc; 00430 C = (ppos[0]-c->pos[0])*axb[0] + (ppos[1]-c->pos[1])*axb[1] + (ppos[2]-c->pos[2])*axb[2]; 00431 C /= c_dot_axb; 00432 00433 if(B <= 0 && C <= 0) 00434 { 00435 tmp = (ppos[0]-c->pos[0])*c->a[0] + (ppos[1]-c->pos[1])*c->a[1] + (ppos[2]-c->pos[2])*c->a[2]; 00436 tmp /= c->a[0]*c->a[0] + c->a[1]*c->a[1] + c->a[2]*c->a[2]; 00437 00438 vec[0] = ppos[0]-c->pos[0] - c->a[0]*tmp; 00439 vec[1] = ppos[1]-c->pos[1] - c->a[1]*tmp; 00440 vec[2] = ppos[2]-c->pos[2] - c->a[2]*tmp; 00441 00442 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00443 00444 return; 00445 } 00446 00447 //check for prism at edge pos, b 00448 00449 A = (ppos[0]-c->pos[0])*bxc[0] + (ppos[1]-c->pos[1])*bxc[1] + (ppos[2]-c->pos[2])*bxc[2]; 00450 A /= a_dot_bxc; 00451 C = (ppos[0]-c->pos[0])*axb[0] + (ppos[1]-c->pos[1])*axb[1] + (ppos[2]-c->pos[2])*axb[2]; 00452 C /= c_dot_axb; 00453 00454 if(A <= 0 && C <= 0) 00455 { 00456 tmp = (ppos[0]-c->pos[0])*c->b[0] + (ppos[1]-c->pos[1])*c->b[1] + (ppos[2]-c->pos[2])*c->b[2]; 00457 tmp /= c->b[0]*c->b[0] + c->b[1]*c->b[1] + c->b[2]*c->b[2]; 00458 00459 vec[0] = ppos[0]-c->pos[0] - c->b[0]*tmp; 00460 vec[1] = ppos[1]-c->pos[1] - c->b[1]*tmp; 00461 vec[2] = ppos[2]-c->pos[2] - c->b[2]*tmp; 00462 00463 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00464 00465 return; 00466 } 00467 00468 //check for prism at edge pos, c 00469 00470 A = (ppos[0]-c->pos[0])*bxc[0] + (ppos[1]-c->pos[1])*bxc[1] + (ppos[2]-c->pos[2])*bxc[2]; 00471 A /= a_dot_bxc; 00472 B = (ppos[0]-c->pos[0])*axc[0] + (ppos[1]-c->pos[1])*axc[1] + (ppos[2]-c->pos[2])*axc[2]; 00473 B /= b_dot_axc; 00474 00475 if(A <= 0 && B <= 0) 00476 { 00477 tmp = (ppos[0]-c->pos[0])*c->c[0] + (ppos[1]-c->pos[1])*c->c[1] + (ppos[2]-c->pos[2])*c->c[2]; 00478 tmp /= c->c[0]*c->c[0] + c->c[1]*c->c[1] + c->c[2]*c->c[2]; 00479 00480 vec[0] = ppos[0]-c->pos[0] - c->c[0]*tmp; 00481 vec[1] = ppos[1]-c->pos[1] - c->c[1]*tmp; 00482 vec[2] = ppos[2]-c->pos[2] - c->c[2]*tmp; 00483 00484 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00485 00486 return; 00487 } 00488 00489 //check for prism at edge pos+a, b 00490 00491 A = (ppos[0]-c->pos[0]-c->a[0])*bxc[0] + (ppos[1]-c->pos[1]-c->a[1])*bxc[1] + (ppos[2]-c->pos[2]-c->a[2])*bxc[2]; 00492 A /= a_dot_bxc; 00493 C = (ppos[0]-c->pos[0]-c->a[0])*axb[0] + (ppos[1]-c->pos[1]-c->a[1])*axb[1] + (ppos[2]-c->pos[2]-c->a[2])*axb[2]; 00494 C /= c_dot_axb; 00495 00496 if(A >= 0 && C <= 0) 00497 { 00498 tmp = (ppos[0]-c->pos[0]-c->a[0])*c->b[0] + (ppos[1]-c->pos[1]-c->a[1])*c->b[1] + (ppos[2]-c->pos[2]-c->a[2])*c->b[2]; 00499 tmp /= c->b[0]*c->b[0] + c->b[1]*c->b[1] + c->b[2]*c->b[2]; 00500 00501 vec[0] = ppos[0]-c->pos[0]-c->a[0] - c->b[0]*tmp; 00502 vec[1] = ppos[1]-c->pos[1]-c->a[1] - c->b[1]*tmp; 00503 vec[2] = ppos[2]-c->pos[2]-c->a[2] - c->b[2]*tmp; 00504 00505 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00506 00507 return; 00508 } 00509 00510 //check for prism at edge pos+a, c 00511 00512 A = (ppos[0]-c->pos[0]-c->a[0])*bxc[0] + (ppos[1]-c->pos[1]-c->a[1])*bxc[1] + (ppos[2]-c->pos[2]-c->a[2])*bxc[2]; 00513 A /= a_dot_bxc; 00514 B = (ppos[0]-c->pos[0]-c->a[0])*axc[0] + (ppos[1]-c->pos[1]-c->a[1])*axc[1] + (ppos[2]-c->pos[2]-c->a[2])*axc[2]; 00515 B /= b_dot_axc; 00516 00517 if(A >= 0 && B <= 0) 00518 { 00519 tmp = (ppos[0]-c->pos[0]-c->a[0])*c->c[0] + (ppos[1]-c->pos[1]-c->a[1])*c->c[1] + (ppos[2]-c->pos[2]-c->a[2])*c->c[2]; 00520 tmp /= c->c[0]*c->c[0] + c->c[1]*c->c[1] + c->c[2]*c->c[2]; 00521 00522 vec[0] = ppos[0]-c->pos[0]-c->a[0] - c->c[0]*tmp; 00523 vec[1] = ppos[1]-c->pos[1]-c->a[1] - c->c[1]*tmp; 00524 vec[2] = ppos[2]-c->pos[2]-c->a[2] - c->c[2]*tmp; 00525 00526 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00527 00528 return; 00529 } 00530 00531 //check for prism at edge pos+b+c, c 00532 00533 A = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*bxc[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*bxc[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*bxc[2]; 00534 A /= a_dot_bxc; 00535 B = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*axc[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*axc[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*axc[2]; 00536 B /= b_dot_axc; 00537 00538 if(A <= 0 && B >= 0) 00539 { 00540 tmp = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*c->c[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*c->c[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*c->c[2]; 00541 tmp /= c->c[0]*c->c[0] + c->c[1]*c->c[1] + c->c[2]*c->c[2]; 00542 00543 vec[0] = ppos[0]-c->pos[0]-c->b[0]-c->c[0] - c->c[0]*tmp; 00544 vec[1] = ppos[1]-c->pos[1]-c->b[1]-c->c[1] - c->c[1]*tmp; 00545 vec[2] = ppos[2]-c->pos[2]-c->b[2]-c->c[2] - c->c[2]*tmp; 00546 00547 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00548 00549 return; 00550 } 00551 00552 //check for prism at edge pos+b+c, b 00553 00554 A = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*bxc[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*bxc[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*bxc[2]; 00555 A /= a_dot_bxc; 00556 C = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*axb[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*axb[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*axb[2]; 00557 C /= c_dot_axb; 00558 00559 if(A <= 0 && C >= 0) 00560 { 00561 tmp = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*c->b[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*c->b[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*c->b[2]; 00562 tmp /= c->b[0]*c->b[0] + c->b[1]*c->b[1] + c->b[2]*c->b[2]; 00563 00564 vec[0] = ppos[0]-c->pos[0]-c->b[0]-c->c[0] - c->b[0]*tmp; 00565 vec[1] = ppos[1]-c->pos[1]-c->b[1]-c->c[1] - c->b[1]*tmp; 00566 vec[2] = ppos[2]-c->pos[2]-c->b[2]-c->c[2] - c->b[2]*tmp; 00567 00568 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00569 00570 return; 00571 } 00572 00573 //check for prism at edge pos+b+c, a 00574 00575 B = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*axc[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*axc[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*axc[2]; 00576 B /= b_dot_axc; 00577 C = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*axb[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*axb[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*axb[2]; 00578 C /= c_dot_axb; 00579 00580 if(B >= 0 && C >= 0) 00581 { 00582 tmp = (ppos[0]-c->pos[0]-c->b[0]-c->c[0])*c->a[0] + (ppos[1]-c->pos[1]-c->b[1]-c->c[1])*c->a[1] + (ppos[2]-c->pos[2]-c->b[2]-c->c[2])*c->a[2]; 00583 tmp /= c->a[0]*c->a[0] + c->a[1]*c->a[1] + c->a[2]*c->a[2]; 00584 00585 vec[0] = ppos[0]-c->pos[0]-c->b[0]-c->c[0] - c->a[0]*tmp; 00586 vec[1] = ppos[1]-c->pos[1]-c->b[1]-c->c[1] - c->a[1]*tmp; 00587 vec[2] = ppos[2]-c->pos[2]-c->b[2]-c->c[2] - c->a[2]*tmp; 00588 00589 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00590 00591 return; 00592 } 00593 00594 //check for prism at edge pos+a+b, a 00595 00596 B = (ppos[0]-c->pos[0]-c->a[0]-c->b[0])*axc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1])*axc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2])*axc[2]; 00597 B /= b_dot_axc; 00598 C = (ppos[0]-c->pos[0]-c->a[0]-c->b[0])*axb[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1])*axb[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2])*axb[2]; 00599 C /= c_dot_axb; 00600 00601 if(B >= 0 && C <= 0) 00602 { 00603 tmp = (ppos[0]-c->pos[0]-c->a[0]-c->b[0])*c->a[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1])*c->a[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2])*c->a[2]; 00604 tmp /= c->a[0]*c->a[0] + c->a[1]*c->a[1] + c->a[2]*c->a[2]; 00605 00606 vec[0] = ppos[0]-c->pos[0]-c->a[0]-c->b[0] - c->a[0]*tmp; 00607 vec[1] = ppos[1]-c->pos[1]-c->a[1]-c->b[1] - c->a[1]*tmp; 00608 vec[2] = ppos[2]-c->pos[2]-c->a[2]-c->b[2] - c->a[2]*tmp; 00609 00610 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00611 00612 return; 00613 } 00614 00615 //check for prism at edge pos+a+b, c 00616 00617 A = (ppos[0]-c->pos[0]-c->a[0]-c->b[0])*bxc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1])*bxc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2])*bxc[2]; 00618 A /= a_dot_bxc; 00619 B = (ppos[0]-c->pos[0]-c->a[0]-c->b[0])*axc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1])*axc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2])*axc[2]; 00620 B /= b_dot_axc; 00621 00622 if(A >= 0 && B >= 0) 00623 { 00624 tmp = (ppos[0]-c->pos[0]-c->a[0]-c->b[0])*c->c[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1])*c->c[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2])*c->c[2]; 00625 tmp /= c->c[0]*c->c[0] + c->c[1]*c->c[1] + c->c[2]*c->c[2]; 00626 00627 vec[0] = ppos[0]-c->pos[0]-c->a[0]-c->b[0] - c->c[0]*tmp; 00628 vec[1] = ppos[1]-c->pos[1]-c->a[1]-c->b[1] - c->c[1]*tmp; 00629 vec[2] = ppos[2]-c->pos[2]-c->a[2]-c->b[2] - c->c[2]*tmp; 00630 00631 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00632 00633 return; 00634 } 00635 00636 //check for prism at edge pos+a+c, a 00637 00638 B = (ppos[0]-c->pos[0]-c->a[0]-c->c[0])*axc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->c[1])*axc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->c[2])*axc[2]; 00639 B /= b_dot_axc; 00640 C = (ppos[0]-c->pos[0]-c->a[0]-c->c[0])*axb[0] + (ppos[1]-c->pos[1]-c->a[1]-c->c[1])*axb[1] + (ppos[2]-c->pos[2]-c->a[2]-c->c[2])*axb[2]; 00641 C /= c_dot_axb; 00642 00643 if(B <= 0 && C >= 0) 00644 { 00645 tmp = (ppos[0]-c->pos[0]-c->a[0]-c->c[0])*c->a[0] + (ppos[1]-c->pos[1]-c->a[1]-c->c[1])*c->a[1] + (ppos[2]-c->pos[2]-c->a[2]-c->c[2])*c->a[2]; 00646 tmp /= c->a[0]*c->a[0] + c->a[1]*c->a[1] + c->a[2]*c->a[2]; 00647 00648 vec[0] = ppos[0]-c->pos[0]-c->a[0]-c->c[0] - c->a[0]*tmp; 00649 vec[1] = ppos[1]-c->pos[1]-c->a[1]-c->c[1] - c->a[1]*tmp; 00650 vec[2] = ppos[2]-c->pos[2]-c->a[2]-c->c[2] - c->a[2]*tmp; 00651 00652 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00653 00654 return; 00655 } 00656 00657 //check for prism at edge pos+a+c, b 00658 00659 A = (ppos[0]-c->pos[0]-c->a[0]-c->c[0])*bxc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->c[1])*bxc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->c[2])*bxc[2]; 00660 A /= a_dot_bxc; 00661 C = (ppos[0]-c->pos[0]-c->a[0]-c->c[0])*axb[0] + (ppos[1]-c->pos[1]-c->a[1]-c->c[1])*axb[1] + (ppos[2]-c->pos[2]-c->a[2]-c->c[2])*axb[2]; 00662 C /= c_dot_axb; 00663 00664 if(A >= 0 && C >= 0) 00665 { 00666 tmp = (ppos[0]-c->pos[0]-c->a[0]-c->c[0])*c->b[0] + (ppos[1]-c->pos[1]-c->a[1]-c->c[1])*c->b[1] + (ppos[2]-c->pos[2]-c->a[2]-c->c[2])*c->b[2]; 00667 tmp /= c->b[0]*c->b[0] + c->b[1]*c->b[1] + c->b[2]*c->b[2]; 00668 00669 vec[0] = ppos[0]-c->pos[0]-c->a[0]-c->c[0] - c->b[0]*tmp; 00670 vec[1] = ppos[1]-c->pos[1]-c->a[1]-c->c[1] - c->b[1]*tmp; 00671 vec[2] = ppos[2]-c->pos[2]-c->a[2]-c->c[2] - c->b[2]*tmp; 00672 00673 *dist = c->direction * sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2]); 00674 00675 return; 00676 } 00677 00678 //check for face with normal -axb 00679 00680 *dist = (ppos[0]-c->pos[0])*axb[0] + (ppos[1]-c->pos[1])*axb[1] + (ppos[2]-c->pos[2])*axb[2]; 00681 *dist *= -1.; 00682 00683 if(*dist >= 0) 00684 { 00685 tmp = sqrt( axb[0]*axb[0] + axb[1]*axb[1] + axb[2]*axb[2] ); 00686 *dist /= tmp; 00687 00688 vec[0] = -*dist * axb[0]/tmp; 00689 vec[1] = -*dist * axb[1]/tmp; 00690 vec[2] = -*dist * axb[2]/tmp; 00691 00692 *dist *= c->direction; 00693 00694 return; 00695 } 00696 00697 //calculate distance to face with normal axc 00698 00699 *dist = (ppos[0]-c->pos[0])*axc[0] + (ppos[1]-c->pos[1])*axc[1] + (ppos[2]-c->pos[2])*axc[2]; 00700 00701 if(*dist >= 0) 00702 { 00703 tmp = sqrt( axc[0]*axc[0] + axc[1]*axc[1] + axc[2]*axc[2] ); 00704 *dist /= tmp; 00705 00706 vec[0] = *dist * axc[0]/tmp; 00707 vec[1] = *dist * axc[1]/tmp; 00708 vec[2] = *dist * axc[2]/tmp; 00709 00710 *dist *= c->direction; 00711 00712 return; 00713 } 00714 00715 //calculate distance to face with normal -bxc 00716 00717 *dist = (ppos[0]-c->pos[0])*bxc[0] + (ppos[1]-c->pos[1])*bxc[1] + (ppos[2]-c->pos[2])*bxc[2]; 00718 *dist *= -1.; 00719 00720 if(*dist >= 0) 00721 { 00722 tmp = sqrt( bxc[0]*bxc[0] + bxc[1]*bxc[1] + bxc[2]*bxc[2] ); 00723 *dist /= tmp; 00724 00725 vec[0] = -*dist * bxc[0]/tmp; 00726 vec[1] = -*dist * bxc[1]/tmp; 00727 vec[2] = -*dist * bxc[2]/tmp; 00728 00729 *dist *= c->direction; 00730 00731 return; 00732 } 00733 00734 //calculate distance to face with normal axb 00735 00736 *dist = (ppos[0]-c->pos[0]-c->a[0]-c->b[0]-c->c[0])*axb[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1]-c->c[1])*axb[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2]-c->c[2])*axb[2]; 00737 00738 if(*dist >= 0) 00739 { 00740 tmp = sqrt( axb[0]*axb[0] + axb[1]*axb[1] + axb[2]*axb[2] ); 00741 *dist /= tmp; 00742 00743 vec[0] = *dist * axb[0]/tmp; 00744 vec[1] = *dist * axb[1]/tmp; 00745 vec[2] = *dist * axb[2]/tmp; 00746 00747 *dist *= c->direction; 00748 00749 return; 00750 } 00751 00752 //calculate distance to face with normal -axc 00753 00754 *dist = (ppos[0]-c->pos[0]-c->a[0]-c->b[0]-c->c[0])*axc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1]-c->c[1])*axc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2]-c->c[2])*axc[2]; 00755 *dist *= -1.; 00756 00757 if(*dist >= 0) 00758 { 00759 tmp = sqrt( axc[0]*axc[0] + axc[1]*axc[1] + axc[2]*axc[2] ); 00760 *dist /= tmp; 00761 00762 vec[0] = -*dist * axc[0]/tmp; 00763 vec[1] = -*dist * axc[1]/tmp; 00764 vec[2] = -*dist * axc[2]/tmp; 00765 00766 *dist *= c->direction; 00767 00768 return; 00769 } 00770 00771 //calculate distance to face with normal bxc 00772 00773 *dist = (ppos[0]-c->pos[0]-c->a[0]-c->b[0]-c->c[0])*bxc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1]-c->c[1])*bxc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2]-c->c[2])*bxc[2]; 00774 00775 if(*dist >= 0) 00776 { 00777 tmp = sqrt( bxc[0]*bxc[0] + bxc[1]*bxc[1] + bxc[2]*bxc[2] ); 00778 *dist /= tmp; 00779 00780 vec[0] = *dist * bxc[0]/tmp; 00781 vec[1] = *dist * bxc[1]/tmp; 00782 vec[2] = *dist * bxc[2]/tmp; 00783 00784 *dist *= c->direction; 00785 00786 return; 00787 } 00788 00789 //ppos lies within rhomboid. Find nearest wall for interaction. 00790 00791 //check for face with normal -axb 00792 00793 *dist = (ppos[0]-c->pos[0])*axb[0] + (ppos[1]-c->pos[1])*axb[1] + (ppos[2]-c->pos[2])*axb[2]; 00794 *dist *= -1.; 00795 tmp = sqrt( axb[0]*axb[0] + axb[1]*axb[1] + axb[2]*axb[2] ); 00796 *dist /= tmp; 00797 00798 vec[0] = -*dist * axb[0]/tmp; 00799 vec[1] = -*dist * axb[1]/tmp; 00800 vec[2] = -*dist * axb[2]/tmp; 00801 00802 *dist *= c->direction; 00803 00804 //calculate distance to face with normal axc 00805 00806 d = (ppos[0]-c->pos[0])*axc[0] + (ppos[1]-c->pos[1])*axc[1] + (ppos[2]-c->pos[2])*axc[2]; 00807 tmp = sqrt( axc[0]*axc[0] + axc[1]*axc[1] + axc[2]*axc[2] ); 00808 d /= tmp; 00809 00810 if(abs(d) < abs(*dist)) 00811 { 00812 vec[0] = d * axc[0]/tmp; 00813 vec[1] = d * axc[1]/tmp; 00814 vec[2] = d * axc[2]/tmp; 00815 00816 *dist = c->direction * d; 00817 } 00818 00819 //calculate distance to face with normal -bxc 00820 00821 d = (ppos[0]-c->pos[0])*bxc[0] + (ppos[1]-c->pos[1])*bxc[1] + (ppos[2]-c->pos[2])*bxc[2]; 00822 d *= -1.; 00823 tmp = sqrt( bxc[0]*bxc[0] + bxc[1]*bxc[1] + bxc[2]*bxc[2] ); 00824 d /= tmp; 00825 00826 if(abs(d) < abs(*dist)) 00827 { 00828 vec[0] = -d * bxc[0]/tmp; 00829 vec[1] = -d * bxc[1]/tmp; 00830 vec[2] = -d * bxc[2]/tmp; 00831 00832 *dist = c->direction * d; 00833 } 00834 00835 //calculate distance to face with normal axb 00836 00837 d = (ppos[0]-c->pos[0]-c->a[0]-c->b[0]-c->c[0])*axb[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1]-c->c[1])*axb[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2]-c->c[2])*axb[2]; 00838 tmp = sqrt( axb[0]*axb[0] + axb[1]*axb[1] + axb[2]*axb[2] ); 00839 d /= tmp; 00840 00841 if(abs(d) < abs(*dist)) 00842 { 00843 vec[0] = d * axb[0]/tmp; 00844 vec[1] = d * axb[1]/tmp; 00845 vec[2] = d * axb[2]/tmp; 00846 00847 *dist = c->direction * d; 00848 } 00849 00850 //calculate distance to face with normal -axc 00851 00852 d = (ppos[0]-c->pos[0]-c->a[0]-c->b[0]-c->c[0])*axc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1]-c->c[1])*axc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2]-c->c[2])*axc[2]; 00853 d *= -1.; 00854 tmp = sqrt( axc[0]*axc[0] + axc[1]*axc[1] + axc[2]*axc[2] ); 00855 d /= tmp; 00856 00857 if(abs(d) < abs(*dist)) 00858 { 00859 vec[0] = -d * axc[0]/tmp; 00860 vec[1] = -d * axc[1]/tmp; 00861 vec[2] = -d * axc[2]/tmp; 00862 00863 *dist = c->direction * d; 00864 } 00865 00866 //calculate distance to face with normal bxc 00867 00868 d = (ppos[0]-c->pos[0]-c->a[0]-c->b[0]-c->c[0])*bxc[0] + (ppos[1]-c->pos[1]-c->a[1]-c->b[1]-c->c[1])*bxc[1] + (ppos[2]-c->pos[2]-c->a[2]-c->b[2]-c->c[2])*bxc[2]; 00869 tmp = sqrt( bxc[0]*bxc[0] + bxc[1]*bxc[1] + bxc[2]*bxc[2] ); 00870 d /= tmp; 00871 00872 if(abs(d) < abs(*dist)) 00873 { 00874 vec[0] = d * bxc[0]/tmp; 00875 vec[1] = d * bxc[1]/tmp; 00876 vec[2] = d * bxc[2]/tmp; 00877 00878 *dist = c->direction * d; 00879 } 00880 } 00881 00882 void calculate_pore_dist(Particle *p1, double ppos[3], Particle *c_p, Constraint_pore *c, double *dist, double *vec) 00883 { 00884 int i; 00885 double c_dist[3]; /* cartesian distance from pore center */ 00886 double z , r; /* cylindrical coordinates, coordinate system parallel to 00887 pore, origin at pore centera */ 00888 double z_vec[3], r_vec[3]; /* cartesian vectors that correspond to these coordinates */ 00889 double e_z[3], e_r[3]; /* unit vectors in the cylindrical coordinate system */ 00890 /* helper variables, for performance reasons should the be move the the 00891 * constraint struct*/ 00892 double slope, z_left, z_right; 00893 /* and another helper that is hopefully optmized out */ 00894 double norm; 00895 double c1_r, c1_z, c2_r, c2_z; 00896 double cone_vector_r, cone_vector_z, p1_r, p1_z, dist_vector_z, dist_vector_r, temp; 00897 00898 00899 slope = (c->rad_right - c->rad_left)/2./(c->length-c->smoothing_radius); 00900 00901 /* compute the position relative to the center of the pore */ 00902 for(i=0;i<3;i++) { 00903 c_dist[i] = ppos[i] - c->pos[i]; 00904 } 00905 00906 /* compute the component parallel to the pore axis */ 00907 z =0.; 00908 for(i=0;i<3;i++) { 00909 z += (c_dist[i] * c->axis[i]); 00910 } 00911 00912 /* decompose the position into parallel and perpendicular to the axis */ 00913 r = 0.; 00914 for(i=0;i<3;i++) { 00915 z_vec[i] = z * c->axis[i]; 00916 r_vec[i] = c_dist[i] - z_vec[i]; 00917 r += r_vec[i]*r_vec[i]; 00918 } 00919 r = sqrt(r); 00920 00921 00922 /* calculate norm and unit vectors for both */ 00923 norm = 0; 00924 for(i=0;i<3;i++) 00925 norm += z_vec[i]*z_vec[i]; 00926 norm = sqrt(norm); 00927 for(i=0;i<3;i++) 00928 e_z[i] = c->axis[i]; 00929 norm = 0; 00930 for(i=0;i<3;i++) 00931 norm += r_vec[i]*r_vec[i]; 00932 norm = sqrt(norm); 00933 for(i=0;i<3;i++) 00934 e_r[i] = r_vec[i]/norm; 00935 00936 /* c?_r/z and are the centers of the circles that are used to smooth 00937 * the entrance of the pore in cylindrical coordinates*/ 00938 c1_z = - (c->length - c->smoothing_radius); 00939 c2_z = + (c->length - c->smoothing_radius); 00940 z_left = c1_z - sign(slope) * sqrt(slope*slope/(1+slope*slope))*c->smoothing_radius; 00941 z_right = c2_z + sign(slope) * sqrt(slope*slope/(1+slope*slope))*c->smoothing_radius; 00942 00943 c1_r = c->rad_left + slope * ( z_left + c->length ) + 00944 sqrt( c->smoothing_radius * c->smoothing_radius - SQR( z_left - c1_z ) ); 00945 c2_r = c->rad_left + slope * ( z_right + c->length ) + 00946 sqrt( c->smoothing_radius * c->smoothing_radius - SQR( z_right - c2_z ) ); 00947 c1_r = c->rad_left+c->smoothing_radius; 00948 c2_r = c->rad_right+c->smoothing_radius; 00949 00950 /* Check if we are in the region of the left wall */ 00951 if (( (r >= c1_r) && (z <= c1_z) ) || ( ( z <= 0 ) && (r>=max(c1_r, c2_r)))) { 00952 dist_vector_z=-z - c->length; 00953 dist_vector_r=0; 00954 *dist = -z - c->length; 00955 for (i=0; i<3; i++) vec[i]=-dist_vector_r*e_r[i] - dist_vector_z*e_z[i]; 00956 return; 00957 } 00958 /* Check if we are in the region of the right wall */ 00959 if (( (r >= c2_r) && (z <= c2_z) ) || ( ( z >= 0 ) && (r>=max(c1_r, c2_r)))) { 00960 dist_vector_z=-z + c->length; 00961 dist_vector_r=0; 00962 *dist = +z - c->length; 00963 for (i=0; i<3; i++) vec[i]=-dist_vector_r*e_r[i] - dist_vector_z*e_z[i]; 00964 return; 00965 } 00966 00967 /* check if the particle should feel the smoothed ends or the middle of the pore */ 00968 /* calculate aufpunkt in z direction first. */ 00969 00970 /* the distance of the particle from the pore cylinder/cone calculated by projection on the 00971 * cone normal. Should be > 0 if particle is inside the pore */ 00972 00973 cone_vector_z=1/sqrt(1+slope*slope); 00974 cone_vector_r=slope/sqrt(1+slope*slope); 00975 00976 p1_r = c1_r+ ( (r-c1_r)*cone_vector_r + (z-c1_z)*cone_vector_z) * cone_vector_r; 00977 p1_z = c1_z+ ( (r-c1_r)*cone_vector_r + (z-c1_z)*cone_vector_z) * cone_vector_z; 00978 00979 dist_vector_r = p1_r-r; 00980 dist_vector_z = p1_z-z; 00981 00982 if ( p1_z>=c1_z && p1_z<=c2_z ) { 00983 if ( dist_vector_r <= 0 ) { 00984 if (z<0) { 00985 dist_vector_z=-z - c->length; 00986 dist_vector_r=0; 00987 *dist = -z - c->length; 00988 for (i=0; i<3; i++) vec[i]=-dist_vector_r*e_r[i] - dist_vector_z*e_z[i]; 00989 return; 00990 } else { 00991 dist_vector_z=-z + c->length; 00992 dist_vector_r=0; 00993 *dist = +z - c->length; 00994 for (i=0; i<3; i++) vec[i]=-dist_vector_r*e_r[i] - dist_vector_z*e_z[i]; 00995 return; 00996 } 00997 } 00998 temp=sqrt( dist_vector_r*dist_vector_r + dist_vector_z*dist_vector_z ); 00999 *dist=temp-c->smoothing_radius; 01000 dist_vector_r-=dist_vector_r/temp*c->smoothing_radius; 01001 dist_vector_z-=dist_vector_z/temp*c->smoothing_radius; 01002 for (i=0; i<3; i++) vec[i]=-dist_vector_r*e_r[i] - dist_vector_z*e_z[i]; 01003 return; 01004 } 01005 01006 01007 /* Check if we are in the range of the left smoothing circle */ 01008 if (p1_z <= c1_z ) { 01009 /* distance from the smoothing center */ 01010 norm = sqrt( (z - c1_z)*(z - c1_z) + (r - c1_r)*(r - c1_r) ); 01011 *dist = norm - c->smoothing_radius; 01012 dist_vector_r=(c->smoothing_radius/norm -1)*(r - c1_r); 01013 dist_vector_z=(c->smoothing_radius/norm - 1)*(z - c1_z); 01014 for (i=0; i<3; i++) vec[i]=-dist_vector_r*e_r[i] - dist_vector_z*e_z[i]; 01015 return; 01016 } 01017 /* Check if we are in the range of the right smoothing circle */ 01018 if (p1_z >= c2_z ) { 01019 norm = sqrt( (z - c2_z)*(z - c2_z) + (r - c2_r)*(r - c2_r) ); 01020 *dist = norm - c->smoothing_radius; 01021 dist_vector_r=(c->smoothing_radius/norm -1)*(r - c2_r); 01022 dist_vector_z=(c->smoothing_radius/norm - 1)*(z - c2_z); 01023 for (i=0; i<3; i++) vec[i]=-dist_vector_r*e_r[i] - dist_vector_z*e_z[i]; 01024 return; 01025 } 01026 exit(printf("should never be reached, z %f, r%f\n",z, r)); 01027 } 01028 01029 void calculate_plane_dist(Particle *p1, double ppos[3], Particle *c_p, Constraint_plane *c, double *dist, double *vec) 01030 { 01031 int i; 01032 double c_dist_sqr,c_dist; 01033 01034 c_dist_sqr=0.0; 01035 for(i=0;i<3;i++) { 01036 if(c->pos[i] >= 0) { 01037 vec[i] = c->pos[i] - ppos[i]; 01038 c_dist_sqr += SQR(vec[i]); 01039 }else{ 01040 vec[i] = 0.0; 01041 c_dist_sqr += SQR(vec[i]); 01042 } 01043 } 01044 c_dist = sqrt(c_dist_sqr); 01045 *dist = c_dist; 01046 01047 01048 for(i=0;i<3;i++) { 01049 vec[i] *= -1; 01050 } 01051 } 01052 01053 void add_rod_force(Particle *p1, double ppos[3], Particle *c_p, Constraint_rod *c) 01054 { 01055 #ifdef ELECTROSTATICS 01056 int i; 01057 double fac, vec[2], c_dist_2; 01058 01059 c_dist_2 = 0.0; 01060 for(i=0;i<2;i++) { 01061 vec[i] = ppos[i] - c->pos[i]; 01062 c_dist_2 += SQR(vec[i]); 01063 } 01064 01065 if (coulomb.prefactor != 0.0 && p1->p.q != 0.0 && c->lambda != 0.0) { 01066 fac = 2*coulomb.prefactor*c->lambda*p1->p.q/c_dist_2; 01067 p1->f.f[0] += fac*vec[0]; 01068 p1->f.f[1] += fac*vec[1]; 01069 c_p->f.f[0] -= fac*vec[0]; 01070 c_p->f.f[1] -= fac*vec[1]; 01071 } 01072 #endif 01073 } 01074 01075 double rod_energy(Particle *p1, double ppos[3], Particle *c_p, Constraint_rod *c) 01076 { 01077 #ifdef ELECTROSTATICS 01078 int i; 01079 double vec[2], c_dist_2; 01080 01081 c_dist_2 = 0.0; 01082 for(i=0;i<2;i++) { 01083 vec[i] = ppos[i] - c->pos[i]; 01084 c_dist_2 += SQR(vec[i]); 01085 } 01086 01087 if (coulomb.prefactor != 0.0 && p1->p.q != 0.0 && c->lambda != 0.0) 01088 return coulomb.prefactor*p1->p.q*c->lambda*(-log(c_dist_2*SQR(box_l_i[2])) + 2*(M_LN2 - C_GAMMA)); 01089 #endif 01090 return 0; 01091 } 01092 01093 void add_plate_force(Particle *p1, double ppos[3], Particle *c_p, Constraint_plate *c) 01094 { 01095 #ifdef ELECTROSTATICS 01096 double f; 01097 01098 if (coulomb.prefactor != 0.0 && p1->p.q != 0.0 && c->sigma != 0.0) { 01099 f = 2*M_PI*coulomb.prefactor*c->sigma*p1->p.q; 01100 if (ppos[2] < c->pos) 01101 f = -f; 01102 p1->f.f[2] += f; 01103 c_p->f.f[2] -= f; 01104 } 01105 #endif 01106 } 01107 01108 double plate_energy(Particle *p1, double ppos[3], Particle *c_p, Constraint_plate *c) 01109 { 01110 #ifdef ELECTROSTATICS 01111 if (coulomb.prefactor != 0.0 && p1->p.q != 0.0 && c->sigma != 0.0) 01112 return -2*M_PI*coulomb.prefactor*c->sigma*p1->p.q*fabs(ppos[2] - c->pos); 01113 #endif 01114 return 0; 01115 } 01116 01117 //ER 01118 void add_ext_magn_field_force(Particle *p1, Constraint_ext_magn_field *c) 01119 { 01120 #ifdef ROTATION 01121 #ifdef DIPOLES 01122 p1->f.torque[0] += p1->r.dip[1]*c->ext_magn_field[2]-p1->r.dip[2]*c->ext_magn_field[1]; 01123 p1->f.torque[1] += p1->r.dip[2]*c->ext_magn_field[0]-p1->r.dip[0]*c->ext_magn_field[2]; 01124 p1->f.torque[2] += p1->r.dip[0]*c->ext_magn_field[1]-p1->r.dip[1]*c->ext_magn_field[0]; 01125 #endif 01126 #endif 01127 } 01128 01129 double ext_magn_field_energy(Particle *p1, Constraint_ext_magn_field *c) 01130 { 01131 #ifdef DIPOLES 01132 return -1.0 * scalar(c->ext_magn_field,p1->r.dip); 01133 #endif 01134 return 0; 01135 } 01136 //end ER 01137 01138 void reflect_particle(Particle *p1, double *distance_vec, int reflecting) { 01139 double vec[3]; 01140 double norm; 01141 01142 double folded_pos[3]; 01143 int img[3]; 01144 01145 memcpy(folded_pos, p1->r.p, 3*sizeof(double)); 01146 memcpy(img, p1->l.i, 3*sizeof(int)); 01147 fold_position(folded_pos, img); 01148 01149 memcpy(vec, distance_vec, 3*sizeof(double)); 01150 /* For Debugging your can show the folded coordinates of the particle before 01151 * and after the reflecting by uncommenting these lines */ 01152 // printf("position before reflection %f %f %f\n",folded_pos[0], folded_pos[1], folded_pos[2]); 01153 01154 01155 reflection_happened = 1; 01156 norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]); 01157 p1->r.p[0] = p1->r.p[0]-2*vec[0]; 01158 p1->r.p[1] = p1->r.p[1]-2*vec[1]; 01159 p1->r.p[2] = p1->r.p[2]-2*vec[2]; 01160 01161 /* This can show the folded position after reflection 01162 memcpy(folded_pos, p1->r.p, 3*sizeof(double)); 01163 memcpy(img, p1->l.i, 3*sizeof(int)); 01164 fold_position(folded_pos, img); 01165 printf("position after reflection %f %f %f\n",folded_pos[0], folded_pos[1], folded_pos[2]); */ 01166 01167 /* vec seams to be the vector that points from the wall to the particle*/ 01168 /* now normalize it */ 01169 if ( reflecting==1 ) { 01170 vec[0] /= norm; 01171 vec[1] /= norm; 01172 vec[2] /= norm; 01173 /* calculating scalar product - reusing var norm */ 01174 norm = vec[0] * p1->m.v[0] + vec[1] * p1->m.v[1] + vec[2] * p1->m.v[2]; 01175 /* now add twice the normal component to the velcity */ 01176 p1->m.v[0] = p1->m.v[0]-2*vec[0]*norm; /* norm is still the scalar product! */ 01177 p1->m.v[1] = p1->m.v[1]-2*vec[1]*norm; 01178 p1->m.v[2] = p1->m.v[2]-2*vec[2]*norm; 01179 } else if (reflecting == 2) { 01180 /* if bounce back, invert velocity */ 01181 p1->m.v[0] =-p1->m.v[0]; /* norm is still the scalar product! */ 01182 p1->m.v[1] =-p1->m.v[1]; 01183 p1->m.v[2] =-p1->m.v[2]; 01184 01185 } 01186 01187 } 01188 01189 void add_constraints_forces(Particle *p1) 01190 { 01191 if (n_constraints==0) 01192 return; 01193 int n, j; 01194 double dist, vec[3], force[3], torque1[3], torque2[3]; 01195 01196 IA_parameters *ia_params; 01197 char *errtxt; 01198 double folded_pos[3]; 01199 int img[3]; 01200 01201 /* fold the coordinate[2] of the particle */ 01202 memcpy(folded_pos, p1->r.p, 3*sizeof(double)); 01203 memcpy(img, p1->l.i, 3*sizeof(int)); 01204 fold_position(folded_pos, img); 01205 01206 for(n=0;n<n_constraints;n++) { 01207 ia_params=get_ia_param(p1->p.type, (&constraints[n].part_rep)->p.type); 01208 dist=0.; 01209 for (j = 0; j < 3; j++) { 01210 force[j] = 0; 01211 #ifdef ROTATION 01212 torque1[j] = torque2[j] = 0; 01213 #endif 01214 } 01215 01216 switch(constraints[n].type) { 01217 case CONSTRAINT_WAL: 01218 if(checkIfInteraction(ia_params)) { 01219 calculate_wall_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.wal, &dist, vec); 01220 if ( dist > 0 ) { 01221 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01222 ia_params,vec,dist,dist*dist, force, 01223 torque1, torque2); 01224 } 01225 else if ( dist <= 0 && constraints[n].c.wal.penetrable == 1 ) { 01226 if ( dist < 0 ) { 01227 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01228 ia_params,vec,-1.0*dist,dist*dist, force, 01229 torque1, torque2); 01230 } 01231 } 01232 else { 01233 if(constraints[n].c.wal.reflecting){ 01234 reflect_particle(p1, &(vec[0]), constraints[n].c.wal.reflecting); 01235 } else { 01236 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01237 ERROR_SPRINTF(errtxt, "{061 wall constraint %d violated by particle %d} ", n, p1->p.identity); 01238 } 01239 } 01240 } 01241 break; 01242 01243 case CONSTRAINT_SPH: 01244 if(checkIfInteraction(ia_params)) { 01245 calculate_sphere_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.sph, &dist, vec); 01246 if ( dist > 0 ) { 01247 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01248 ia_params,vec,dist,dist*dist, force, 01249 torque1, torque2); 01250 } 01251 else if ( dist <= 0 && constraints[n].c.sph.penetrable == 1 ) { 01252 if ( dist < 0 ) { 01253 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01254 ia_params,vec,-1.0*dist,dist*dist, force, 01255 torque1, torque2); 01256 } 01257 } 01258 else { 01259 if(constraints[n].c.sph.reflecting){ 01260 reflect_particle(p1, &(vec[0]), constraints[n].c.sph.reflecting); 01261 } else { 01262 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01263 ERROR_SPRINTF(errtxt, "{062 sphere constraint %d violated by particle %d} ", n, p1->p.identity); 01264 } 01265 } 01266 } 01267 break; 01268 01269 case CONSTRAINT_CYL: 01270 if(checkIfInteraction(ia_params)) { 01271 calculate_cylinder_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.cyl, &dist, vec); 01272 if ( dist > 0 ) { 01273 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01274 ia_params,vec,dist,dist*dist, force, 01275 torque1, torque2); 01276 } 01277 else if ( dist <= 0 && constraints[n].c.cyl.penetrable == 1 ) { 01278 if ( dist < 0 ) { 01279 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01280 ia_params,vec,-1.0*dist,dist*dist, force, 01281 torque1, torque2); 01282 } 01283 } 01284 else { 01285 if(constraints[n].c.cyl.reflecting){ 01286 reflect_particle(p1, &(vec[0]), constraints[n].c.cyl.reflecting); 01287 } else { 01288 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01289 ERROR_SPRINTF(errtxt, "{063 cylinder constraint %d violated by particle %d} ", n, p1->p.identity); 01290 } 01291 } 01292 } 01293 break; 01294 01295 case CONSTRAINT_RHOMBOID: 01296 if(checkIfInteraction(ia_params)) { 01297 calculate_rhomboid_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.rhomboid, &dist, vec); 01298 if ( dist > 0 ) { 01299 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01300 ia_params,vec,dist,dist*dist, force, 01301 torque1, torque2); 01302 } 01303 else if ( dist <= 0 && constraints[n].c.rhomboid.penetrable == 1 ) { 01304 if ( dist < 0 ) { 01305 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01306 ia_params,vec,-1.0*dist,dist*dist, force, 01307 torque1, torque2); 01308 } 01309 } 01310 else { 01311 if(constraints[n].c.rhomboid.reflecting){ 01312 reflect_particle(p1, &(vec[0]), constraints[n].c.rhomboid.reflecting); 01313 } else { 01314 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01315 ERROR_SPRINTF(errtxt, "{063 rhomboid constraint %d violated by particle %d} ", n, p1->p.identity); 01316 } 01317 } 01318 } 01319 break; 01320 01321 case CONSTRAINT_MAZE: 01322 if(checkIfInteraction(ia_params)) { 01323 calculate_maze_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.maze, &dist, vec); 01324 if ( dist > 0 ) { 01325 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01326 ia_params,vec,dist,dist*dist, force, 01327 torque1, torque2); 01328 } 01329 else if ( dist <= 0 && constraints[n].c.maze.penetrable == 1 ) { 01330 if ( dist < 0 ) { 01331 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01332 ia_params,vec,-1.0*dist,dist*dist, force, 01333 torque1, torque2); 01334 } 01335 } 01336 else { 01337 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01338 ERROR_SPRINTF(errtxt, "{064 maze constraint %d violated by particle %d} ", n, p1->p.identity); 01339 } 01340 } 01341 break; 01342 01343 case CONSTRAINT_PORE: 01344 if(checkIfInteraction(ia_params)) { 01345 calculate_pore_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.pore, &dist, vec); 01346 if ( dist >= 0 ) { 01347 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01348 ia_params,vec,dist,dist*dist, force, 01349 torque1, torque2); 01350 } 01351 else { 01352 if(constraints[n].c.pore.reflecting){ 01353 reflect_particle(p1, &(vec[0]), constraints[n].c.pore.reflecting); 01354 } else { 01355 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01356 ERROR_SPRINTF(errtxt, "{063 pore constraint %d violated by particle %d} ", n, p1->p.identity); 01357 } 01358 } 01359 } 01360 break; 01361 01362 /* electrostatic "constraints" */ 01363 case CONSTRAINT_ROD: 01364 add_rod_force(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.rod); 01365 break; 01366 01367 case CONSTRAINT_PLATE: 01368 add_plate_force(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.plate); 01369 break; 01370 01371 #ifdef DIPOLES 01372 case CONSTRAINT_EXT_MAGN_FIELD: 01373 add_ext_magn_field_force(p1, &constraints[n].c.emfield); 01374 break; 01375 #endif 01376 01377 case CONSTRAINT_PLANE: 01378 if(checkIfInteraction(ia_params)) { 01379 calculate_plane_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.plane, &dist, vec); 01380 if (dist > 0) { 01381 calc_non_bonded_pair_force(p1, &constraints[n].part_rep, 01382 ia_params,vec,dist,dist*dist, force, 01383 torque1, torque2); 01384 #ifdef TUNABLE_SLIP 01385 add_tunable_slip_pair_force(p1, &constraints[n].part_rep,ia_params,vec,dist,force); 01386 #endif 01387 } 01388 else { 01389 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01390 ERROR_SPRINTF(errtxt, "{063 plane constraint %d violated by particle %d} ", n, p1->p.identity); 01391 } 01392 } 01393 break; 01394 } 01395 for (j = 0; j < 3; j++) { 01396 p1->f.f[j] += force[j]; 01397 constraints[n].part_rep.f.f[j] -= force[j]; 01398 #ifdef ROTATION 01399 p1->f.torque[j] += torque1[j]; 01400 constraints[n].part_rep.f.torque[j] += torque2[j]; 01401 #endif 01402 } 01403 } 01404 } 01405 01406 double add_constraints_energy(Particle *p1) 01407 { 01408 int n, type; 01409 double dist, vec[3]; 01410 double nonbonded_en, coulomb_en, magnetic_en; 01411 IA_parameters *ia_params; 01412 char *errtxt; 01413 double folded_pos[3]; 01414 int img[3]; 01415 01416 /* fold the coordinate[2] of the particle */ 01417 memcpy(folded_pos, p1->r.p, 3*sizeof(double)); 01418 memcpy(img, p1->l.i, 3*sizeof(int)); 01419 fold_position(folded_pos, img); 01420 for(n=0;n<n_constraints;n++) { 01421 ia_params = get_ia_param(p1->p.type, (&constraints[n].part_rep)->p.type); 01422 nonbonded_en = 0.; 01423 coulomb_en = 0.; 01424 magnetic_en = 0.; 01425 01426 dist=0.; 01427 switch(constraints[n].type) { 01428 case CONSTRAINT_WAL: 01429 if(checkIfInteraction(ia_params)) { 01430 calculate_wall_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.wal, &dist, vec); 01431 if ( dist > 0 ) { 01432 nonbonded_en = calc_non_bonded_pair_energy(p1, &constraints[n].part_rep, 01433 ia_params, vec, dist, dist*dist); 01434 } 01435 else if ( dist <= 0 && constraints[n].c.wal.penetrable == 1 ) { 01436 if ( dist < 0 ) { 01437 nonbonded_en = calc_non_bonded_pair_energy(p1, &constraints[n].part_rep, 01438 ia_params, vec, -1.0*dist, dist*dist); 01439 } 01440 } 01441 else { 01442 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01443 ERROR_SPRINTF(errtxt, "{065 wall constraint %d violated by particle %d} ", n, p1->p.identity); 01444 } 01445 } 01446 break; 01447 01448 case CONSTRAINT_SPH: 01449 if(checkIfInteraction(ia_params)) { 01450 calculate_sphere_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.sph, &dist, vec); 01451 if ( dist > 0 ) { 01452 nonbonded_en = calc_non_bonded_pair_energy(p1, &constraints[n].part_rep, 01453 ia_params, vec, dist, dist*dist); 01454 } 01455 else if ( dist <= 0 && constraints[n].c.sph.penetrable == 1 ) { 01456 if ( dist < 0 ) { 01457 nonbonded_en = calc_non_bonded_pair_energy(p1, &constraints[n].part_rep, 01458 ia_params, vec, -1.0*dist, dist*dist); 01459 } 01460 } 01461 else { 01462 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01463 ERROR_SPRINTF(errtxt, "{066 sphere constraint %d violated by particle %d} ", n, p1->p.identity); 01464 } 01465 } 01466 break; 01467 01468 case CONSTRAINT_CYL: 01469 if(checkIfInteraction(ia_params)) { 01470 calculate_cylinder_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.cyl, &dist , vec); 01471 if ( dist > 0 ) { 01472 nonbonded_en = calc_non_bonded_pair_energy(p1, &constraints[n].part_rep, 01473 ia_params, vec, dist, dist*dist); 01474 01475 } 01476 else if ( dist <= 0 && constraints[n].c.cyl.penetrable == 1 ) { 01477 if ( dist < 0 ) { 01478 nonbonded_en = calc_non_bonded_pair_energy(p1, &constraints[n].part_rep, 01479 ia_params, vec, -1.0*dist, dist*dist); 01480 } 01481 } 01482 else { 01483 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01484 ERROR_SPRINTF(errtxt, "{067 cylinder constraint %d violated by particle %d} ", n, p1->p.identity); 01485 } 01486 } 01487 break; 01488 01489 case CONSTRAINT_RHOMBOID: 01490 if(checkIfInteraction(ia_params)) { 01491 calculate_rhomboid_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.rhomboid, &dist , vec); 01492 if ( dist > 0 ) { 01493 nonbonded_en = calc_non_bonded_pair_energy(p1, &constraints[n].part_rep, 01494 ia_params, vec, dist, dist*dist); 01495 01496 } 01497 else if ( dist <= 0 && constraints[n].c.rhomboid.penetrable == 1 ) { 01498 if ( dist < 0 ) { 01499 nonbonded_en = calc_non_bonded_pair_energy(p1, &constraints[n].part_rep, 01500 ia_params, vec, -1.0*dist, dist*dist); 01501 } 01502 } 01503 else { 01504 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01505 ERROR_SPRINTF(errtxt, "{067 cylinder constraint %d violated by particle %d} ", n, p1->p.identity); 01506 } 01507 } 01508 break; 01509 01510 case CONSTRAINT_MAZE: 01511 if(checkIfInteraction(ia_params)) { 01512 calculate_maze_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.maze, &dist, vec); 01513 if ( dist > 0 ) { 01514 nonbonded_en = calc_non_bonded_pair_energy(p1, &constraints[n].part_rep, 01515 ia_params, vec, dist, dist*dist); 01516 } 01517 else if ( dist <= 0 && constraints[n].c.maze.penetrable == 1 ) { 01518 if ( dist < 0 ) { 01519 nonbonded_en = calc_non_bonded_pair_energy(p1, &constraints[n].part_rep, 01520 ia_params, vec, -1.0*dist, dist*dist); 01521 } 01522 } 01523 else { 01524 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01525 ERROR_SPRINTF(errtxt, "{068 maze constraint %d violated by particle %d} ", n, p1->p.identity); 01526 } 01527 } 01528 break; 01529 01530 case CONSTRAINT_PORE: 01531 if(checkIfInteraction(ia_params)) { 01532 calculate_pore_dist(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.pore, &dist , vec); 01533 if ( dist > 0 ) { 01534 nonbonded_en = calc_non_bonded_pair_energy(p1, &constraints[n].part_rep, 01535 ia_params, vec, dist, dist*dist); 01536 01537 } 01538 else { 01539 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 01540 ERROR_SPRINTF(errtxt, "{067 pore constraint %d violated by particle %d} ", n, p1->p.identity); 01541 } 01542 } 01543 break; 01544 01545 case CONSTRAINT_ROD: 01546 coulomb_en = rod_energy(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.rod); 01547 break; 01548 01549 case CONSTRAINT_PLATE: 01550 coulomb_en = plate_energy(p1, folded_pos, &constraints[n].part_rep, &constraints[n].c.plate); 01551 break; 01552 case CONSTRAINT_EXT_MAGN_FIELD: 01553 magnetic_en = ext_magn_field_energy(p1, &constraints[n].c.emfield); 01554 break; 01555 } 01556 01557 if (energy.n_coulomb > 0) 01558 energy.coulomb[0] += coulomb_en; 01559 01560 if (energy.n_dipolar > 0) 01561 energy.dipolar[0] += magnetic_en; 01562 01563 type = (&constraints[n].part_rep)->p.type; 01564 if (type >= 0) 01565 *obsstat_nonbonded(&energy, p1->p.type, type) += nonbonded_en; 01566 } 01567 return 0.; 01568 } 01569 01570 #endif 01571
1.7.5.1