// This file is part of the ESPResSo distribution (http://www.espresso.mpg.de). // It is therefore subject to the ESPResSo license agreement which you accepted upon receiving the distribution // and by which you are legally bound while utilizing this file in any form or way. // There is NO WARRANTY, not even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. // You should have received a copy of that license along with this program; // if not, refer to http://www.espresso.mpg.de/license.html where its current version can be found, or // write to Max-Planck-Institute for Polymer Research, Theory Group, PO Box 3148, 55021 Mainz, Germany. // Copyright (c) 2002-2006; all rights reserved unless otherwise stated. #ifndef THERMOSTAT_H #define THERMOSTAT_H /** \file thermostat.h Responsible: Hanjo */ #include #include #include "utils.h" #include "particle_data.h" #include "parser.h" #include "random.h" #include "global.h" #include "communication.h" #include "integrate.h" #include "cells.h" #include "pressure.h" #include "lb.h" #include "dpd.h" /** \name Thermostat switches*/ /************************************************************/ /address@hidden/ #define THERMO_OFF 0 #define THERMO_LANGEVIN 1 #define THERMO_DPD 2 #define THERMO_NPT_ISO 4 #define THERMO_LB 8 #define THERMO_INTER_DPD 16 /address@hidden/ /************************************************ * exported variables ************************************************/ /** Switch determining which thermostat to use. This is a or'd value of the different possible thermostats (defines: \ref THERMO_OFF, \ref THERMO_LANGEVIN, \ref THERMO_DPD \ref THERMO_NPT_ISO). If it is zero all thermostats are switched off and the temperature is set to zero. */ extern int thermo_switch; /** temperature. */ extern double temperature; /** Langevin friction coefficient gamma. */ extern double langevin_gamma; /** Friction coefficient for nptiso-thermostat's inline-function friction_therm0_nptiso */ extern double nptiso_gamma0; /** Friction coefficient for nptiso-thermostat's inline-function friction_thermV_nptiso */ extern double nptiso_gammav; /************************************************ * functions ************************************************/ /** Implementation of the tcl command \ref tcl_thermostat. This function allows to change the used thermostat and to set its parameters. */ int thermostat(ClientData data, Tcl_Interp *interp, int argc, char **argv); /** initialize constants of the thermostat on start of integration */ void thermo_init(); /** very nasty: if we recalculate force when leaving/reentering the integrator, a(t) and a((t-dt)+dt) are NOT equal in the vv algorithm. The random numbers are drawn twice, resulting in a different variance of the random force. This is corrected by additional heat when restarting the integrator here. Currently only works for the Langevin thermostat, although probably also others are affected. */ void thermo_heat_up(); /** pendant to \ref thermo_heat_up */ void thermo_cool_down(); #ifdef NPT /** add velocity-dependend noise and friction for NpT-sims to the particle's velocity @param dt_vj j-component of the velocity scaled by time_step dt @return j-component of the noise added to the velocity, also scaled by dt (contained in prefactors) */ MDINLINE double friction_therm0_nptiso(double dt_vj) { extern double nptiso_pref1, nptiso_pref2; if(thermo_switch & THERMO_NPT_ISO) return ( nptiso_pref1*dt_vj + nptiso_pref2*(d_random()-0.5) ); return 0.0; } /** add p_diff-dependend noise and friction for NpT-sims to \ref nptiso_struct::p_diff */ MDINLINE double friction_thermV_nptiso(double p_diff) { extern double nptiso_pref3, nptiso_pref4; if(thermo_switch & THERMO_NPT_ISO) return ( nptiso_pref3*p_diff + nptiso_pref4*(d_random()-0.5) ); return 0.0; } #endif /** Callback marking setting the temperature as outdated */ int thermo_ro_callback(Tcl_Interp *interp, void *_data); /** overwrite the forces of a particle with the friction term, i.e. \f$ F_i= -\gamma v_i + \xi_i\f$. */ MDINLINE void friction_thermo_langevin(Particle *p) { extern double langevin_pref1, langevin_pref2; int j; #ifdef MASS double massf = sqrt(PMASS(*p)); #else double massf = 1; #endif for ( j = 0 ; j < 3 ; j++) { #ifdef VIRTUAL_SITES if (ifParticleIsVirtual(p)) continue; #endif #ifdef EXTERNAL_FORCES if (!(p->l.ext_flag & COORD_FIXED(j))) #endif p->f.f[j] = langevin_pref1*p->m.v[j]*PMASS(*p) + langevin_pref2*(d_random()-0.5)*massf; #ifdef EXTERNAL_FORCES else p->f.f[j] = 0; #endif } ONEPART_TRACE(if(p->p.identity==check_id) fprintf(stderr,"%d: OPT: LANG f = (%.3e,%.3e,%.3e)\n",this_node,p->f.f[0],p->f.f[1],p->f.f[2])); THERMO_TRACE(fprintf(stderr,"%d: Thermo: P %d: force=(%.3e,%.3e,%.3e)\n",this_node,p->p.identity,p->f.f[0],p->f.f[1],p->f.f[2])); } #ifdef ROTATION /** set the particle torques to the friction term, i.e. \f$\tau_i=-\gamma w_i + \xi_i\f$. The same friction coefficient \f$\gamma\f$ is used as that for translation. */ MDINLINE void friction_thermo_langevin_rotation(Particle *p) { extern double langevin_pref1,langevin_pref2; int j; #ifdef EXTERNAL_FORCES if(!(p->l.ext_flag & COORDS_FIX_MASK)) #endif { for ( j = 0 ; j < 3 ; j++) #ifdef ROTATIONAL_INERTIA // If the torques were rescaled by the inertia (like the mass...the following line would used // p->f.torque[j] = -langevin_gamma*p->m.omega[j] + langevin_pref2*(d_random()-0.5)*sqrt(p->p.rinertia[j]); // p->f.torque[j] = langevin_pref1*p->m.omega[j]*p->p.rinertia[j]/3 + 1.732*langevin_pref2*(d_random()-0.5)*sqrt(p->p.rinertia[j]); p->f.torque[j] = langevin_pref1*p->m.omega[j]*p->p.rinertia[j]/3 + langevin_pref2*(d_random()-0.5)*sqrt(p->p.rinertia[j]/1.732); #else p->f.torque[j] = langevin_pref1*p->m.omega[j] + langevin_pref2*(d_random()-0.5); #endif ONEPART_TRACE(if(p->p.identity==check_id) fprintf(stderr,"%d: OPT: LANG f = (%.3e,%.3e,%.3e)\n",this_node,p->f.f[0],p->f.f[1],p->f.f[2])); THERMO_TRACE(fprintf(stderr,"%d: Thermo: P %d: force=(%.3e,%.3e,%.3e)\n",this_node,p->p.identity,p->f.f[0],p->f.f[1],p->f.f[2])); } } #endif #ifdef LB int thermo_parse_lb(Tcl_Interp * interp, int argc, char ** argv); #endif #endif