![]() |
ESPResSo 3.2.0-11-g9950804-git
Extensible Simulation Package for Soft Matter Research
|
00001 /* 00002 Copyright (C) 2010,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.h 00022 Pressure calculation. Really similar to \ref energy.h "energy.h". 00023 */ 00024 00025 #ifndef _PRESSURE_H 00026 #define _PRESSURE_H 00027 00028 #include "utils.h" 00029 #include "integrate.h" 00030 #include "statistics.h" 00031 #include "thermostat.h" 00032 #include "adresso.h" 00033 #include "forces.h" 00034 #include "npt.h" 00035 00036 /** \name Exported Variables */ 00037 /************************************************************/ 00038 /*@{*/ 00039 /// 00040 extern Observable_stat virials, total_pressure, p_tensor, total_p_tensor; 00041 /// 00042 extern Observable_stat_non_bonded virials_non_bonded, total_pressure_non_bonded, p_tensor_non_bonded, total_p_tensor_non_bonded; 00043 /*@}*/ 00044 00045 /** \name Exported Functions */ 00046 /************************************************************/ 00047 /*@{*/ 00048 void init_virials(Observable_stat *stat); 00049 void init_virials_non_bonded(Observable_stat_non_bonded *stat_nb); 00050 void init_p_tensor_non_bonded(Observable_stat_non_bonded *stat_nb); 00051 void init_p_tensor(Observable_stat *stat); 00052 void master_pressure_calc(int v_comp); 00053 00054 00055 /** Calculates the pressure in the system from a virial expansion using the terms from \ref calculate_verlet_virials or \ref nsq_calculate_virials dependeing on the used cell system.<BR> 00056 @param result here the data about the scalar pressure are stored 00057 @param result_t here the data about the stress tensor are stored 00058 @param result_nb here the data about the intra- and inter- molecular nonbonded contributions to scalar pressure are stored 00059 @param result_t_nb here the data about the intra- and inter- molecular nonbonded contributions to stress tensor are stored 00060 @param v_comp flag which enables (1) compensation of the velocities required 00061 for deriving a pressure reflecting \ref nptiso_struct::p_inst 00062 (hence it only works with domain decomposition); naturally it 00063 therefore doesn't make sense to use it without NpT. 00064 */ 00065 void pressure_calc(double *result, double *result_t, double *result_nb, double *result_t_nb, int v_comp); 00066 00067 /** Calculate non bonded energies between a pair of particles. 00068 @param p1 pointer to particle 1. 00069 @param p2 pointer to particle 2. 00070 @param d vector between p1 and p2. 00071 @param dist distance between p1 and p2. 00072 @param dist2 distance squared between p1 and p2. */ 00073 MDINLINE void add_non_bonded_pair_virials(Particle *p1, Particle *p2, double d[3], 00074 double dist, double dist2) 00075 { 00076 int p1molid, p2molid, k, l; 00077 double force[3] = {0, 0, 0}; 00078 00079 calc_non_bonded_pair_force_simple(p1, p2,d, dist, dist2,force); 00080 00081 *obsstat_nonbonded(&virials, p1->p.type, p2->p.type) += d[0]*force[0] + d[1]*force[1] + d[2]*force[2]; 00082 00083 /* stress tensor part */ 00084 for(k=0;k<3;k++) 00085 for(l=0;l<3;l++) 00086 obsstat_nonbonded(&p_tensor, p1->p.type, p2->p.type)[k*3 + l] += force[k]*d[l]; 00087 00088 p1molid = p1->p.mol_id; 00089 p2molid = p2->p.mol_id; 00090 if ( p1molid == p2molid ) { 00091 *obsstat_nonbonded_intra(&virials_non_bonded, p1->p.type, p2->p.type) += d[0]*force[0] + d[1]*force[1] + d[2]*force[2]; 00092 00093 for(k=0;k<3;k++) 00094 for(l=0;l<3;l++) 00095 obsstat_nonbonded_intra(&p_tensor_non_bonded, p1->p.type, p2->p.type)[k*3 + l] += force[k]*d[l]; 00096 } 00097 if ( p1molid != p2molid ) { 00098 *obsstat_nonbonded_inter(&virials_non_bonded, p1->p.type, p2->p.type) += d[0]*force[0] + d[1]*force[1] + d[2]*force[2]; 00099 00100 for(k=0;k<3;k++) 00101 for(l=0;l<3;l++) 00102 obsstat_nonbonded_inter(&p_tensor_non_bonded, p1->p.type, p2->p.type)[k*3 + l] += force[k]*d[l]; 00103 } 00104 00105 #ifdef ELECTROSTATICS 00106 /* real space coulomb */ 00107 if (coulomb.method != COULOMB_NONE) { 00108 switch (coulomb.method) { 00109 #ifdef P3M 00110 case COULOMB_P3M: 00111 virials.coulomb[0] += p3m_pair_energy(p1->p.q*p2->p.q,d,dist2,dist); 00112 break; 00113 #endif 00114 00115 /* short range potentials, where we use the virial */ 00116 /***************************************************/ 00117 case COULOMB_DH: { 00118 double force[3] = {0, 0, 0}; 00119 00120 add_dh_coulomb_pair_force(p1,p2,d,dist, force); 00121 for(k=0;k<3;k++) 00122 for(l=0;l<3;l++) 00123 p_tensor.coulomb[k*3 + l] += force[k]*d[l]; 00124 virials.coulomb[0] += force[0]*d[0] + force[1]*d[1] + force[2]*d[2]; 00125 break; 00126 } 00127 case COULOMB_RF: { 00128 double force[3] = {0, 0, 0}; 00129 00130 add_rf_coulomb_pair_force(p1,p2,d,dist, force); 00131 for(k=0;k<3;k++) 00132 for(l=0;l<3;l++) 00133 p_tensor.coulomb[k*3 + l] += force[k]*d[l]; 00134 virials.coulomb[0] += force[0]*d[0] + force[1]*d[1] + force[2]*d[2]; 00135 break; 00136 } 00137 case COULOMB_INTER_RF: 00138 // this is done together with the other short range interactions 00139 break; 00140 default: 00141 fprintf(stderr,"calculating pressure for electrostatics method that doesn't have it implemented\n"); 00142 break; 00143 } 00144 } 00145 #endif /*ifdef ELECTROSTATICS */ 00146 00147 #ifdef DIPOLES 00148 /* real space magnetic dipole-dipole */ 00149 if (coulomb.Dmethod != DIPOLAR_NONE) { 00150 fprintf(stderr,"calculating pressure for magnetostatics which doesn't have it implemented\n"); 00151 } 00152 #endif /*ifdef DIPOLES */ 00153 } 00154 00155 MDINLINE void calc_bonded_force(Particle *p1, Particle *p2, Bonded_ia_parameters *iaparams, int *i, double dx[3], double force[3]) { 00156 #ifdef TABULATED 00157 char* errtxt; 00158 #endif 00159 00160 #ifdef ADRESS 00161 int j; 00162 double force_weight=1; 00163 //adress_bonded_force_weight(p1); 00164 if (force_weight<ROUND_ERROR_PREC) return; 00165 #endif 00166 00167 /* Calculates the bonded force between two particles */ 00168 switch(iaparams->type) { 00169 case BONDED_IA_FENE: 00170 calc_fene_pair_force(p1,p2,iaparams,dx,force); 00171 break; 00172 case BONDED_IA_HARMONIC: 00173 calc_harmonic_pair_force(p1,p2,iaparams,dx,force); 00174 break; 00175 #ifdef LENNARD_JONES 00176 case BONDED_IA_SUBT_LJ: 00177 calc_subt_lj_pair_force(p1,p2,iaparams,dx,force); 00178 break; 00179 #endif 00180 /* since it is not clear at the moment how to handle a many body interaction here, I skip it */ 00181 case BONDED_IA_ANGLE_HARMONIC: 00182 (*i)++; force[0] = force[1] = force[2] = 0; break; 00183 case BONDED_IA_ANGLE_COSINE: 00184 (*i)++; force[0] = force[1] = force[2] = 0; break; 00185 case BONDED_IA_ANGLE_COSSQUARE: 00186 (*i)++; force[0] = force[1] = force[2] = 0; break; 00187 case BONDED_IA_ANGLEDIST: 00188 (*i)++; force[0] = force[1] = force[2] = 0; break; 00189 case BONDED_IA_DIHEDRAL: 00190 (*i)+=2; force[0] = force[1] = force[2] = 0; break; 00191 00192 #ifdef TABULATED 00193 case BONDED_IA_TABULATED: 00194 // printf("BONDED TAB, Particle: %d, P2: %d TYPE_TAB: %d\n",p1->p.identity,p2->p.identity,iparams->p.tab.type); 00195 switch(iaparams->p.tab.type) { 00196 case TAB_BOND_LENGTH: 00197 calc_tab_bond_force(p1, p2, iaparams, dx, force); break; 00198 case TAB_BOND_ANGLE: 00199 (*i)++; force[0] = force[1] = force[2] = 0; break; 00200 case TAB_BOND_DIHEDRAL: 00201 (*i)+=2; force[0] = force[1] = force[2] = 0; break; 00202 default: 00203 errtxt = runtime_error(128 + ES_INTEGER_SPACE); 00204 ERROR_SPRINTF(errtxt,"{081 calc_bonded_force: tabulated bond type of atom %d unknown\n", p1->p.identity); 00205 return; 00206 } 00207 break; 00208 #endif 00209 #ifdef OVERLAPPED 00210 case BONDED_IA_OVERLAPPED: 00211 // printf("BONDED OVERLAP, Particle: %d, P2: %d TYPE_OVERLAP: %d\n",p1->p.identity,p2->p.identity,iparams->p.tab.type); 00212 switch(iaparams->p.overlap.type) { 00213 case OVERLAP_BOND_LENGTH: 00214 calc_overlap_bond_force(p1, p2, iaparams, dx, force); break; 00215 case OVERLAP_BOND_ANGLE: 00216 (*i)++; force[0] = force[1] = force[2] = 0; break; 00217 case OVERLAP_BOND_DIHEDRAL: 00218 (*i)+=2; force[0] = force[1] = force[2] = 0; break; 00219 default: 00220 errtxt = runtime_error(128 + ES_INTEGER_SPACE); 00221 ERROR_SPRINTF(errtxt,"{081 calc_bonded_force: overlapped bond type of atom %d unknown\n", p1->p.identity); 00222 return; 00223 } 00224 break; 00225 #endif 00226 #ifdef BOND_CONSTRAINT 00227 case BONDED_IA_RIGID_BOND: 00228 force[0] = force[1] = force[2] = 0; break; 00229 #endif 00230 #ifdef BOND_VIRTUAL 00231 case BONDED_IA_VIRTUAL_BOND: 00232 force[0] = force[1] = force[2] = 0; break; 00233 #endif 00234 default : 00235 // fprintf(stderr,"add_bonded_virials: WARNING: Bond type %d of atom %d unhandled\n",bonded_ia_params[type_num].type,p1->p.identity); 00236 fprintf(stderr,"add_bonded_virials: WARNING: Bond type %d , atom %d unhandled, Atom 2: %d\n",iaparams->type,p1->p.identity,p2->p.identity); 00237 force[0] = force[1] = force[2] = 0; 00238 break; 00239 } 00240 #ifdef ADRESS 00241 if((get_mol_com_particle(p1))->p.identity == (get_mol_com_particle(p2))->p.identity) 00242 force_weight = 1.0; 00243 else 00244 force_weight=adress_non_bonded_force_weight(p1,p2); 00245 for (j=0;j<3;j++){ 00246 force[j]*=force_weight; 00247 } 00248 #endif 00249 } 00250 00251 00252 /* calc_three_body_bonded_forces is called by add_three_body_bonded_stress. This 00253 routine is only entered for angular potentials. */ 00254 MDINLINE void calc_three_body_bonded_forces(Particle *p1, Particle *p2, Particle *p3, 00255 Bonded_ia_parameters *iaparams, double force1[3], double force2[3], double force3[3]) { 00256 00257 #ifdef TABULATED 00258 char* errtxt; 00259 #endif 00260 00261 switch(iaparams->type) { 00262 #ifdef BOND_ANGLE_OLD 00263 case BONDED_IA_ANGLE_OLD: 00264 // p1 is *p_mid, p2 is *p_left, p3 is *p_right 00265 calc_angle_3body_forces(p1, p2, p3, iaparams, force1, force2, force3); 00266 break; 00267 #endif 00268 #ifdef BOND_ANGLE 00269 case BONDED_IA_ANGLE_HARMONIC: 00270 // p1 is *p_mid, p2 is *p_left, p3 is *p_right 00271 calc_angle_harmonic_3body_forces(p1, p2, p3, iaparams, force1, force2, force3); 00272 break; 00273 case BONDED_IA_ANGLE_COSINE: 00274 // p1 is *p_mid, p2 is *p_left, p3 is *p_right 00275 calc_angle_cosine_3body_forces(p1, p2, p3, iaparams, force1, force2, force3); 00276 break; 00277 case BONDED_IA_ANGLE_COSSQUARE: 00278 // p1 is *p_mid, p2 is *p_left, p3 is *p_right 00279 calc_angle_cossquare_3body_forces(p1, p2, p3, iaparams, force1, force2, force3); 00280 break; 00281 #endif 00282 #ifdef TABULATED 00283 case BONDED_IA_TABULATED: 00284 switch(iaparams->p.tab.type) { 00285 case TAB_BOND_ANGLE: 00286 // p1 is *p_mid, p2 is *p_left, p3 is *p_right 00287 calc_angle_3body_tabulated_forces(p1, p2, p3, iaparams, force1, force2, force3); 00288 break; 00289 default: 00290 errtxt = runtime_error(128 + ES_INTEGER_SPACE); 00291 ERROR_SPRINTF(errtxt,"{081 calc_bonded_force: tabulated bond type of atom %d unknown\n", p1->p.identity); 00292 return; 00293 } 00294 break; 00295 #endif 00296 default : 00297 fprintf(stderr,"calc_three_body_bonded_forces: \ 00298 WARNING: Bond type %d , atom %d unhandled, Atom 2: %d\n", \ 00299 iaparams->type, p1->p.identity, p2->p.identity); 00300 break; 00301 } 00302 } 00303 00304 00305 /** Calculate bonded virials for one particle. 00306 For performance reasons the force routines add their values directly to the particles. 00307 So here we do some tricks to get the value out without changing the forces. 00308 @param p1 particle for which to calculate virials 00309 */ 00310 MDINLINE void add_bonded_virials(Particle *p1) 00311 { 00312 double dx[3], force[3] = {0,0,0}; 00313 char *errtxt; 00314 Particle *p2; 00315 Bonded_ia_parameters *iaparams; 00316 00317 int i, k, l; 00318 int type_num; 00319 00320 i = 0; 00321 while(i<p1->bl.n) { 00322 type_num = p1->bl.e[i++]; 00323 iaparams = &bonded_ia_params[type_num]; 00324 00325 /* fetch particle 2 */ 00326 p2 = local_particles[p1->bl.e[i++]]; 00327 if ( ! p2 ) { 00328 // for harmonic spring: 00329 // if cutoff was defined and p2 is not there it is anyway outside the cutoff, see calc_maximal_cutoff() 00330 if ((type_num==BONDED_IA_HARMONIC)&&(iaparams->p.harmonic.r_cut>0)) return; 00331 errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE); 00332 ERROR_SPRINTF(errtxt,"{088 bond broken between particles %d and %d (particles not stored on the same node)} ", 00333 p1->p.identity, p1->bl.e[i-1]); 00334 return; 00335 } 00336 00337 get_mi_vector(dx, p1->r.p, p2->r.p); 00338 calc_bonded_force(p1,p2,iaparams,&i,dx,force); 00339 *obsstat_bonded(&virials, type_num) += dx[0]*force[0] + dx[1]*force[1] + dx[2]*force[2]; 00340 00341 /* stress tensor part */ 00342 for(k=0;k<3;k++) 00343 for(l=0;l<3;l++) 00344 obsstat_bonded(&p_tensor, type_num)[k*3 + l] += force[k]*dx[l]; 00345 00346 } 00347 } 00348 00349 /** Calculate the contribution to the stress tensor from angular potentials. 00350 The central particle of the three-particle interaction is responsible 00351 for the contribution of the entire interaction - this is the coding 00352 not the physics. 00353 */ 00354 MDINLINE void add_three_body_bonded_stress(Particle *p1) { 00355 double dx12[3]; // espresso notation 00356 double dx21[3]; 00357 double dx31[3]; 00358 double force1[3]; 00359 double force2[3]; 00360 double force3[3]; 00361 00362 char *errtxt; 00363 Particle *p2; 00364 Particle *p3; 00365 Bonded_ia_parameters *iaparams; 00366 00367 int i, k, j, l; 00368 int type_num; 00369 int type; 00370 00371 i = 0; 00372 while(i < p1->bl.n) { 00373 /* scan bond list for angular interactions */ 00374 type_num = p1->bl.e[i]; 00375 iaparams = &bonded_ia_params[type_num]; 00376 type = iaparams->type; 00377 00378 if(type == BONDED_IA_ANGLE_HARMONIC || type == BONDED_IA_ANGLE_COSINE || type == BONDED_IA_ANGLE_COSSQUARE){ 00379 p2 = local_particles[p1->bl.e[++i]]; 00380 p3 = local_particles[p1->bl.e[++i]]; 00381 00382 get_mi_vector(dx12, p1->r.p, p2->r.p); 00383 for(j = 0; j < 3; j++) 00384 dx21[j] = -dx12[j]; 00385 00386 get_mi_vector(dx31, p3->r.p, p1->r.p); 00387 00388 for(j = 0; j < 3; j++) { 00389 force1[j] = 0.0; 00390 force2[j] = 0.0; 00391 force3[j] = 0.0; 00392 } 00393 00394 calc_three_body_bonded_forces(p1, p2, p3, iaparams, force1, force2, force3); 00395 00396 /* uncomment the next line to see that the virial is indeed zero */ 00397 //printf("W = %g\n", scalar(force2, dx21) + scalar(force3, dx31)); 00398 00399 /* three-body bonded interactions contribute to the stress but not the scalar pressure */ 00400 for(k = 0; k < 3; k++) { 00401 for(l = 0; l < 3; l++) { 00402 obsstat_bonded(&p_tensor, type_num)[3 * k + l] += force2[k] * dx21[l] + force3[k] * dx31[l]; 00403 } 00404 } 00405 i = i + 1; 00406 } 00407 // skip over non-angular interactions 00408 else if(type == BONDED_IA_FENE) { 00409 i = i + 2; 00410 } 00411 else if(type == BONDED_IA_STRETCHING_FORCE) { 00412 i = i + 2; 00413 } 00414 else if(type == BONDED_IA_AREA_FORCE_LOCAL) { 00415 i = i + 3; 00416 } 00417 else if(type == BONDED_IA_AREA_FORCE_GLOBAL) { 00418 i = i + 3; 00419 } 00420 else if(type == BONDED_IA_BENDING_FORCE) { 00421 i = i + 4; 00422 } 00423 else if(type == BONDED_IA_VOLUME_FORCE) { 00424 i = i + 3; 00425 } 00426 else if(type == BONDED_IA_HARMONIC) { 00427 i = i + 2; 00428 } 00429 #ifdef LENNARD_JONES 00430 else if(type == BONDED_IA_SUBT_LJ) { 00431 i = i + 2; 00432 } 00433 #endif 00434 else if(type == BONDED_IA_ANGLEDIST) { 00435 i = i + 3; 00436 } 00437 else if(type == BONDED_IA_DIHEDRAL) { 00438 i = i + 4; 00439 } 00440 #ifdef TABULATED 00441 else if(type == BONDED_IA_TABULATED) { 00442 if(iaparams->p.tab.type == TAB_BOND_LENGTH) { 00443 i = i + 2; 00444 } 00445 else if(iaparams->p.tab.type == TAB_BOND_ANGLE) { 00446 p2 = local_particles[p1->bl.e[++i]]; 00447 p3 = local_particles[p1->bl.e[++i]]; 00448 00449 get_mi_vector(dx12, p1->r.p, p2->r.p); 00450 for(j = 0; j < 3; j++) 00451 dx21[j] = -dx12[j]; 00452 00453 get_mi_vector(dx31, p3->r.p, p1->r.p); 00454 00455 for(j = 0; j < 3; j++) { 00456 force1[j] = 0.0; 00457 force2[j] = 0.0; 00458 force3[j] = 0.0; 00459 } 00460 00461 calc_three_body_bonded_forces(p1, p2, p3, iaparams, force1, force2, force3); 00462 00463 /* uncomment the next line to see that the virial is indeed zero */ 00464 //printf("W = %g\n", scalar(force2, dx21) + scalar(force3, dx31)); 00465 00466 /* three-body bonded interactions contribute to the stress but not the scalar pressure */ 00467 for(k = 0; k < 3; k++) { 00468 for(l = 0; l < 3; l++) { 00469 obsstat_bonded(&p_tensor, type_num)[3 * k + l] += force2[k] * dx21[l] + force3[k] * dx31[l]; 00470 } 00471 } 00472 i = i + 1; 00473 } 00474 else if (iaparams->p.tab.type == TAB_BOND_DIHEDRAL) { 00475 i = i + 4; 00476 } 00477 else { 00478 errtxt = runtime_error(128 + ES_INTEGER_SPACE); 00479 ERROR_SPRINTF(errtxt,"add_three_body_bonded_stress: match not found for particle %d.\n", p1->p.identity); 00480 } 00481 } 00482 #endif 00483 #ifdef BOND_CONSTRAINT 00484 else if(type == BONDED_IA_RIGID_BOND) { 00485 i = i + 2; 00486 } 00487 #endif 00488 #ifdef BOND_VIRTUAL 00489 else if(type == BONDED_IA_VIRTUAL_BOND) { 00490 i = i + 2; 00491 } 00492 #endif 00493 else { 00494 errtxt = runtime_error(128 + ES_INTEGER_SPACE); 00495 ERROR_SPRINTF(errtxt,"add_three_body_bonded_stress: match not found for particle %d.\n", p1->p.identity); 00496 } 00497 } 00498 } 00499 00500 /** Calculate kinetic pressure (aka energy) for one particle. 00501 @param p1 particle for which to calculate pressure 00502 @param v_comp flag which enables (1) compensation of the velocities required 00503 for deriving a pressure reflecting \ref nptiso_struct::p_inst 00504 (hence it only works with domain decomposition); naturally it 00505 therefore doesn't make sense to use it without NpT. 00506 */ 00507 MDINLINE void add_kinetic_virials(Particle *p1,int v_comp) 00508 { 00509 int k, l; 00510 /* kinetic energy */ 00511 if(v_comp) 00512 virials.data.e[0] += (SQR(p1->m.v[0] - p1->f.f[0]) + SQR(p1->m.v[1] - p1->f.f[1]) + SQR(p1->m.v[2] - p1->f.f[2]))*PMASS(*p1); 00513 else 00514 virials.data.e[0] += (SQR(p1->m.v[0]) + SQR(p1->m.v[1]) + SQR(p1->m.v[2]))*PMASS(*p1); 00515 00516 00517 /* ideal gas contribution (the rescaling of the velocities by '/=time_step' each will be done later) */ 00518 for(k=0;k<3;k++) 00519 for(l=0;l<3;l++) 00520 p_tensor.data.e[k*3 + l] += (p1->m.v[k])*(p1->m.v[l])*PMASS(*p1); 00521 00522 } 00523 00524 /** implementation of 'analyse local_stress_tensor */ 00525 int local_stress_tensor_calc (DoubleList *TensorInBin, int bins[3], int periodic[3], double range_start[3], double range[3]); 00526 00527 /** function to calculate stress tensor for the observables */ 00528 int observable_compute_stress_tensor(int v_comp, double *A, unsigned int n_A); 00529 00530 00531 /*@}*/ 00532 00533 #endif
1.7.5.1