![]() |
ESPResSo 3.2.0-159-gf5c8922-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 pressure.c 00022 Implementation of \ref pressure.h "pressure.h". 00023 */ 00024 #include "pressure.h" 00025 #include "cells.h" 00026 #include "integrate.h" 00027 #include "initialize.h" 00028 #include "domain_decomposition.h" 00029 #include "nsquare.h" 00030 #include "layered.h" 00031 00032 Observable_stat virials = {0, {NULL,0,0}, 0,0,0,0}; 00033 Observable_stat total_pressure = {0, {NULL,0,0}, 0,0,0,0}; 00034 Observable_stat p_tensor = {0, {NULL,0,0},0,0,0,0}; 00035 Observable_stat total_p_tensor = {0, {NULL,0,0},0,0,0,0}; 00036 00037 /* Observables used in the calculation of intra- and inter- molecular 00038 non-bonded contributions to pressure and to stress tensor */ 00039 Observable_stat_non_bonded virials_non_bonded = {0, {NULL,0,0}, 0,0,0}; 00040 Observable_stat_non_bonded total_pressure_non_bonded = {0, {NULL,0,0}, 0,0,0}; 00041 Observable_stat_non_bonded p_tensor_non_bonded = {0, {NULL,0,0},0,0,0}; 00042 Observable_stat_non_bonded total_p_tensor_non_bonded = {0, {NULL,0,0},0,0,0}; 00043 00044 nptiso_struct nptiso = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,{0.0,0.0,0.0},{0.0,0.0,0.0},1, 0 ,{NPTGEOM_XDIR, NPTGEOM_YDIR, NPTGEOM_ZDIR},0,0,0}; 00045 00046 /************************************************************/ 00047 /* callbacks for setmd */ 00048 /************************************************************/ 00049 00050 00051 00052 /************************************************************/ 00053 /* local prototypes */ 00054 /************************************************************/ 00055 00056 /** Calculate long range virials (P3M, MMM2d...). */ 00057 void calc_long_range_virials(); 00058 00059 /** Initializes a virials Observable stat. */ 00060 void init_virials(Observable_stat *stat); 00061 00062 /** Initializes a virials Observable stat. */ 00063 void init_virials_non_bonded(Observable_stat_non_bonded *stat_nb); 00064 00065 /** on the master node: calc energies only if necessary 00066 @param v_comp flag which enables (1) compensation of the velocities required 00067 for deriving a pressure reflecting \ref nptiso_struct::p_inst 00068 (hence it only works with domain decomposition); naturally it 00069 therefore doesn't make sense to use it without NpT. */ 00070 void master_pressure_calc(int v_comp); 00071 00072 /** Initializes stat to be used by \ref pressure_calc. */ 00073 void init_p_tensor(Observable_stat *stat); 00074 00075 /** Initializes stat_nb to be used by \ref pressure_calc. */ 00076 void init_p_tensor_non_bonded(Observable_stat_non_bonded *stat_nb); 00077 00078 /*********************************/ 00079 /* Scalar and Tensorial Pressure */ 00080 /*********************************/ 00081 00082 void pressure_calc(double *result, double *result_t, double *result_nb, double *result_t_nb, int v_comp) 00083 { 00084 int n, i; 00085 double volume = box_l[0]*box_l[1]*box_l[2]; 00086 00087 if (!check_obs_calc_initialized()) 00088 return; 00089 00090 init_virials(&virials); 00091 00092 init_p_tensor(&p_tensor); 00093 00094 init_virials_non_bonded(&virials_non_bonded); 00095 00096 init_p_tensor_non_bonded(&p_tensor_non_bonded); 00097 00098 on_observable_calc(); 00099 00100 switch (cell_structure.type) { 00101 case CELL_STRUCTURE_LAYERED: 00102 layered_calculate_virials(v_comp); 00103 break; 00104 case CELL_STRUCTURE_DOMDEC: 00105 if(dd.use_vList) { 00106 if (rebuild_verletlist) 00107 build_verlet_lists(); 00108 calculate_verlet_virials(v_comp); 00109 } 00110 else 00111 calculate_link_cell_virials(v_comp); 00112 break; 00113 case CELL_STRUCTURE_NSQUARE: 00114 nsq_calculate_virials(v_comp); 00115 } 00116 /* rescale kinetic energy (=ideal contribution) */ 00117 #ifdef ROTATION_PER_PARTICLE 00118 fprintf(stderr, "Switching rotation per particle (#define ROTATION_PER_PARTICLE) and pressure calculation are incompatible.\n"); 00119 #endif 00120 00121 virials.data.e[0] /= (3.0*volume*time_step*time_step); 00122 00123 calc_long_range_virials(); 00124 00125 for (n = 1; n < virials.data.n; n++) 00126 virials.data.e[n] /= 3.0*volume; 00127 00128 00129 /* stress tensor part */ 00130 /* The ROTATION option does not effect stress tensor calculations 00131 since rotational energy is not included in the ideal term (unlike 00132 for the pressure) */ 00133 for(i=0; i<9; i++) 00134 p_tensor.data.e[i] /= (volume*time_step*time_step); 00135 00136 for(i=9; i<p_tensor.data.n; i++) 00137 p_tensor.data.e[i] /= volume; 00138 00139 /* Intra- and Inter- part of nonbonded interaction */ 00140 for (n = 0; n < virials_non_bonded.data_nb.n; n++) 00141 virials_non_bonded.data_nb.e[n] /= 3.0*volume; 00142 00143 for(i=0; i<p_tensor_non_bonded.data_nb.n; i++) 00144 p_tensor_non_bonded.data_nb.e[i] /= volume; 00145 00146 /* gather data */ 00147 MPI_Reduce(virials.data.e, result, virials.data.n, MPI_DOUBLE, MPI_SUM, 0, comm_cart); 00148 MPI_Reduce(p_tensor.data.e, result_t, p_tensor.data.n, MPI_DOUBLE, MPI_SUM, 0, comm_cart); 00149 00150 MPI_Reduce(virials_non_bonded.data_nb.e, result_nb, virials_non_bonded.data_nb.n, MPI_DOUBLE, MPI_SUM, 0, comm_cart); 00151 MPI_Reduce(p_tensor_non_bonded.data_nb.e, result_t_nb, p_tensor_non_bonded.data_nb.n, MPI_DOUBLE, MPI_SUM, 0, comm_cart); 00152 } 00153 00154 /************************************************************/ 00155 00156 void calc_long_range_virials() 00157 { 00158 #ifdef ELECTROSTATICS 00159 /* calculate k-space part of electrostatic interaction. */ 00160 switch (coulomb.method) { 00161 #ifdef P3M 00162 case COULOMB_ELC_P3M: 00163 fprintf(stderr, "WARNING: pressure calculated, but ELC pressure not implemented\n"); 00164 break; 00165 case COULOMB_P3M_GPU: 00166 fprintf(stderr, "WARNING: pressure calculated, but GPU P3M pressure not implemented\n"); 00167 break; 00168 case COULOMB_P3M: { 00169 int k; 00170 p3m_charge_assign(); 00171 virials.coulomb[1] = p3m_calc_kspace_forces(0,1); 00172 00173 for(k=0;k<3;k++) 00174 p_tensor.coulomb[9+ k*3 + k] = virials.coulomb[1]/3.; 00175 p3m_calc_kspace_stress(p_tensor.coulomb); 00176 break; 00177 } 00178 #endif 00179 case COULOMB_MMM2D: 00180 fprintf(stderr, "WARNING: pressure calculated, but MMM2D pressure not implemented\n"); 00181 break; 00182 case COULOMB_MMM1D: 00183 fprintf(stderr, "WARNING: pressure calculated, but MMM1D pressure not implemented\n"); 00184 break; 00185 } 00186 #endif /*ifdef ELECTROSTATICS */ 00187 00188 #ifdef DIPOLES 00189 /* calculate k-space part of magnetostatic interaction. */ 00190 switch (coulomb.Dmethod) { 00191 case DIPOLAR_ALL_WITH_ALL_AND_NO_REPLICA: 00192 fprintf(stderr, "WARNING: pressure calculated, but DAWAANR pressure not implemented\n"); 00193 break; 00194 case DIPOLAR_MDLC_DS: 00195 fprintf(stderr, "WARNING: pressure calculated, but DLC pressure not implemented\n"); 00196 break; 00197 case DIPOLAR_DS: 00198 fprintf(stderr, "WARNING: pressure calculated, but MAGNETIC DIRECT SUM pressure not implemented\n"); 00199 break; 00200 00201 00202 #ifdef DP3M 00203 case DIPOLAR_MDLC_P3M: 00204 fprintf(stderr, "WARNING: pressure calculated, but DLC pressure not implemented\n"); 00205 break; 00206 case DIPOLAR_P3M: { 00207 int k; 00208 dp3m_dipole_assign(); 00209 virials.dipolar[1] = dp3m_calc_kspace_forces(0,1); 00210 00211 for(k=0;k<3;k++) 00212 p_tensor.coulomb[9+ k*3 + k] = virials.dipolar[1]/3.; 00213 fprintf(stderr, "WARNING: stress tensor calculated, but dipolar P3M stress tensor not implemented\n"); 00214 fprintf(stderr, "WARNING: things have been added to the coulomb virial and p_tensor arrays !!!!!!!\n"); 00215 00216 break; 00217 } 00218 #endif 00219 } 00220 #endif /*ifdef DIPOLES */ 00221 } 00222 00223 /* Initialize the virials used in the calculation of the scalar pressure */ 00224 /************************************************************/ 00225 void init_virials(Observable_stat *stat) 00226 { 00227 int n_pre, n_non_bonded, n_coulomb, n_dipolar; 00228 00229 n_pre = 1; 00230 n_non_bonded = (n_particle_types*(n_particle_types+1))/2; 00231 00232 n_coulomb = 0; 00233 n_dipolar = 0; 00234 #ifdef ELECTROSTATICS 00235 switch (coulomb.method) { 00236 case COULOMB_NONE: n_coulomb = 0; break; 00237 case COULOMB_P3M_GPU: 00238 case COULOMB_P3M: n_coulomb = 2; break; 00239 default: n_coulomb = 1; 00240 } 00241 #endif 00242 #ifdef DIPOLES 00243 switch (coulomb.Dmethod) { 00244 case DIPOLAR_NONE: n_dipolar = 0; break; 00245 case DIPOLAR_ALL_WITH_ALL_AND_NO_REPLICA: n_dipolar = 0; break; 00246 case DIPOLAR_DS: n_dipolar = 0; break; 00247 case DIPOLAR_P3M: n_dipolar = 2; break; 00248 } 00249 #endif 00250 00251 00252 00253 obsstat_realloc_and_clear(stat, n_pre, n_bonded_ia, n_non_bonded, n_coulomb, n_dipolar, 1); 00254 stat->init_status = 0; 00255 } 00256 00257 /************************************************************/ 00258 void init_virials_non_bonded(Observable_stat_non_bonded *stat_nb) 00259 { 00260 int n_non_bonded; 00261 00262 n_non_bonded = (n_particle_types*(n_particle_types+1))/2; 00263 00264 obsstat_realloc_and_clear_non_bonded(stat_nb, n_non_bonded, 1); 00265 stat_nb->init_status_nb = 0; 00266 } 00267 00268 /* Initialize the p_tensor */ 00269 /***************************/ 00270 void init_p_tensor(Observable_stat *stat) 00271 { 00272 int n_pre, n_non_bonded, n_coulomb, n_dipolar; 00273 00274 n_pre = 1; 00275 n_non_bonded = (n_particle_types*(n_particle_types+1))/2; 00276 00277 n_coulomb = 0; 00278 n_dipolar = 0; 00279 00280 #ifdef ELECTROSTATICS 00281 switch (coulomb.method) { 00282 case COULOMB_NONE: n_coulomb = 0; break; 00283 case COULOMB_P3M_GPU: 00284 case COULOMB_P3M: n_coulomb = 2; break; 00285 default: n_coulomb = 1; 00286 } 00287 #endif 00288 00289 #ifdef DIPOLES 00290 switch (coulomb.Dmethod) { 00291 case DIPOLAR_NONE: n_dipolar = 0; break; 00292 case DIPOLAR_ALL_WITH_ALL_AND_NO_REPLICA: n_dipolar = 0; break; 00293 case DIPOLAR_DS: n_dipolar = 0; break; 00294 case DIPOLAR_P3M: n_dipolar = 2; break; 00295 } 00296 #endif 00297 00298 obsstat_realloc_and_clear(stat, n_pre, n_bonded_ia, n_non_bonded, n_coulomb, n_dipolar, 9); 00299 stat->init_status = 0; 00300 } 00301 00302 /***************************/ 00303 void init_p_tensor_non_bonded(Observable_stat_non_bonded *stat_nb) 00304 { 00305 int n_nonbonded; 00306 n_nonbonded = (n_particle_types*(n_particle_types+1))/2; 00307 00308 obsstat_realloc_and_clear_non_bonded(stat_nb, n_nonbonded, 9); 00309 stat_nb->init_status_nb = 0; 00310 } 00311 00312 /************************************************************/ 00313 void master_pressure_calc(int v_comp) { 00314 if(v_comp) 00315 mpi_gather_stats(3, total_pressure.data.e, total_p_tensor.data.e, total_pressure_non_bonded.data_nb.e, total_p_tensor_non_bonded.data_nb.e); 00316 else 00317 mpi_gather_stats(2, total_pressure.data.e, total_p_tensor.data.e, total_pressure_non_bonded.data_nb.e, total_p_tensor_non_bonded.data_nb.e); 00318 00319 total_pressure.init_status = 1+v_comp; 00320 total_p_tensor.init_status = 1+v_comp; 00321 total_pressure_non_bonded.init_status_nb = 1+v_comp; 00322 total_p_tensor_non_bonded.init_status_nb = 1+v_comp; 00323 } 00324 00325 00326 /*****************************************************/ 00327 /* Routines for Local Stress Tensor */ 00328 /*****************************************************/ 00329 00330 int getintersection(double pos1[3], double pos2[3],int given, int get, double value, double *answer, double box_size[3]) 00331 { 00332 /*pos1 and pos2 are two particle positions. */ 00333 /*given and get are integers from 0 to 2. 0 = x direction. 1 = y direction. 2 = z direction */ 00334 /*there is a point on the line between the two particles p1 and p2 such that r[given]=value */ 00335 /*this procedure returns the value of r[get] at that point */ 00336 00337 double p2r[3]; 00338 int i; 00339 00340 for (i=0;i<3;i++) { 00341 p2r[i] = drem_down((pos2[i]-pos1[i])+box_size[i]/2.0,box_size[i])-box_size[i]/2.0; 00342 } 00343 value = drem_down((value-pos1[given])+box_size[given]/2.0,box_size[given])-box_size[given]/2.0; 00344 //PTENSOR_TRACE(fprintf(stderr,"%d: getintersection: p1 is %f %f %f p2 is %f %f %f p2r is %f %f %f newvalue is %f\n",this_node,pos1[0],pos1[1],pos1[2],pos2[0],pos2[1],pos2[2],p2r[0],p2r[1],p2r[2],value);); 00345 00346 if ((value)*(p2r[given]) < -0.0001) { 00347 char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); 00348 ERROR_SPRINTF(errtxt, "{analyze stress_profile: getintersection: intersection is not between the two given particles - %e is not between %e and %e and box size is %e, given is %d\n ",value,0.0,p2r[given],box_size[given],given); 00349 return 0; 00350 } else if (given == get) { 00351 *answer = drem_down(value + pos1[given],box_size[given]);; 00352 } else if (0==p2r[given]) { 00353 char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); 00354 ERROR_SPRINTF(errtxt, "{analyze stress_profile: getintersection: intersection is a line, not a point - value is %g same as %g and %g\n",value,0.0,p2r[given]); 00355 return 0; 00356 } else { 00357 *answer = drem_down(pos1[get]+p2r[get]/p2r[given]*value,box_size[get]); 00358 } 00359 return 1; 00360 } 00361 00362 int getlength(double pos1[3], double pos2[3], int d1, double val1, int d2, double val2, int l, double *answer) 00363 { 00364 /*p1 and p2 are two particles positions 00365 d1 and d2 are integers between 0 and 2 denoting an axis (x, y, or z) 00366 l and k are integers between 0 and 2 denoting an axis (x, y, or z) 00367 two points on the line connecting these particles are defined by r[d1]=val1 and r[d2]=val2 00368 call these two points p3 and p4 (not program variables) 00369 this program returns the distance between p3 and p4 in the l direction 00370 */ 00371 00372 double intersect1, intersect2; 00373 00374 *answer = 0; 00375 00376 if (! getintersection(pos1,pos2,d2,l,val2,&intersect1,box_l) || ! getintersection(pos1,pos2,d1,l,val1,&intersect2,box_l)) { 00377 return 0; 00378 } else { 00379 *answer = drem_down(intersect2 - intersect1 + box_l[l]/2.0, box_l[l]) - box_l[l]/2.0; 00380 return 1; 00381 } 00382 } 00383 00384 int does_line_go_through_cube(double pos1[3], double pos2[3], double range_start[3], double range[3], int sign[3], double entry[3], double exit[3],int *facein, int *faceout) 00385 /* p1 and p2 are two particle positions 00386 there is a cube in the simulation box with one vertex at range_start and the opposite vertex at range_start + range 00387 this routine calculates where the line connecting p1 and p2 enters and exits this cube 00388 these points are returned in the variables entry and exit 00389 the function returns a 0 if the line does not pass through the cube and 1 if it does 00390 */ 00391 { 00392 00393 double centre[3]; /* centre of the cube */ 00394 double vect2centre1[3]; /* vectors from centre of cube to pos1 and pos2 */ 00395 double vect2centre2[3]; 00396 int i; 00397 00398 int doesntenter = 0; /* boolean that indicates whether we have already determined that the line does not enter the cube at all */ 00399 double intersection1 = 0.0, intersection2 = 0.0; 00400 int found_entry = 0; /* boolean that indicates whether we have determined where the line enters */ 00401 int found_exit = 0; /* boolean that indicates whether we have determined where the line exits */ 00402 int i1, i2; 00403 int inside1, inside2; 00404 00405 /* find centre of analyzed cube */ 00406 for (i=0;i<3;i++) { 00407 centre[i] = range_start[i] + range[i]/2.0; 00408 } 00409 00410 /* find vectors connecting two particles to centre */ 00411 get_mi_vector(vect2centre1,pos1,centre); 00412 get_mi_vector(vect2centre2,pos2,centre); 00413 00414 *facein = -1; 00415 *faceout = -1; 00416 00417 /* check if particles are inside cube */ 00418 inside1 = 1; 00419 inside2 = 1; 00420 for (i=0;i<3;i++) { 00421 if (fabs(vect2centre1[i])>range[i]/2.0) inside1 = 0; 00422 if (fabs(vect2centre2[i])>range[i]/2.0) inside2 = 0; 00423 } 00424 PTENSOR_TRACE(fprintf(stderr,"%d: does_line_go_through_cube: Particle1 inside cube = %d Particle2 inside cube = %d \n",this_node,inside1,inside2);); 00425 00426 /* work out which face connecting line enters through */ 00427 if (! inside1) { 00428 for (i=0;i<3;i++) { 00429 i1 = (i+1)%3; 00430 i2 = (i+2)%3; 00431 /*does the line start outside the cube in direction i?*/ 00432 if ( (! doesntenter ) && (! found_entry) && fabs(vect2centre1[i])>range[i]/2.0 ) { 00433 /*does the bond heads away from the cube or is part2 is before the cube in direction i? */ 00434 if ((vect2centre1[i] * sign[i] > 0) || (vect2centre2[i]*sign[i] < -range[i]/2.0)) { 00435 doesntenter = 1; 00436 } else { 00437 getintersection(vect2centre1, vect2centre2, i, i1, -range[i]/2.0*sign[i],&intersection1,box_l); 00438 if (intersection1 > box_l[i1]/2) intersection1 -= box_l[i1]; 00439 if (fabs(intersection1) < range[i1]/2.0) { 00440 getintersection(vect2centre1, vect2centre2, i, i2, -range[i]/2.0*sign[i],&intersection2,box_l); 00441 if (intersection2 > box_l[i2]/2) intersection2 -= box_l[i2]; 00442 if (fabs(intersection2) < range[i2]/2.0) { 00443 found_entry = 1; 00444 entry[i] = centre[i] -range[i]/2.0*sign[i]; 00445 entry[i1] = centre[i1] + intersection1; 00446 entry[i2] = centre[i2] + intersection2; 00447 *facein = i; 00448 } 00449 } 00450 } 00451 } 00452 } 00453 } else { 00454 entry[0] = pos1[0]; 00455 entry[1] = pos1[1]; 00456 entry[2] = pos1[2]; 00457 } 00458 if (! (found_entry) && ! (inside1)) { 00459 PTENSOR_TRACE(fprintf(stderr,"%d: does_line_go_through_cube: Line does not pass through cube \n",this_node);); 00460 return 0; 00461 } else { 00462 PTENSOR_TRACE(fprintf(stderr,"%d: does_line_go_through_cube: Entry is %f %f %f \n",this_node,entry[0], entry[1], entry[2]);); 00463 if (! inside2) { 00464 /*check which outside faces of box the line exits through */ 00465 for (i=0;i<3;i++) { 00466 i1 = (i+1)%3; 00467 i2 = (i+2)%3; 00468 /* does it enter into the box through the i face */ 00469 if ((found_exit == 0) && (fabs(vect2centre2[i]) > range[i]/2.0)) { /*starts outside cube in i direction */ 00470 getintersection(vect2centre1, vect2centre2, i, i1, range[i]/2.0*sign[i],&intersection1,box_l); 00471 if (intersection1 > box_l[i1]/2) intersection1 -= box_l[i1]; 00472 if (fabs(intersection1) < range[i1]/2.0) { 00473 getintersection(vect2centre1, vect2centre2, i, i2, range[i]/2.0*sign[i],&intersection2,box_l); 00474 if (intersection2 > box_l[i2]/2) intersection2 -= box_l[i2]; 00475 if (fabs(intersection2) < range[i2]/2.0) { 00476 found_exit = 1; 00477 exit[i] = centre[i] + range[i]/2.0*sign[i]; 00478 exit[i1] = centre[i1] + intersection1; 00479 exit[i2] = centre[i2] + intersection2; 00480 *faceout = i; 00481 } 00482 } 00483 } 00484 } 00485 } else { 00486 exit[0] = pos2[0]; 00487 exit[1] = pos2[1]; 00488 exit[2] = pos2[2]; 00489 } 00490 PTENSOR_TRACE(fprintf(stderr,"%d: does_line_go_through_cube: Exit is %f %f %f\n",this_node,exit[0], exit[1], exit[2]);); 00491 } 00492 PTENSOR_TRACE(fprintf(stderr,"%d: does_line_go_through_cube: facein is %d faceout is %d\n",this_node,*facein,*faceout);); 00493 return 1; 00494 } 00495 00496 int distribute_tensors(DoubleList *TensorInBin, double *force, int bins[3], double range_start[3], double range[3], double pos1[3], double pos2[3]) 00497 { 00498 /*calculates how to distribute a force tensor between two particles between various bins 00499 the amount distributed to a bin is proportional to the length of the line between the 00500 two particles p1 and p2 that passes through the bin volume 00501 we consider a cube of space starting with a corner at {x_range_start, y_range_start, z_range_start} extending to 00502 {x_range_start+x_range, y_range_start+y_range, z_range_start+z_range} 00503 this cube is split into x_bins bins in the x direction - we refer to these as x-bins 00504 each x-bin into y_bins bins in the y direction - we refer to these as y-bins 00505 each y_bin into z_bins bins in the z direction - we refer to these as z-bins 00506 */ 00507 00508 int sign[3],sign10[3]; /* indicates whether the line goes in the positive or negative direction in each dimension */ 00509 double entry[3], exit[3]; /* the positions at which the line enters and exits the cube */ 00510 int startx, endx; /* x-bins in which the line starts and ends in */ 00511 int occupiedxbins; /* number of x-bins occuped by the line */ 00512 int *starty; /* y-bins in which the line starts in for each x-bin. This array has dimension occupiedxbins+1. */ 00513 int totoccupiedybins; /* total number of y-bins through which the line passes */ 00514 int *occupiedybins; /* number of occupied y-bins for each x-bin */ 00515 int *occupiedzbins; /* number of occupied z-bins for each y-bin */ 00516 int *startz; /* z-bins in which the line starts in for each y_bin. This array has dimension totaloccupiedybins. */ 00517 int xbin, ybin, zbin; /* counters to keep track of bins x_bin goes from 0 to x_bins-1, y_bins from 0 to y_bins-1, z_bins from 0 to Z-bins-1 */ 00518 int i ,k, l; 00519 int counter; /* keeps track of where we are in the startz array */ 00520 int zi; 00521 double length; /* length of line between the two points */ 00522 int d1,d2; /* for each z-bin d1 and d2 are calculated. they indicate through which faces of the bin the line enters and leaves the bin. i.e. if the line enters through the face corresponding to y = 0.34 then d1 = 1 (y-direction) and val1 = 0.34 */ 00523 double val1, val2; 00524 double intersect; 00525 double segment,segment2; 00526 double calclength; 00527 int xa, ya, za; /* counters for bins */ 00528 double temp[3]; 00529 double redentry[3], redexit[3]; /* like entry and exit but using a coordinate system where range_start corresponds to (0,0,0) and the length scale in each direction is the bin width */ 00530 double redbox_l[3]; /* box size is reduced units */ 00531 int facein,faceout; 00532 00533 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: Distributing tensors for particle p1 %f %f %f and p2 %f %f %f\n",this_node,pos1[0],pos1[1],pos1[2],pos2[0],pos2[1],pos2[2]);); 00534 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: range_start is %f %f %f range is %f %f %f bins is %d %d %d\n",this_node,range_start[0],range_start[1],range_start[2],range[0],range[1],range[2],bins[0],bins[1],bins[2]);); 00535 /* work out what direction the line joining the particles goes in */ 00536 length = 0; 00537 get_mi_vector(temp, pos2, pos1); 00538 for (i=0;i<3;i++) { 00539 sign[i] = (temp[i] > 0)*2-1; 00540 sign10[i] = (sign[i]+1)/2.0; 00541 } 00542 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: sign is %d %d %d\n",this_node,sign[0],sign[1],sign[2]);); 00543 00544 calclength = 0; 00545 00546 /* check if the line passes through the cube and if so where it enters and exits it */ 00547 if (does_line_go_through_cube(pos1, pos2, range_start, range, sign, entry, exit,&facein,&faceout)) { 00548 00549 /* calculate reduced coordinates */ 00550 /* range_start becomes (0,0,0) and range_start + range becomes (bins[0],bins[1],bins[2]) */ 00551 get_mi_vector(redentry, entry, range_start); 00552 get_mi_vector(redexit, exit, range_start); 00553 for (i=0;i<3;i++) { 00554 redentry[i] = drem_down(redentry[i]+box_l[i],box_l[i]); 00555 redexit[i] = drem_down(redexit[i]+box_l[i],box_l[i]); 00556 } 00557 length = 0; 00558 get_mi_vector(temp, exit, entry); 00559 for (i=0;i<3;i++) { 00560 redentry[i] = redentry[i]/range[i]*bins[i]; 00561 redexit[i] = redexit[i]/range[i]*bins[i]; 00562 length += pow(temp[i],2); 00563 } 00564 length = pow(length,0.5); 00565 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: Reduced Entry is %f %f %f Reduced Exit is %f %f %f \n",this_node,redentry[0],redentry[1],redentry[2],redexit[0], redexit[1], redexit[2]);); 00566 00567 for (i=0;i<3;i++) { 00568 redbox_l[i] = box_l[i]/range[i]*bins[i]; 00569 } 00570 00571 /* find in which x-bins the line starts and stops */ 00572 if (facein == 0) { 00573 startx = dround(redentry[0]) - 1 + sign10[0]; 00574 } else { 00575 startx = floor(redentry[0]); 00576 } 00577 if ((startx < 0) && (range[0]==box_l[0])) startx += bins[0]; 00578 if (faceout == 0) { 00579 endx = dround(redexit[0] - sign10[0]); 00580 } else { 00581 endx = floor(redexit[0]); 00582 } 00583 if ((endx < 0) && (range[0]==box_l[0])) startx += bins[0]; 00584 occupiedxbins = (sign[0]*(endx-startx) + bins[0])%bins[0] +1; 00585 00586 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: x goes from %d to %d\n",this_node,startx, endx);) 00587 /* Initialise starty array */ 00588 starty = (int *)malloc(sizeof(int)*(occupiedxbins+1)); 00589 occupiedybins = (int *)malloc(sizeof(int)*occupiedxbins); 00590 00591 /* find in which y-bins the line starts and stops for each x-bin */ 00592 /* in xbin the line starts in y-bin number starty[xbin-startx] and ends in starty[xbin-startx+1] */ 00593 totoccupiedybins = 0; 00594 if (facein == 1) { 00595 starty[0] = dround(redentry[1]) - 1 + sign10[1]; 00596 } else { 00597 starty[0] = floor(redentry[1]); 00598 } 00599 if ((starty[0] < 0) && (range[1]==box_l[1])) starty[0] += bins[1]; 00600 for (xa=0; xa < occupiedxbins; xa++) { 00601 xbin = (startx + xa*sign[0]+bins[0])%bins[0]; 00602 if (xbin == endx) { 00603 intersect = redexit[1]; 00604 if (faceout == 1) intersect -= sign10[1]; 00605 if (( intersect < 0) && (range[1]==box_l[1])) intersect += bins[1]; 00606 } else { 00607 if (getintersection(redentry,redexit,0,1,xbin+sign10[0],&intersect,redbox_l) != 1) return 0; 00608 } 00609 starty[xa+1]=floor(intersect); 00610 occupiedybins[xa] = ((starty[xa+1]-starty[xa])*sign[1]+bins[1])%bins[1]+1; 00611 totoccupiedybins += occupiedybins[xa]; 00612 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: in xbin %d y goes from %d to %d\n",this_node, xbin, starty[xa],starty[xa+1]);); 00613 } 00614 00615 /* Initialise startz array */ 00616 occupiedzbins = (int *)malloc(sizeof(int)*totoccupiedybins); 00617 startz = (int *)malloc(sizeof(int)*(totoccupiedybins+1)); 00618 /* find in which z-bins the line starts and stops for each y-bin*/ 00619 counter = 0; 00620 if (facein == 2) { 00621 zi = dround(redentry[2]) - 1 + sign10[2]; 00622 } else { 00623 zi = floor(redentry[2]); 00624 } 00625 if (( zi < 0) && (range[2]==box_l[2])) zi += bins[2]; 00626 startz[counter] = zi; 00627 00628 for (xa=0; xa < occupiedxbins; xa++) { 00629 xbin = (startx + xa*sign[0]+bins[0])%bins[0]; 00630 for (ya = 0; ya < occupiedybins[xa]-1; ya++) { 00631 ybin = (starty[xa] + ya*sign[1] + bins[1])%bins[1]; 00632 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: xbin is %d ya is %d, occupiedybins[xa] is %d, ybin is %d\n",this_node,xbin,ya,occupiedybins[xa],ybin);); 00633 if (getintersection(redentry,redexit,1,2,ybin+sign10[1],&intersect,redbox_l) != 1) return 0; 00634 zi = floor(intersect); 00635 startz[counter+1] = zi; 00636 occupiedzbins[counter]= (sign[2]*(startz[counter+1]-startz[counter]) + bins[2])%bins[2] +1; 00637 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: in xbin %d ybin %d zbin goes from %d to %d\n",this_node,xbin,ybin,startz[counter],startz[counter+1]);); 00638 counter ++; 00639 } 00640 ybin = starty[xa+1]; 00641 if (xbin == endx) { 00642 if (faceout == 2) { 00643 zi = dround(redexit[2] -sign10[2]); 00644 } else { 00645 zi = floor(redexit[2]); 00646 } 00647 if (( zi < 0) && (range[2]==box_l[2])) zi += bins[2]; 00648 00649 } else { 00650 if (getintersection(redentry,redexit,0,2,xbin+sign10[0], &intersect, redbox_l) != 1) return 0; 00651 zi = floor(intersect); 00652 } 00653 startz[counter+1]=zi; 00654 occupiedzbins[counter]= (sign[2]*(startz[counter+1]-startz[counter]) + bins[2])%bins[2] +1; 00655 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: in xbin %d ybin %d zbin goes from %d to %d\n",this_node,xbin,ybin,startz[counter],startz[counter+1]);); 00656 counter ++; 00657 } 00658 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: occupiedxbins is %d,occupiedybins[0] is %d, occupiedzbins[0] is %d\n",this_node,occupiedxbins,occupiedybins[0],occupiedzbins[0]);); 00659 00660 /* find out what length of the line passes through each z-bin */ 00661 counter = 0; 00662 for (xa = 0; xa < occupiedxbins; xa ++) { 00663 xbin = (startx + xa*sign[0]+bins[0])%bins[0]; 00664 for (ya = 0; ya < occupiedybins[xa]; ya++) { 00665 ybin = (starty[xa] + ya*sign[1] + bins[1])%bins[1]; 00666 for (za = 0; za < occupiedzbins[counter]; za++) { 00667 zbin = (startz[counter] + za*sign[2] +bins[2])%bins[2]; 00668 if (zbin == startz[counter]) { 00669 if (ybin == starty[xa]) { 00670 if (xbin == startx) { 00671 if (entry[0]-exit[0] != 0) { 00672 d1 = 0; 00673 val1 = redentry[0]; 00674 } else if (entry[1]-exit[1] != 0){ 00675 d1 = 1; 00676 val1 = redentry[1]; 00677 } else { 00678 d1 = 2; 00679 val1 = redentry[2]; 00680 } 00681 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: %d %d %d line starts at point p1 inside bin\n",this_node,xbin,ybin,zbin);); 00682 } else { 00683 d1 = 0; 00684 val1 = xbin+1-sign10[0]; 00685 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: %d %d %d line enters through x = %e face of box\n",this_node,xbin,ybin,zbin,val1);); 00686 } 00687 } else { 00688 d1 = 1; 00689 val1 = ybin+1-sign10[1]; 00690 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: %d %d %d line enters through y = %e face of box\n",this_node,xbin,ybin,zbin,val1);); 00691 } 00692 } else { 00693 d1 = 2; 00694 val1 = zbin+1-sign10[2]; 00695 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: %d %d %d line enters through z = %e face of box zbin is %d\n",this_node,xbin,ybin,zbin,val1,zbin);); 00696 } 00697 if (zbin == startz[counter+1]) { 00698 if (ybin == starty[xa+1]) { 00699 if (xbin == endx) { 00700 if (entry[0]-exit[0] != 0) { 00701 d2 = 0; 00702 val2 = redexit[0]; 00703 } else if (entry[1]-exit[1]!= 0){ 00704 d2 = 1; 00705 val2 = redexit[1]; 00706 } else { 00707 d2 = 2; 00708 val2 = redexit[2]; 00709 } 00710 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: %d %d %d line ends at p2 inside bin\n",this_node,xbin,ybin,zbin);); 00711 } 00712 else { 00713 d2 = 0; 00714 val2 = xbin+sign10[0]; 00715 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: %d %d %d line leaves through x = %e face of box\n",this_node,xbin,ybin,zbin,val2);); 00716 } 00717 } 00718 else { 00719 d2 = 1; 00720 val2 = ybin+sign10[1]; 00721 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: %d %d %d line leaves through y = %e face of box direction %d\n",this_node,xbin,ybin,zbin,val2,sign[1]);); 00722 } 00723 } 00724 else { 00725 d2= 2; 00726 val2 = zbin+sign10[2]; 00727 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: %d %d %d line leaves through z = %e face of box\n",this_node,xbin,ybin,zbin,val2);); 00728 } 00729 segment2 = 0; 00730 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: entry %f %f %f exit %f %f %f d1 %d val1 %f d2 %d val2 %f\n",this_node,entry[0],entry[1],entry[2],exit[0],exit[1],exit[2],d1,range_start[d1]+val1*range[d1]/(double)bins[d1],d2,range_start[d2]+val2*range[d2]/(double)bins[d2]);); 00731 for (l=0;l<3;l++) { 00732 if (getlength(entry,exit,d1,range_start[d1]+val1*range[d1]/(double)bins[d1],d2,range_start[d2]+val2*range[d2]/(double)bins[d2],l,&segment) != 1) return 0; 00733 segment2 += pow(segment,2); 00734 for (k=0;k<3;k++) { 00735 TensorInBin[xbin*bins[1]*bins[2]+ybin*bins[2]+zbin].e[3*k+l] += force[k] * segment; 00736 } 00737 } 00738 calclength += pow(segment2,0.5); 00739 } 00740 counter ++; 00741 } 00742 } 00743 PTENSOR_TRACE(fprintf(stderr,"%d: distribute_tensors: calclength is %e and length is %e\n}",this_node,calclength,length);); 00744 00745 if (calclength - length >0.0000000001) { 00746 char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); 00747 ERROR_SPRINTF(errtxt, "{%d: analyze stress_profile: bug in distribute tensor code - calclength is %e and length is %e}",this_node,calclength,length); 00748 return 0; 00749 } 00750 free(occupiedzbins); 00751 free(occupiedybins); 00752 free(starty); 00753 free(startz); 00754 } 00755 return 1; 00756 } 00757 00758 int reducepos(double pos[3], int bins[3], double centre[3], double range[3], int reducedpos[3]) { 00759 int i; 00760 double working[3]; 00761 get_mi_vector(working, pos, centre); 00762 for (i=0;i<3;i++) { 00763 reducedpos[i] = floor((working[i]+range[i]/2.0)*(double)bins[i]/range[i]); 00764 } 00765 return 1; 00766 } 00767 00768 int incubewithskin(double pos[3], double centre[3], double range[3]) 00769 { 00770 double working[3]; 00771 int i; 00772 get_mi_vector(working, pos, centre); 00773 for (i=0; i <3; i++) { 00774 if (fabs(working[i]) > range[i]/2.0 + skin+max_cut) return 0; 00775 } 00776 return 1; 00777 } 00778 00779 int whichbin(double pos[3], int bins[3], double centre[3], double range[3], int *bin) 00780 /*calculates which bin a particle is in for local_stress_tensor */ 00781 { 00782 int reducedpos[3]; 00783 int i; 00784 reducepos(pos, bins, centre, range, reducedpos); 00785 for (i=0;i<3;i++) { 00786 if ((reducedpos[i] < 0) || (reducedpos[i] >= bins[i])) { 00787 *bin = -1; 00788 return 1; 00789 } 00790 } 00791 *bin = reducedpos[0]*bins[1]*bins[2] + reducedpos[1]*bins[2] + reducedpos[2]; 00792 return 1; 00793 } 00794 00795 int get_nonbonded_interaction(Particle *p1, Particle *p2, double *force) 00796 { 00797 /* returns the non_bonded interaction between two particles */ 00798 00799 double dist2, dist; 00800 double d[3]; 00801 #ifdef ELECTROSTATICS 00802 int i; 00803 double eforce[3]; 00804 #endif 00805 00806 force[0]=0; force[1]=0; force[2]=0; 00807 00808 00809 if ((p1->p.identity != p2->p.identity)&&(checkIfParticlesInteract(p1->p.type, p2->p.type))) { 00810 /* distance calculation */ 00811 get_mi_vector(d, p1->r.p, p2->r.p); 00812 dist2 = SQR(d[0]) + SQR(d[1]) + SQR(d[2]); 00813 dist = sqrt(dist2); 00814 calc_non_bonded_pair_force_simple(p1,p2,d,dist,dist2,force); 00815 #ifdef ELECTROSTATICS 00816 if (coulomb.method != COULOMB_NONE) { 00817 switch (coulomb.method) { 00818 #ifdef P3M 00819 case COULOMB_P3M_GPU: 00820 fprintf(stderr,"WARNING: Local stress tensor calculation cannot handle GPU P3M electrostatics so it is left out\n"); 00821 break; 00822 case COULOMB_P3M: 00823 fprintf(stderr,"WARNING: Local stress tensor calculation cannot handle P3M electrostatics so it is left out\n"); 00824 break; 00825 #endif 00826 case COULOMB_DH: 00827 for (i = 0; i < 3; i++) 00828 eforce[i] = 0; 00829 add_dh_coulomb_pair_force(p1,p2,d,dist, eforce); 00830 for(i=0;i<3;i++) 00831 force[i] += eforce[i]; 00832 break; 00833 case COULOMB_RF: 00834 for (i = 0; i < 3; i++) 00835 eforce[i] = 0; 00836 add_rf_coulomb_pair_force(p1,p2,d,dist, eforce); 00837 for(i=0;i<3;i++) 00838 force[i] += eforce[i]; 00839 break; 00840 case COULOMB_INTER_RF: 00841 // this is done elsewhere 00842 break; 00843 case COULOMB_MMM1D: 00844 fprintf(stderr,"WARNING: Local stress tensor calculation cannot handle MMM1D electrostatics so it is left out\n"); 00845 default: 00846 fprintf(stderr,"WARNING: Local stress tensor calculation does not recognise this electrostatic interaction\n"); 00847 } 00848 } 00849 #endif /*ifdef ELECTROSTATICS */ 00850 00851 #ifdef DIPOLES 00852 if (coulomb.Dmethod != DIPOLAR_NONE) { 00853 switch (coulomb.Dmethod) { 00854 #ifdef DP3M 00855 case DIPOLAR_P3M: 00856 fprintf(stderr,"WARNING: Local stress tensor calculation cannot handle P3M magnetostatics so it is left out\n"); 00857 break; 00858 #endif 00859 case DIPOLAR_ALL_WITH_ALL_AND_NO_REPLICA: 00860 fprintf(stderr,"WARNING: Local stress tensor calculation cannot handle DAWAANR magnetostatics so it is left out\n"); 00861 break; 00862 case DIPOLAR_DS: 00863 fprintf(stderr,"WARNING: Local stress tensor calculation cannot handle MAGNETIC DIPOLAR SUM magnetostatics so it is left out\n"); 00864 break; 00865 00866 default: 00867 fprintf(stderr,"WARNING: Local stress tensor calculation does not recognise this magnetostatic interaction\n"); 00868 } 00869 } 00870 #endif /*ifdef DIPOLES */ 00871 00872 00873 } /*if p1-> ... */ 00874 return 0; 00875 } 00876 00877 int local_stress_tensor_calc(DoubleList *TensorInBin, int bins[3], int periodic[3], double range_start[3], double range[3]) 00878 { 00879 /*calculates local stress tensors in cuboid bins 00880 uses Irving Kirkwood method 00881 we consider a cube of space starting with a corner at position range_start extending to 00882 range_start + range 00883 if the variable periodic is set to 1 in dimension i then the cube is assumed to span the periodic box 00884 this cube is divided into bins[0] bins in the x direction bins[1] in the y direction, and bins[2] in the z direction 00885 */ 00886 00887 int i,j; /*counter for dimension */ 00888 double binvolume; 00889 int c, np, n, bin; 00890 double centre[3]; 00891 Cell *cell; 00892 Particle *p1, *p2, **pairs; 00893 Particle *particles; 00894 double force[3]; 00895 int k,l; 00896 int type_num; 00897 Bonded_ia_parameters *iaparams; 00898 double dx[3]; 00899 00900 00901 for (i = 0; i < 3; i ++) { 00902 if (periodic[i]) { 00903 range[i] = box_l[i]; 00904 range_start[i] = 0; 00905 } 00906 } 00907 00908 /* find centre of analyzed cube */ 00909 for (i=0;i<3;i++) { 00910 centre[i] = range_start[i] + range[i]/2.0; 00911 } 00912 00913 /* We consider all particles that are within a certain distance of the cube. The skin is used as this distance. If the 00914 skin from on opposite sides of the box overlaps then we produce an error message. To code dround this would be 00915 creating unnecessary work since I can't imagine when we might want that */ 00916 00917 if (skin < 0.0) { 00918 char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); 00919 ERROR_SPRINTF(errtxt, "{analyze stress_profile: parameter skin not set}"); 00920 return 0; 00921 } 00922 for (i=0;i<3;i++) { 00923 if ((! periodic[i]) && (range[i] + 2*skin +2*max_cut > box_l[i])) { 00924 char *errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE); 00925 ERROR_SPRINTF(errtxt, "{analyze stress_profile: Analyzed box (%g) with skin+max_cut(%g) is larger than simulation box (%g).\n",range[i],skin+max_cut,box_l[i]); 00926 return 0; 00927 } 00928 range_start[i] = drem_down(range_start[i],box_l[i]); 00929 } 00930 PTENSOR_TRACE(fprintf(stderr,"%d: Running stress_profile\n",this_node)); 00931 00932 binvolume = range[0]*range[1]*range[2]/(double)bins[0]/(double)bins[1]/(double)bins[2]; 00933 00934 /* this next bit loops over all pair of particles, calculates the force between them, and distributes it amongst the tensors */ 00935 00936 // loop over all local cells 00937 for (c = 0; c < local_cells.n; c++) { 00938 cell = local_cells.cell[c]; 00939 particles = cell->part; 00940 np = cell->n; 00941 // loop over all particles in this cell 00942 for(i = 0; i < np; i++) { 00943 p1 = &(particles[i]); 00944 whichbin(p1->r.p,bins,centre, range, &bin); 00945 if (bin >= 0) { 00946 PTENSOR_TRACE(fprintf(stderr,"%d:Got particle number %d i is %d pos is %f %f %f \n",this_node,p1->p.identity,i,p1->r.p[0],p1->r.p[1],p1->r.p[2])); 00947 PTENSOR_TRACE(fprintf(stderr,"%d:Ideal gas component is {",this_node)); 00948 for(k=0;k<3;k++) { 00949 for(l=0;l<3;l++) { 00950 TensorInBin[bin].e[k*3 + l] += (p1->m.v[k])*(p1->m.v[l])*PMASS(*p1)/time_step/time_step; 00951 PTENSOR_TRACE(fprintf(stderr,"%f ",(p1->m.v[k])*(p1->m.v[l])*PMASS(*p1)/time_step/time_step)); 00952 } 00953 } 00954 00955 PTENSOR_TRACE(fprintf(stderr,"}\n")); 00956 } 00957 00958 /* bonded contributions */ 00959 j = 0; 00960 while(j < p1->bl.n) { 00961 type_num = p1->bl.e[j++]; 00962 iaparams = &bonded_ia_params[type_num]; 00963 00964 /* fetch particle 2 */ 00965 p2 = local_particles[p1->bl.e[j++]]; 00966 get_mi_vector(dx, p1->r.p, p2->r.p); 00967 calc_bonded_force(p1,p2,iaparams,&j,dx,force); 00968 PTENSOR_TRACE(fprintf(stderr,"%d: Bonded to particle %d with force %f %f %f\n",this_node,p2->p.identity,force[0],force[1],force[2])); 00969 if ((pow(force[0],2)+pow(force[1],2)+pow(force[2],2)) > 0) { 00970 if (distribute_tensors(TensorInBin,force,bins,range_start,range,p1->r.p, p2->r.p) != 1) return 0; 00971 } 00972 } 00973 } 00974 00975 // Loop cell neighbors 00976 for (n = 0; n < dd.cell_inter[c].n_neighbors; n++) { 00977 pairs = dd.cell_inter[c].nList[n].vList.pair; 00978 np = dd.cell_inter[c].nList[n].vList.n; 00979 00980 // verlet list loop // 00981 for(i=0; i<2*np; i+=2) { 00982 p1 = pairs[i]; // pointer to particle 1 00983 p2 = pairs[i+1]; // pointer to particle 2 00984 if ((incubewithskin(p1->r.p,centre,range)) && (incubewithskin(p2->r.p,centre,range))) { 00985 get_nonbonded_interaction(p1,p2, force); 00986 PTENSOR_TRACE(fprintf(stderr,"%d:Looking at pair %d %d force is %f %f %f\n",this_node,p1->p.identity, p2->p.identity,force[0],force[1], force[2])); 00987 if ((pow(force[0],2)+pow(force[1],2)+pow(force[2],2)) > 0) { 00988 if (distribute_tensors(TensorInBin,force,bins,range_start,range,p1->r.p, p2->r.p) != 1) return 0; 00989 } 00990 } else { 00991 // PTENSOR_TRACE(fprintf(stderr,"%d:Looking at pair %d %d not in cube with skin\n",this_node,p1->p.identity, p2->p.identity)); 00992 } 00993 } 00994 } 00995 } 00996 00997 for (i=0;i<bins[0]*bins[1]*bins[2];i++) { 00998 for (j=0;j<9;j++) { 00999 TensorInBin[i].e[j] /= binvolume; 01000 } 01001 } 01002 01003 return 1; 01004 } 01005 01006 01007 /************************************************************/ 01008 int observable_compute_stress_tensor(int v_comp, double *A, unsigned int n_A) 01009 { 01010 int i, j; 01011 double value; 01012 double p_vel[3]; 01013 01014 /* if desired (v_comp==1) replace ideal component with instantaneous one */ 01015 if (total_pressure.init_status != 1+v_comp ) { 01016 init_virials(&total_pressure); 01017 init_p_tensor(&total_p_tensor); 01018 01019 init_virials_non_bonded(&total_pressure_non_bonded); 01020 init_p_tensor_non_bonded(&total_p_tensor_non_bonded); 01021 01022 if(v_comp && (integ_switch == INTEG_METHOD_NPT_ISO) && !(nptiso.invalidate_p_vel)) { 01023 if (total_pressure.init_status == 0) 01024 master_pressure_calc(0); 01025 p_tensor.data.e[0] = 0.0; 01026 MPI_Reduce(nptiso.p_vel, p_vel, 3, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD); 01027 for(i=0; i<3; i++) 01028 if(nptiso.geometry & nptiso.nptgeom_dir[i]) 01029 p_tensor.data.e[0] += p_vel[i]; 01030 p_tensor.data.e[0] /= (nptiso.dimension*nptiso.volume); 01031 total_pressure.init_status = 1+v_comp; } 01032 else 01033 master_pressure_calc(v_comp); 01034 } 01035 01036 for(j=0; j<9; j++) { 01037 value = total_p_tensor.data.e[j]; 01038 for (i = 1; i < total_p_tensor.data.n/9; i++) value += total_p_tensor.data.e[9*i + j]; 01039 A[j]=value; 01040 } 01041 return 0; 01042 }
1.7.5.1