From 702b0ad636ee11a10d175bc57d6d4e86ba151e1d Mon Sep 17 00:00:00 2001 From: Gareth Tribello <gareth.tribello@gmail.com> Date: Thu, 9 Aug 2012 16:21:36 +0200 Subject: [PATCH] Added parsing for command line tools that works like actions. This makes command line tools easy to document in the same manner as Actions are easy to document --- regtest/rt-mpi0/config | 2 +- regtest/rt-mpi1/config | 2 +- regtest/rt0/config | 2 +- regtest/rt1/config | 2 +- regtest/rt10/config | 2 +- regtest/rt11/config | 2 +- regtest/rt12/config | 2 +- regtest/rt14/config | 2 +- regtest/rt15/config | 2 +- regtest/rt16/config | 2 +- regtest/rt17/config | 2 +- regtest/rt18/config | 2 +- regtest/rt19-mpi/config | 2 +- regtest/rt19/config | 2 +- regtest/rt2/config | 2 +- regtest/rt20-mpi/config | 2 +- regtest/rt20/config | 2 +- regtest/rt21/config | 2 +- regtest/rt22/config | 2 +- regtest/rt23/config | 2 +- regtest/rt24/config | 2 +- regtest/rt25/config | 2 +- regtest/rt26/config | 2 +- regtest/rt27/config | 2 +- regtest/rt28/config | 2 +- regtest/rt29/config | 2 +- regtest/rt3/config | 2 +- regtest/rt30/config | 2 +- regtest/rt31/config | 2 +- regtest/rt32/config | 2 +- regtest/rt33/config | 2 +- regtest/rt34/config | 2 +- regtest/rt35/config | 2 +- regtest/rt36/config | 2 +- regtest/rt37/config | 2 +- regtest/rt4/config | 2 +- regtest/rt5/config | 2 +- regtest/rt6/config | 2 +- regtest/rt7/config | 2 +- regtest/rt8/config | 2 +- regtest/rt9/config | 2 +- src/ActionRegister.cpp | 2 +- src/CLTool.cpp | 193 ++++++++++++++++++++++++++++++++++++++++ src/CLTool.h | 62 +++++++++++-- src/CLToolDriver.cpp | 193 +++++++++++++++++----------------------- src/CLToolInfo.cpp | 76 +++++++--------- src/CLToolMain.cpp | 8 +- src/CLToolManual.cpp | 87 ++++++++---------- src/CLToolRegister.cpp | 19 +++- src/CLToolRegister.h | 13 ++- src/CLToolSimpleMD.cpp | 176 ++++++++++++++++++------------------ src/Keywords.cpp | 76 +++++++++++++++- src/Keywords.h | 10 ++- src/Tools.cpp | 6 ++ src/Tools.h | 2 + 55 files changed, 651 insertions(+), 354 deletions(-) create mode 100644 src/CLTool.cpp diff --git a/regtest/rt-mpi0/config b/regtest/rt-mpi0/config index 28f95533b..714d1d6dd 100644 --- a/regtest/rt-mpi0/config +++ b/regtest/rt-mpi0/config @@ -1,5 +1,5 @@ mpiprocs=4 type=driver # this is to test a different name -arg="--plumed=plumed.dat --timestep=0.05 trajectory.xyz --dump-forces ff" +arg="--plumed=plumed.dat --timestep=0.05 --ixyz trajectory.xyz --dump-forces ff" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt-mpi1/config b/regtest/rt-mpi1/config index 30fb3be36..fd743c293 100644 --- a/regtest/rt-mpi1/config +++ b/regtest/rt-mpi1/config @@ -1,5 +1,5 @@ mpiprocs=4 type=driver # this is to test a different name -arg="--plumed=plumed.dat --timestep=0.05 trajectory.xyz --dump-forces ff --debug-pd" +arg="--plumed=plumed.dat --timestep=0.05 --ixyz trajectory.xyz --dump-forces ff --debug-pd" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt0/config b/regtest/rt0/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt0/config +++ b/regtest/rt0/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt1/config b/regtest/rt1/config index f2791e103..d343ccfdc 100644 --- a/regtest/rt1/config +++ b/regtest/rt1/config @@ -3,4 +3,4 @@ # to avoid problems with the numerical derivatives (it is exactly at the border between # two images) type=driver -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" diff --git a/regtest/rt10/config b/regtest/rt10/config index 623ad3cc5..a87726a91 100644 --- a/regtest/rt10/config +++ b/regtest/rt10/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt11/config b/regtest/rt11/config index 623ad3cc5..a87726a91 100644 --- a/regtest/rt11/config +++ b/regtest/rt11/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt12/config b/regtest/rt12/config index 623ad3cc5..a87726a91 100644 --- a/regtest/rt12/config +++ b/regtest/rt12/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt14/config b/regtest/rt14/config index 623ad3cc5..a87726a91 100644 --- a/regtest/rt14/config +++ b/regtest/rt14/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt15/config b/regtest/rt15/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt15/config +++ b/regtest/rt15/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt16/config b/regtest/rt16/config index 623ad3cc5..a87726a91 100644 --- a/regtest/rt16/config +++ b/regtest/rt16/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt17/config b/regtest/rt17/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt17/config +++ b/regtest/rt17/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt18/config b/regtest/rt18/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt18/config +++ b/regtest/rt18/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt19-mpi/config b/regtest/rt19-mpi/config index ecb920ffc..36dba8dbc 100644 --- a/regtest/rt19-mpi/config +++ b/regtest/rt19-mpi/config @@ -1,5 +1,5 @@ mpiprocs=4 type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt19/config b/regtest/rt19/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt19/config +++ b/regtest/rt19/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt2/config b/regtest/rt2/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt2/config +++ b/regtest/rt2/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt20-mpi/config b/regtest/rt20-mpi/config index ecb920ffc..36dba8dbc 100644 --- a/regtest/rt20-mpi/config +++ b/regtest/rt20-mpi/config @@ -1,5 +1,5 @@ mpiprocs=4 type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt20/config b/regtest/rt20/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt20/config +++ b/regtest/rt20/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt21/config b/regtest/rt21/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt21/config +++ b/regtest/rt21/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt22/config b/regtest/rt22/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt22/config +++ b/regtest/rt22/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt23/config b/regtest/rt23/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt23/config +++ b/regtest/rt23/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt24/config b/regtest/rt24/config index 47df6596d..192611df2 100644 --- a/regtest/rt24/config +++ b/regtest/rt24/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt25/config b/regtest/rt25/config index 47df6596d..192611df2 100644 --- a/regtest/rt25/config +++ b/regtest/rt25/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt26/config b/regtest/rt26/config index e592546b3..0a8ccbb18 100644 --- a/regtest/rt26/config +++ b/regtest/rt26/config @@ -1,3 +1,3 @@ type=driver -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt27/config b/regtest/rt27/config index e592546b3..0a8ccbb18 100644 --- a/regtest/rt27/config +++ b/regtest/rt27/config @@ -1,3 +1,3 @@ type=driver -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt28/config b/regtest/rt28/config index e441f5aec..ae36d62c2 100644 --- a/regtest/rt28/config +++ b/regtest/rt28/config @@ -1,3 +1,3 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" diff --git a/regtest/rt29/config b/regtest/rt29/config index e441f5aec..ae36d62c2 100644 --- a/regtest/rt29/config +++ b/regtest/rt29/config @@ -1,3 +1,3 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" diff --git a/regtest/rt3/config b/regtest/rt3/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt3/config +++ b/regtest/rt3/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt30/config b/regtest/rt30/config index ee245fbbb..980c469ec 100644 --- a/regtest/rt30/config +++ b/regtest/rt30/config @@ -1,2 +1,2 @@ type=driver -arg="--plumed plumed.dat --stride 10 --timestep 0.005 ala12_trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz ala12_trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" diff --git a/regtest/rt31/config b/regtest/rt31/config index ee245fbbb..980c469ec 100644 --- a/regtest/rt31/config +++ b/regtest/rt31/config @@ -1,2 +1,2 @@ type=driver -arg="--plumed plumed.dat --stride 10 --timestep 0.005 ala12_trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz ala12_trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" diff --git a/regtest/rt32/config b/regtest/rt32/config index ee245fbbb..980c469ec 100644 --- a/regtest/rt32/config +++ b/regtest/rt32/config @@ -1,2 +1,2 @@ type=driver -arg="--plumed plumed.dat --stride 10 --timestep 0.005 ala12_trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz ala12_trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" diff --git a/regtest/rt33/config b/regtest/rt33/config index 7d0e9d21d..b3efe6c3c 100644 --- a/regtest/rt33/config +++ b/regtest/rt33/config @@ -1,2 +1,2 @@ type=driver -arg="--plumed plumed.dat --stride 10 --timestep 0.005 amyloid.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz amyloid.xyz --dump-forces forces --dump-forces-fmt=%10.6f" diff --git a/regtest/rt34/config b/regtest/rt34/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt34/config +++ b/regtest/rt34/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt35/config b/regtest/rt35/config index cbf38b9c3..45386cb93 100644 --- a/regtest/rt35/config +++ b/regtest/rt35/config @@ -1,2 +1,2 @@ type=driver -arg="--plumed plumed.dat --stride 10 --timestep 0.005 ../../trajectories/diala_traj_nm.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz ../../trajectories/diala_traj_nm.xyz --dump-forces forces --dump-forces-fmt=%10.6f" diff --git a/regtest/rt36/config b/regtest/rt36/config index 20af628e0..fce7937b0 100644 --- a/regtest/rt36/config +++ b/regtest/rt36/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%8.4f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt37/config b/regtest/rt37/config index cbf38b9c3..45386cb93 100644 --- a/regtest/rt37/config +++ b/regtest/rt37/config @@ -1,2 +1,2 @@ type=driver -arg="--plumed plumed.dat --stride 10 --timestep 0.005 ../../trajectories/diala_traj_nm.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz ../../trajectories/diala_traj_nm.xyz --dump-forces forces --dump-forces-fmt=%10.6f" diff --git a/regtest/rt4/config b/regtest/rt4/config index 623ad3cc5..a87726a91 100644 --- a/regtest/rt4/config +++ b/regtest/rt4/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt5/config b/regtest/rt5/config index 623ad3cc5..a87726a91 100644 --- a/regtest/rt5/config +++ b/regtest/rt5/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt6/config b/regtest/rt6/config index 623ad3cc5..a87726a91 100644 --- a/regtest/rt6/config +++ b/regtest/rt6/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt7/config b/regtest/rt7/config index 623ad3cc5..a87726a91 100644 --- a/regtest/rt7/config +++ b/regtest/rt7/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt8/config b/regtest/rt8/config index 623ad3cc5..a87726a91 100644 --- a/regtest/rt8/config +++ b/regtest/rt8/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/regtest/rt9/config b/regtest/rt9/config index 623ad3cc5..a87726a91 100644 --- a/regtest/rt9/config +++ b/regtest/rt9/config @@ -1,4 +1,4 @@ type=driver # this is to test a different name -arg="--plumed plumed.dat --stride 10 --timestep 0.005 trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" +arg="--plumed plumed.dat --stride 10 --timestep 0.005 --ixyz trajectory.xyz --dump-forces forces --dump-forces-fmt=%10.6f" extra_files="../trajectories/trajectory.xyz" diff --git a/src/ActionRegister.cpp b/src/ActionRegister.cpp index fd976193c..87d0081c6 100644 --- a/src/ActionRegister.cpp +++ b/src/ActionRegister.cpp @@ -89,7 +89,7 @@ Action* ActionRegister::create(const ActionOptions&ao){ bool ActionRegister::printManual( const std::string& action ){ if ( check(action) ){ Keywords keys; mk[action](keys); - keys.print_html(); keys.destroyData(); + keys.print_html(true); keys.destroyData(); return true; } else { return false; diff --git a/src/CLTool.cpp b/src/CLTool.cpp new file mode 100644 index 000000000..6a4b749d1 --- /dev/null +++ b/src/CLTool.cpp @@ -0,0 +1,193 @@ +/* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + Copyright (c) 2012 The plumed team + (see the PEOPLE file at the root of the distribution for a list of names) + + See http://www.plumed-code.org for more information. + + This file is part of plumed, version 2.0. + + plumed is free software: you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + plumed is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with plumed. If not, see <http://www.gnu.org/licenses/>. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ +#include "CLTool.h" + +using namespace PLMD; + +Keywords CLToolOptions::emptyKeys; + +CLToolOptions::CLToolOptions(const std::string &name): +line(1,name), +keys(emptyKeys) +{ +} + +CLToolOptions::CLToolOptions(const CLToolOptions& co, const Keywords& k): +line(co.line), +keys(k) +{ +} + +void CLTool::registerKeywords( Keywords& keys ){ + keys.addFlag("--help",false,"print this help"); +} + +CLTool::CLTool(const CLToolOptions& co ): +name(co.line[0]), +keywords(co.keys), +inputdata(unset) +{ +} + +void CLTool::parseFlag( const std::string&key, bool&t ){ + plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); + plumed_massert(keywords.style(key,"flag"),"keyword " + key + " has not been registered as a flag"); + plumed_assert(inputData.count(key)>0); + if( inputData[key]=="true") t=true; + else if( inputData[key]=="false") t=false; + else plumed_assert(0); +} + +bool CLTool::readInput( int argc, char**argv, FILE* in, FILE*out ){ + plumed_massert( inputdata!=unset,"You have not specified where your tool reads its input. " + "If it is from the command line (like driver) add inputdata=commandline to the " + "tools constructor. If it reads everything from an input file (like simplemd) " + "add inputdata=ifile to the tools constructor"); + if(inputdata==commandline) return readCommandLineArgs( argc, argv, out ); + if(inputdata==ifile) return readInputFile( argc, argv, in, out ); + readInput( argc, argv, in, out ); // This allows the user to specify the particular form for input + return true; +} + +bool CLTool::readCommandLineArgs( int argc, char**argv, FILE*out ){ + plumed_assert(inputdata==commandline); + std::string prefix(""), a(""), thiskey; + + // Set all flags to default false + for(int k=0;k<keywords.size();++k){ + thiskey=keywords.get(k); + if( keywords.style(thiskey,"flag") ) inputData.insert(std::pair<std::string,std::string>(thiskey,"false")); + } + + // Read command line arguments + bool printhelp=false; + for(int i=1;i<argc;i++){ + a=prefix+argv[i]; + if(a.length()==0) continue; + if(a=="-h" || a=="--help"){ + printhelp=true; + } else { + bool found=false; + for(int k=0;k<keywords.size();++k){ + thiskey=keywords.get(k); + if( keywords.style(thiskey,"flag") ){ + if( a==thiskey ){ found=true; inputData[thiskey]="true"; } + } else { + if( a==thiskey ){ + prefix=thiskey+"="; found=true; + inputData.insert(std::pair<std::string,std::string>(thiskey,"")); + } else if( a.find(thiskey+"=")==0){ + a.erase(0,a.find("=")+1); prefix=""; found=true; + if(inputData.count(thiskey)==0){ + inputData.insert(std::pair<std::string,std::string>(thiskey,a)); + } else { + inputData[thiskey]=a; + } + } + } + } + if(!found){ + fprintf(out,"ERROR : unknown option %s\n\n", a.c_str() ); + printhelp=true; + } + } + if(printhelp) break; + } + + if(!printhelp) setRemainingToDefault(out); + + if(printhelp){ + fprintf(out,"Usage: %s [options] \n\n", name.c_str() ); + keywords.print( out ); + } + + return !printhelp; +} + +void CLTool::setRemainingToDefault(FILE* out){ + std::string def, thiskey; + for(int k=0;k<keywords.size();++k){ + thiskey=keywords.get(k); + if( keywords.style(thiskey,"compulsory") ){ + if( inputData.count(thiskey)==0 ){ + if( keywords.getDefaultValue(thiskey,def) ){ + plumed_assert( def.length()>0 ); + inputData.insert(std::pair<std::string,std::string>(thiskey,def)); + } else { + fprintf(out,"ERROR : argument %s is compulsory. Use --help option for help\n",thiskey.c_str() ); + } + } + } + } +} + +bool CLTool::readInputFile( int argc, char**argv, FILE* in, FILE*out ){ + plumed_assert(inputdata==ifile); + + // Check if use is just asking for help + std::string a; + for(int i=1;i<argc;i++){ + a=argv[i]; + if(a.length()==0) continue; + if(a=="-h" || a=="--help"){ + fprintf(out,"Usage: %s < inputFile \n", name.c_str() ); + fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n"); + keywords.print( out ); + return false; + } + } + + FILE* mystdin=in; + if(argc==2) mystdin=fopen(argv[1],"r"); + + char buffer[256]; std::string line; line.resize(256); + while(fgets(buffer,256,mystdin)){ + line=buffer; + for(int i=0;i<line.length();++i) if(line[i]=='#' || line[i]=='\n') line.erase(i); + Tools::stripLeadingAndTrailingBlanks( line ); + if(line.length()==0) continue; + sscanf(line.c_str(),"%s",buffer); + std::string keyword=buffer; bool found=false; + for(unsigned i=0;i<keywords.size();++i){ + std::string thiskey=keywords.get(i); + if(thiskey==keyword){ + found=true; + std::size_t keypos=line.find_first_of(keyword)+keyword.length(); + inputData.insert(std::pair<std::string,std::string>(thiskey,line.substr(keypos))); + Tools::stripLeadingAndTrailingBlanks( inputData[thiskey] ); + } + } + if(!found){ + fprintf(stderr,"Unknown keyword found in input file :%s\n",keyword.c_str()); + return false; + } + } + + if(argc==2) fclose(mystdin); + setRemainingToDefault(out); + return true; +} + +void CLTool::readInputData( int argc, char**argv, FILE* in, FILE*out ){ + plumed_assert( inputdata!=commandline && inputdata!=ifile ); + if( inputdata==userspec ) plumed_massert(0, "You have to actually write the routine in the base class!"); +} diff --git a/src/CLTool.h b/src/CLTool.h index 1dc435baa..354e608d3 100644 --- a/src/CLTool.h +++ b/src/CLTool.h @@ -25,17 +25,25 @@ #include <cstdio> #include <vector> #include <string> +#include <cstdio> +#include "Tools.h" +#include "Keywords.h" namespace PLMD{ class PlumedCommunicator; class CLToolOptions{ + friend class CLTool; friend class CLToolRegister; +private: std::vector<std::string> line; +/// The documentation for this command line tool + const Keywords& keys; + static Keywords emptyKeys; public: - CLToolOptions(const std::string &name): - line(1,name) { } + CLToolOptions(const std::string &name); + CLToolOptions(const CLToolOptions& co, const Keywords& k); }; /** @@ -44,18 +52,62 @@ Interface to all the command-line tools. This class just define an interface, and does not implement anything. Inherits from this class to create a new command-line tool. */ -class CLTool -{ +class CLTool { +// This is a fried so we can create input data quickly +// when you do debug-float. +template <typename real> +friend class CLToolDriver; +private: +/// The name of this command line tool + const std::string name; +/// The list of keywords for this CLTool + const Keywords& keywords; +/// The data read in from the command line stored in a map with the keywords + std::map<std::string,std::string> inputData; +/// Read the arguments from the command line + bool readCommandLineArgs( int argc, char**argv, FILE*out ); +/// Read the arguments from an input file specified on the command line + bool readInputFile( int argc, char**argv, FILE* in, FILE*out ); +/// Set arguments from the default options provided to Keywords + void setRemainingToDefault(FILE* out); +protected: +/// Get the value of one of the command line arguments + template<class T> + bool parse(const std::string&key,T&t); +/// Find out whether one of the command line flags is present or not + void parseFlag(const std::string&key,bool&t); public: +/// How is the input specified on the command line or in an input file + enum {unset,commandline,ifile,userspec} inputdata; +/// Create the help keywords + static void registerKeywords( Keywords& keys ); + CLTool(const CLToolOptions& co ); +/// Read the arguments from the command line + bool readInput( int argc, char**argv, FILE* in, FILE*out ); +/// Read the input in the derived class (overwrite this if you are not using +/// command line arguments or an input file in the style of simplemd's) + virtual void readInputData( int argc, char**argv, FILE* in, FILE*out ); /// virtual function mapping to the specific main for each tool - virtual int main(int argc, char **argv,FILE*in,FILE*out,PlumedCommunicator&pc)=0; + virtual int main( FILE*out, PlumedCommunicator&pc )=0; /// virtual function returning a one-line descriptor for the tool virtual std::string description()const{return "(no description available)";}; /// virtual destructor to allow inheritance virtual ~CLTool(){}; }; +template<class T> +bool CLTool::parse(const std::string&key,T&t){ + plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered"); + if(keywords.style(key,"compulsory") ){ + plumed_assert(inputData.count(key)>0); + plumed_assert( Tools::convert(inputData[key],t) ); + return true; + } + if( inputData.count(key)==0 ) return false; + Tools::convert(inputData[key],t); + return true; } +} #endif diff --git a/src/CLToolDriver.cpp b/src/CLToolDriver.cpp index 73b155e44..b1c9e6721 100644 --- a/src/CLToolDriver.cpp +++ b/src/CLToolDriver.cpp @@ -34,21 +34,53 @@ using namespace std; namespace PLMD { //+PLUMEDOC TOOLS driver -/** -driver is a tool that allows one to to use plumed to post-process -an existing trajectory. +/* +driver is a tool that allows one to to use plumed to post-process an existing trajectory. + +The input to driver is specified using the command line arguments described below. + +\par Examples + +The following command tells plumed to postprocess the trajectory contained in trajectory.xyz + by calcualting the actions described in the input file plumed.dat. +\verbatim +plumed driver --plumed plumed.dat --ixyz trajectory.xyz +\endverbatim + */ //+ENDPLUMEDOC template<typename real> -class CLToolDriver: -public CLTool -{ +class CLToolDriver : public CLTool { public: - int main(int argc,char**argv,FILE*in,FILE*out,PlumedCommunicator& pc); + static void registerKeywords( Keywords& keys ); + CLToolDriver(const CLToolOptions& co ); + int main(FILE*out,PlumedCommunicator& pc); string description()const; }; +template<typename real> +void CLToolDriver<real>::registerKeywords( Keywords& keys ){ + CLTool::registerKeywords( keys ); + keys.addFlag("--help-debug",false,"print special options that can be used to create regtests"); + keys.add("compulsory","--plumed","plumed.dat","specify the name of the plumed input file"); + keys.add("compulsory","--timestep","0.001","the timestep for the trajectory in picoseconds"); + keys.add("compulsory","--stride","1","stride between frames on which to do the calculation"); + keys.add("atoms","--ixyz","the trajectory in xyz format"); + keys.add("optional","--dump-forces","dump the forces on a file"); + keys.add("optional","--dump-forces-fmt","( default=%%f ) the format to use to dump the forces"); + keys.add("hidden","--debug-float","turns on the single precision version (to check float interface)"); + keys.add("hidden","--debug-dd","use a fake domain decomposition"); + keys.add("hidden","--debug-pd","use a fake particle decomposition"); +} + +template<typename real> +CLToolDriver<real>::CLToolDriver(const CLToolOptions& co ): +CLTool(co) +{ + inputdata=commandline; +} + template<typename real> string CLToolDriver<real>::description()const{ return "analyze trajectories with plumed"; } @@ -57,110 +89,49 @@ string CLToolDriver<float>::description()const{ return "analyze trajectories wit template<typename real> -int CLToolDriver<real>::main(int argc,char**argv,FILE*in,FILE*out,PlumedCommunicator& pc){ - -// to avoid warnings: - (void) in; - - string plumedFile("plumed.dat"); - string dumpforces(""); - string dumpforcesFmt("%f"); - string trajectoryFile(""); - real timestep(real(0.001)); - unsigned stride(1); - bool printhelp=false; - bool printhelpdebug=false; - bool debug_dd=false; - bool debug_pd=false; - -// Start parsing options - string prefix(""); - string a(""); - for(int i=1;i<argc;i++){ - a=prefix+argv[i]; - if(a.length()==0) continue; - if(a=="-h" || a=="--help"){ - printhelp=true; - break; - } else if(a=="--help-debug"){ - printhelp=true; - printhelpdebug=true; - break; - } else if(a=="--debug-float"){ - if(sizeof(real)!=sizeof(float)){ - CLTool* cl=new CLToolDriver<float>; - int ret=cl->main(argc,argv,in,out,pc); - delete cl; - return ret; - } - } else if(a=="--debug-pd"){ - debug_pd=true; - } else if(a=="--debug-dd"){ - debug_dd=true; - } else if(a.find("--plumed=")==0){ - a.erase(0,a.find("=")+1); - plumedFile=a; - prefix=""; - } else if(a=="--plumed"){ - prefix="--plumed="; - } else if(a.find("--timestep=")==0){ - a.erase(0,a.find("=")+1); - double t; - Tools::convert(a,t); - timestep=real(t); - prefix=""; - } else if(a=="--timestep"){ - prefix="--timestep="; - } else if(a.find("--stride=")==0){ - a.erase(0,a.find("=")+1); - Tools::convert(a,stride); - prefix=""; - } else if(a=="--stride"){ - prefix="--stride="; - } else if(a.find("--dump-forces=")==0){ - a.erase(0,a.find("=")+1); - dumpforces=a; - prefix=""; - } else if(a=="--dump-forces"){ - prefix="--dump-forces="; - } else if(a.find("--dump-forces-fmt=")==0){ - a.erase(0,a.find("=")+1); - dumpforcesFmt=a; - prefix=""; - } else if(a=="--dump-forces-fmt"){ - prefix="--dump-forces-fmt="; - } else if(a[0]=='-') { - string msg="ERROR: Unknown option " +a; - fprintf(stderr,"%s\n",msg.c_str()); - return 1; - } else if(trajectoryFile.length()==0){ - trajectoryFile=a; - } else { - string msg="ERROR: maximum one file at a time"; - fprintf(stderr,"%s\n",msg.c_str()); - return 1; - } +int CLToolDriver<real>::main(FILE*out,PlumedCommunicator& pc){ + +// Parse everything + bool printhelpdebug; parseFlag("--help-debug",printhelpdebug); + if( printhelpdebug ){ + fprintf(out,"%s", + "Additional options for debug (only to be used in regtest):\n" + " [--debug-float] : turns on the single precision version (to check float interface)\n" + " [--debug-dd] : use a fake domain decomposition\n" + " [--debug-pd] : use a fake particle decomposition\n" + ); + return 0; + } + std::string fakein; + bool debugfloat=parse("--debug-float",fakein); + if(debugfloat && sizeof(real)!=sizeof(float)){ + CLTool* cl=cltoolRegister().create(CLToolOptions("driver-float")); //new CLToolDriver<float>(*this); + cl->inputData=this->inputData; + int ret=cl->main(out,pc); + delete cl; + return ret; } - if(printhelp){ - fprintf(out,"%s", - "Usage: driver [options] trajectory.xyz\n" - "Options:\n" - " [--help|-h] : prints this help\n" - " [--help-debug] : prints this help plus special options for debug\n" - " [--plumed FILE] : plumed script file (default: plumed.dat)\n" - " [--timestep TS] : timestep (default: 0.001) in picoseconds\n" - " [--stride ST] : stride between frames (default: 1)\n" - " [--dump-forces FILE] : dump forces on file FILE (default: do not dump)\n" - " [--dump-forces-fmt FMT] : dump forces on file FILE (default: %f)\n" -); - if(printhelpdebug) - fprintf(out,"%s", - "Additional options for debug (only to be used in regtest):\n" - " [--debug-float] : turns on the single precision version (to check float interface)\n" - " [--debug-dd] : use a fake domain decomposition\n" - " [--debug-pd] : use a fake particle decomposition\n" -); + bool debug_pd=parse("--debug-pd",fakein); + bool debug_dd=parse("--debug-dd",fakein); +// Read the plumed input file name + string plumedFile; parse("--plumed",plumedFile); +// the timestep + double t; parse("--timestep",t); + real timestep=real(t); +// the stride + unsigned stride; parse("--stride",stride); +// are we writing forces + string dumpforces(""), dumpforcesFmt("%f");; + parse("--dump-forces",dumpforces); + if(dumpforces!="") parse("--dump-forces-fmt",dumpforcesFmt); + +// Read in an xyz file + string trajectoryFile(""); + std::string traj_xyz; parse("--ixyz",traj_xyz); + if(traj_xyz.length()>0 && trajectoryFile.length()==0) trajectoryFile=traj_xyz; + if(trajectoryFile.length()==0){ + fprintf(out,"ERROR: missing trajectory data\n"); return 0; } @@ -179,7 +150,6 @@ int CLToolDriver<real>::main(int argc,char**argv,FILE*in,FILE*out,PlumedCommunic p.cmd("setRealPrecision",&rr); int checknatoms=0; int step=0; - FILE* fp=fopen(trajectoryFile.c_str(),"r"); @@ -316,8 +286,9 @@ int CLToolDriver<real>::main(int argc,char**argv,FILE*in,FILE*out,PlumedCommunic } typedef CLToolDriver<double> CLToolDriverDouble; - +typedef CLToolDriver<float> CLToolDriverFloat; PLUMED_REGISTER_CLTOOL(CLToolDriverDouble,"driver") +PLUMED_REGISTER_CLTOOL(CLToolDriverFloat,"driver-float") diff --git a/src/CLToolInfo.cpp b/src/CLToolInfo.cpp index 44c407979..393649e44 100644 --- a/src/CLToolInfo.cpp +++ b/src/CLToolInfo.cpp @@ -32,8 +32,19 @@ using namespace std; namespace PLMD { //+PLUMEDOC TOOLS info -/** -This is a tool that allows you to obtain information about your plumed version +/* +This tool allows you to obtain information about your plumed version + +You can specify the information you require using the following command line +arguments + +\par Examples + +The following command returns the root directory for your plumed distribution. +\verbatim +plumed info --root +\endverbatim + */ //+ENDPLUMEDOC @@ -41,56 +52,35 @@ class CLToolInfo: public CLTool { public: - int main(int argc,char**argv,FILE*in,FILE*out,PlumedCommunicator& pc); + static void registerKeywords( Keywords& keys ); + CLToolInfo(const CLToolOptions& co ); + int main(FILE*out,PlumedCommunicator& pc); string description()const{ return "provide informations about plumed"; } }; - PLUMED_REGISTER_CLTOOL(CLToolInfo,"info") -int CLToolInfo::main(int argc,char**argv,FILE*in,FILE*out,PlumedCommunicator& pc){ - -// to avoid warnings: - (void) in; - - bool printconfiguration(false); - bool printhelp(false); - -// Start parsing options - string prefix(""); - string a(""); - for(int i=1;i<argc;i++){ - a=prefix+argv[i]; - if(a.length()==0) continue; - if(a=="-h" || a=="--help"){ - printhelp=true; - break; - } - if(a=="--configuration"){ - printconfiguration=true; - break; - } else if(a=="--root"){ - fprintf(out,"%s\n",plumedRoot.c_str()); - } else { - string msg="ERROR: maximum one file at a time"; - fprintf(stderr,"%s\n",msg.c_str()); - return 1; - } - } +void CLToolInfo::registerKeywords( Keywords& keys ){ + CLTool::registerKeywords( keys ); + keys.addFlag("--configuration",false,"prints the configuration file"); + keys.addFlag("--root",false,"print the location of the root directory for the plumed source"); +} - if(printhelp){ - fprintf(out,"%s", - "Usage: info [options]\n" - "Options:\n" - " [--help|-h] : prints this help\n" - " [--configuration] : prints the configuration file\n" -); - return 0; - } +CLToolInfo::CLToolInfo(const CLToolOptions& co ): +CLTool(co) +{ + inputdata=commandline; +} + +int CLToolInfo::main(FILE*out,PlumedCommunicator& pc){ + + bool printconfiguration; parseFlag("--configuration",printconfiguration); + bool printroot; parseFlag("--root",printroot); + if(printroot) fprintf(out,"%s\n",plumedRoot.c_str()); - if(printconfiguration){ + if(printconfiguration){ static const unsigned char conf [] ={ #include "Makefile.conf.xxd" , 0x00 }; diff --git a/src/CLToolMain.cpp b/src/CLToolMain.cpp index ce4dd6aed..1dd927a5f 100644 --- a/src/CLToolMain.cpp +++ b/src/CLToolMain.cpp @@ -203,8 +203,10 @@ int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,PlumedCommunicator& p if(find(availableCxx.begin(),availableCxx.end(),command)!=availableCxx.end()){ CLTool *cl=cltoolRegister().create(command); - plumed_assert(cl); - int ret=cl->main(argc-i,&argv[i],in,out,pc); + plumed_assert(cl); + // Read the command line options (returns false if we are just printing help) + if( !cl->readInput( argc-i,&argv[i],in,out ) ){ delete cl; return 0; } + int ret=cl->main(out,pc); delete cl; return ret; } @@ -218,7 +220,7 @@ int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,PlumedCommunicator& p return 0; } - string msg="ERROR: unknown command " + command; + string msg="ERROR: unknown command " + command + ". Use 'plumed help' for help"; fprintf(stderr,"%s\n",msg.c_str()); return 1; diff --git a/src/CLToolManual.cpp b/src/CLToolManual.cpp index 0754891bc..3f35621ee 100644 --- a/src/CLToolManual.cpp +++ b/src/CLToolManual.cpp @@ -34,9 +34,22 @@ using namespace std; namespace PLMD { //+PLUMEDOC TOOLS manual -/** +/* manual is a tool that you can use to construct the manual page for a particular action + +The manual constructed by this action is in html. In all probability you will never need to use this +tool. However, it is used within the scripts that generate plumed's html manual. If you need to use this +tool outside those scripts the input is specified using the following command line arguments. + +\par Examples + +The following generates the html manual for the action DISTANCE. +\verbatim +plumed manual --action DISTANCE +\endverbatim + + */ //+ENDPLUMEDOC @@ -44,7 +57,9 @@ class CLToolManual: public CLTool { public: - int main(int argc,char**argv,FILE*in,FILE*out,PlumedCommunicator& pc); + static void registerKeywords( Keywords& keys ); + CLToolManual(const CLToolOptions& co ); + int main(FILE*out,PlumedCommunicator& pc); string description()const{ return "print out a description of the keywords for an action in html"; } @@ -52,56 +67,28 @@ public: PLUMED_REGISTER_CLTOOL(CLToolManual,"manual") -int CLToolManual::main(int argc,char**argv,FILE*in,FILE*out,PlumedCommunicator& pc){ - -// to avoid warnings: - (void) in; - - std::string action="none"; - bool printhelp(false); - -// Start parsing options - string prefix(""); - std::string a(""); - for(int i=1;i<argc;i++){ - a=prefix+argv[i]; - if(a.length()==0) continue; - if(a=="-h" || a=="--help"){ - printhelp=true; - break; - } - if(a.find("--action=")==0){ - a.erase(0,a.find("=")+1); - action=a; - prefix=""; - } else if(a=="--action"){ - prefix="--action="; - } else { - string msg="ERROR: unknown option"+a; - fprintf(stderr,"%s\n",msg.c_str()); - return 1; - } - } - - if(printhelp){ - fprintf(out,"%s", - "Usage: info [options]\n" - "Options:\n" - " [--help|-h] : prints this help\n" - " [--action] : print the manual for this action\n" -); - return 0; - } +void CLToolManual::registerKeywords( Keywords& keys ){ + CLTool::registerKeywords( keys ); + keys.add("compulsory","--action","print the manual for this particular action"); +} - if(action=="none"){ - fprintf(stderr,"missing --action flag\n"); - return 1; - } +CLToolManual::CLToolManual(const CLToolOptions& co ): +CLTool(co) +{ + inputdata=commandline; +} - std::cerr<<actionRegister(); - if( !actionRegister().printManual(action) ){ - fprintf(stderr,"specified action is not registered\n"); - return 1; +int CLToolManual::main(FILE*out,PlumedCommunicator& pc){ + + std::string action; + if( !parse("--action",action) ) return 1; + std::cerr<<"LIST OF DOCUMENTED ACTIONS:\n"; + std::cerr<<actionRegister()<<"\n"; + std::cerr<<"LIST OF DOCUMENTED COMMAND LINE TOOLS:\n"; + std::cerr<<cltoolRegister()<<"\n\n"; + if( !actionRegister().printManual(action) && !cltoolRegister().printManual(action) ){ + fprintf(stderr,"specified action is not registered\n"); + return 1; } return 0; diff --git a/src/CLToolRegister.cpp b/src/CLToolRegister.cpp index 4d9292b99..b382de20d 100644 --- a/src/CLToolRegister.cpp +++ b/src/CLToolRegister.cpp @@ -50,12 +50,14 @@ void CLToolRegister::remove(creator_pointer f){ } } -void CLToolRegister::add(string key,creator_pointer f){ +void CLToolRegister::add(string key,creator_pointer f,keywords_pointer kf){ if(m.count(key)){ m.erase(key); disabled.insert(key); }else{ m.insert(pair<string,creator_pointer>(key,f)); + Keywords keys; kf(keys); + mk.insert(pair<string,Keywords>(key,keys)); }; } @@ -67,8 +69,10 @@ bool CLToolRegister::check(string key){ CLTool* CLToolRegister::create(const CLToolOptions&ao){ if(ao.line.size()<1)return NULL; CLTool* cltool; - if(check(ao.line[0])) cltool=m[ao.line[0]](ao); - else cltool=NULL; + if(check(ao.line[0])){ + CLToolOptions nao( ao,mk[ao.line[0]] ); + cltool=m[ao.line[0]](nao); + } else cltool=NULL; return cltool; } @@ -88,6 +92,15 @@ std::ostream & PLMD::operator<<(std::ostream &log,const CLToolRegister&ar){ return log; } +bool CLToolRegister::printManual( const std::string& cltool ){ + if ( check(cltool) ){ + mk[cltool].print_html(false); + return true; + } else { + return false; + } +} + vector<string> CLToolRegister::list()const{ vector<string> s; for(const_mIterator it=m.begin();it!=m.end();++it) diff --git a/src/CLToolRegister.h b/src/CLToolRegister.h index 251a1be8c..7c1331461 100644 --- a/src/CLToolRegister.h +++ b/src/CLToolRegister.h @@ -27,6 +27,7 @@ #include <set> #include <vector> #include <iosfwd> +#include "Keywords.h" namespace PLMD{ @@ -39,8 +40,12 @@ class CLToolRegister{ friend std::ostream &operator<<(std::ostream &,const CLToolRegister&); /// Pointer to a function which, given the options, create an CLTool typedef CLTool*(*creator_pointer)(const CLToolOptions&); +/// Pointer to a function which, returns the keywords allowed + typedef void(*keywords_pointer)(Keywords&); /// Map cltool to a function which creates the related object std::map<std::string,creator_pointer> m; +/// Map cltool name to the keywords for this function + std::map<std::string,Keywords> mk; /// Iterator over the map typedef std::map<std::string,creator_pointer>::iterator mIterator; /// Iterator over the map @@ -51,7 +56,7 @@ public: /// Register a new class. /// \param key The name of the directive to be used in the input file /// \param key A pointer to a function which creates an object of that class - void add(std::string key,creator_pointer); + void add(std::string key,creator_pointer,keywords_pointer); /// Verify if a directive is present in the register bool check(std::string cltool); /// Create an CLTool of the type indicated in the options @@ -61,6 +66,8 @@ public: ~CLToolRegister(); /// Returns a list of the allowed CLTools std::vector<std::string> list()const; +/// Print out the instructions for using the tool in html ready for input into the manual + bool printManual(const std::string& cltool); }; /// Function returning a reference to the CLToolRegister. @@ -83,9 +90,9 @@ std::ostream & operator<<(std::ostream &log,const CLToolRegister&ar); /// This macro should be used in the .cpp file of the corresponding class #define PLUMED_REGISTER_CLTOOL(classname,directive) \ static class classname##RegisterMe{ \ - static PLMD::CLTool* create(const PLMD::CLToolOptions&ao){(void)ao;return new classname;} \ + static PLMD::CLTool* create(const PLMD::CLToolOptions&ao){return new classname(ao);} \ public: \ - classname##RegisterMe(){PLMD::cltoolRegister().add(directive,create);}; \ + classname##RegisterMe(){PLMD::cltoolRegister().add(directive,create,classname::registerKeywords);}; \ ~classname##RegisterMe(){PLMD::cltoolRegister().remove(create);}; \ } classname##RegisterMeObject; diff --git a/src/CLToolSimpleMD.cpp b/src/CLToolSimpleMD.cpp index 0a7d9ca49..925b0d095 100644 --- a/src/CLToolSimpleMD.cpp +++ b/src/CLToolSimpleMD.cpp @@ -34,6 +34,45 @@ using namespace PLMD; namespace PLMD{ +//+PLUMEDOC TOOLS simplemd +/* +simplemd allows one to do molecular dynamics on systems of Lennard-Jones atoms. + +The input to simplemd is spcified in an input file. Configurations are input and +output in xyz format. The input file should contain one directive per line. +The directives available are as follows: + +\par Examples + +You run an MD simulation using simplemd with the following command: +\verbatim +plumed simplemd < in +\endverbatim + +The following is an example of an input file for a simplemd calculation. This file +instructs simplemd to do 50 steps of MD at a temperature of 0.722 +\verbatim +nputfile input.xyz +outputfile output.xyz +temperature 0.722 +tstep 0.005 +friction 1 +forcecutoff 2.5 +listcutoff 3.0 +nstep 50 +nconfig 10 trajectory.xyz +nstat 10 energies.dat +\endverbatim + +If you run the following a description of all the directives that can be used in the +input file will be output. +\verbatim +plumed simplemd --help +\endverbatim + +*/ +//+ENDPLUMEDOC + class CLToolSimpleMD: public PLMD::CLTool { @@ -52,7 +91,26 @@ FILE* write_statistics_fp; public: -CLToolSimpleMD(){ +static void registerKeywords( Keywords& keys ){ + keys.add("compulsory","nstep","The number of steps of dynamics you want to run"); + keys.add("compulsory","temperature","NVE","the temperature at which you wish to run the simulation in LJ units"); + keys.add("compulsory","friction","off","The friction (in LJ units) for the langevin thermostat that is used to keep the temperature constant"); + keys.add("compulsory","tstep","0.005","the integration timestep in LJ units"); + keys.add("compulsory","inputfile","An xyz file containing the initial configuration of the system"); + keys.add("compulsory","forcecutoff","2.5",""); + keys.add("compulsory","listcutoff","3.0",""); + keys.add("compulsory","outputfile","An output xyz file containing the final configuration of the system"); + keys.add("compulsory","nconfig","10","The frequency with which to write configurations to the trajectory file followed by the name of the trajectory file"); + keys.add("compulsory","nstat","1","The frequency with which to write the statistics to the statistics file followed by the name of the statistics file"); + keys.add("compulsory","maxneighbours","10000","The maximum number of neighbours an atom can have"); + keys.add("compulsory","idum","0","The random number seed"); + keys.add("compulsory","ndim","3","The dimensionality of the system (some interesting LJ clusters are two dimensional)"); +} + +CLToolSimpleMD( const CLToolOptions& co ) : +CLTool(co) +{ + inputdata=ifile; for(int i=0;i<32;i++) iv[i]=0.0; iy=0; iset=0; @@ -66,8 +124,7 @@ CLToolSimpleMD(){ private: void -read_input(FILE* fp, - double& temperature, +read_input(double& temperature, double& tstep, double& friction, double& forcecutoff, @@ -84,99 +141,49 @@ read_input(FILE* fp, int& ndim, int& idum) { - temperature=1.0; - tstep=0.005; - friction=0.0; - forcecutoff=2.5; - listcutoff=3.0; - nstep=1; - nconfig=10; - nstat=1; - maxneighbours=1000; - idum=0; - ndim=3; - wrapatoms=false; - statfile=""; - trajfile=""; - outputfile=""; - inputfile=""; - - string line; - - line.resize(256); - char buffer[256]; - char buffer1[256]; - - while(fgets(buffer,256,fp)){ - line=buffer; - for(int i=0;i<line.length();++i) if(line[i]=='#' || line[i]=='\n') line.erase(i); - for(int i=line.length()-1;i>=0;--i){ - if(line[i]!=' ')break; - line.erase(i); - } - if(line.length()==0) continue; - sscanf(line.c_str(),"%s",buffer); - string keyword=buffer; - if(keyword=="temperature") - sscanf(line.c_str(),"%s %lf",buffer,&temperature); - else if(keyword=="tstep") - sscanf(line.c_str(),"%s %lf",buffer,&tstep); - else if(keyword=="friction") - sscanf(line.c_str(),"%s %lf",buffer,&friction); - else if(keyword=="forcecutoff") - sscanf(line.c_str(),"%s %lf",buffer,&forcecutoff); - else if(keyword=="listcutoff") - sscanf(line.c_str(),"%s %lf",buffer,&listcutoff); - else if(keyword=="nstep") - sscanf(line.c_str(),"%s %d",buffer,&nstep); - else if(keyword=="nconfig") - { - sscanf(line.c_str(),"%s %d %s",buffer,&nconfig,buffer1); - trajfile=buffer1; - } - else if(keyword=="nstat") - { - sscanf(line.c_str(),"%s %d %s",buffer,&nstat,buffer1); - statfile=buffer1; - } - else if(keyword=="maxneighbours") - sscanf(line.c_str(),"%s %d",buffer,&maxneighbours); - else if(keyword=="inputfile") - { - sscanf(line.c_str(),"%s %s",buffer,buffer1); - inputfile=buffer1; - } - else if(keyword=="outputfile") - { - sscanf(line.c_str(),"%s %s",buffer,buffer1); - outputfile=buffer1; - } - else if(keyword=="idum") - sscanf(line.c_str(),"%s %d",buffer,&idum); - else if(keyword=="ndim") - sscanf(line.c_str(),"%s %d",buffer,&ndim); - else{ - fprintf(stderr,"Unknown keywords :%s\n",keyword.c_str()); - exit(1); - } - } + // Read everything from input file + char buffer1[256]; + std::string tempstr; parse("temperature",tempstr); + if( tempstr!="NVE" ) Tools::convert(tempstr,temperature); + parse("tstep",tstep); + std::string frictionstr; parse("friction",frictionstr); + if( tempstr!="NVE" ){ + if(frictionstr=="off"){ fprintf(stderr,"Specify friction for thermostat\n"); exit(1); } + Tools::convert(frictionstr,friction); + } + parse("forcecutoff",forcecutoff); + parse("listcutoff",listcutoff); + parse("nstep",nstep); + parse("maxneighbours",maxneighbours); + parse("idum",idum); + + // Read in stuff with sanity checks + parse("inputfile",inputfile); if(inputfile.length()==0){ fprintf(stderr,"Specify input file\n"); exit(1); } + parse("outputfile",outputfile); if(outputfile.length()==0){ fprintf(stderr,"Specify output file\n"); exit(1); } + std::string nconfstr; parse("nconfig",nconfstr); + sscanf(nconfstr.c_str(),"%d %s",&nconfig,buffer1); + trajfile=buffer1; if(trajfile.length()==0){ fprintf(stderr,"Specify traj file\n"); exit(1); } + std::string nstatstr; parse("nstat",nstatstr); + sscanf(nstatstr.c_str(),"%d %s",&nconfig,buffer1); + statfile=buffer1; if(statfile.length()==0){ fprintf(stderr,"Specify stat file\n"); exit(1); } + parse("ndim",ndim); if(ndim<1 || ndim>3){ fprintf(stderr,"ndim should be 1,2 or 3\n"); exit(1); @@ -369,7 +376,7 @@ void write_statistics(const string & statfile,const int istep,const double tstep -int main(int argc,char**argv,FILE*in,FILE*out,PLMD::PlumedCommunicator& pc){ +int main(FILE*out,PLMD::PlumedCommunicator& pc){ int natoms; // number of atoms vector<Vector> positions; // atomic positions vector<Vector> velocities; // velocities @@ -423,18 +430,11 @@ int main(int argc,char**argv,FILE*in,FILE*out,PLMD::PlumedCommunicator& pc){ plumed->cmd("setRealPrecision",&s); } - FILE* mystdin=in; - - if(argc==2) mystdin=fopen(argv[1],"r"); - - read_input(mystdin,temperature,tstep,friction,forcecutoff, + read_input(temperature,tstep,friction,forcecutoff, listcutoff,nstep,nconfig,nstat, wrapatoms,inputfile,outputfile,trajfile,statfile, maxneighbour,ndim,idum); - if(argc==2) fclose(mystdin); - - // number of atoms is read from file inputfile read_natoms(inputfile,natoms); diff --git a/src/Keywords.cpp b/src/Keywords.cpp index d1d302508..de9a5e083 100644 --- a/src/Keywords.cpp +++ b/src/Keywords.cpp @@ -218,13 +218,14 @@ bool Keywords::reserved( const std::string & k ) const { return false; } -void Keywords::print_html() const { +void Keywords::print_html( const bool isaction ) const { unsigned nkeys=0; for(unsigned i=0;i<keys.size();++i){ if ( (types.find(keys[i])->second).isAtomList() ) nkeys++; } if( nkeys>0 ){ - std::cout<<"\\par Specifying the atoms involved\n\n"; + if(isaction) std::cout<<"\\par Specifying the atoms involved\n\n"; + else std::cout<<"\\par The input trajectory is specified using one of the following\n\n"; std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n"; for(unsigned i=0;i<keys.size();++i){ if ( (types.find(keys[i])->second).isAtomList() ) print_html_item( keys[i] ); @@ -236,7 +237,8 @@ void Keywords::print_html() const { if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++; } if( nkeys>0 ){ - std::cout<< "\\par Compulsory keywords\n\n"; + if(isaction) std::cout<< "\\par Compulsory keywords\n\n"; + else std::cout<<"\\par The following must be present\n\n"; std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n"; for(unsigned i=0;i<keys.size();++i){ if ( (types.find(keys[i])->second).isCompulsory() ) print_html_item( keys[i] ); @@ -248,7 +250,8 @@ void Keywords::print_html() const { if ( (types.find(keys[i])->second).isFlag() ) nkeys++; } if( nkeys>0 ){ - std::cout<<"\\par Options\n\n"; + if(isaction) std::cout<<"\\par Options\n\n"; + else std::cout<<"\\par The following options are available\n\n"; std::cout<<" <table align=center frame=void width=95%% cellpadding=5%%> \n"; for(unsigned i=0;i<keys.size();++i){ if ( (types.find(keys[i])->second).isFlag() ) print_html_item( keys[i] ); @@ -270,6 +273,66 @@ void Keywords::print_html() const { std::cout<<"</table>\n\n"; } +void Keywords::print( FILE* out ) const { + unsigned nkeys=0; + for(unsigned i=0;i<keys.size();++i){ + if ( (types.find(keys[i])->second).isAtomList() ) nkeys++; + } + if( nkeys>0 ){ + fprintf(out,"The input trajectory can be in any of the following formats: \n\n"); + for(unsigned i=0;i<keys.size();++i){ + if ( (types.find(keys[i])->second).isAtomList() ) printKeyword( keys[i], out ); + } + } + nkeys=0; + for(unsigned i=0;i<keys.size();++i){ + if ( (types.find(keys[i])->second).isCompulsory() ) nkeys++; + } + if( nkeys>0 ){ + fprintf(out,"\nThe following arguments are compulsory: \n\n"); + for(unsigned i=0;i<keys.size();++i){ + if ( (types.find(keys[i])->second).isCompulsory() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); + } + } + nkeys=0; + for(unsigned i=0;i<keys.size();++i){ + if ( (types.find(keys[i])->second).isFlag() ) nkeys++; + } + if( nkeys>0 ){ + fprintf( out,"\nIn addition you may use the following options: \n\n"); + for(unsigned i=0;i<keys.size();++i){ + if ( (types.find(keys[i])->second).isFlag() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); + } + } + nkeys=0; + for(unsigned i=0;i<keys.size();++i){ + if ( (types.find(keys[i])->second).isOptional() ) nkeys++; + } + if( nkeys>0 ){ + for(unsigned i=0;i<keys.size();++i){ + if ( (types.find(keys[i])->second).isOptional() ) printKeyword( keys[i], out ); //log.printKeyword( keys[i], documentation[i] ); + } + fprintf(out,"\n"); + } +} + +void Keywords::printKeyword( const std::string& key, FILE* out ) const { + bool killdot=( (documentation.find(key)->second).find("\\f$")!=std::string::npos ); // Check for latex + std::vector<std::string> w=Tools::getWords( documentation.find(key)->second ); + fprintf(out,"%23s - ", key.c_str() ); + unsigned nl=0; std::string blank=" "; + for(unsigned i=0;i<w.size();++i){ + nl+=w[i].length() + 1; + if( nl>60 ){ + fprintf(out,"\n%23s %s ", blank.c_str(), w[i].c_str() ); nl=0; + } else { + fprintf(out,"%s ", w[i].c_str() ); + } + if( killdot && w[i].find(".")!=std::string::npos ) break; // If there is latex only write up to first dot + } + fprintf(out,"\n"); +} + void Keywords::print( Log& log ) const { unsigned nkeys=0; for(unsigned i=0;i<keys.size();++i){ @@ -338,6 +401,11 @@ void Keywords::print_html_item( const std::string& key ) const { printf("</tr>\n"); } +std::string Keywords::get( const unsigned k ) const { + plumed_assert( k<size() ); + return keys[k]; +} + bool Keywords::getLogicalDefault( std::string key, bool& def ) const { if( booldefs.find(key)!=booldefs.end() ){ def=booldefs.find(key)->second; diff --git a/src/Keywords.h b/src/Keywords.h index dfd87ea9f..e1923248e 100644 --- a/src/Keywords.h +++ b/src/Keywords.h @@ -76,11 +76,13 @@ private: void print_html_item( const std::string& ) const; /// Print a particular keyword void printKeyword( const std::string& j, Log& log ) const ; +/// Print a particular keyword (copy of the above that works with files) + void printKeyword( const std::string& j, FILE* out ) const ; /// find out whether flag key is on or off by default. bool getLogicalDefault( std::string key, bool& def ) const ; +public: /// Get the value of the default for the keyword named key bool getDefaultValue( std::string key, std::string& def ) const ; -public: /// Return the number of defined keywords unsigned size() const; /// Check if numbered keywords are allowed for this action @@ -89,12 +91,16 @@ public: std::string getKeyword( const unsigned i ) const ; /// Print the documentation to the log file (used by PLMD::Action::error) void print( Log& log ) const ; +/// Print the documentation to a file (use by PLUMED::CLTool::readCommandLineArgs) + void print( FILE* out ) const ; /// Reserve a keyword void reserve( const std::string & t, const std::string & k, const std::string & d ); /// Reserve a flag void reserveFlag( const std::string & k, const bool def, const std::string & d ); /// Use one of the reserved keywords void use( const std::string k ); +/// Get the ith keyword + std::string get( const unsigned k ) const ; /// Add a new keyword of type t with name k and description d void add( const std::string & t, const std::string & k, const std::string & d ); /// Add a new compulsory keyword (t must equal compulsory) with name k, default value def and description d @@ -110,7 +116,7 @@ public: /// Check if the keyword with name k has style t bool style( const std::string & k, const std::string & t ) const ; /// Print an html version of the documentation - void print_html() const ; + void print_html( const bool isaction ) const ; /// Change the style of a keyword void reset_style( const std::string & k, const std::string & style ); /// Add keywords from one keyword object to another diff --git a/src/Tools.cpp b/src/Tools.cpp index 987462134..161ec8227 100644 --- a/src/Tools.cpp +++ b/src/Tools.cpp @@ -235,3 +235,9 @@ vector<string> Tools::ls(const string&d){ } return result; } + +void Tools::stripLeadingAndTrailingBlanks( std::string& str ){ + std::size_t first=str.find_first_not_of(' '); + std::size_t last=str.find_last_not_of(' '); + if( first<last ) str=str.substr(first,last+1); +} diff --git a/src/Tools.h b/src/Tools.h index 65b7c5c41..1c4f62f8d 100644 --- a/src/Tools.h +++ b/src/Tools.h @@ -104,6 +104,8 @@ public: static void interpretLabel(std::vector<std::string>&s); /// list files in a directory static std::vector<std::string> ls(const std::string&); +/// removes leading and trailing blanks from a string + static void stripLeadingAndTrailingBlanks( std::string& str ); }; template <class T> -- GitLab