ESPResSo 3.2.0-167-g2c9ead1-git
Extensible Simulation Package for Soft Matter Research
thermostat_tcl.c
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 thermostat.c
00022     Implementation of \ref thermostat.h "thermostat.h"
00023  */
00024 #include <math.h>
00025 #include "utils.h"
00026 
00027 #include "communication.h"
00028 #include "lattice.h"
00029 #include "npt.h"
00030 #include "ghmc.h"
00031 
00032 #include "particle_data.h"
00033 #include "parser.h"
00034 #include "random.h"
00035 #include "global.h"
00036 #include "integrate.h"
00037 #include "cells.h"
00038 #include "lb.h"
00039 #include "dpd.h"
00040 #include "dpd_tcl.h"
00041 #include "virtual_sites.h"
00042 #include "thermostat_tcl.h"
00043 
00044 
00045 int tclcommand_thermostat_parse_off(Tcl_Interp *interp, int argc, char **argv) 
00046 {
00047   /* set temperature to zero */
00048   temperature = 0;
00049   mpi_bcast_parameter(FIELD_TEMPERATURE);
00050   /* langevin thermostat */
00051   langevin_gamma = 0;
00052   mpi_bcast_parameter(FIELD_LANGEVIN_GAMMA);
00053   /* dpd thermostat */
00054 #ifdef DPD
00055   dpd_switch_off();
00056 #endif
00057 #ifdef INTER_DPD
00058   inter_dpd_switch_off();
00059 #endif
00060 #ifdef NPT
00061   /* npt isotropic thermostat */
00062   nptiso_gamma0 = 0;
00063   mpi_bcast_parameter(FIELD_NPTISO_G0);
00064   nptiso_gammav = 0;
00065   mpi_bcast_parameter(FIELD_NPTISO_GV);
00066 #endif
00067 #ifdef GHMC
00068   /* ghmc thermostat */
00069   ghmc_nmd = 1;
00070   mpi_bcast_parameter(FIELD_GHMC_NMD);
00071   ghmc_phi = 1;
00072   mpi_bcast_parameter(FIELD_GHMC_PHI);
00073   ghmc_mflip = GHMC_MFLIP_OFF;
00074   mpi_bcast_parameter(FIELD_GHMC_FLIP);
00075   ghmc_tscale = GHMC_TSCALE_OFF;
00076   mpi_bcast_parameter(FIELD_GHMC_SCALE);
00077 #endif
00078   /* switch thermostat off */
00079   thermo_switch = THERMO_OFF;
00080   mpi_bcast_parameter(FIELD_THERMO_SWITCH);
00081   return (TCL_OK);
00082 }
00083 
00084 int tclcommand_thermostat_parse_langevin(Tcl_Interp *interp, int argc, char **argv) 
00085 {
00086   double temp, gamma;
00087 
00088   /* check number of arguments */
00089   if (argc < 4) {
00090     Tcl_AppendResult(interp, "wrong # args:  should be \n\"",
00091                      argv[0]," ",argv[1]," <temp> <gamma>\"", (char *)NULL);
00092     return (TCL_ERROR);
00093   }
00094 
00095   /* check argument types */
00096   if ( !ARG_IS_D(2, temp) || !ARG_IS_D(3, gamma)) {
00097     Tcl_AppendResult(interp, argv[0]," ",argv[1]," needs two DOUBLES", (char *)NULL);
00098     return (TCL_ERROR);
00099   }
00100 
00101   if (temp < 0 || gamma < 0) {
00102     Tcl_AppendResult(interp, "temperature and gamma must be positive", (char *)NULL);
00103     return (TCL_ERROR);
00104   }
00105 
00106   /* broadcast parameters */
00107   temperature = temp;
00108   langevin_gamma = gamma;
00109   thermo_switch = ( thermo_switch | THERMO_LANGEVIN );
00110   mpi_bcast_parameter(FIELD_THERMO_SWITCH);
00111   mpi_bcast_parameter(FIELD_TEMPERATURE);
00112   mpi_bcast_parameter(FIELD_LANGEVIN_GAMMA);
00113   return (TCL_OK);
00114 }
00115 
00116 #ifdef NPT
00117 int tclcommand_thermostat_parse_npt_isotropic(Tcl_Interp *interp, int argc, char **argv) 
00118 {
00119   double temp, gamma0, gammav;
00120   /* check number of arguments */
00121   if (argc < 5) {
00122     Tcl_AppendResult(interp, "wrong # args:  should be \n\"",
00123                      argv[0]," set ",argv[1]," <temp> <gamma0> <gammav>\"", (char *)NULL);
00124     return (TCL_ERROR);
00125   }
00126   /* check argument types */
00127   if ( !ARG_IS_D(2, temp) || !ARG_IS_D(3, gamma0) || !ARG_IS_D(4, gammav) ) {
00128     Tcl_AppendResult(interp, argv[0]," ",argv[1]," needs four DOUBLES", (char *)NULL);
00129     return (TCL_ERROR);
00130   }
00131   /* broadcast parameters */
00132   temperature = temp;
00133   nptiso_gamma0 = gamma0;
00134   nptiso_gammav = gammav;
00135 
00136   thermo_switch = ( thermo_switch | THERMO_NPT_ISO );
00137   mpi_bcast_parameter(FIELD_THERMO_SWITCH);
00138   mpi_bcast_parameter(FIELD_TEMPERATURE);
00139   mpi_bcast_parameter(FIELD_NPTISO_G0);
00140   mpi_bcast_parameter(FIELD_NPTISO_GV);
00141   return (TCL_OK);
00142 }
00143 #endif
00144 
00145 #ifdef GHMC
00146 int tclcommand_thermostat_parse_ghmc(Tcl_Interp *interp, int argc, char **argv) 
00147 {
00148   double temp, phi;
00149         int n_md_steps;
00150 
00151   /* check number of arguments */
00152   if (argc < 5) {
00153     Tcl_AppendResult(interp, "wrong # args:  should be \n\"",
00154                      argv[0]," ",argv[1]," <temp> <md_steps> <phi> {flip|no_flip|random_flip}\"", (char *)NULL);
00155     return (TCL_ERROR);
00156   }
00157   /* check argument types */
00158   if ( !ARG_IS_D(2, temp) || !ARG_IS_I(3, n_md_steps) || !ARG_IS_D(4, phi) ) {
00159     Tcl_AppendResult(interp, argv[2]," ",argv[3]," needs two DOUBLES and one INTEGER", (char *)NULL);
00160     return (TCL_ERROR);
00161   }
00162   
00163   if (temp < 0 || n_md_steps <= 0) {
00164     Tcl_AppendResult(interp, "temperature and number of MD steps must be positive", (char *)NULL);
00165     return (TCL_ERROR);
00166   }
00167 
00168   if (phi < 0 || phi > 1) {
00169     Tcl_AppendResult(interp, "the parameter phi must be between zero and one", (char *)NULL);
00170     return (TCL_ERROR);
00171   }
00172   
00173   if(argc > 5) {
00174     if (ARG_IS_S(5,"-flip")) {
00175       ghmc_mflip = GHMC_MFLIP_ON;
00176       
00177     } 
00178     else if (ARG_IS_S(5,"-no_flip")) {
00179       ghmc_mflip = GHMC_MFLIP_OFF;
00180     } 
00181     else if (ARG_IS_S(5,"-random_flip")) {
00182       ghmc_mflip = GHMC_MFLIP_RAND;
00183     } 
00184   } else {
00185     ghmc_mflip = GHMC_MFLIP_OFF;
00186   }
00187   
00188         if(argc > 6) {
00189     if (ARG_IS_S(6,"-scale")) {
00190       ghmc_tscale = GHMC_TSCALE_ON;
00191     } 
00192     else if (ARG_IS_S(6,"-no_scale")) {
00193       ghmc_tscale = GHMC_TSCALE_OFF;
00194     } 
00195   } else {
00196     ghmc_tscale = GHMC_TSCALE_OFF;
00197   }
00198   
00199   /* broadcast parameters */
00200   temperature = temp;
00201   ghmc_nmd = n_md_steps;
00202   ghmc_phi = phi;
00203 
00204   thermo_switch = ( thermo_switch | THERMO_GHMC );
00205   mpi_bcast_parameter(FIELD_THERMO_SWITCH);
00206   mpi_bcast_parameter(FIELD_TEMPERATURE);
00207   mpi_bcast_parameter(FIELD_GHMC_NMD);
00208   mpi_bcast_parameter(FIELD_GHMC_PHI);
00209   mpi_bcast_parameter(FIELD_GHMC_FLIP);
00210   mpi_bcast_parameter(FIELD_GHMC_SCALE);
00211   return (TCL_OK);
00212 }
00213 #endif
00214 
00215 int tclcommand_thermostat_print_all(Tcl_Interp *interp)
00216 {
00217   char buffer[TCL_DOUBLE_SPACE];
00218   /* thermostat not initialized */
00219   if(temperature == -1.0) {
00220     Tcl_AppendResult(interp,"{ not initialized } ", (char *)NULL);
00221     return (TCL_OK);
00222   }
00223 
00224   /* no thermostat on */
00225   if(thermo_switch == THERMO_OFF) {
00226     Tcl_AppendResult(interp,"{ off } ", (char *)NULL);
00227     return (TCL_OK);
00228   }
00229 
00230   /* langevin */
00231   if(thermo_switch & THERMO_LANGEVIN ) {
00232     Tcl_PrintDouble(interp, temperature, buffer);
00233     Tcl_AppendResult(interp,"{ langevin ",buffer, (char *)NULL);
00234     Tcl_PrintDouble(interp, langevin_gamma, buffer);
00235     Tcl_AppendResult(interp," ",buffer," } ", (char *)NULL);
00236   }
00237     
00238 #ifdef DPD
00239  /* dpd */
00240   if(thermo_switch & THERMO_DPD) { tclcommand_thermostat_parse_and_print_dpd(interp);}
00241 #endif
00242 
00243 #ifdef NPT
00244   /* npt_isotropic */
00245   if(thermo_switch & THERMO_NPT_ISO) {
00246     Tcl_PrintDouble(interp, temperature, buffer);
00247     Tcl_AppendResult(interp,"{ npt_isotropic ",buffer, (char *)NULL);
00248     Tcl_PrintDouble(interp, nptiso_gamma0, buffer);
00249     Tcl_AppendResult(interp," ",buffer, (char *)NULL);
00250     Tcl_PrintDouble(interp, nptiso_gammav, buffer);
00251     Tcl_AppendResult(interp," ",buffer, " } ", (char *)NULL);
00252   }
00253 #endif
00254 
00255 #ifdef GHMC
00256   /* ghmc */
00257   if(thermo_switch & THERMO_GHMC) {
00258     Tcl_PrintDouble(interp, temperature, buffer);
00259     Tcl_AppendResult(interp,"{ ghmc ",buffer, (char *)NULL);
00260     Tcl_PrintDouble(interp, ghmc_nmd, buffer);
00261     Tcl_AppendResult(interp," ",buffer, (char *)NULL);
00262     Tcl_PrintDouble(interp, ghmc_phi, buffer);
00263     Tcl_AppendResult(interp," ",buffer, " ", (char *)NULL);
00264     switch (ghmc_mflip) {
00265       case GHMC_MFLIP_OFF:
00266         Tcl_AppendResult(interp, "-no_flip ", (char *)NULL);
00267                                 break;
00268       case GHMC_MFLIP_ON:
00269         Tcl_AppendResult(interp, "-flip ", (char *)NULL);
00270                                 break;
00271       case GHMC_MFLIP_RAND:
00272         Tcl_AppendResult(interp, "-random_flip ", (char *)NULL);
00273                                 break;
00274     }
00275     if (ghmc_tscale == GHMC_TSCALE_ON)
00276                         Tcl_AppendResult(interp, "-scale }", (char *)NULL);
00277                 else
00278                         Tcl_AppendResult(interp, "-no_scale }", (char *)NULL);
00279         }
00280 #endif
00281 
00282 #if defined(LB) || defined(LB_GPU)
00283  /* lb */
00284   if(thermo_switch & THERMO_LB) {
00285     Tcl_PrintDouble(interp, temperature, buffer);
00286     Tcl_AppendResult(interp,"{ lb ",buffer, " } ", (char *)NULL);
00287   }
00288 #endif
00289 
00290 #ifdef INTER_DPD
00291  /* inter_dpd */
00292   if(thermo_switch & THERMO_INTER_DPD) {
00293     Tcl_PrintDouble(interp, temperature, buffer);
00294     Tcl_AppendResult(interp,"{ inter_dpd ",buffer, " } ", (char *)NULL);
00295   }
00296 #endif
00297   return (TCL_OK);
00298 }
00299 
00300 int tclcommand_thermostat_print_usage(Tcl_Interp *interp, int argc, char **argv)
00301 {
00302   Tcl_AppendResult(interp, "Usage of tcl-command thermostat:\n", (char *)NULL);
00303   Tcl_AppendResult(interp, "'", argv[0], "' for status return or \n ", (char *)NULL);
00304   Tcl_AppendResult(interp, "'", argv[0], " set off' to deactivate it (=> NVE-ensemble) \n ", (char *)NULL);
00305   Tcl_AppendResult(interp, "'", argv[0], " set langevin <temp> <gamma>' or \n ", (char *)NULL);
00306 #ifdef DPD
00307   tclcommand_thermostat_print_usage_dpd(interp,argc,argv);
00308 #endif
00309 #ifdef NPT
00310   Tcl_AppendResult(interp, "'", argv[0], " set npt_isotropic <temp> <gamma0> <gammav>' ", (char *)NULL);
00311 #endif
00312 #ifdef LB
00313   Tcl_AppendResult(interp, "'", argv[0], " set lb <temperature>" , (char *)NULL);
00314 #endif
00315 #ifdef LB_GPU
00316   Tcl_AppendResult(interp, "'", argv[0], " set lb_gpu <temperature>" , (char *)NULL);
00317 #endif
00318   return (TCL_ERROR);
00319 }
00320 
00321 int tclcommand_thermostat(ClientData data, Tcl_Interp *interp, int argc, char **argv) 
00322 {
00323   int err = TCL_OK;
00324   THERMO_TRACE(fprintf(stderr,"%d: thermostat:\n",this_node));
00325 
00326   /* print thermostat status */
00327   if(argc == 1) return tclcommand_thermostat_print_all(interp);
00328   
00329   if ( ARG1_IS_S("set") )          {
00330     argc--;
00331     argv++;
00332 
00333     if (argc == 1) {
00334       Tcl_AppendResult(interp, "wrong # args: \n", (char *)NULL);
00335       return tclcommand_thermostat_print_usage(interp, argc, argv);
00336     }
00337   }
00338   if ( ARG1_IS_S("off") )
00339     err = tclcommand_thermostat_parse_off(interp, argc, argv);
00340   else if ( ARG1_IS_S("langevin"))
00341     err = tclcommand_thermostat_parse_langevin(interp, argc, argv);
00342 #ifdef DPD
00343   else if ( ARG1_IS_S("dpd") )
00344     err = tclcommand_thermostat_parse_dpd(interp, argc, argv);
00345 #endif
00346 #ifdef INTER_DPD
00347   else if ( ARG1_IS_S("inter_dpd") )
00348     err = tclcommand_thermostat_parse_inter_dpd(interp, argc, argv);
00349 #endif
00350 #ifdef NPT
00351   else if ( ARG1_IS_S("npt_isotropic") )
00352     err = tclcommand_thermostat_parse_npt_isotropic(interp, argc, argv);
00353 #endif
00354 #if defined(LB) || defined(LB_GPU)
00355   else if ( ARG1_IS_S("lb"))
00356     err = tclcommand_thermostat_parse_lb(interp, argc-1, argv+1);
00357 #endif
00358 #ifdef GHMC
00359   else if ( ARG1_IS_S("ghmc") )
00360     err = tclcommand_thermostat_parse_ghmc(interp, argc, argv);
00361 #endif
00362   else {
00363     Tcl_AppendResult(interp, "Unknown thermostat ", argv[1], "\n", (char *)NULL);
00364     return tclcommand_thermostat_print_usage(interp, argc, argv);
00365   }
00366   return gather_runtime_errors(interp, err);
00367 }
00368 
00369 int tclcommand_thermostat_parse_lb(Tcl_Interp *interp, int argc, char ** argv)
00370 {
00371 
00372 #if defined(LB) || defined(LB_GPU)
00373   double temp;
00374 
00375   /* get lb interaction type */
00376   if (argc < 2) {
00377     Tcl_AppendResult(interp, "lattice-Boltzmann needs 1 parameter: "
00378                      "<temperature>",
00379                      (char *) NULL);
00380     return TCL_ERROR;
00381   }
00382 
00383   /* copy lattice-boltzmann parameters */
00384   if (! ARG_IS_D(1, temp)) { return TCL_ERROR; }
00385 
00386   if ( temp < 0.0 ) {
00387     Tcl_AppendResult(interp, "temperature must be non-negative", (char *) NULL);
00388     return TCL_ERROR;
00389   }
00390   temperature = temp;
00391   thermo_switch = ( thermo_switch | THERMO_LB );
00392   mpi_bcast_parameter(FIELD_THERMO_SWITCH);
00393   mpi_bcast_parameter(FIELD_TEMPERATURE);
00394   
00395 #endif
00396   return TCL_OK;
00397 }