ESPResSo 3.2.0-11-g9950804-git
Extensible Simulation Package for Soft Matter Research
forces.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 #ifndef _FORCES_H
00022 #define _FORCES_H
00023 /** \file forces.h Force calculation. 
00024  *
00025  *  \todo Preprocessor switches for all forces (Default: everything is turned on).
00026  *  \todo Implement more flexible thermostat, %e.g. which thermostat to use.
00027  *
00028  *  For more information see forces.c .
00029  */
00030 #include "utils.h"
00031 #include "thermostat.h"
00032 #ifdef MOLFORCES
00033 #include "topology.h"
00034 #endif
00035 #include "npt.h"
00036 #include "adresso.h"
00037 #include "virtual_sites.h"
00038 #include "metadynamics.h"
00039 
00040 /* include the force files */
00041 #include "p3m.h"
00042 #include "p3m-dipolar.h"
00043 #include "lj.h"
00044 #include "ljgen.h"
00045 #include "steppot.h"
00046 #include "hertzian.h"
00047 #include "gaussian.h"
00048 #include "bmhtf-nacl.h"
00049 #include "buckingham.h"
00050 #include "soft_sphere.h"
00051 #include "hat.h"
00052 #include "maggs.h"
00053 #include "tab.h"
00054 #include "overlap.h"
00055 #include "ljcos.h"
00056 #include "ljcos2.h"
00057 #include "ljangle.h"
00058 #include "gb.h"
00059 #include "fene.h"
00060 #include "object-in-fluid/stretching_force.h"
00061 #include "object-in-fluid/area_force_local.h"
00062 #include "object-in-fluid/area_force_global.h"
00063 #include "object-in-fluid/bending_force.h"
00064 #include "object-in-fluid/volume_force.h"
00065 #include "harmonic.h"
00066 #include "subt_lj.h"
00067 #include "angle.h"
00068 #include "angle_harmonic.h"
00069 #include "angle_cosine.h"
00070 #include "angle_cossquare.h"
00071 #include "angledist.h"
00072 #include "dihedral.h"
00073 #include "debye_hueckel.h"
00074 #include "endangledist.h"
00075 #include "reaction_field.h"
00076 #include "mmm1d.h"
00077 #include "mmm2d.h"
00078 #include "comforce.h"
00079 #include "comfixed.h"
00080 #include "molforces.h"
00081 #include "morse.h"
00082 #include "elc.h"
00083 #include "iccp3m.h"
00084 #include "collision.h" 
00085 /* end of force files */
00086 
00087 /** \name Exported Functions */
00088 /************************************************************/
00089 /*@{*/
00090 
00091 /** Calculate forces.
00092  *
00093  *  A short list, what the function is doing:
00094  *  <ol>
00095  *  <li> Initialize forces with: \ref friction_thermo_langevin (ghost forces with zero).
00096  *  <li> Calculate bonded interaction forces:<br>
00097  *       Loop all local particles (not the ghosts). 
00098  *       <ul>
00099  *       <li> FENE
00100  *       <li> ANGLE (cos bend potential)
00101  *       </ul>
00102  *  <li> Calculate non-bonded short range interaction forces:<br>
00103  *       Loop all \ref IA_Neighbor::vList "verlet lists" of all \ref #cells.
00104  *       <ul>
00105  *       <li> Lennard-Jones.
00106  *       <li> Buckingham.
00107  *       <li> Real space part: Coulomb.
00108  *       <li> Ramp.
00109  *       </ul>
00110  *  <li> Calculate long range interaction forces:<br>
00111          Uses <a href=P3M_calc_kspace_forces> P3M_calc_kspace_forces </a>
00112  *  </ol>
00113  */
00114 void force_calc();
00115 
00116 /** Set forces of all ghosts to zero
00117 */
00118 void init_forces_ghosts();
00119 
00120 /** Check if forces are NAN 
00121 */
00122 void check_forces();
00123 
00124 
00125 MDINLINE void calc_non_bonded_pair_force_parts(Particle *p1, Particle *p2, IA_parameters *ia_params,double d[3],
00126                                          double dist, double dist2, double force[3],double torgue1[3],double torgue2[3])
00127 {
00128 #ifdef NO_INTRA_NB
00129   if (p1->p.mol_id==p2->p.mol_id) return;
00130 #endif
00131   /* lennard jones */
00132 #ifdef LENNARD_JONES
00133   add_lj_pair_force(p1,p2,ia_params,d,dist, force);
00134 #endif
00135   /* lennard jones generic */
00136 #ifdef LENNARD_JONES_GENERIC
00137   add_ljgen_pair_force(p1,p2,ia_params,d,dist, force);
00138 #endif
00139   /* Directional LJ */
00140 #ifdef LJ_ANGLE
00141   /* The forces are propagated within the function */
00142   add_ljangle_pair_force(p1,p2,ia_params,d,dist);
00143 #endif
00144   /* smooth step */
00145 #ifdef SMOOTH_STEP
00146   add_SmSt_pair_force(p1,p2,ia_params,d,dist,dist2, force);
00147 #endif
00148   /* Hertzian force */
00149 #ifdef HERTZIAN
00150   add_hertzian_pair_force(p1,p2,ia_params,d,dist,dist2, force);
00151 #endif
00152   /* Gaussian force */
00153 #ifdef GAUSSIAN
00154   add_gaussian_pair_force(p1,p2,ia_params,d,dist,dist2, force);
00155 #endif
00156   /* BMHTF NaCl */
00157 #ifdef BMHTF_NACL
00158   add_BMHTF_pair_force(p1,p2,ia_params,d,dist,dist2, force);
00159 #endif
00160   /* buckingham*/
00161 #ifdef BUCKINGHAM
00162   add_buck_pair_force(p1,p2,ia_params,d,dist,force);
00163 #endif
00164   /* morse*/
00165 #ifdef MORSE
00166   add_morse_pair_force(p1,p2,ia_params,d,dist,force);
00167 #endif
00168  /*soft-sphere potential*/
00169 #ifdef SOFT_SPHERE
00170   add_soft_pair_force(p1,p2,ia_params,d,dist,force);
00171 #endif
00172  /*hat potential*/
00173 #ifdef HAT
00174   add_hat_pair_force(p1,p2,ia_params,d,dist,force);
00175 #endif
00176   /* lennard jones cosine */
00177 #ifdef LJCOS
00178   add_ljcos_pair_force(p1,p2,ia_params,d,dist,force);
00179 #endif
00180   /* lennard jones cosine */
00181 #ifdef LJCOS2
00182   add_ljcos2_pair_force(p1,p2,ia_params,d,dist,force);
00183 #endif
00184   /* tabulated */
00185 #ifdef TABULATED
00186   add_tabulated_pair_force(p1,p2,ia_params,d,dist,force);
00187 #endif
00188   /* Gay-Berne */
00189 #ifdef GAY_BERNE
00190   add_gb_pair_force(p1,p2,ia_params,d,dist,force,torgue1,torgue2);
00191 #endif
00192 #ifdef INTER_RF
00193   add_interrf_pair_force(p1,p2,ia_params,d,dist, force);
00194 #endif
00195 #ifdef ADRESS
00196 #ifdef INTERFACE_CORRECTION
00197   add_adress_tab_pair_force(p1,p2,ia_params,d,dist,force);
00198 #endif
00199 #endif
00200 }
00201 
00202 MDINLINE void calc_non_bonded_pair_force(Particle *p1,Particle *p2,IA_parameters *ia_params,double d[3],double dist,double dist2,double force[3],double t1[3],double t2[3]){
00203 #ifdef MOL_CUT
00204    //You may want to put a correction factor and correction term for smoothing function else then theta
00205    if (checkIfParticlesInteractViaMolCut(p1,p2,ia_params)==1)
00206 #endif
00207    {
00208       calc_non_bonded_pair_force_parts(p1, p2, ia_params,d, dist, dist2,force,t1,t2);
00209    }
00210 }
00211 
00212 MDINLINE void calc_non_bonded_pair_force_simple(Particle *p1,Particle *p2,double d[3],double dist,double dist2,double force[3]){
00213    IA_parameters *ia_params = get_ia_param(p1->p.type,p2->p.type);
00214    double t1[3],t2[3];
00215 #ifdef ADRESS
00216   int j;
00217   double force_weight=adress_non_bonded_force_weight(p1,p2);
00218   if (force_weight<ROUND_ERROR_PREC) return;
00219 #endif
00220   calc_non_bonded_pair_force(p1,p2,ia_params,d,dist,dist2,force,t1,t2);
00221 #ifdef ADRESS
00222    for (j=0;j<3;j++){
00223       force[j]*=force_weight;
00224    }
00225 #endif
00226 }
00227 
00228 MDINLINE void calc_non_bonded_pair_force_from_partcfg(Particle *p1,Particle *p2,IA_parameters *ia_params,double d[3],double dist,double dist2,double force[3],double t1[3],double t2[3]){
00229 #ifdef MOL_CUT
00230    //You may want to put a correction factor and correction term for smoothing function else then theta
00231    if (checkIfParticlesInteractViaMolCut_partcfg(p1,p2,ia_params)==1)
00232 #endif
00233    {
00234      calc_non_bonded_pair_force_parts(p1, p2, ia_params,d, dist, dist2,force,t1,t2);
00235    }
00236 }
00237 
00238 MDINLINE void calc_non_bonded_pair_force_from_partcfg_simple(Particle *p1,Particle *p2,double d[3],double dist,double dist2,double force[3]){
00239    IA_parameters *ia_params = get_ia_param(p1->p.type,p2->p.type);
00240    double t1[3],t2[3];
00241    calc_non_bonded_pair_force_from_partcfg(p1,p2,ia_params,d,dist,dist2,force,t1,t2);
00242 }
00243 
00244 /** Calculate non bonded forces between a pair of particles.
00245     @param p1        pointer to particle 1.
00246     @param p2        pointer to particle 2.
00247     @param d         vector between p1 and p2. 
00248     @param dist      distance between p1 and p2.
00249     @param dist2     distance squared between p1 and p2. */
00250 MDINLINE void add_non_bonded_pair_force(Particle *p1, Particle *p2, 
00251                                         double d[3], double dist, double dist2)
00252 {
00253   IA_parameters *ia_params = get_ia_param(p1->p.type,p2->p.type);
00254   double force[3] = { 0., 0., 0. };
00255   double torque1[3] = { 0., 0., 0. };
00256   double torque2[3] = { 0., 0., 0. };
00257   int j;
00258   
00259 
00260 #ifdef COLLISION_DETECTION
00261   if (collision_params.mode > 0)
00262     detect_collision(p1,p2);
00263 #endif
00264 
00265 #ifdef ADRESS
00266   double tmp,force_weight=adress_non_bonded_force_weight(p1,p2);
00267   if (force_weight<ROUND_ERROR_PREC) return;
00268 #endif
00269 
00270   FORCE_TRACE(fprintf(stderr, "%d: interaction %d<->%d dist %f\n", this_node, p1->p.identity, p2->p.identity, dist));
00271 
00272   /***********************************************/
00273   /* thermostat                                  */
00274   /***********************************************/
00275 
00276 #ifdef DPD
00277   /* DPD thermostat forces */
00278   if ( thermo_switch & THERMO_DPD ) add_dpd_thermo_pair_force(p1,p2,d,dist,dist2);
00279 #endif
00280 
00281 #ifdef INTER_DPD
00282   if ( thermo_switch == THERMO_INTER_DPD ) add_inter_dpd_pair_force(p1,p2,ia_params,d,dist,dist2);
00283 #endif
00284 
00285   /***********************************************/
00286   /* non bonded pair potentials                  */
00287   /***********************************************/
00288 
00289    calc_non_bonded_pair_force(p1,p2,ia_params,d,dist,dist2,force,torque1,torque2);
00290 
00291   /***********************************************/
00292   /* short range electrostatics                  */
00293   /***********************************************/
00294 
00295 #ifdef ELECTROSTATICS
00296   if (coulomb.method == COULOMB_DH)
00297     add_dh_coulomb_pair_force(p1,p2,d,dist,force);
00298   
00299   if (coulomb.method == COULOMB_RF)
00300     add_rf_coulomb_pair_force(p1,p2,d,dist,force);
00301 #endif
00302 
00303   /*********************************************************************/
00304   /* everything before this contributes to the virial pressure in NpT, */
00305   /* but nothing afterwards                                            */
00306   /*********************************************************************/
00307 #ifdef NPT
00308   for (j = 0; j < 3; j++)
00309     if(integ_switch == INTEG_METHOD_NPT_ISO)
00310       nptiso.p_vir[j] += force[j] * d[j];
00311 #endif
00312 
00313   /***********************************************/
00314   /* long range electrostatics                   */
00315   /***********************************************/
00316 
00317 #ifdef ELECTROSTATICS
00318 
00319   /* real space coulomb */
00320   double q1q2 = p1->p.q*p2->p.q;
00321   if (!(iccp3m_initialized && iccp3m_cfg.set_flag)) {
00322     switch (coulomb.method) {
00323   #ifdef P3M
00324     case COULOMB_ELC_P3M: {
00325       if (q1q2) {
00326         p3m_add_pair_force(q1q2,d,dist2,dist,force); 
00327       
00328         // forces from the virtual charges
00329         // they go directly onto the particles, since they are not pairwise forces
00330         if (elc_params.dielectric_contrast_on)
00331         ELC_P3M_dielectric_layers_force_contribution(p1, p2, p1->f.f, p2->f.f);
00332       }
00333       break;
00334     }
00335     case COULOMB_P3M: {
00336   #ifdef NPT
00337       if (q1q2) {
00338         double eng = p3m_add_pair_force(q1q2,d,dist2,dist,force);
00339         if(integ_switch == INTEG_METHOD_NPT_ISO)
00340         nptiso.p_vir[0] += eng;
00341       }
00342   #else
00343       if (q1q2) p3m_add_pair_force(q1q2,d,dist2,dist,force); 
00344   #endif
00345       break;
00346     }
00347   #endif
00348     case COULOMB_MMM1D:
00349       if (q1q2) add_mmm1d_coulomb_pair_force(q1q2,d,dist2,dist,force);
00350       break;
00351     case COULOMB_MMM2D:
00352       if (q1q2) add_mmm2d_coulomb_pair_force(q1q2,d,dist2,dist,force);
00353       break;
00354     case COULOMB_NONE:
00355       break;
00356     }
00357   }
00358 
00359 #endif /*ifdef ELECTROSTATICS */
00360 
00361 
00362   /***********************************************/
00363   /* long range magnetostatics                   */
00364   /***********************************************/
00365 
00366 
00367 #ifdef DIPOLES
00368   /* real space magnetic dipole-dipole */
00369   switch (coulomb.Dmethod) {
00370 #ifdef DP3M
00371   case  DIPOLAR_MDLC_P3M: 
00372    //fall trough 
00373   case DIPOLAR_P3M: {
00374 #ifdef NPT
00375     double eng = dp3m_add_pair_force(p1,p2,d,dist2,dist,force);
00376     if(integ_switch == INTEG_METHOD_NPT_ISO)
00377       nptiso.p_vir[0] += eng;
00378 #else
00379     dp3m_add_pair_force(p1,p2,d,dist2,dist,force);
00380 #endif
00381     break;
00382   }
00383 #endif /*ifdef DP3M */
00384   }  
00385 #endif /* ifdef DIPOLES */
00386 
00387   /***********************************************/
00388   /* add total nonbonded forces to particle      */
00389   /***********************************************/
00390 
00391   for (j = 0; j < 3; j++) {
00392 #ifdef ADRESS
00393     tmp=force_weight*force[j];
00394     p1->f.f[j] += tmp;
00395     p2->f.f[j] -= tmp;
00396 #else
00397     p1->f.f[j] += force[j];
00398     p2->f.f[j] -= force[j];
00399 #endif
00400 #ifdef ROTATION
00401     p1->f.torque[j] += torque1[j];
00402     p2->f.torque[j] += torque2[j];
00403 #endif
00404   }
00405 }
00406 
00407 /** Calculate bonded forces for one particle.
00408     @param p1 particle for which to calculate forces
00409 */
00410 MDINLINE void add_bonded_force(Particle *p1)
00411 {
00412   double dx[3]     = { 0., 0., 0. };
00413   double force[3]  = { 0., 0., 0. };
00414   double force2[3] = { 0., 0., 0. };
00415   double force3[3] = { 0., 0., 0. };
00416 #ifdef ROTATION
00417   double torque1[3] = { 0., 0., 0. };
00418   double torque2[3] = { 0., 0., 0. };
00419 #endif
00420   char *errtxt;
00421   Particle *p2, *p3 = NULL, *p4 = NULL;
00422   Bonded_ia_parameters *iaparams;
00423   int i, j, type_num, type, n_partners, bond_broken;
00424 
00425 #ifdef ADRESS
00426   double tmp, force_weight=1;
00427   //double tmp,force_weight=adress_bonded_force_weight(p1);
00428   //if (force_weight<ROUND_ERROR_PREC) return;
00429 #endif
00430 
00431   i = 0;
00432   while(i<p1->bl.n) {
00433     type_num = p1->bl.e[i++];
00434     iaparams = &bonded_ia_params[type_num];
00435     type = iaparams->type;
00436     n_partners = iaparams->num;
00437 
00438     /* fetch particle 2, which is always needed */
00439     p2 = local_particles[p1->bl.e[i++]];
00440     if (!p2) {
00441       errtxt = runtime_error(128 + 2*ES_INTEGER_SPACE);
00442       ERROR_SPRINTF(errtxt,"{078 bond broken between particles %d and %d (particles not stored on the same node)} ",
00443               p1->p.identity, p1->bl.e[i-1]);
00444       return;
00445     }
00446 
00447     /* fetch particle 3 eventually */
00448     if (n_partners >= 2) {
00449       p3 = local_particles[p1->bl.e[i++]];
00450       if (!p3) {
00451         errtxt = runtime_error(128 + 3*ES_INTEGER_SPACE);
00452         ERROR_SPRINTF(errtxt,"{079 bond broken between particles %d, %d and %d (particles not stored on the same node)} ",
00453                 p1->p.identity, p1->bl.e[i-2], p1->bl.e[i-1]);
00454         return;
00455       }
00456     }
00457 
00458     /* fetch particle 4 eventually */
00459     if (n_partners >= 3) {
00460       p4 = local_particles[p1->bl.e[i++]];
00461       if (!p4) {
00462         errtxt = runtime_error(128 + 4*ES_INTEGER_SPACE);
00463         ERROR_SPRINTF(errtxt,"{080 bond broken between particles %d, %d, %d and %d (particles not stored on the same node)} ",
00464                 p1->p.identity, p1->bl.e[i-3], p1->bl.e[i-2], p1->bl.e[i-1]);
00465         return;
00466       }
00467     }
00468 
00469     if (n_partners == 1) {
00470       /* because of the NPT pressure calculation for pair forces, we need the
00471          1->2 distance vector here. For many body interactions this vector is not needed,
00472          and the pressure calculation not yet clear. */
00473       get_mi_vector(dx, p1->r.p, p2->r.p);
00474     }
00475 
00476     switch (type) {
00477     case BONDED_IA_FENE:
00478       bond_broken = calc_fene_pair_force(p1, p2, iaparams, dx, force);
00479       break;
00480     case BONDED_IA_HARMONIC:
00481       bond_broken = calc_harmonic_pair_force(p1, p2, iaparams, dx, force);
00482       break;
00483     case BONDED_IA_STRETCHING_FORCE:
00484       bond_broken = calc_stretching_force_pair_force(p1, p2, iaparams, dx, force);
00485       break;
00486     case BONDED_IA_AREA_FORCE_LOCAL:
00487       bond_broken = calc_area_force_local(p1, p2, p3, iaparams, force, force2, force3);
00488       break;
00489 #ifdef AREA_FORCE_GLOBAL
00490     case BONDED_IA_AREA_FORCE_GLOBAL:
00491       bond_broken = 0;
00492       break;
00493 #endif
00494     case BONDED_IA_BENDING_FORCE:
00495       bond_broken = calc_bending_force(p1, p2, p3, p4, iaparams, force, force2);
00496       break;
00497 #ifdef VOLUME_FORCE
00498     case BONDED_IA_VOLUME_FORCE:
00499       bond_broken = 0;
00500       break;
00501 #endif
00502 #ifdef LENNARD_JONES
00503     case BONDED_IA_SUBT_LJ:
00504       bond_broken = calc_subt_lj_pair_force(p1, p2, iaparams, dx, force);
00505       break;
00506 #endif
00507 #ifdef BOND_ANGLE_OLD
00508         /* the first case is not needed and should not be called */ 
00509     case BONDED_IA_ANGLE_OLD:
00510       bond_broken = calc_angle_force(p1, p2, p3, iaparams, force, force2);
00511       break;
00512 #endif
00513 #ifdef BOND_ANGLE
00514     case BONDED_IA_ANGLE_HARMONIC:
00515       bond_broken = calc_angle_harmonic_force(p1, p2, p3, iaparams, force, force2);
00516       break;
00517     case BONDED_IA_ANGLE_COSINE:
00518       bond_broken = calc_angle_cosine_force(p1, p2, p3, iaparams, force, force2);
00519       break;
00520     case BONDED_IA_ANGLE_COSSQUARE:
00521       bond_broken = calc_angle_cossquare_force(p1, p2, p3, iaparams, force, force2);
00522       break;
00523 #endif
00524 #ifdef BOND_ANGLEDIST
00525     case BONDED_IA_ANGLEDIST:
00526       bond_broken = calc_angledist_force(p1, p2, p3, iaparams, force, force2);
00527       break;
00528 #endif
00529 #ifdef BOND_ENDANGLEDIST
00530     case BONDED_IA_ENDANGLEDIST:
00531       bond_broken = calc_endangledist_pair_force(p1, p2, iaparams, dx, force, force2);
00532       break;
00533 #endif
00534     case BONDED_IA_DIHEDRAL:
00535       bond_broken = calc_dihedral_force(p1, p2, p3, p4, iaparams, force, force2, force3);
00536       break;
00537 #ifdef BOND_CONSTRAINT
00538     case BONDED_IA_RIGID_BOND:
00539       //add_rigid_bond_pair_force(p1,p2, iaparams, force, force2);
00540       bond_broken = 0; 
00541       force[0]=force[1]=force[2]=0.0;
00542       break;
00543 #endif
00544 #ifdef TABULATED
00545     case BONDED_IA_TABULATED:
00546       switch(iaparams->p.tab.type) {
00547       case TAB_BOND_LENGTH:
00548         bond_broken = calc_tab_bond_force(p1, p2, iaparams, dx, force);
00549         break;
00550       case TAB_BOND_ANGLE:
00551         bond_broken = calc_tab_angle_force(p1, p2, p3, iaparams, force, force2);
00552         break;
00553       case TAB_BOND_DIHEDRAL:
00554         bond_broken = calc_tab_dihedral_force(p1, p2, p3, p4, iaparams, force, force2, force3);
00555         break;
00556       default:
00557         errtxt = runtime_error(128 + ES_INTEGER_SPACE);
00558         ERROR_SPRINTF(errtxt,"{081 add_bonded_force: tabulated bond type of atom %d unknown\n", p1->p.identity);
00559         return;
00560       }
00561       break;
00562 #endif
00563 #ifdef OVERLAPPED
00564     case BONDED_IA_OVERLAPPED:
00565       switch(iaparams->p.overlap.type) {
00566       case OVERLAP_BOND_LENGTH:
00567         bond_broken = calc_overlap_bond_force(p1, p2, iaparams, dx, force);
00568         break;
00569       case OVERLAP_BOND_ANGLE:
00570         bond_broken = calc_overlap_angle_force(p1, p2, p3, iaparams, force, force2);
00571         break;
00572       case OVERLAP_BOND_DIHEDRAL:
00573         bond_broken = calc_overlap_dihedral_force(p1, p2, p3, p4, iaparams, force, force2, force3);
00574         break;
00575       default:
00576         errtxt = runtime_error(128 + ES_INTEGER_SPACE);
00577         ERROR_SPRINTF(errtxt,"{081 add_bonded_force: overlapped bond type of atom %d unknown\n", p1->p.identity);
00578         return;
00579       }
00580       break;
00581 #endif
00582 #ifdef BOND_VIRTUAL
00583     case BONDED_IA_VIRTUAL_BOND:
00584       bond_broken = 0;
00585       force[0]=force[1]=force[2]=0.0;
00586       break;
00587 #endif
00588     default :
00589       errtxt = runtime_error(128 + ES_INTEGER_SPACE);
00590       ERROR_SPRINTF(errtxt,"{082 add_bonded_force: bond type of atom %d unknown\n", p1->p.identity);
00591       return;
00592     }
00593 
00594     switch (n_partners) {
00595     case 1:
00596       if (bond_broken) {
00597         char *errtext = runtime_error(128 + 2*ES_INTEGER_SPACE);
00598         ERROR_SPRINTF(errtext,"{083 bond broken between particles %d and %d} ",
00599                 p1->p.identity, p2->p.identity); 
00600         continue;
00601       }
00602       
00603 #ifdef ADRESS
00604       force_weight = adress_bonded_force_weight(p1,p2);
00605 #endif
00606 
00607       for (j = 0; j < 3; j++) {
00608 #ifdef ADRESS
00609         tmp=force_weight*force[j];
00610         p1->f.f[j] += tmp;
00611         p2->f.f[j] -= tmp;
00612 #else // ADRESS
00613 
00614         switch (type) {
00615 #ifdef BOND_ENDANGLEDIST
00616         case BONDED_IA_ENDANGLEDIST:
00617           p1->f.f[j] += force[j];
00618           p2->f.f[j] += force2[j];
00619           break;
00620 #endif // BOND_ENDANGLEDIST
00621         default:
00622           p1->f.f[j] += force[j];
00623           p2->f.f[j] -= force[j];
00624 #ifdef ROTATION
00625           p1->f.torque[j] += torque1[j];
00626           p2->f.torque[j] += torque2[j];
00627 #endif
00628         }
00629 #endif // NOT ADRESS
00630 
00631 #ifdef NPT
00632         if(integ_switch == INTEG_METHOD_NPT_ISO)
00633           nptiso.p_vir[j] += force[j] * dx[j];
00634 #endif
00635       }
00636       break;
00637     case 2:
00638       if (bond_broken) {
00639         char *errtext = runtime_error(128 + 3*ES_INTEGER_SPACE);
00640         ERROR_SPRINTF(errtext,"{084 bond broken between particles %d, %d and %d} ",
00641                 p1->p.identity, p2->p.identity, p3->p.identity); 
00642         continue;
00643       }
00644       
00645 #ifdef ADRESS
00646       force_weight=adress_angle_force_weight(p1,p2,p3);
00647 #endif
00648       for (j = 0; j < 3; j++) {
00649 #ifdef ADRESS
00650         p1->f.f[j] += force_weight*force[j];
00651         p2->f.f[j] += force_weight*force2[j];
00652         p3->f.f[j] -= force_weight*(force[j] + force2[j]);
00653 #else
00654 switch (type) {
00655         case BONDED_IA_AREA_FORCE_LOCAL:
00656                 p1->f.f[j] += force[j];
00657                 p2->f.f[j] += force2[j];
00658                 p3->f.f[j] += force3[j];
00659                 break;
00660 #ifdef AREA_FORCE_GLOBAL
00661         case BONDED_IA_AREA_FORCE_GLOBAL:
00662                 break;
00663 #endif
00664 #ifdef VOLUME_FORCE
00665         case BONDED_IA_VOLUME_FORCE:
00666                 break;
00667 #endif
00668         default:
00669                 p1->f.f[j] += force[j];
00670                 p2->f.f[j] += force2[j];
00671                 p3->f.f[j] -= (force[j] + force2[j]);
00672         }
00673 #endif
00674       }
00675       break;
00676     case 3:
00677       if (bond_broken) {
00678         char *errtext = runtime_error(128 + 4*ES_INTEGER_SPACE);
00679         ERROR_SPRINTF(errtext,"{085 bond broken between particles %d, %d, %d and %d} ",
00680                 p1->p.identity, p2->p.identity, p3->p.identity, p4->p.identity); 
00681         continue;
00682       }
00683 #ifdef ADRESS
00684       force_weight=adress_dihedral_force_weight(p1,p2,p3,p4);
00685 #endif 
00686       for (j = 0; j < 3; j++) {
00687 #ifdef ADRESS
00688         p1->f.f[j] += force_weight*force[j];
00689         p2->f.f[j] += force_weight*force2[j];
00690         p3->f.f[j] += force_weight*force3[j];
00691         p4->f.f[j] -= force_weight*(force[j] + force2[j] + force3[j]);
00692 #else
00693         
00694         switch (type) {
00695         case BONDED_IA_BENDING_FORCE:
00696                 p1->f.f[j] -= (force[j]*0.5+force2[j]*0.5);
00697                 p2->f.f[j] += force[j];
00698                 p3->f.f[j] -= (force[j]*0.5+force2[j]*0.5);
00699                 p4->f.f[j] += force2[j];
00700                 break;
00701         default:
00702                 p1->f.f[j] += force[j];
00703                 p2->f.f[j] += force2[j];
00704                 p3->f.f[j] += force3[j];
00705                 p4->f.f[j] -= (force[j] + force2[j] + force3[j]);
00706         }
00707         
00708 #endif
00709       }
00710       break;
00711     }
00712   }
00713 }  
00714 
00715 /** add force to another. This is used when collecting ghost forces. */
00716 MDINLINE void add_force(ParticleForce *F_to, ParticleForce *F_add)
00717 {
00718   int i;
00719   for (i = 0; i < 3; i++)
00720     F_to->f[i] += F_add->f[i];
00721 #ifdef ROTATION
00722   for (i = 0; i < 3; i++)
00723     F_to->torque[i] += F_add->torque[i];
00724 #endif
00725 }
00726 
00727 MDINLINE void check_particle_force(Particle *part)
00728 {
00729   
00730   int i;
00731   for (i=0; i< 3; i++) {
00732     if isnan(part->f.f[i]) {
00733       char *errtext = runtime_error(128);
00734       ERROR_SPRINTF(errtext,"{999 force on particle was NAN.} ");
00735     }
00736   }
00737 
00738 #ifdef ROTATION
00739   for (i=0; i< 3; i++) {
00740     if isnan(part->f.torque[i]) {
00741       char *errtext = runtime_error(128);
00742       ERROR_SPRINTF(errtext,"{999 force on particle was NAN.} ");
00743     }
00744   }
00745 #endif
00746 }
00747 
00748 /*@}*/
00749 
00750 #endif