diff --git a/regtest/basic/rt-atomic-units/Makefile b/regtest/basic/rt-atomic-units/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3703b27cea227aa053fb6d1d73f861e4384dbcee --- /dev/null +++ b/regtest/basic/rt-atomic-units/Makefile @@ -0,0 +1 @@ +include ../../scripts/test.make diff --git a/regtest/basic/rt-atomic-units/colvar.data.reference b/regtest/basic/rt-atomic-units/colvar.data.reference new file mode 100644 index 0000000000000000000000000000000000000000..14f234c39b778f82691ae0206267048eef099daa --- /dev/null +++ b/regtest/basic/rt-atomic-units/colvar.data.reference @@ -0,0 +1,6 @@ +#! FIELDS time d1_bohr d2_bohr d1_angs d2_angs uw_d1.bias uw_d1.force2 uw_d2.bias uw_d2.force2 + 0.000000 2.6212 7.0204 1.3871 3.7150 0.0000 0.0000 0.4154 1661.5891 + 20.670687 2.7518 6.8551 1.4562 3.6276 0.0000 0.0000 0.0000 0.0000 + 41.341373 2.8810 6.6913 1.5246 3.5409 0.0000 0.0000 0.0000 0.0000 + 62.012060 3.0084 6.5295 1.5920 3.4552 0.0000 0.0000 0.0000 0.0000 + 82.682747 3.1338 6.3694 1.6584 3.3706 0.0000 0.0000 0.0000 0.0000 diff --git a/regtest/basic/rt-atomic-units/config b/regtest/basic/rt-atomic-units/config new file mode 100644 index 0000000000000000000000000000000000000000..1c4f1da4113ae2d12fed7b5a7582c6b414a90768 --- /dev/null +++ b/regtest/basic/rt-atomic-units/config @@ -0,0 +1,3 @@ +type=driver +# this is to test a different name +arg="--plumed plumed.dat --trajectory-stride 1 --timestep 0.0005 --ixyz coord.xyz --length-units A" diff --git a/regtest/basic/rt-atomic-units/coord.xyz b/regtest/basic/rt-atomic-units/coord.xyz new file mode 100644 index 0000000000000000000000000000000000000000..4495c06a59c470befd2c951b8708fa96e28482f5 --- /dev/null +++ b/regtest/basic/rt-atomic-units/coord.xyz @@ -0,0 +1,40 @@ +6 +-599.95814 frame 0 + C -1.1153338489 1.1595963725 0.0026633595 + F 0.2717008097 1.1635701532 -0.0037364057 + H -1.4766016787 0.5671994739 0.8176316738 + H -1.4859910559 0.7392102656 -0.9294986560 + H -1.4639581356 2.1727043518 0.1272290666 + Cl -4.8295226891 1.2384273800 0.0007732197 +6 +-599.94812 frame 1 + C -1.1818659490 1.1524095206 0.0051714001 + F 0.2741763941 1.1670785764 -0.0075315334 + H -1.4691409094 0.5862287847 0.7989327007 + H -1.4884499890 0.7229913626 -0.9006674950 + H -1.4533091057 2.1388166575 0.1328577020 + Cl -4.8083944813 1.2398436917 0.0015918304 +6 +-599.92929 frame 2 + C -1.2476793848 1.1452612884 0.0073511127 + F 0.2765445930 1.1707086122 -0.0113962548 + H -1.4643209887 0.6002162818 0.7873648326 + H -1.4932190110 0.7049505165 -0.8770485882 + H -1.4459321082 2.1116538815 0.1388695760 + Cl -4.7872579203 1.2413205427 0.0024433571 +6 +-599.91107 frame 3 + C -1.3124432920 1.1381643086 0.0090391471 + F 0.2789248578 1.1742131400 -0.0153725474 + H -1.4632380536 0.6066769390 0.7865741441 + H -1.5014485157 0.6840822273 -0.8611897623 + H -1.4424752128 2.0949336010 0.1447615680 + Cl -4.7661005384 1.2426817556 0.0033284437 +6 +-599.90230 frame 4 + C -1.3763183333 1.1310957950 0.0101704350 + F 0.2811203252 1.1777617486 -0.0193599672 + H -1.4665738669 0.6028655802 0.8001849044 + H -1.5132096145 0.6600601686 -0.8548781193 + H -1.4429893590 2.0914195557 0.1511298281 + Cl -4.7449797329 1.2439224601 0.0042030197 diff --git a/regtest/basic/rt-atomic-units/plumed.dat b/regtest/basic/rt-atomic-units/plumed.dat new file mode 100644 index 0000000000000000000000000000000000000000..61ccd3680707be80c5543f2253698424970d43a9 --- /dev/null +++ b/regtest/basic/rt-atomic-units/plumed.dat @@ -0,0 +1,26 @@ +UNITS LENGTH=Bohr TIME=atomic ENERGY=Ha CHARGE=e MASS=amu +d1_bohr: DISTANCE ATOMS=1,2 NOPBC +d2_bohr: DISTANCE ATOMS=1,6 NOPBC +d1_angs: CUSTOM ARG=d1_bohr FUNC=0.52917721067*x PERIODIC=NO +d2_angs: CUSTOM ARG=d2_bohr FUNC=0.52917721067*x PERIODIC=NO + +UPPER_WALLS ... + ARG=d1_bohr + AT=7.0 + KAPPA=1000.0 + LABEL=uw_d1 +... UPPER_WALLS + +UPPER_WALLS ... + ARG=d2_bohr + AT=7.0 + KAPPA=1000.0 + LABEL=uw_d2 +... UPPER_WALLS + +PRINT ... + STRIDE=1 + ARG=d1_bohr,d2_bohr,d1_angs,d2_angs,uw_d1.*,uw_d2.* + FILE=colvar.data + FMT=%8.4f +... PRINT diff --git a/src/setup/Units.cpp b/src/setup/Units.cpp index b47dda7049b613a1f45226a84532b3215b332ab4..804002c242e094a46d6030bc64b4556c1db02928 100644 --- a/src/setup/Units.cpp +++ b/src/setup/Units.cpp @@ -33,9 +33,10 @@ namespace setup { //+PLUMEDOC GENERIC UNITS /* This command sets the internal units for the code. A new unit can be set by either -specifying how to convert from the plumed default unit into that new unit or by using -the shortcuts described below. This directive MUST appear at the BEGINNING of the -plumed.dat file. The same units must be used througout the plumed.dat file. +specifying a conversion factor from the plumed default unit or by using a string +corresponding to one of the defined units given below. This directive MUST +appear at the BEGINNING of the plumed.dat file. The same units must be used +througout the plumed.dat file. Notice that all input/output will then be made using the specified units. That is: all the input parameters, all the output files, etc. The only @@ -43,10 +44,19 @@ exceptions are file formats for which there is a specific convention concerning the units. For example, trajectories written in .gro format (with \ref DUMPATOMS) are going to be always in nm. +The following strings can be used to specify units. Note that the strings are +case senstive. +- LENGTH: nm (default), A (for Angstrom), um (for micrometer), Bohr (0.052917721067 nm) +- ENERGY: kj/mol (default), j/mol, kcal/mol (4.184 kj/mol), eV (96.48530749925792 kj/mol), Ha (for Hartree, 2625.499638 kj/mol) +- TIME: ps (default), fs, ns, atomic (2.418884326509e-5 ps) +- MASS: amu (default) +- CHARGE: e (default) + + \par Examples \plumedfile -# this is using nm - kj/mol - fs +# this is using Angstrom - kj/mol - fs UNITS LENGTH=A TIME=fs # compute distance between atoms 1 and 4 @@ -89,9 +99,9 @@ PLUMED_REGISTER_ACTION(Units,"UNITS") void Units::registerKeywords( Keywords& keys ) { ActionSetup::registerKeywords(keys); - keys.add("optional","LENGTH","the units of lengths. Either specify a conversion factor from the default, nm, or A (for angstroms) or um"); - keys.add("optional","ENERGY","the units of energy. Either specify a conversion factor from the default, kj/mol, or use j/mol or kcal/mol"); - keys.add("optional","TIME","the units of time. Either specify a conversion factor from the default, ps, or use ns or fs"); + keys.add("optional","LENGTH","the units of lengths. Either specify a conversion factor from the default, nm, or use one of the defined units, A (for angstroms), um (for micrometer), and Bohr."); + keys.add("optional","ENERGY","the units of energy. Either specify a conversion factor from the default, kj/mol, or use one of the defined units, j/mol, kcal/mol and Ha (for Hartree)"); + keys.add("optional","TIME","the units of time. Either specify a conversion factor from the default, ps, or use one of the defined units, ns, fs, and atomic"); keys.add("optional","MASS","the units of masses. Specify a conversion factor from the default, amu"); keys.add("optional","CHARGE","the units of charges. Specify a conversion factor from the default, e"); keys.addFlag("NATURAL",false,"use natural units"); @@ -108,32 +118,67 @@ Units::Units(const ActionOptions&ao): s=""; parse("LENGTH",s); if(s.length()>0) u.setLength(s); - if(u.getLengthString().length()>0) log.printf(" length: %s\n",u.getLengthString().c_str()); - else log.printf(" length: %f nm\n",u.getLength()); + if(u.getLengthString().length()>0 && u.getLengthString()=="nm") { + log.printf(" length: %s\n",u.getLengthString().c_str()); + } + else if(u.getLengthString().length()>0 && u.getLengthString()!="nm") { + log.printf(" length: %s = %g nm\n",u.getLengthString().c_str(),u.getLength()); + } + else { + log.printf(" length: %g nm\n",u.getLength()); + } s=""; parse("ENERGY",s); if(s.length()>0) u.setEnergy(s); - if(u.getEnergyString().length()>0) log.printf(" energy: %s\n",u.getEnergyString().c_str()); - else log.printf(" energy: %f kj/mol\n",u.getEnergy()); + if(u.getEnergyString().length()>0 && u.getEnergyString()=="kj/mol") { + log.printf(" energy: %s\n",u.getEnergyString().c_str()); + } + else if(u.getEnergyString().length()>0 && u.getEnergyString()!="kj/mol") { + log.printf(" energy: %s = %g kj/mol\n",u.getEnergyString().c_str(),u.getEnergy()); + } + else { + log.printf(" energy: %g kj/mol\n",u.getEnergy()); + } s=""; parse("TIME",s); if(s.length()>0) u.setTime(s); - if(u.getTimeString().length()>0) log.printf(" time: %s\n",u.getTimeString().c_str()); - else log.printf(" time: %f ps\n",u.getTime()); + if(u.getTimeString().length()>0 && u.getTimeString()=="ps") { + log.printf(" time: %s\n",u.getTimeString().c_str()); + } + else if(u.getTimeString().length()>0 && u.getTimeString()!="ps") { + log.printf(" time: %s = %g ps\n",u.getTimeString().c_str(),u.getTime()); + } + else { + log.printf(" time: %g ps\n",u.getTime()); + } s=""; parse("CHARGE",s); if(s.length()>0) u.setCharge(s); - if(u.getChargeString().length()>0) log.printf(" charge: %s\n",u.getChargeString().c_str()); - else log.printf(" charge: %f e\n",u.getCharge()); + if(u.getChargeString().length()>0 && u.getChargeString()=="e") { + log.printf(" charge: %s\n",u.getChargeString().c_str()); + } + else if(u.getChargeString().length()>0 && u.getChargeString()!="e") { + log.printf(" charge: %s = %g e\n",u.getChargeString().c_str(),u.getCharge()); + } + else { + log.printf(" charge: %g e\n",u.getCharge()); + } s=""; parse("MASS",s); if(s.length()>0) u.setMass(s); - if(u.getMassString().length()>0) log.printf(" mass: %s\n",u.getMassString().c_str()); - else log.printf(" mass: %f amu\n",u.getMass()); + if(u.getMassString().length()>0 && u.getMassString()=="amu") { + log.printf(" mass: %s\n",u.getMassString().c_str()); + } + else if(u.getMassString().length()>0 && u.getMassString()!="amu") { + log.printf(" mass: %s = %g amu\n",u.getMassString().c_str(),u.getMass()); + } + else { + log.printf(" mass: %g amu\n",u.getMass()); + } bool natural=false; parseFlag("NATURAL",natural); @@ -147,9 +192,8 @@ Units::Units(const ActionOptions&ao): } else { log.printf(" using physical units\n"); } - log.printf(" inside PLUMED, Boltzmann constant is %f\n",plumed.getAtoms().getKBoltzmann()); + log.printf(" inside PLUMED, Boltzmann constant is %g\n",plumed.getAtoms().getKBoltzmann()); } } } - diff --git a/src/tools/Units.cpp b/src/tools/Units.cpp index 1389b7dfb9a658fdfe1e50f87edc958209596801..68340ee30f25e1ed5d37dc55c0e08c1a70ce94d0 100644 --- a/src/tools/Units.cpp +++ b/src/tools/Units.cpp @@ -50,11 +50,15 @@ void Units::setEnergy(const std::string &s) { energy=0.001; } else if(s=="eV") { energy=96.48530749925792; + } else if(s =="Ha") { + energy=2625.499638; } else { energy=-1.0; energyString=""; - Tools::convert(s,energy); - plumed_massert(energy>0.0,"energy units should be positive"); + if(!Tools::convert(s,energy)) { + plumed_merror("problem with setting the energy unit, either use give an numerical value or use one of the defined units: kj/mol, kcal/mol, j/mol, eV, Ha (case senstive)"); + } + plumed_massert(energy>0.0,"energy unit should be positive"); } } @@ -66,11 +70,15 @@ void Units::setLength(const std::string &s) { length=0.1; } else if(s=="um") { length=1000.0; + } else if(s=="Bohr") { + length=0.052917721067; } else { length=-1.0; lengthString=""; - Tools::convert(s,length); - plumed_massert(length>0.0,"length units should be positive"); + if(!Tools::convert(s,length)) { + plumed_merror("problem with setting the length unit, either use give an numerical value or use one of the defined units: nm, A, um, Bohr (case senstive)"); + } + plumed_massert(length>0.0,"length unit should be positive"); } } @@ -82,11 +90,15 @@ void Units::setTime(const std::string &s) { time=1000.0; } else if(s=="fs") { time=0.001; + } else if(s=="atomic") { + time=2.418884326509e-5; } else { time=-1.0; timeString=""; - Tools::convert(s,time); - plumed_massert(time>0.0,"time units should be positive"); + if(!Tools::convert(s,time)) { + plumed_merror("problem with setting the time unit, either use give an numerical value or use one of the defined units: ps, fs, atomic (case senstive)"); + } + plumed_massert(time>0.0,"time unit should be positive"); } } @@ -97,8 +109,10 @@ void Units::setCharge(const std::string &s) { } else { charge=-1.0; chargeString=""; - Tools::convert(s,charge); - plumed_massert(charge>0.0,"charge units should be positive"); + if(!Tools::convert(s,charge)) { + plumed_merror("problem with setting the charge unit, either use give an numerical value or use one of the defined units: e (case senstive)"); + } + plumed_massert(charge>0.0,"charge unit should be positive"); } } @@ -109,8 +123,10 @@ void Units::setMass(const std::string &s) { } else { mass=-1.0; massString=""; - Tools::convert(s,mass); - plumed_massert(mass>0.0,"mass units should be positive"); + if(!Tools::convert(s,mass)) { + plumed_merror("problem with setting the mass unit, either use give an numerical value or use one of the defined units: amu (case senstive)"); + } + plumed_massert(mass>0.0,"mass unit should be positive"); } } @@ -142,4 +158,3 @@ void Units::setMass(const double s) { } - diff --git a/src/tools/Units.h b/src/tools/Units.h index dd35cddbcfd18a7a436446f5cd58a094adf466da..79417eca1f5e836ba0f0e9cf9a5368560fde8816 100644 --- a/src/tools/Units.h +++ b/src/tools/Units.h @@ -59,15 +59,15 @@ public: Units(); /// Set energy units from string. /// Also understands the following strings: -/// kj/mol, kcal/mol, j/mol, and eV. +/// kj/mol, kcal/mol, j/mol, eV, and Ha. void setEnergy(const std::string &); /// Set time units from string. /// Also understands the following strings: -/// ps, ns, fs. +/// ps, ns, fs, and atomic. void setTime(const std::string &); /// Set lengh units from string. /// Also understands the following strings: -/// nm, A, um. +/// nm, A, um, and Bohr. void setLength(const std::string &); /// Set charge units from string. void setCharge(const std::string &);