From 479f13a647c911dac513fdd130f1e8508d5d8884 Mon Sep 17 00:00:00 2001 From: Giovanni Bussi Date: Tue, 19 May 2026 16:56:36 +0200 Subject: [PATCH 1/3] added test for digits in time with single precision --- .../COLVAR.reference | 4 ++ .../rt-make-settimestep-rounding/Makefile | 1 + .../basic/rt-make-settimestep-rounding/config | 1 + .../rt-make-settimestep-rounding/main.cpp | 53 +++++++++++++++++++ 4 files changed, 59 insertions(+) create mode 100644 regtest/basic/rt-make-settimestep-rounding/COLVAR.reference create mode 100644 regtest/basic/rt-make-settimestep-rounding/Makefile create mode 100644 regtest/basic/rt-make-settimestep-rounding/config create mode 100644 regtest/basic/rt-make-settimestep-rounding/main.cpp diff --git a/regtest/basic/rt-make-settimestep-rounding/COLVAR.reference b/regtest/basic/rt-make-settimestep-rounding/COLVAR.reference new file mode 100644 index 0000000000..110e53892d --- /dev/null +++ b/regtest/basic/rt-make-settimestep-rounding/COLVAR.reference @@ -0,0 +1,4 @@ +#! FIELDS time c + 20000.000000 1.000000 +#! FIELDS time c + 20000.000000 1.000000 diff --git a/regtest/basic/rt-make-settimestep-rounding/Makefile b/regtest/basic/rt-make-settimestep-rounding/Makefile new file mode 100644 index 0000000000..3703b27cea --- /dev/null +++ b/regtest/basic/rt-make-settimestep-rounding/Makefile @@ -0,0 +1 @@ +include ../../scripts/test.make diff --git a/regtest/basic/rt-make-settimestep-rounding/config b/regtest/basic/rt-make-settimestep-rounding/config new file mode 100644 index 0000000000..df1f95bf3e --- /dev/null +++ b/regtest/basic/rt-make-settimestep-rounding/config @@ -0,0 +1 @@ +type=make diff --git a/regtest/basic/rt-make-settimestep-rounding/main.cpp b/regtest/basic/rt-make-settimestep-rounding/main.cpp new file mode 100644 index 0000000000..187ce283d3 --- /dev/null +++ b/regtest/basic/rt-make-settimestep-rounding/main.cpp @@ -0,0 +1,53 @@ +#include +#include +#include "plumed/wrapper/Plumed.h" +#include + +using namespace PLMD; + +template +void run(){ + + auto natoms=10; + std::vector masses; + std::vector> positions; + std::vector> forces; + T box[3][3]; + T virial[3][3]; + + Plumed p; + + p.cmd("setRealPrecision",int(sizeof(T))); + p.cmd("setNatoms",natoms); + p.cmd("setTimestep",(T)0.002); + p.cmd("init"); + + p.cmd("readInputLines", + "c: CONSTANT VALUE=1.0 \n" + "PRINT ARG=c FILE=COLVAR RESTART=YES\n" + ); + + // dummy settings, not really used + positions.resize(natoms); + masses.resize(natoms); + forces.resize(natoms); + + for(unsigned i=0;i(); + run(); +} From c547d387f5a2235e00337317e73757d75c1b63ce Mon Sep 17 00:00:00 2001 From: Gareth Aneurin Tribello Date: Wed, 20 May 2026 10:12:07 +0100 Subject: [PATCH 2/3] Tentative fix for issue #1417 Timestep was passed correctly with code for dealing with rounding error when converting float to double. When updating unit, however, the timestep is reset using the data that was pssed from the MD code. This has now been changed so you use the value of the timestep that was set in PLUMED. --- src/core/ActionToPutData.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/core/ActionToPutData.cpp b/src/core/ActionToPutData.cpp index 24b52e0d22..1ac7522411 100644 --- a/src/core/ActionToPutData.cpp +++ b/src/core/ActionToPutData.cpp @@ -164,7 +164,13 @@ void ActionToPutData::updateUnits( DataPassingTools* passtools ) { double vunits=passtools->getUnitConversion( getUnitName() ); mydata->setUnit(vunits); if( fixed && wasset ) { - mydata->share_data( 0, getPntrToValue()->getNumberOfValues(), getPntrToValue() ); + // We don't use share_data here because the timestep has been adjusted when + // it is passed to deal with rounding if we pass a float instead of a double. + // We thus take the values that have been passed and multiply them by the unit conversion + Value* myval = getPntrToValue(); + for(unsigned i=0; igetNumberOfValues(); ++i) { + myval->set( i, vunits*myval->get(i) ); + } } if( funit==eng ) { mydata->setForceUnit( 1/passtools->getUnitConversion("energy")); From fe922367fff963ae1c60a89d2a70dd6ba5559a13 Mon Sep 17 00:00:00 2001 From: Gareth Aneurin Tribello Date: Wed, 20 May 2026 11:13:00 +0100 Subject: [PATCH 3/3] Better tentative fix for #1419 --- src/core/ActionToPutData.cpp | 8 +------- src/core/DataPassingObject.cpp | 11 +++++++++++ src/core/PlumedMain.cpp | 8 -------- 3 files changed, 12 insertions(+), 15 deletions(-) diff --git a/src/core/ActionToPutData.cpp b/src/core/ActionToPutData.cpp index 1ac7522411..24b52e0d22 100644 --- a/src/core/ActionToPutData.cpp +++ b/src/core/ActionToPutData.cpp @@ -164,13 +164,7 @@ void ActionToPutData::updateUnits( DataPassingTools* passtools ) { double vunits=passtools->getUnitConversion( getUnitName() ); mydata->setUnit(vunits); if( fixed && wasset ) { - // We don't use share_data here because the timestep has been adjusted when - // it is passed to deal with rounding if we pass a float instead of a double. - // We thus take the values that have been passed and multiply them by the unit conversion - Value* myval = getPntrToValue(); - for(unsigned i=0; igetNumberOfValues(); ++i) { - myval->set( i, vunits*myval->get(i) ); - } + mydata->share_data( 0, getPntrToValue()->getNumberOfValues(), getPntrToValue() ); } if( funit==eng ) { mydata->setForceUnit( 1/passtools->getUnitConversion("energy")); diff --git a/src/core/DataPassingObject.cpp b/src/core/DataPassingObject.cpp index a92202004b..d1bb720e47 100644 --- a/src/core/DataPassingObject.cpp +++ b/src/core/DataPassingObject.cpp @@ -94,6 +94,17 @@ void DataPassingObjectTyped::saveValueAsDouble( const TypesafePtr & val ) { bvalue=double(val.template get()); } +template <> +void DataPassingObjectTyped::saveValueAsDouble( const TypesafePtr & val ) { + hasbackup=true; + bvalue=double(val.template get()); + // The following is to avoid extra digits in case the MD code uses floats + // e.g.: float f=0.002 when converted to double becomes 0.002000000094995 + // To avoid this, we keep only up to 6 significant digits after first one + double magnitude=std::pow(10,std::floor(std::log10(bvalue))); + bvalue = std::round(bvalue/magnitude*1e6)/1e6*magnitude; +} + template void DataPassingObjectTyped::setValuePointer( const TypesafePtr & val, const std::vector& shape, const bool& isconst ) { if( shape.size()==0 ) { diff --git a/src/core/PlumedMain.cpp b/src/core/PlumedMain.cpp index 21ebfcfa7a..af72978504 100644 --- a/src/core/PlumedMain.cpp +++ b/src/core/PlumedMain.cpp @@ -737,14 +737,6 @@ void PlumedMain::cmd(std::string_view word,const TypesafePtr & val) { if( !ts->setValuePointer("timestep", val ) ) { plumed_error(); } - // The following is to avoid extra digits in case the MD code uses floats - // e.g.: float f=0.002 when converted to double becomes 0.002000000094995 - // To avoid this, we keep only up to 6 significant digits after first one - if( getRealPrecision()<=4 ) { - Value* tstepv = ts->copyOutput(0); - double magnitude=std::pow(10,std::floor(std::log10(tstepv->get()))); - tstepv->set( std::round(tstepv->get()/magnitude*1e6)/1e6*magnitude ); - } ts->updateUnits( passtools.get() ); } break;