ESPResSo 3.2.0-167-g2c9ead1-git
Extensible Simulation Package for Soft Matter Research
ljcos2.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 _LJCOS2_H
00022 #define _LJCOS2_H
00023 
00024 /** \file ljcos2.h
00025  *  Routines to calculate the lennard-jones with cosine tail energy and/or  force 
00026  *  for a particle pair.  Cosine tail is different from that in ljcos.h
00027  *  Used for attractive tail/tail interactions in lipid bilayer calculations
00028  *  \ref forces.c
00029 */
00030 
00031 #include "utils.h"
00032 #include "interaction_data.h"
00033 #include "particle_data.h"
00034 #include "mol_cut.h"
00035 #include "forcecap.h"
00036 
00037 #ifdef LJCOS2
00038 #include <math.h>
00039 
00040 int ljcos2_set_params(int part_type_a, int part_type_b,
00041                       double eps, double sig, double offset,
00042                       double w);
00043 
00044 /** Calculate lj-cos2 force between particle p1 and p2 */
00045 MDINLINE void add_ljcos2_pair_force(Particle *p1, Particle *p2, IA_parameters *ia_params,
00046                                 double d[3], double dist, double force[3])
00047 {
00048   int j;
00049   double r_off, frac2, frac6, fac=0.0;
00050   if(CUTOFF_CHECK(dist < ia_params->LJCOS2_cut+ia_params->LJCOS2_offset)) { 
00051     r_off = dist - ia_params->LJCOS2_offset;
00052     /* normal case: resulting force/energy smaller than capping. */
00053     if(r_off > ia_params->LJCOS2_capradius) {
00054       if(r_off < ia_params->LJCOS2_rchange) {
00055         frac2 = SQR(ia_params->LJCOS2_sig/r_off);
00056         frac6 = frac2*frac2*frac2;
00057         fac   = 48.0 * ia_params->LJCOS2_eps * frac6*(frac6 - 0.5) / (r_off*dist);
00058       }
00059       else if (r_off< ia_params->LJCOS2_rchange + ia_params->LJCOS2_w) {
00060         fac   = -ia_params->LJCOS2_eps*M_PI/2/ia_params->LJCOS2_w/dist * sin(M_PI*(r_off-ia_params->LJCOS2_rchange)/ia_params->LJCOS2_w);
00061       }
00062       
00063       for(j=0;j<3;j++)
00064         force[j] += fac * d[j];
00065 
00066 #ifdef LJ_WARN_WHEN_CLOSE
00067       if(fac*dist > 1000) fprintf(stderr,"%d: LJ-Warning: Pair (%d-%d) force=%f dist=%f\n",
00068                                   this_node,p1->p.identity,p2->p.identity,fac*dist,dist);
00069 #endif
00070     }
00071     /* capped part of lj-cos2 potential. */
00072     else if(dist > 0.0) {
00073       frac2 = SQR(ia_params->LJCOS2_sig/ia_params->LJCOS2_capradius);
00074       frac6 = frac2*frac2*frac2;
00075       fac   = 48.0 * ia_params->LJCOS2_eps * frac6*(frac6 - 0.5) / (ia_params->LJCOS2_capradius * dist);
00076       for(j=0;j<3;j++)
00077         /* vector d is rescaled to length LJCOS2_capradius */
00078         force[j] += fac * d[j];
00079     }
00080     /* this should not happen! */
00081     else {
00082       LJ_TRACE(fprintf(stderr, "%d: Lennard-Jones warning: Particles id1=%d id2=%d exactly on top of each other\n",this_node,p1->p.identity,p2->p.identity));
00083 
00084       frac2 = SQR(ia_params->LJCOS2_sig/ia_params->LJCOS2_capradius);
00085       frac6 = frac2*frac2*frac2;
00086       fac   = 48.0 * ia_params->LJCOS2_eps * frac6*(frac6 - 0.5) / ia_params->LJCOS2_capradius;
00087 
00088       force[0] += fac * ia_params->LJCOS2_capradius;
00089     }
00090 
00091     ONEPART_TRACE(if(p1->p.identity==check_id) fprintf(stderr,"%d: OPT: LJ   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p1->f.f[0],p1->f.f[1],p1->f.f[2],p2->p.identity,dist,fac));
00092     ONEPART_TRACE(if(p2->p.identity==check_id) fprintf(stderr,"%d: OPT: LJ   f = (%.3e,%.3e,%.3e) with part id=%d at dist %f fac %.3e\n",this_node,p2->f.f[0],p2->f.f[1],p2->f.f[2],p1->p.identity,dist,fac));
00093 
00094     LJ_TRACE(fprintf(stderr,"%d: LJ: Pair (%d-%d) dist=%.3f: force+-: (%.3e,%.3e,%.3e)\n",
00095                      this_node,p1->p.identity,p2->p.identity,dist,fac*d[0],fac*d[1],fac*d[2]));
00096   }
00097 }
00098 
00099 /** calculate lj-cos2 energy between particle p1 and p2. */
00100 MDINLINE double ljcos2_pair_energy(Particle *p1, Particle *p2, IA_parameters *ia_params,
00101                                 double d[3], double dist)
00102 {
00103   double r_off, frac2, frac6;
00104 
00105   if(CUTOFF_CHECK(dist < ia_params->LJCOS2_cut+ia_params->LJCOS2_offset)) {
00106     r_off = dist - ia_params->LJCOS2_offset;
00107     /* normal case: resulting force/energy smaller than capping. */
00108     if(r_off > ia_params->LJCOS2_capradius) {
00109       if (r_off < ia_params->LJCOS2_rchange){
00110         frac2 = SQR(ia_params->LJCOS2_sig/r_off);
00111         frac6 = frac2*frac2*frac2;
00112         return 4.0*ia_params->LJCOS2_eps*(SQR(frac6)-frac6);
00113       }
00114       else if (r_off < ia_params->LJCOS2_rchange + ia_params->LJCOS2_w){
00115         return -ia_params->LJCOS2_eps/2 * (cos(M_PI*(r_off-ia_params->LJCOS2_rchange)/ia_params->LJCOS2_w)+1);
00116       }
00117     }
00118     /* capped part of lj-cos2 potential. */
00119     else if(dist > 0.0) {
00120       frac2 = SQR(ia_params->LJCOS2_sig/ia_params->LJCOS2_capradius);
00121       frac6 = frac2*frac2*frac2;
00122       return 4.0*ia_params->LJCOS2_eps*(SQR(frac6)-frac6);
00123     }
00124     /* this should not happen! */
00125     else {
00126       frac2 = SQR(ia_params->LJCOS2_sig/ia_params->LJCOS2_capradius);
00127       frac6 = frac2*frac2*frac2;
00128       return 4.0*ia_params->LJCOS2_eps*(SQR(frac6)-frac6);
00129     }
00130   }
00131   return 0.0;
00132 }
00133 
00134 /** calculate ljcos2_capradius from force_cap */
00135 void calc_ljcos2_cap_radii();
00136 
00137 #endif /* ifdef LJCOS2 */
00138 #endif