ESPResSo 3.2.0-11-g9950804-git
Extensible Simulation Package for Soft Matter Research
pressure.h
Go to the documentation of this file.
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