Merge branch 'master' into rotation
authorCarsten Kutzner <ckutzne@ckutzne.mpibpc.intern>
Tue, 6 Jul 2010 09:41:22 +0000 (11:41 +0200)
committerCarsten Kutzner <ckutzne@ckutzne.mpibpc.intern>
Tue, 6 Jul 2010 09:41:22 +0000 (11:41 +0200)
Conflicts:
src/gmxlib/tpxio.c
src/kernel/runner.c

519 files changed:
.gitignore
CMakeLists.txt
COPYING-GPU [new file with mode: 0644]
INSTALL
INSTALL-GPU [new file with mode: 0644]
Makefile.am
README
README-GPU [new file with mode: 0644]
acinclude.m4
admin/programs.txt
cmake/FindCUDA.cmake
cmake/FindCUDA/make2cmake.cmake [changed mode: 0755->0644]
cmake/FindCUDA/run_nvcc.cmake [changed mode: 0755->0644]
cmake/FindGit.cmake
cmake/FindOpenMM.cmake
cmake/ThreadMPI.cmake
cmake/gmxCFlags.cmake
cmake/gmxCheckGCCVersion.cmake [new file with mode: 0644]
cmake/gmxGenerateVersionInfo.cmake
cmake/gmxTestInlineASM.cmake
configure.ac
include/3dview.h
include/Makefile.am
include/calcgrid.h
include/checkpoint.h
include/copyrite.h
include/domdec.h
include/domdec_network.h
include/edsam.h
include/enxio.h
include/fftgrid.h [deleted file]
include/filenm.h
include/force.h
include/futil.h
include/gmx_ana.h
include/gmx_fatal.h
include/gmx_fft.h
include/gmx_matrix.h [new file with mode: 0644]
include/gmx_parallel_3dfft.h
include/gmx_random.h
include/gmx_sort.h [new file with mode: 0644]
include/gmx_sse2_single.h
include/gmx_statistics.h
include/gmxcpp.h
include/gmxfio.h
include/grompp.h
include/hackblock.h
include/histogram.h
include/index.h
include/indexutil.h
include/main.h
include/mdrun.h
include/mpelogging.h
include/nbsearch.h
include/network.h
include/nrama.h
include/oenv.h
include/pdbio.h
include/pme.h
include/poscalc.h
include/pppm.h
include/readinp.h
include/resall.h
include/rmpbc.h
include/selection.h
include/selmethod.h
include/selvalue.h
include/sfactor.h [new file with mode: 0644]
include/sighandler.h
include/smalloc.h
include/sortwater.h
include/statusio.h [deleted file]
include/statutil.h
include/thread_mpi/Makefile.am
include/thread_mpi/atomic.h
include/thread_mpi/atomic/gcc_x86.h
include/thread_mpi/atomic/xlc_ppc.h
include/thread_mpi/barrier.h
include/thread_mpi/collective.h
include/thread_mpi/event.h
include/thread_mpi/list.h
include/thread_mpi/lock.h [moved from src/gmxlib/thread_mpi/event.h with 56% similarity]
include/thread_mpi/mpi_bindings.h
include/thread_mpi/threads.h
include/thread_mpi/tmpi.h
include/thread_mpi/wait.h [moved from src/gmxlib/thread_mpi/wait.h with 100% similarity]
include/tpxio.h
include/trnio.h
include/typedefs.h
include/types/commrec.h
include/types/fcdata.h
include/types/idef.h
include/types/inputrec.h
include/types/qmmmrec.h
include/types/state.h
include/types/topology.h
include/types/trx.h
include/update.h
include/vec.h
include/vmdio.h
include/xdrf.h
include/xtcio.h
scripts/make_gromos_nb.pl
scripts/make_gromos_rtp.py
share/html/online/mdp_opt.html
share/html/online/xtc.html
share/top/Makefile.am
share/top/benzamide.itp [deleted file]
share/top/bondadd.itp [deleted file]
share/top/buck.itp [deleted file]
share/top/charmm27.ff/Makefile.am
share/top/charmm27.ff/aminoacids.c.tdb
share/top/charmm27.ff/aminoacids.r2b
share/top/charmm27.ff/aminoacids.rtp
share/top/charmm27.ff/atomtypes.atp
share/top/charmm27.ff/ffnb.itp
share/top/charmm27.ff/gb.itp
share/top/charmm27.ff/spce.itp [new file with mode: 0644]
share/top/charmm27.ff/tip3p.itp
share/top/charmm27.ff/tips3p.itp [new file with mode: 0644]
share/top/charmm27.ff/watermodels.dat [new file with mode: 0644]
share/top/defselection.dat
share/top/dmso.gro [deleted file]
share/top/dmso.itp [deleted file]
share/top/encads.ff/Makefile.am
share/top/encads.ff/aminoacids.c.tdb
share/top/encads.ff/aminoacids.r2b [new file with mode: 0644]
share/top/encads.ff/forcefield.doc
share/top/encads.ff/watermodels.dat [new file with mode: 0644]
share/top/encadv.ff/Makefile.am
share/top/encadv.ff/aminoacids.c.tdb
share/top/encadv.ff/aminoacids.r2b [new file with mode: 0644]
share/top/encadv.ff/forcefield.doc
share/top/encadv.ff/watermodels.dat [new file with mode: 0644]
share/top/gmx.ff/1mlg.itp [moved from share/top/1mlg.itp with 100% similarity]
share/top/gmx.ff/2mlg.itp [moved from share/top/2mlg.itp with 100% similarity]
share/top/gmx.ff/Makefile.am
share/top/gmx.ff/aminoacids.rtp
share/top/gmx.ff/decane.itp [moved from share/top/decane.itp with 100% similarity]
share/top/gmx.ff/decane50.gro [moved from share/top/dec50.gro with 100% similarity]
share/top/gmx.ff/dlg.itp [moved from share/top/dlg.itp with 100% similarity]
share/top/gmx.ff/fa.itp [moved from share/top/fa.itp with 100% similarity]
share/top/gmx.ff/h2p4o13.itp [moved from share/top/h2p4o13.itp with 100% similarity]
share/top/gmx.ff/h2p8o25.itp [moved from share/top/h2p8o25.itp with 100% similarity]
share/top/gmx.ff/h2po4.itp [moved from share/top/h2po4.itp with 100% similarity]
share/top/gmx.ff/tfe.itp [moved from share/top/tfe.itp with 100% similarity]
share/top/gmx.ff/watermodels.dat [new file with mode: 0644]
share/top/gmx2.ff/Makefile.am
share/top/gmx2.ff/aminoacids.rtp
share/top/gmx2.ff/watermodels.dat [new file with mode: 0644]
share/top/gromos43a1.ff/Makefile.am
share/top/gromos43a1.ff/aminoacids.r2b [new file with mode: 0644]
share/top/gromos43a1.ff/aminoacids.rtp
share/top/gromos43a1.ff/atomtypes.atp
share/top/gromos43a1.ff/ffnonbonded.itp
share/top/gromos43a1.ff/methanol.itp [moved from share/top/methanol.itp with 100% similarity]
share/top/gromos43a1.ff/methanol216.gro [moved from share/top/methanol216.gro with 100% similarity]
share/top/gromos43a1.ff/watermodels.dat [new file with mode: 0644]
share/top/gromos43a2.ff/Makefile.am
share/top/gromos43a2.ff/aminoacids.r2b [new file with mode: 0644]
share/top/gromos43a2.ff/aminoacids.rtp
share/top/gromos43a2.ff/atomtypes.atp
share/top/gromos43a2.ff/ffnonbonded.itp
share/top/gromos43a2.ff/watermodels.dat [new file with mode: 0644]
share/top/gromos45a3.ff/Makefile.am
share/top/gromos45a3.ff/aminoacids.r2b [new file with mode: 0644]
share/top/gromos45a3.ff/aminoacids.rtp
share/top/gromos45a3.ff/atomtypes.atp
share/top/gromos45a3.ff/ffnonbonded.itp
share/top/gromos45a3.ff/watermodels.dat [new file with mode: 0644]
share/top/gromos53a5.ff/Makefile.am
share/top/gromos53a5.ff/aminoacids.hdb
share/top/gromos53a5.ff/aminoacids.n.tdb
share/top/gromos53a5.ff/aminoacids.r2b [new file with mode: 0644]
share/top/gromos53a5.ff/aminoacids.rtp
share/top/gromos53a5.ff/atomtypes.atp
share/top/gromos53a5.ff/watermodels.dat [new file with mode: 0644]
share/top/gromos53a6.ff/Makefile.am
share/top/gromos53a6.ff/aminoacids.hdb
share/top/gromos53a6.ff/aminoacids.n.tdb
share/top/gromos53a6.ff/aminoacids.r2b [new file with mode: 0644]
share/top/gromos53a6.ff/aminoacids.rtp
share/top/gromos53a6.ff/atomtypes.atp
share/top/gromos53a6.ff/watermodels.dat [new file with mode: 0644]
share/top/gurgle.dat
share/top/oplsaa.ff/1propanol.itp [moved from share/top/opls-1propanol.itp with 100% similarity]
share/top/oplsaa.ff/Makefile.am
share/top/oplsaa.ff/aminoacids.r2b [new file with mode: 0644]
share/top/oplsaa.ff/aminoacids.rtp
share/top/oplsaa.ff/ethanol.itp [moved from share/top/opls-ethanol.itp with 100% similarity]
share/top/oplsaa.ff/ions.itp
share/top/oplsaa.ff/methanol.itp [moved from share/top/opls-methanol.itp with 100% similarity]
share/top/oplsaa.ff/watermodels.dat [new file with mode: 0644]
share/top/sfactor.dat [new file with mode: 0644]
share/top/specbond.dat
share/top/urea+h2o.gro [deleted file]
share/top/urea.itp [deleted file]
src/Makefile.am
src/config.h.cmakein
src/contrib/Makefile.am
src/contrib/options.c
src/gmxlib/CMakeLists.txt
src/gmxlib/Makefile.am
src/gmxlib/atomprop.c
src/gmxlib/calcgrid.c
src/gmxlib/calch.c
src/gmxlib/checkpoint.c
src/gmxlib/confio.c
src/gmxlib/copyrite.c
src/gmxlib/disre.c
src/gmxlib/enxio.c
src/gmxlib/filenm.c
src/gmxlib/futil.c
src/gmxlib/gbutil.c
src/gmxlib/genversion.sh
src/gmxlib/gmx_fatal.c
src/gmxlib/gmx_matrix.c [new file with mode: 0644]
src/gmxlib/gmx_sort.c [new file with mode: 0644]
src/gmxlib/gmx_system_xdr.c
src/gmxlib/gmxcpp.c
src/gmxlib/gmxfio.c
src/gmxlib/gmxfio_asc.c [new file with mode: 0644]
src/gmxlib/gmxfio_bin.c [new file with mode: 0644]
src/gmxlib/gmxfio_int.h [new file with mode: 0644]
src/gmxlib/gmxfio_rw.c [new file with mode: 0644]
src/gmxlib/gmxfio_xdr.c [new file with mode: 0644]
src/gmxlib/index.c
src/gmxlib/libxdrf.c
src/gmxlib/main.c
src/gmxlib/matio.c
src/gmxlib/mshift.c
src/gmxlib/mtop_util.c
src/gmxlib/mtxio.c
src/gmxlib/network.c
src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel400_ia32_sse.c
src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel410_ia32_sse.c
src/gmxlib/nonbonded/nb_kernel_ia32_sse/nb_kernel430_ia32_sse.c
src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel400_ia32_sse2.c
src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel410_ia32_sse2.c
src/gmxlib/nonbonded/nb_kernel_ia32_sse2/nb_kernel430_ia32_sse2.c
src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel400_sse2_single.c
src/gmxlib/nonbonded/nb_kernel_sse2_single/nb_kernel430_sse2_single.c
src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel400_x86_64_sse.c
src/gmxlib/nonbonded/nb_kernel_x86_64_sse/nb_kernel430_x86_64_sse.c
src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel400_x86_64_sse2.c
src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel410_x86_64_sse2.c
src/gmxlib/nonbonded/nb_kernel_x86_64_sse2/nb_kernel430_x86_64_sse2.c
src/gmxlib/nrama.c
src/gmxlib/nrnb.c
src/gmxlib/oenv.c
src/gmxlib/orires.c
src/gmxlib/pbc.c
src/gmxlib/pdbio.c
src/gmxlib/readinp.c
src/gmxlib/rmpbc.c
src/gmxlib/selection/Makefile.am
src/gmxlib/selection/compiler.c
src/gmxlib/selection/evaluate.c
src/gmxlib/selection/evaluate.h
src/gmxlib/selection/keywords.h
src/gmxlib/selection/mempool.c [new file with mode: 0644]
src/gmxlib/selection/mempool.h [new file with mode: 0644]
src/gmxlib/selection/params.c
src/gmxlib/selection/parser.c
src/gmxlib/selection/parser.h
src/gmxlib/selection/parser.y
src/gmxlib/selection/parsetree.c
src/gmxlib/selection/parsetree.h
src/gmxlib/selection/selcollection.h
src/gmxlib/selection/selection.c
src/gmxlib/selection/selelem.c
src/gmxlib/selection/selelem.h
src/gmxlib/selection/selhelp.c
src/gmxlib/selection/selmethod.c
src/gmxlib/selection/sm_compare.c
src/gmxlib/selection/sm_distance.c
src/gmxlib/selection/sm_insolidangle.c
src/gmxlib/selection/sm_keywords.c
src/gmxlib/selection/sm_merge.c
src/gmxlib/selection/sm_permute.c
src/gmxlib/selection/sm_position.c
src/gmxlib/selection/sm_same.c
src/gmxlib/selection/sm_simple.c
src/gmxlib/selection/symrec.h
src/gmxlib/selection/test_selection.c
src/gmxlib/sfactor.c [new file with mode: 0644]
src/gmxlib/shift_util.c
src/gmxlib/sighandler.c
src/gmxlib/smalloc.c
src/gmxlib/splitter.c
src/gmxlib/statistics/gmx_statistics.c
src/gmxlib/statutil.c
src/gmxlib/strdb.c
src/gmxlib/string2.c
src/gmxlib/thread_mpi/CMakeLists.txt
src/gmxlib/thread_mpi/Makefile.am
src/gmxlib/thread_mpi/barrier.c
src/gmxlib/thread_mpi/collective.c
src/gmxlib/thread_mpi/comm.c
src/gmxlib/thread_mpi/impl.h
src/gmxlib/thread_mpi/lock.c [moved from src/gmxlib/thread_mpi/barrier.h with 70% similarity]
src/gmxlib/thread_mpi/p2p_protocol.c
src/gmxlib/thread_mpi/profile.c
src/gmxlib/thread_mpi/profile.h
src/gmxlib/thread_mpi/reduce.c
src/gmxlib/thread_mpi/settings.h
src/gmxlib/thread_mpi/tmpi_impl.h [deleted file]
src/gmxlib/thread_mpi/tmpi_init.c
src/gmxlib/thread_mpi/topology.c
src/gmxlib/thread_mpi/winthreads.c
src/gmxlib/topsort.c
src/gmxlib/tpxio.c
src/gmxlib/trajana/indexutil.c
src/gmxlib/trajana/nbsearch.c
src/gmxlib/trajana/poscalc.c
src/gmxlib/trajana/trajana.c
src/gmxlib/trnio.c
src/gmxlib/trxio.c
src/gmxlib/typedefs.c
src/gmxlib/wgms.c
src/gmxlib/xdrd.c
src/gmxlib/xtcio.c
src/kernel/CMakeLists.txt
src/kernel/Makefile.am
src/kernel/fflibutil.c
src/kernel/fflibutil.h
src/kernel/g_luck.c [moved from src/kernel/luck.c with 100% similarity]
src/kernel/g_protonate.c [moved from src/kernel/protonate.c with 99% similarity]
src/kernel/g_x2top.c [moved from src/kernel/x2top.c with 94% similarity]
src/kernel/g_x2top.h [moved from src/kernel/x2top.h with 96% similarity]
src/kernel/gen_vsite.c
src/kernel/gen_vsite.h
src/kernel/genhydro.c
src/kernel/gmx_gpu_utils/CMakeLists.txt
src/kernel/gmx_gpu_utils/gmx_gpu_utils.cu
src/kernel/gmx_gpu_utils/gmx_gpu_utils.h
src/kernel/gmx_gpu_utils/memtestG80_core.h
src/kernel/gmxcheck.c
src/kernel/gmxdump.c
src/kernel/gpp_atomtype.c
src/kernel/grompp.c
src/kernel/h_db.c
src/kernel/h_db.h
src/kernel/hizzie.c
src/kernel/md.c
src/kernel/md_openmm.c
src/kernel/md_openmm.h
src/kernel/mdrun.c
src/kernel/nm2type.c
src/kernel/openmm_wrapper.cpp
src/kernel/openmm_wrapper.h
src/kernel/pdb2gmx.c
src/kernel/pdb2top.c
src/kernel/pdb2top.h
src/kernel/readir.c
src/kernel/readpull.c
src/kernel/repl_ex.c
src/kernel/repl_ex.h
src/kernel/resall.c
src/kernel/runner.c
src/kernel/specbond.c
src/kernel/specbond.h
src/kernel/ter_db.c
src/kernel/ter_db.h
src/kernel/topdirs.c
src/kernel/topio.c
src/kernel/toppush.c
src/kernel/toputil.c
src/kernel/tpbcmp.c
src/kernel/tpbconv.c
src/kernel/xlate.c
src/kernel/xlate.h
src/mdlib/Makefile.am
src/mdlib/constr.c
src/mdlib/coupling.c
src/mdlib/domdec.c
src/mdlib/domdec_network.c
src/mdlib/domdec_setup.c
src/mdlib/domdec_top.c
src/mdlib/edsam.c
src/mdlib/ewald.c
src/mdlib/fft5d.c [new file with mode: 0644]
src/mdlib/fft5d.h [new file with mode: 0644]
src/mdlib/fftgrid.c [deleted file]
src/mdlib/force.c
src/mdlib/forcerec.c
src/mdlib/genborn.c
src/mdlib/genborn_sse2_double.c
src/mdlib/genborn_sse2_double.h
src/mdlib/genborn_sse2_single.c
src/mdlib/genborn_sse2_single.h
src/mdlib/ghat.c
src/mdlib/gmx_fft.c
src/mdlib/gmx_fft_fftw3.c
src/mdlib/gmx_parallel_3dfft.c
src/mdlib/gmx_qhop_db.h
src/mdlib/init.c
src/mdlib/mdebin.c
src/mdlib/minimize.c
src/mdlib/nsgrid.c
src/mdlib/perf_est.c
src/mdlib/pme.c
src/mdlib/pme_pp.c
src/mdlib/pppm.c
src/mdlib/pull.c
src/mdlib/qm_orca.c [new file with mode: 0644]
src/mdlib/qmmm.c
src/mdlib/shakef.c
src/mdlib/sim_util.c
src/mdlib/stat.c
src/mdlib/tables.c
src/mdlib/tpi.c
src/ngmx/CMakeLists.txt
src/ngmx/Makefile.am
src/ngmx/g_highway.c [moved from src/ngmx/highway.c with 100% similarity]
src/ngmx/g_logo.c [moved from src/ngmx/gmxlogo.c with 97% similarity]
src/ngmx/g_showcol.c [moved from src/ngmx/showcol.c with 97% similarity]
src/ngmx/g_xrama.c [moved from src/ngmx/xrama.c with 100% similarity]
src/ngmx/logo.c
src/ngmx/logo.h
src/ngmx/manager.c
src/ngmx/manager.h
src/ngmx/molps.c
src/ngmx/ngmx.c
src/ngmx/nmol.c
src/ngmx/scrollw.c [deleted file]
src/ngmx/test_ngmx_dialog.c [moved from src/ngmx/dlg.c with 100% similarity]
src/tools/CMakeLists.txt
src/tools/Makefile.am
src/tools/addconf.c
src/tools/anadih.c
src/tools/autocorr.c
src/tools/average.c [deleted file]
src/tools/calcpot.c
src/tools/do_dssp.c
src/tools/eigio.c
src/tools/expfit.c
src/tools/g_anadock.c [moved from src/tools/anadock.c with 100% similarity]
src/tools/g_membed.c [new file with mode: 0644]
src/tools/g_sigeps.c [moved from src/tools/sigeps.c with 100% similarity]
src/tools/g_wheel.c [moved from src/tools/wheel.c with 100% similarity]
src/tools/geminate.c [new file with mode: 0644]
src/tools/geminate.h [new file with mode: 0644]
src/tools/gmx_anaeig.c
src/tools/gmx_analyze.c
src/tools/gmx_angle.c
src/tools/gmx_bar.c
src/tools/gmx_bond.c
src/tools/gmx_bundle.c
src/tools/gmx_chi.c
src/tools/gmx_cluster.c
src/tools/gmx_clustsize.c
src/tools/gmx_confrms.c
src/tools/gmx_covar.c
src/tools/gmx_current.c
src/tools/gmx_density.c
src/tools/gmx_densmap.c
src/tools/gmx_dielectric.c
src/tools/gmx_dih.c
src/tools/gmx_dipoles.c
src/tools/gmx_disre.c
src/tools/gmx_dist.c
src/tools/gmx_dyndom.c
src/tools/gmx_editconf.c
src/tools/gmx_eneconv.c
src/tools/gmx_enemat.c
src/tools/gmx_energy.c
src/tools/gmx_filter.c
src/tools/gmx_genconf.c
src/tools/gmx_gyrate.c
src/tools/gmx_h2order.c
src/tools/gmx_hbond.c
src/tools/gmx_helix.c
src/tools/gmx_helixorient.c
src/tools/gmx_kinetics.c
src/tools/gmx_mdmat.c
src/tools/gmx_membed.c [new file with mode: 0644]
src/tools/gmx_mindist.c
src/tools/gmx_morph.c
src/tools/gmx_msd.c
src/tools/gmx_multipoles.c
src/tools/gmx_nmens.c
src/tools/gmx_nmtraj.c
src/tools/gmx_order.c
src/tools/gmx_polystat.c
src/tools/gmx_potential.c
src/tools/gmx_principal.c
src/tools/gmx_rdf.c
src/tools/gmx_relax.c
src/tools/gmx_rms.c
src/tools/gmx_rmsdist.c
src/tools/gmx_rmsf.c
src/tools/gmx_rotacf.c
src/tools/gmx_rotmat.c
src/tools/gmx_saltbr.c
src/tools/gmx_sas.c
src/tools/gmx_sdf.c
src/tools/gmx_sgangle.c
src/tools/gmx_sham.c
src/tools/gmx_sorient.c
src/tools/gmx_spatial.c
src/tools/gmx_spol.c
src/tools/gmx_tcaf.c
src/tools/gmx_traj.c
src/tools/gmx_trjcat.c
src/tools/gmx_trjconv.c
src/tools/gmx_trjorder.c
src/tools/gmx_tune_pme.c
src/tools/gmx_vanhove.c
src/tools/gmx_velacc.c
src/tools/gmx_wham.c
src/tools/gmx_wheel.c
src/tools/hxprops.c
src/tools/make_edi.c
src/tools/make_ndx.c
src/tools/proptim.c
src/tools/readev.c
src/tools/recomb.c
tests/CMakeLists.txt [new file with mode: 0644]

index b3a51ccc37007a380ba9596a3522837f05560d82..47e0b64846b6c4904ae579618363725ea05adb19 100644 (file)
@@ -23,3 +23,5 @@ Makefile
 lib*.pc
 Doxyfile
 doxygen-doc
+.project
+.cproject
index 3e55db1a68ca6371908e6c25f8d088018a858afb..f98139e8c7fe6d7ba5adf2b4e414d3bd6f464c07 100644 (file)
@@ -1,6 +1,7 @@
 cmake_minimum_required(VERSION 2.6)
 
 project(Gromacs)
+include(Dart)
 # PROJECT_VERSION should have the following structure: 
 # VERSION[-dev-SUFFIX] where the VERSION can have any form and the suffix
 set(PROJECT_VERSION "4.0.99-dev-20100315"
@@ -9,6 +10,39 @@ set(PROJECT_VERSION "4.0.99-dev-20100315"
 # Cmake modules/macros are in a subdirectory to keep this file cleaner
 set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
 
+if(NOT CMAKE_BUILD_TYPE)
+    set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build, options are: Debug Release RelWithDebInfo MinSizeRel." FORCE)
+endif(NOT CMAKE_BUILD_TYPE)
+
+enable_language(C)
+
+
+########################################################################
+# Fix stupid flags on MSVC
+########################################################################
+IF(CMAKE_GENERATOR MATCHES "Visual Studio")
+    STRING(REPLACE /MD /MT CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})
+    SET(CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} CACHE STRING "" FORCE)
+    STRING(REPLACE /MD /MT CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
+    SET(CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} CACHE STRING "" FORCE)   
+ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio")
+
+set(GMX_EXTRA_LIBRARIES)
+
+######################################################################
+# compiler tests
+# these need ot be done early (before further tests).
+#####################################################################
+
+include(CheckCCompilerFlag)
+include(CheckCXXCompilerFlag)
+
+# check for buggy GCC 4.1.x 
+include(gmxCheckGCCVersion)
+
+include(gmxCFlags)
+gmx_c_flags()
+
 ########################################################################
 # User input options                                                   #
 ########################################################################
@@ -26,57 +60,22 @@ set(GMX_FFT_LIBRARY "fftw3"
 option(GMX_DISABLE_FFTW_MEASURE 
        "Do not optimize FFTW setups (not needed with SSE)" OFF)
 set(GMX_QMMM_PROGRAM "none" 
-    CACHE STRING "QM package choices: none,gaussian,mopac,gamess")
+    CACHE STRING "QM package choices: none,gaussian,mopac,gamess,orca")
 option(GMX_BROKEN_CALLOC "Work around broken calloc()" OFF)
 option(BUILD_SHARED_LIBS "Enable shared libraries (can be problematic with MPI)" OFF)
 option(GMX_MPI_IN_PLACE "Enable MPI_IN_PLACE for MPIs that have it defined" ON)
 option(GMX_DLOPEN "Compile with dlopen, needed to read VMD supported file formats" ON)
 mark_as_advanced(GMX_MPI_IN_PLACE)
 
-enable_language(C)
 
 option(GMX_IA32_ASM "Add SSE assembly files for IA32" OFF)
 option(GMX_X86_64_ASM "Add SSE assembly files for X86_64" OFF)
 option(USE_VERSION_H "Generate development version string/information" ON)
+option(GMX_DISABLE_GCC41_CHECK "Disable check for (buggy) gcc 4.1.x" OFF)
 
-#######################################################################
-# Check for options incompatible with OpenMM build                    #
-#######################################################################
-if(GMX_OPENMM)
-    cmake_minimum_required(VERSION 2.6.4)
-    # we'll use the built-in fft to avoid unnecessary dependencies
-    set (GMX_FFT_LIBRARY "fftpack")
-    if(GMX_MPI)
-        message(FATAL_ERROR "The OpenMM build is not compatible with MPI!")
-    endif(GMX_MPI)
-    if(GMX_THREADS)
-        message(STATUS "Threads not compatible with OpenMM build, disabled")
-        set(GMX_THREADS OFF)
-    endif(GMX_THREADS)
-    if(GMX_SOFTWARE_INVSQRT)
-        set(GMX_SOFTWARE_INVSQRT OFF)
-    endif(GMX_SOFTWARE_INVSQRT)
-    if(NOT GMX_ACCELERATION MATCHES "none")    
-        message(WARNING "The OpenMM build does not support other acceleration modes!")
-        set(GMX_ACCELERATION "none")
-    endif()
-    if(GMX_FAHCORE)
-        message(FATAL_ERROR "The OpenMM build does not support FAH build!")
-    endif(GMX_FAHCORE)
-endif(GMX_OPENMM)
-
+set(GMX_BINARY_SUFFIX "" CACHE STRING "Suffix for GROMACS binaries.")
 
-########################################################################
-# Fix stupid flags on MSVC
-########################################################################
-IF(CMAKE_GENERATOR MATCHES "Visual Studio")
-    STRING(REPLACE /MD /MT CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE})
-    SET(CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELEASE} CACHE STRING "" FORCE)
-    STRING(REPLACE /MD /MT CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG})
-    SET(CMAKE_C_FLAGS_DEBUG ${CMAKE_C_FLAGS_DEBUG} CACHE STRING "" FORCE)   
-ENDIF(CMAKE_GENERATOR MATCHES "Visual Studio")
 
-set(GMX_EXTRA_LIBRARIES)
 
 ########################################################################
 #Process MPI settings
@@ -111,11 +110,41 @@ if(GMX_MPI)
     set(GMX_LIB_MPI 1)
 endif(GMX_MPI)
 
+
+#######################################################################
+# Check for options incompatible with OpenMM build                    #
+#######################################################################
+if(GMX_OPENMM)
+    cmake_minimum_required(VERSION 2.6.4)
+    # we'll use the built-in fft to avoid unnecessary dependencies
+    set (GMX_FFT_LIBRARY "fftpack")
+    if(GMX_MPI)
+        message(FATAL_ERROR "The OpenMM build is not compatible with MPI!")
+    endif(GMX_MPI)
+    if(GMX_THREADS)
+        message(STATUS "Threads not compatible with OpenMM build, disabled")
+        set(GMX_THREADS OFF)
+    endif(GMX_THREADS)
+    if(GMX_SOFTWARE_INVSQRT)
+        set(GMX_SOFTWARE_INVSQRT OFF)
+    endif(GMX_SOFTWARE_INVSQRT)
+    if(NOT GMX_ACCELERATION MATCHES "none|None|NONE" OR NOT ${GMX_ACCELERATION} STREQUAL "")
+        message(WARNING "The OpenMM build does not support other acceleration modes!")
+        set(GMX_ACCELERATION "none")
+    endif()
+    if(GMX_FAHCORE)
+        message(FATAL_ERROR "The OpenMM build does not support FAH build!")
+    endif(GMX_FAHCORE)
+endif(GMX_OPENMM)
+
+
+
 ########################################################################
 # Basic system tests (standard libraries, headers, functions, types)   #
 ########################################################################
 include(CheckIncludeFiles)
 check_include_files(string.h     HAVE_STRING_H)
+check_include_files(math.h       HAVE_MATH_H)
 check_include_files(limits.h     HAVE_LIMITS_H)
 check_include_files(memory.h     HAVE_MEMORY_H)
 check_include_files(unistd.h    HAVE_UNISTD_H)
@@ -126,6 +155,7 @@ check_include_files(pthread.h    HAVE_PTHREAD_H)
 check_include_files(dirent.h     HAVE_DIRENT_H)
 check_include_files(inttypes.h   HAVE_INTTYPES_H)
 check_include_files(regex.h      HAVE_REGEX_H)
+check_include_files(copyfile.h   HAVE_COPYFILE_H)
 check_include_files(sys/types.h  HAVE_SYS_TYPES_H)
 check_include_files(sys/stat.h   HAVE_SYS_STAT_H)
 check_include_files(sys/time.h   HAVE_SYS_TIME_H)
@@ -136,21 +166,33 @@ check_include_files(xmmintrin.h  HAVE_XMMINTRIN_H)
 check_include_files(emmintrin.h  HAVE_EMMINTRIN_H)
 check_include_files(pmmintrin.h  HAVE_PMMINTRIN_H)
 check_include_files(smmintrin.h  HAVE_SMMINTRIN_H)
+check_include_files(io.h                HAVE_IO_H)
+
 
 include(CheckFunctionExists)
 check_function_exists(strcasecmp        HAVE_STRCASECMP)
 check_function_exists(strdup            HAVE_STRDUP)
 check_function_exists(vprintf           HAVE_VPRINTF)
 check_function_exists(memcmp            HAVE_MEMCMP)
+check_function_exists(posix_memalign    HAVE_POSIX_MEMALIGN)
+check_function_exists(memalign          HAVE_MEMALIGN)
+check_function_exists(_aligned_malloc   HAVE__ALIGNED_MALLOC)
 check_function_exists(gettimeofday      HAVE_GETTIMEOFDAY)
 check_function_exists(isnan             HAVE_ISNAN)
 check_function_exists(_isnan            HAVE__ISNAN)
 check_function_exists(isfinite          HAVE_ISFINITE)
 check_function_exists(_isfinite         HAVE__ISFINITE)
+check_function_exists(fsync             HAVE_FSYNC)
+check_function_exists(_fileno           HAVE__FILENO)
+check_function_exists(fileno            HAVE_FILENO)
+check_function_exists(_commit           HAVE__COMMIT)
+check_function_exists(copyfile          HAVE_COPYFILE)
+# check_function_exists(CopyFile          HAVE_WIN_COPYFILE)
 # After large files? check_function_exists(fseeko     HAVE_FSEEKO)
 
 include(CheckLibraryExists)
 check_library_exists(m sqrt "" HAVE_LIBM)
+check_library_exists(m cbrt "" HAVE_CBRT)
 
 include(CheckTypeSize)
 check_type_size("bool"          SIZEOF_BOOL) # will also set HAVE_BOOL
@@ -160,6 +202,12 @@ check_type_size("long long int" SIZEOF_LONG_LONG_INT)
 check_type_size("off_t"         SIZEOF_OFF_T)
 check_type_size("void *"        SIZEOF_VOIDP)
 
+if (SIZEOF_VOIDP LESS 8)
+    set(GMX_64_BIT FALSE)
+else (SIZEOF_VOIDP LESS 8)
+    set(GMX_64_BIT TRUE)
+endif (SIZEOF_VOIDP LESS 8)
+
 # Check for some basic types that we *need*, so set these to int if they are not present 
 check_type_size(uid_t uid_t)
 if(NOT uid_t)
@@ -194,6 +242,7 @@ test_big_endian(GMX_INTEGER_BIG_ENDIAN)
 
 
 
+
 ########################################################################
 # Find external packages                                               #
 ########################################################################
@@ -242,7 +291,8 @@ if(EXISTS "${CMAKE_SOURCE_DIR}/.git")
         # We need at least git v1.5.1 be able to parse git's date output. If not 
         # fund or the version is too small, we can't generate version information.
         find_package(Git 1.5.1)
-        if(NOT Git_FOUND OR Git_VERSION VERSION_LESS "1.5.1")
+        # this should at some point become VERSION_LESS
+        if(NOT Git_FOUND OR Git_VERSION STRLESS "1.5.1")
             message("No compatible git version found, won't be able to generate proper development version information.")
         endif()
     endif()
@@ -250,6 +300,10 @@ else()
     set(USE_VERSION_H OFF)
 endif()
 
+if (GMX_DLOPEN)
+    list(APPEND GMX_EXTRA_LIBRARIES ${CMAKE_DL_LIBS})
+endif (GMX_DLOPEN)
+
 ########################################################################
 # Generate development version info for cache
 ########################################################################
@@ -260,9 +314,6 @@ endif()
 # Our own GROMACS tests
 ########################################################################
 
-include(gmxCFlags)
-gmx_c_flags()
-
 add_definitions( -DHAVE_CONFIG_H )
 include_directories(${CMAKE_BINARY_DIR}/src)
 include_directories(${CMAKE_SOURCE_DIR}/include)
@@ -291,6 +342,24 @@ include(gmxTestInlineASM)
 gmx_test_inline_asm_gcc_x86(GMX_X86_GCC_INLINE_ASM)
 gmx_test_inline_asm_msvc_x86(GMX_X86_MSVC_INLINE_ASM)
 
+# reasonable defaults for fast binaries.
+if (NOT DEFINED GMX_SSE_SET)
+    if (GMX_X86_GCC_INLINE_ASM)
+        set(GMX_ACCELERATION "SSE" CACHE STRING "Accelerated kernels. Pick one of: SSE, BlueGene, Power6, ia64, altivec" FORCE)
+        if (GMX_64_BIT)
+            set(GMX_X86_64_ASM ON CACHE BOOL 
+                "Add SSE assembly files for x86_64" FORCE)
+        else (GMX_64_BIT)
+            set(GMX_IA32_ASM ON CACHE BOOL 
+                "Add SSE assembly files for IA32" FORCE)
+        endif (GMX_64_BIT)
+    endif (GMX_X86_GCC_INLINE_ASM)
+    set (GMX_SSE_SET true CACHE INTERNAL "SSE is set" FORCE)
+endif (NOT DEFINED GMX_SSE_SET)
+
+
+
+
 include(gmxTestXDR)
 gmx_test_xdr(GMX_SYSTEM_XDR)
 if(NOT GMX_SYSTEM_XDR)
@@ -324,6 +393,17 @@ string(TOUPPER ${GMX_ACCELERATION} ${GMX_ACCELERATION})
 if(${GMX_ACCELERATION} STREQUAL "NONE")
   # nothing to do
 elseif(${GMX_ACCELERATION} STREQUAL "SSE")
+    if (NOT GMX_64_BIT)
+        # for 32-bit compiles, we might need to turn on sse 
+        CHECK_C_COMPILER_FLAG("-msse2" XFLAGS_SSE)
+        if (XFLAGS_SSE)
+            set(GROMACS_C_FLAGS "-msse2 ${GROMACS_C_FLAGS}")
+        endif (XFLAGS_SSE)
+        CHECK_CXX_COMPILER_FLAG("-msse2" XXFLAGS_SSE)
+        if (XXFLAGS_SSE)
+            set(GROMACS_CXX_FLAGS "-msse2 ${GROMACS_CXX_FLAGS}")
+        endif (XXFLAGS_SSE)
+    endif (NOT GMX_64_BIT)
     if(HAVE_XMMINTRIN_H)
         if(GMX_IA32_ASM)
           option(GMX_ASM_USEASM-ATT "Use ATT-style assembly" ON)
@@ -382,10 +462,12 @@ elseif(${GMX_QMMM_PROGRAM} STREQUAL "MOPAC")
     set(GMX_QMMM_MOPAC 1)
 elseif(${GMX_QMMM_PROGRAM} STREQUAL "GAMESS")
     set(GMX_QMMM_GAMESS 1)
+elseif(${GMX_QMMM_PROGRAM} STREQUAL "ORCA")
+    set(GMX_QMMM_ORCA 1)
 elseif(${GMX_QMMM_PROGRAM} STREQUAL "NONE")
     # nothing to do
 else(${GMX_QMMM_PROGRAM} STREQUAL "GAUSSIAN")
-    MESSAGE(FATAL_ERROR "Invalid QM/MM program option: ${GMX_QMMM_PROGRAM}. Choose one of: Gaussian, Mopac, Gamess, None")
+    MESSAGE(FATAL_ERROR "Invalid QM/MM program option: ${GMX_QMMM_PROGRAM}. Choose one of: Gaussian, Mopac, Gamess, Orca, None")
 endif(${GMX_QMMM_PROGRAM} STREQUAL "GAUSSIAN")
 
 # Process FFT library settings - if not OpenMM build 
@@ -471,8 +553,18 @@ if(GMX_FAHCORE)
 endif(GMX_FAHCORE)
 
 # # # # # # # # # # NO MORE TESTS AFTER THIS LINE! # # # # # # # # # # #
-set(CMAKE_C_FLAGS ${GROMACS_C_FLAGS} CACHE STRING "Compiler flags")
-set(CMAKE_EXE_LINKER_FLAGS ${GROMACS_LINKER_FLAGS} CACHE STRING "Linker flags")
+# these are set after everything else
+if (NOT DEFINED GROMACS_C_FLAGS_SET)
+    set(GROMACS_C_FLAGS_SET true CACHE INTERNAL "Whether to reset the C flags" 
+        FORCE)
+    set(CMAKE_C_FLAGS "${GROMACS_C_FLAGS} ${CMAKE_C_FLAGS}" CACHE STRING 
+        "Flags used by the compiler during all build types" FORCE)
+    set(CMAKE_CXX_FLAGS "${GROMACS_CXX_FLAGS} ${CMAKE_CXX_FLAGS}" CACHE STRING 
+        "Flags used by the compiler during all build types" FORCE)
+    set(CMAKE_EXE_LINKER_FLAGS 
+        "${GROMACS_LINKER_FLAGS} ${CMAKE_EXE_LINKER_FLAGS}" 
+        CACHE STRING "Linker flags" FORCE) 
+endif (NOT DEFINED GROMACS_C_FLAGS_SET)
 
 ########################################################################
 # Specify install locations and which subdirectories to process        #
@@ -491,4 +583,11 @@ add_subdirectory(man)
 
 add_subdirectory(src)
 
+########################################################################
+# Tests                                                                #
+########################################################################
+
+enable_testing()
+add_test(TestBuildAll make)
 
+add_subdirectory(tests)
diff --git a/COPYING-GPU b/COPYING-GPU
new file mode 100644 (file)
index 0000000..d241a7b
--- /dev/null
@@ -0,0 +1,51 @@
+GROMACS is free software, distributed under the GNU General Public License. 
+The GROMACS-GPU release however includes / relies on code covered by several 
+different licences as described below.
+
+
+1. GROMACS source 
+
+The major parts of the GROMACS source are covered by the GNU General Public 
+License, a copy of this license can be found in the file COPYING.
+
+
+2. The memtestG80 library
+
+The memtestG80 library, written by Imran Haque, is Copyright 2009 Stanford University, 
+covered by the LGPL license. It may be used under the following terms: 
+
+IN NO EVENT SHALL STANFORD UNIVERSITY BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF STANFORD UNIVERSITY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+STANFORD UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION PROVIDED HEREUNDER IS PROVIDED "AS IS". Folding@home HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+
+Restrictions:
+
+You may use this software on a computer system only if you own the system or have the written permission of the owner.
+
+You may not alter the software or associated data files. 
+
+Certain builds of this software incorporate by linkage code from the libintl
+and libiconv libraries, which are covered by the Library GNU Public License,
+available at http://www.gnu.org/licenses/lgpl-3.0.txt.
+
+
+3. OpenMM (binary distributions only)
+
+There are several licenses which cover different parts of OpenMM as described
+in the file openmm/licenses/Licenses.txt accompanying the binary distribution.
+
+
+4. FindCUDA.cmake script 
+
+The FindCUDA.cmake script may be used under the terms of the MIT License:
+
+  James Bigler, NVIDIA Corp (nvidia.com - jbigler)
+  Abe Stephens, SCI Institute -- http://www.sci.utah.edu/~abe/FindCuda.html
+
+  Copyright (c) 2008 - 2009 NVIDIA Corporation.  All rights reserved.
+
+  Copyright (c) 2007-2009
+  Scientific Computing and Imaging Institute, University of Utah
+
+  This code is licensed under the MIT License.  See the FindCUDA.cmake script
+  for the text of the license.
diff --git a/INSTALL b/INSTALL
index 2d371f1bf98e8cb00bf358efdd8c6974958c8edb..d6f7bccba00658764c1e381b497cb801a68d8bb1 100644 (file)
--- a/INSTALL
+++ b/INSTALL
@@ -1,5 +1,5 @@
 
-                    Welcome to GROMACS 3.1!
+                    Welcome to GROMACS!
 
 Note: Detailed, step-by-step installation instructions
 are available on the website http://www.gromacs.org .
@@ -11,11 +11,9 @@ time you install GROMACS - our configuration script will check it!
 
 * SHORT INSTRUCTIONS FOR THE IMPATIENT:
 
-Starting with version 3.0, the GROMACS compile and install procedure 
-was changed to simplify things for you. We now use a standard 
-autoconf script and makefiles created by automake, like most 
-GNU programs. This means your normal installation actions are 
-limited to:
+GROMACS uses a standard autoconf script and makefiles created 
+by automake, like most GNU programs. This means your normal 
+installation actions are limited to:
 
 ./configure   
 make
diff --git a/INSTALL-GPU b/INSTALL-GPU
new file mode 100644 (file)
index 0000000..08c5b24
--- /dev/null
@@ -0,0 +1,73 @@
+
+                    Welcome to GROMACS-GPU!
+
+Note: Detailed, step-by-step installation instructions as 
+well as additional information are available on the website 
+http://www.gromacs.org/gpu
+
+
+* INSTALLING FROM BINARY DISTRIBUTION:
+
+0. Prerequisites: 
+    - OpenMM (included in the binary release)
+    - NVIDIA CUDA libraries (version >=3.0);
+    - NVIDIA driver (for details on compatiblity consult
+         http://www.nvidia.com/Download/index5.aspx);
+    - NVIDIA CUDA-enabled GPU (for compatiblity list see 
+         http://www.gromacs.org/gpu).
+
+
+1. Download and unpack the binary package for the respective 
+OS and architecture. Copy the content of the package to your 
+normal GROMACS installation directory (or to a custom location). 
+Note that as the distributed Gromacs-GPU packages do not contain 
+the entire set of tools and utilities included in a full GROAMCS 
+installation. Therefore, it is recommended to have a ≥v4.5 
+standard Gromacs installation along the GPU accelerated one.
+e.g. on unix: 
+
+tar -xvf gromacs-4.5-GPU.tar.gz
+cp -R gromacs-4.5-GPU/* PATH_TO_GROMACS_INSTALLATION
+
+
+2. Add the openmm/lib directory to your library path, e.g. in bash:
+
+export LD_LIBRARY_PATH=PATH_TO_GROMACS/openmm/lib:$LD_LIBRARY_PATH
+
+If there are other OpenMM versions installed, make sure that the 
+supplied libraries have preference when running mdrun-gpu. 
+Also, make sure that the CUDA libraries installed match the version 
+of CUDA with which GROMACS-GPU is compiled.
+
+
+3. Set the OPENMM_PLUGIN_DIR environment variable to contain the path 
+to the openmm/lib/plugins directory, e.g. in bash:
+
+export OPENMM_PLUGIN_DIR=PATH_TO_GROMACS/openmm/lib/plugins
+
+
+4. At this point, running the command: 
+
+PATH_TO_GROMACS/bin/mdrun-gpu -h 
+
+should display the standard mdrun help which means that all the 
+necessary libraries are accessible.
+
+
+
+* INSTALLING FROM SOURCE DISTRIBUTION:
+
+GROMACS-GPU uses a cmake build-generator and makefiles on unix. 
+This means your normal installation actions are limited to:
+
+cmake PATH_TO_SOURCE_DIRECTORY -DGMX_OPENMM=ON -DGMX_THREADS=OFF 
+make mdrun
+make install-mdrun
+
+
+
+* ARE YOU STILL HAVING PROBLEMS?
+
+Post it to the GROMACS mailing lists. We read these on a regular basis,
+and in many cases another user might already be familiar with the
+task you're trying to perform!
index 4ba1dec362b4932201f3279a5c213a23b8260ef1..58e83c5195367032563db738e0869ff6bbd0db8a 100644 (file)
@@ -35,7 +35,6 @@ install-exec-hook:
 mdrun:         
        (cd $(top_builddir)/src/gmxlib && $(MAKE) ; exit 0)
        (cd $(top_builddir)/src/mdlib && $(MAKE) ; exit 0)
-       (cd $(top_builddir)/src/kernel && $(MAKE) lib_LTLIBRARIES ; exit 0)
        (cd $(top_builddir)/src/kernel && $(MAKE) mdrun ; exit 0)
 
 install-mdrun:
diff --git a/README b/README
index 873ca331fe05894bd86554d573cbb89e49ad7a33..d24640e3c902f648c0ef821d59b405fa543d81b1 100644 (file)
--- a/README
+++ b/README
@@ -1,12 +1,6 @@
 
                Welcome to the official version of GROMACS!
 
-There are no significant changes to the installation or use between version 
-3.1 and 3.0, so if you're already used to 3.0 you can just go ahead and update.
-A lot of things changed with version 3.0, though. Not only is the code 
-significantly faster, but we also introduced a completely new installation
-process and licensed the package under the GPL (see the COPYING file).
-
 If you are familiar with unix, it should be fairly trivial to compile and
 install GROMACS. Installation instructions are available in the INSTALL file,
 and a more extended step-by-step guide can be found on http://www.gromacs.org .
@@ -37,8 +31,8 @@ The easiest way to avoid this kind of problems is to get your modifications
 included in the main distribution. We'll be happy to consider any decent 
 code. If it's a separate program it can probably be included in the contrib 
 directory straight away (not supported by us), but for major changes in the 
-main code we appreciate if you first test that it works with MPI, 
-double precision, fortran code, etc.
+main code we appreciate if you first test that it works with (and without) 
+MPI, threads, double precision, etc.
 
 If you still want to distribute a modified version or use part of GROMACS
 in your own program, remember that the entire modified must be licensed 
@@ -56,9 +50,10 @@ To help us fund development, we humbly ask that you cite the GROMACS papers:
   H.J.C. Berendsen, D. van der Spoel and R. van Drunen
   Comp. Phys. Comm. 91, 43-56 (1995)
  
-* GROMACS 3.0: A package for molecular simulation and trajectory analysis
-  Erik Lindahl, Berk Hess and David van der Spoel
-  J. Mol. Mod. 7, 306-317 (2001)
+* GROMACS 4: Algorithms for highly efficient, load-balanced, and scalable
+  molecular simulation
+  B. Hess and C. Kutzner and D. van der Spoel and E. Lindahl
+  J. Chem. Theory Comput. 4 (2008) pp. 435-447
 
 There are a lot of cool features we'd like to include in future versions,
 but our resources are limited. All kinds of donations are welcome, both in 
diff --git a/README-GPU b/README-GPU
new file mode 100644 (file)
index 0000000..c449c3d
--- /dev/null
@@ -0,0 +1,21 @@
+
+               Welcome to the official version of GROMACS-GPU!
+
+
+GROMACS-GPU provides GPU-accelerated MD simulations.
+The current release uses the OpenMM library. 
+
+This is a first beta release and therefore it is targeted at developers 
+and advanced users and is NOT intended for production use. 
+
+Installation instructions are available in the INSTALL-GPU file. 
+More details on the GPU accelerated release are available on the 
+GROMACS-GPU website: http://www.gromacs.org/gpu.
+
+Also see the README file for general GROMACS information.
+
+                               * * * * *
+
+GROMACS is free software, distributed under the GNU General Public License.
+The GROMACS-GPU release however includes / relies on code covered by several 
+different licences. For details see the COPYING-GPU file.
index 25501c09ddf5a188960aa6fada3264bbb65b0a05..8a6e330f15279a8f81e6a4aed7bd56d1ea91f1e9 100644 (file)
@@ -999,6 +999,11 @@ if test "$GCC" = "yes"; then
    esac
    ACX_CHECK_CC_FLAGS(-funroll-all-loops,funroll_all_loops,xCFLAGS="$xCFLAGS -funroll-all-loops")
    ACX_CHECK_CC_FLAGS(-std=gnu99,stdgnu99,xCFLAGS="$xCFLAGS -std=gnu99")
+   # C99 requires strict IEEE 754 floating point compliance. Since gcc>=4.5.0 
+   # this is on when asking for c99, potentially impacting floating point 
+   # performance, so we turn it off here.
+   ACX_CHECK_CC_FLAGS(-fexcess-precision=fast, fexcess_precision_fast, 
+                      xCFLAGS="$xCFLAGS -fexcess-precision=fast")
 fi
 
 if test "$enable_debug" = "yes"; then
index ebf765a13314d6cec2302c0dbaddd258d5c77fe1..0dd5172b0fb90de91e49bd71585bae9df9a3a1b3 100644 (file)
@@ -54,6 +54,7 @@ xpm2ps|convert XPM (XPixelMap) file to postscript
 g_sham|read/write xmgr and xvgr data sets
 g_spatial|calculates the spatial distribution function (more control than g_sdf)
 g_sdf|calculates the spatial distribution function (faster than g_spatial)
+g_select|selects groups of atoms based on flexible textual selections
 END
 
 HEAD|Distances between structures
@@ -138,6 +139,7 @@ g_densmap|calculates 2D planar or axial-radial density maps
 g_order|computes the order parameter per atom for carbon tails
 g_h2order|computes the orientation of water molecules
 g_bundle|analyzes bundles of axes, e.g. transmembrane helices
+g_membed|embeds a protein into a lipid bilayer
 END
 
 
index 7c28498d65ab90e67b0c7afb07956687a509af5a..6539057ba9131498aedeb5903bdf1fa1d8b70927 100644 (file)
 #     specified.  All of the non CUDA C files are compiled using the standard
 #     build rules specified by CMAKE and the cuda files are compiled to object
 #     files using nvcc and the host compiler.  In addition CUDA_INCLUDE_DIRS is
-#     added automatically to include_directories().  Standard CMake target calls
-#     can be used on the target after calling this macro
-#     (e.g. set_target_properties and target_link_libraries).
+#     added automatically to include_directories().  Some standard CMake target
+#     calls can be used on the target after calling this macro
+#     (e.g. set_target_properties and target_link_libraries), but setting
+#     properties that adjust compilation flags will not affect code compiled by
+#     nvcc.  Such flags should be modified before calling CUDA_ADD_EXECUTABLE,
+#     CUDA_ADD_LIBRARY or CUDA_WRAP_SRCS.
 #
 #  CUDA_ADD_LIBRARY( cuda_target file0 file1 ...
 #                    [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] [OPTIONS ...] )
@@ -476,7 +479,7 @@ mark_as_advanced(CUDA_NVCC_EXECUTABLE)
 
 if(CUDA_NVCC_EXECUTABLE AND NOT CUDA_VERSION)
   # Compute the version.
-  exec_program(${CUDA_NVCC_EXECUTABLE} ARGS "--version" OUTPUT_VARIABLE NVCC_OUT)
+  execute_process (COMMAND ${CUDA_NVCC_EXECUTABLE} "--version" OUTPUT_VARIABLE NVCC_OUT)
   string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\1" CUDA_VERSION_MAJOR ${NVCC_OUT})
   string(REGEX REPLACE ".*release ([0-9]+)\\.([0-9]+).*" "\\2" CUDA_VERSION_MINOR ${NVCC_OUT})
   set(CUDA_VERSION "${CUDA_VERSION_MAJOR}.${CUDA_VERSION_MINOR}" CACHE STRING "Version of CUDA as computed from nvcc.")
@@ -543,6 +546,14 @@ endmacro()
 # CUDA_LIBRARIES
 find_library_local_first(CUDA_CUDART_LIBRARY cudart "\"cudart\" library")
 set(CUDA_LIBRARIES ${CUDA_CUDART_LIBRARY})
+if(APPLE)
+  # We need to add the path to cudart to the linker using rpath, since the
+  # library name for the cuda libraries is prepended with @rpath.
+  get_filename_component(_cuda_path_to_cudart "${CUDA_CUDART_LIBRARY}" PATH)
+  if(_cuda_path_to_cudart)
+    list(APPEND CUDA_LIBRARIES -Wl,-rpath "-Wl,${_cuda_path_to_cudart}")
+  endif()
+endif()
 
 # 1.1 toolkit on linux doesn't appear to have a separate library on
 # some platforms.
@@ -813,7 +824,11 @@ macro(CUDA_WRAP_SRCS cuda_target format generated_files)
   if(CUDA_HOST_COMPILATION_CPP)
     set(CUDA_C_OR_CXX CXX)
   else(CUDA_HOST_COMPILATION_CPP)
-    set(nvcc_flags ${nvcc_flags} --host-compilation C)
+    if(CUDA_VERSION VERSION_LESS "3.0")
+      set(nvcc_flags ${nvcc_flags} --host-compilation C)
+    else()
+      message(WARNING "--host-compilation flag is deprecated in CUDA version >= 3.0.  Removing --host-compilation C flag" )
+    endif()
     set(CUDA_C_OR_CXX C)
   endif(CUDA_HOST_COMPILATION_CPP)
 
old mode 100755 (executable)
new mode 100644 (file)
old mode 100755 (executable)
new mode 100644 (file)
index d7fde75..7349da3
@@ -164,18 +164,25 @@ if(CUDA_VERSION VERSION_LESS "3.0")
   cmake_policy(POP)
 endif()
 
+# nvcc doesn't define __CUDACC__ for some reason when generating dependency files.  This
+# can cause incorrect dependencies when #including files based on this macro which is
+# defined in the generating passes of nvcc invokation.  We will go ahead and manually
+# define this for now until a future version fixes this bug.
+set(CUDACC_DEFINE -D__CUDACC__)
+
 # Generate the dependency file
 cuda_execute_process(
   "Generating dependency file: ${NVCC_generated_dependency_file}"
   COMMAND "${CUDA_NVCC_EXECUTABLE}"
+  -M
+  ${CUDACC_DEFINE}
   "${source_file}"
-  ${depends_CUDA_NVCC_FLAGS}
-  ${nvcc_flags}
+  -o "${NVCC_generated_dependency_file}"
   ${CCBIN}
+  ${nvcc_flags}
   ${nvcc_host_compiler_flags}
+  ${depends_CUDA_NVCC_FLAGS}
   -DNVCC
-  -M
-  -o "${NVCC_generated_dependency_file}"
   ${CUDA_NVCC_INCLUDE_ARGS}
   )
 
@@ -223,12 +230,12 @@ cuda_execute_process(
   "Generating ${generated_file}"
   COMMAND "${CUDA_NVCC_EXECUTABLE}"
   "${source_file}"
-  ${CUDA_NVCC_FLAGS}
-  ${nvcc_flags}
+  ${format_flag} -o "${generated_file}"
   ${CCBIN}
+  ${nvcc_flags}
   ${nvcc_host_compiler_flags}
+  ${CUDA_NVCC_FLAGS}
   -DNVCC
-  ${format_flag} -o "${generated_file}"
   ${CUDA_NVCC_INCLUDE_ARGS}
   )
 
index 3d553ecc24e0a9221b510a6761db171384693f80..151190f858ae77daa761c5ca69f89b498194a673 100644 (file)
@@ -6,7 +6,7 @@
 # Git_VERSION       - git version
 # Git_FOUND         - tru if git was found, false otherwise
 #
-# Szilard Pall (pszilard@cbr.su.se)
+# Author: Szilard Pall (pszilard@cbr.su.se)
 
 if(Git_EXECUTABLE AND Git_VERSION)
     set(Git_FIND_QUIETLY TRUE)
@@ -14,7 +14,8 @@ endif()
 
 # search for git binary
 find_program(Git_EXECUTABLE git
-    DOC "Git version control tool")
+    PATHS ENV PATH
+    CACHE DOC "Git version control tool")
 
 if(NOT Git_EXECUTABLE)
     set(_err_msg "Git executable not found")
@@ -35,7 +36,8 @@ if(Git_EXECUTABLE AND NOT Git_VERSION)
     
     # check version
     set(_git_version_ok TRUE)
-    if(Git_FIND_VERSION_EXACT AND NOT Git_VERSION VERSION_EQUAL Git_FIND_VERSION)
+    # this should at some point become VERSION_EQUAL
+    if(Git_FIND_VERSION_EXACT AND NOT Git_VERSION STREQUAL Git_FIND_VERSION)
         set(_err_msg "Found git version ${Git_VERSION} but this does not match the requested ${Git_FIND_VERSION}")
         if(Git_FIND_REQUIRED)
             message(FATAL_ERROR " ${_err_msg}")
@@ -44,7 +46,8 @@ if(Git_EXECUTABLE AND NOT Git_VERSION)
         endif()
         set(_git_version_ok FALSE)
     endif()
-    if(Git_FIND_VERSION AND Git_VERSION VERSION_LESS Git_FIND_VERSION)
+    # this should at some point become VERSION_LESS
+    if(Git_FIND_VERSION AND Git_VERSION STRLESS Git_FIND_VERSION)
         set(_err_msg "Found git version ${Git_VERSION} but this is less then the requested ${Git_FIND_VERSION}")
         if(Git_FIND_REQUIRED)
             message(FATAL_ERROR " ${_err_msg}")
index c3c08a8645b0eba2fd00346fd14cf342fd4893eb..5094d1bd942e86ad6f346b19caaccc89ff5e5383 100644 (file)
@@ -1,22 +1,28 @@
-# Find OpenMM library 
+# Find OpenMM library.
 #
-# Defines: 
+# Looks for the OpenMM libraries at the default (/usr/local) location 
+# or custom location found in the OPENMM_ROOT_DIR environment variable. 
+#
+# The script defines defines: 
 #  OpenMM_FOUND     
 #  OpenMM_ROOT_DIR
 #  OpenMM_INCLUDE_DIR
 #  OpenMM_LIBRARY_DIR
-#  OpenMM_LIBRARIES
+#  OpenMM_LIBRARIES      
+#  OpenMM_LIBRARIES_D   - debug version of libraries 
 #  OpenMM_PLUGIN_DIR
 #
 
-# include(LibFindMacros) TODO get this: http://zi.fi/cmake/Modules/LibFindMacros.cmake
+# Author: Szilard Pall (pszilard@cbr.su.se)
 
 if(OpenMM_INCLUDE_DIR AND OpenMM_LIBRARY_DIR AND OpenMM_PLUGIN_DIR)
     set(OpenMM_FIND_QUIETLY)
 endif()
 
-if(IS_DIRECTORY "$ENV{OPENMM_ROOT_DIR}")
-    set(OpenMM_ROOT_DIR $ENV{OPENMM_ROOT_DIR} CACHE PATH "OpenMM installation directory" FORCE)
+file(TO_CMAKE_PATH "$ENV{OPENMM_ROOT_DIR}" _env_OPENMM_ROOT_DIR)
+
+if(IS_DIRECTORY ${_env_OPENMM_ROOT_DIR})
+    set(OpenMM_ROOT_DIR "${_env_OPENMM_ROOT_DIR}" CACHE PATH "OpenMM installation directory" FORCE)
 else()
     if(IS_DIRECTORY "/usr/local/openmm")
         set(OpenMM_ROOT_DIR "/usr/local/openmm" CACHE PATH "OpenMM installation directory" FORCE)
@@ -25,7 +31,19 @@ endif()
 
 find_library(OpenMM_LIBRARIES
     NAMES OpenMM
-    PATHS "${OpenMM_ROOT_DIR}/lib")
+    PATHS "${OpenMM_ROOT_DIR}/lib"
+    CACHE STRING "OpenMM libraries")
+
+find_library(OpenMM_LIBRARIES_D
+    NAMES OpenMM_d
+    PATHS "${OpenMM_ROOT_DIR}/lib"
+    CACHE STRING "OpenMM debug libraries")
+
+if(OpenMM_LIBRARIES_D AND NOT OpenMM_LIBRARIES)
+    set(OpenMM_LIBRARIES ${OpenMM_LIBRARIES_D}
+        CACHE STRING "OpenMM libraries" FORCE)
+    message(WARNING " Only found debug versions of the OpenMM libraries!")
+endif()
 
 get_filename_component(OpenMM_LIBRARY_DIR 
     ${OpenMM_LIBRARIES} 
@@ -43,9 +61,8 @@ if(NOT IS_DIRECTORY ${OpenMM_ROOT_DIR})
     if (IS_DIRECTORY "${OpenMM_LIBRARY_DIR}/..") # just double-checking
         get_filename_component(OpenMM_ROOT_DIR 
             "${OpenMM_LIBRARY_DIR}/.." 
-            ABSOLUTE
-            CACHE PATH "OpenMM installation directory")
-    endif()
+            ABSOLUTE)
+    endif()   
 endif()
 
 if(NOT IS_DIRECTORY ${OpenMM_ROOT_DIR})
@@ -53,7 +70,7 @@ if(NOT IS_DIRECTORY ${OpenMM_ROOT_DIR})
     "variable to the path where your OpenMM installation is located or install it to the default location (/usr/local/openmm)!")
 endif()
 
-if(NOT OpenMM_LIBRARY_DIR)
+if(NOT IS_DIRECTORY ${OpenMM_LIBRARY_DIR})
     message(FATAL_ERROR "Can't find OpenMM libraries. Check your OpenMM installation!")
 endif()
 
@@ -61,8 +78,8 @@ endif()
 if(IS_DIRECTORY "${OpenMM_LIBRARY_DIR}/plugins")
     get_filename_component(OpenMM_PLUGIN_DIR
         "${OpenMM_LIBRARY_DIR}/plugins"
-        ABSOLUTE
-        CACHE PATH "OpenMM plugins directory")
+        ABSOLUTE)
+    set(OpenMM_PLUGIN_DIR ${OpenMM_PLUGIN_DIR} CACHE PATH "OpenMM plugins directory")
 else()
     message(WARNING "Could not detect the OpenMM plugin directory at the default location (${OpenMM_LIBRARY_DIR}/plugins)."
             "Check you OpenMM installation or manually set the OPENMM_PLUGIN_DIR environment variable!")
@@ -72,10 +89,16 @@ if(NOT OpenMM_INCLUDE_DIR)
     message(FATAL_ERROR "Can't find OpenMM includes. Check your OpenMM installation!")
 endif()
 
-include (FindPackageHandleStandardArgs)
+set(OpenMM_ROOT_DIR ${OpenMM_ROOT_DIR} CACHE PATH "OpenMM installation directory")
+
+include(FindPackageHandleStandardArgs)
 find_package_handle_standard_args(OpenMM DEFAULT_MSG 
                                     OpenMM_ROOT_DIR
                                     OpenMM_LIBRARIES 
                                     OpenMM_LIBRARY_DIR 
-                                    OpenMM_INCLUDE_DIR
-                                    OpenMM_PLUGIN_DIR)
+                                    OpenMM_INCLUDE_DIR)
+
+mark_as_advanced(OpenMM_INCLUDE_DIR
+    OpenMM_LIBRARIES
+    OpenMM_LIBRARIES_D
+    OpenMM_LIBRARY_DIR)
index b0197aca2ee8c3954b653f35a5320e4cdcb9e04a..8c472b2c49450269199172e67726f52cd7522691 100644 (file)
@@ -5,6 +5,25 @@ include(CheckFunctionExists)
 
 #option(THREAD_PTHREADS "Use posix threads" ON)
 
+MACRO(TEST_TMPI_ATOMICS VARIABLE)
+    if (NOT DEFINED TMPI_ATOMICS)
+        try_compile(TEST_ATOMICS "${CMAKE_BINARY_DIR}"
+                "${CMAKE_SOURCE_DIR}/cmake/TestAtomics.c"
+                COMPILE_DEFINITIONS "-I${CMAKE_SOURCE_DIR}/include" )
+
+        if (TEST_ATOMICS)
+            message(STATUS "Atomics found")
+            set(${VARIABLE} CACHE INTERNAL 1)
+        else (TEST_ATOMICS)
+            message(WARNING "Atomics not found for this compiler+cpu combination. Thread support will be unbearably slow: disable threads.
+    Atomics should work on all but the most obscure CPU+compiler combinations; if your system is not obscure -- like, for example, x86 with gcc --  please contact the developers.
+    ")
+            set(${VARIABLE} CACHE INTERNAL 0)
+        endif(TEST_ATOMICS)
+    endif(NOT DEFINED TMPI_ATOMICS)
+ENDMACRO(TEST_TMPI_ATOMICS VARIABLE)
+
+
 include(FindThreads)
 if (CMAKE_USE_PTHREADS_INIT)
     check_include_files(pthread.h    HAVE_PTHREAD_H)
@@ -76,17 +95,4 @@ check_function_exists(sysconf       HAVE_SYSCONF)
 #check_include_files(windows.h         HAVE_WINDOWS_H)
 #check_function_exists(GetSystemInfo HAVE_SYSTEM_INFO)
 
-try_compile(TEST_ATOMICS "${CMAKE_BINARY_DIR}"
-            "${CMAKE_SOURCE_DIR}/cmake/TestAtomics.c"
-            COMPILE_DEFINITIONS "-I${CMAKE_SOURCE_DIR}/include" )
-
-if (TEST_ATOMICS)
-    message(STATUS "Atomics found")
-    set(TMPI_ATOMICS 1)
-else (TEST_ATOMICS)
-    message(WARNING "Atomics not found for this compiler+cpu combination. Thread support will be unbearably slow: disable threads.
-Atomics should work on all but the most obscure CPU+compiler combinations; if your system is not obscure -- like, for example, x86 with gcc --  please contact the developers.
-")
-    set(TMPI_ATOMICS 0)
-endif(TEST_ATOMICS)
-
+test_tmpi_atomics(TMPI_ATOMICS)
index 7e2903d5dbdfca4a4b8c72f575299e2568beee56..7171c5c526ec25b7bc4e63c09213046ad9803076 100644 (file)
+
+# Test C flags FLAGS, and set VARIABLE to true if the work. Also add the
+# flags to CFLAGSVAR.
+MACRO(GMX_TEST_CFLAG VARIABLE FLAGS CFLAGSVAR)
+    IF(NOT DEFINED ${VARIABLE})
+        CHECK_C_COMPILER_FLAG("${FLAGS}" ${VARIABLE})
+        IF (${VARIABLE})
+            SET (${CFLAGSVAR} "${FLAGS} ${${CFLAGSVAR}}")
+        ENDIF (${VARIABLE}) 
+    ENDIF(NOT DEFINED ${VARIABLE})
+ENDMACRO(GMX_TEST_CFLAG VARIABLE FLAGS CFLAGSVAR)
+
+# Test C++ flags FLAGS, and set VARIABLE to true if the work. Also add the
+# flags to CXXFLAGSVAR.
+MACRO(GMX_TEST_CXXFLAG VARIABLE FLAGS CXXFLAGSVAR)
+    IF(NOT DEFINED ${VARIABLE})
+        CHECK_CXX_COMPILER_FLAG("${FLAGS}" ${VARIABLE})
+        IF (${VARIABLE})
+            SET (${CXXFLAGSVAR} "${FLAGS} ${${CXXFLAGSVAR}}")
+        ENDIF (${VARIABLE}) 
+    ENDIF(NOT DEFINED ${VARIABLE})
+ENDMACRO(GMX_TEST_CXXFLAG VARIABLE FLAGS CXXFLAGSVAR)
+
+
+# This is the actual exported function to be called 
 MACRO(gmx_c_flags)
 
-include(CheckCCompilerFlag)
+    include(CheckCCompilerFlag)
+    include(CheckCXXCompilerFlag)
 
-if( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
-  CHECK_C_COMPILER_FLAG( "-O3" XFLAGS_O3)
-  IF (XFLAGS_O3)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O3")
-  ENDIF(XFLAGS_O3)
+    # gcc
+    if(CMAKE_COMPILER_IS_GNUCC)
+        GMX_TEST_CFLAG(CFLAGS_WARN "-Wall -Wno-unused" GMXC_CFLAGS)
+        # new in gcc 4.5
+        GMX_TEST_CFLAG(CFLAGS_EXCESS_PREC "-fexcess-precision=fast" GMXC_CFLAGS)
+        GMX_TEST_CFLAG(CFLAGS_COPT "-fomit-frame-pointer -finline-functions -funroll-all-loops" 
+                       GMXC_CFLAGS_RELEASE)
+        GMX_TEST_CFLAG(CFLAGS_NOINLINE "-fno-inline" GMXC_CFLAGS_DEBUG)
+    endif()
+    # g++
+    if(CMAKE_COMPILER_IS_GNUCXX)
+        GMX_TEST_CXXFLAG(CXXFLAGS_WARN "-Wall -Wno-unused" GMXC_CXXFLAGS)
+      # new in gcc 4.5
+        GMX_TEST_CXXFLAG(CXXFLAGS_EXCESS_PREC "-fexcess-precision=fast" 
+                          GMXC_CXXFLAGS)
+        GMX_TEST_CXXFLAG(CXXFLAGS_COPT "-fomit-frame-pointer -finline-functions -funroll-all-loops" 
+                         GMXC_CXXFLAGS_RELEASE)
+        GMX_TEST_CXXFLAG(CXXFLAGS_NOINLINE "-fno-inline" GMXC_CXXFLAGS_DEBUG)
+    endif()
 
-  CHECK_C_COMPILER_FLAG( "-Wall -Wno-unused" XFLAGS_WARN)
-  IF (XFLAGS_WARN)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-unused")
-  ENDIF(XFLAGS_WARN)
-  CHECK_C_COMPILER_FLAG( "-std=gnu99" XFLAGS_GNU99)
-  IF (XFLAGS_GNU99)
-  set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99")
-  ENDIF(XFLAGS_GNU99)
+    # icc
+    if (CMAKE_C_COMPILER_ID MATCHES "Intel")
+        if (NOT WIN32) 
+            GMX_TEST_CFLAG(CFLAGS_OPT "-ip -w -funroll-all-loops -std=gnu99" 
+                            GMXC_CFLAGS)
+            GMX_TEST_CFLAG(CFLAGS_SSE2 "-msse2" GMXC_CFLAGS)
+            GMX_TEST_CFLAG(CFLAGS_X86 "-mtune=core2" GMXC_CFLAGS_RELEASE)
+            GMX_TEST_CFLAG(CFLAGS_IA64 "-mtune=itanium2" GMXC_CFLAGS_RELEASE)
+        else()
+            GMX_TEST_CFLAG(CFLAGS_SSE2 "/arch:SSE2" GMXC_CFLAGS)
+            GMX_TEST_CFLAG(CFLAGS_X86 "/Qip" GMXC_CFLAGS_RELEASE)
+        endif()
+    endif()
 
-  CHECK_C_COMPILER_FLAG( "-march=native" XFLAGS_MARCH)
-  IF (XFLAGS_MARCH)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native")
-  ENDIF(XFLAGS_MARCH)
-endif( CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX )
+    if (CMAKE_CXX_COMPILER_ID MATCHES "Intel")
+        if (NOT WIN32) 
+            GMX_TEST_CXXFLAG(CXXFLAGS_OPT 
+                             "-ip -w -funroll-all-loops -std=gnu99" 
+                             GMXC_CXXFLAGS)
+            GMX_TEST_CXXFLAG(CXXFLAGS_SSE2 "-msse2" GMXC_CXXFLAGS)
+            GMX_TEST_CXXFLAG(CXXFLAGS_X86 "-mtune=core2" GMXC_CXXFLAGS_RELEASE)
+            GMX_TEST_CXXFLAG(CXXFLAGS_IA64 "-mtune=itanium2" 
+                              GMXC_CXXFLAGS_RELEASE)
+        else()
+            GMX_TEST_CXXFLAG(CXXFLAGS_SSE2 "/arch:SSE2" GMXC_CXXFLAGS)
+            GMX_TEST_CXXFLAG(CXXFLAGS_X86 "/Qip" GMXC_CXXFLAGS_RELEASE)
+        endif()
+    endif()
 
-MARK_AS_ADVANCED(XFLAGS_O3 XFLAGS_WARN XFLAGS_GNU99 XFLAGS_MARCH)
+    # pgi
+    if (CMAKE_C_COMPILER_ID MATCHES "PGI")
+        GMX_TEST_CFLAG(CFLAGS_OPT "-fastsse" GMXC_CFLAGS_RELEASE)
+    endif()
+    if (CMAKE_CXX_COMPILER_ID MATCHES "PGI")
+        GMX_TEST_CXXFLAG(CXXFLAGS_OPT "-fastsse" GMXC_CXXFLAGS_RELEASE)
+    endif()
 
+    # Pathscale
+    if (CMAKE_C_COMPILER_ID MATCHES "PathScale")
+        GMX_TEST_CFLAG(CFLAGS_OPT "-OPT:Ofast -fno-math-errno -ffast-math" 
+                         GMXC_CFLAGS_RELEASE)
+        GMX_TEST_CFLAG(CFLAGS_LANG "-std=gnu99" GMXC_CFLAGS)
+    endif()
+    if (CMAKE_CXX_COMPILER_ID MATCHES "PathScale")
+        GMX_TEST_CXXFLAG(CXXFLAGS_OPT "-OPT:Ofast -fno-math-errno -ffast-math" 
+                         GMXC_CXXFLAGS_RELEASE)
+    endif()
+
+    # xlc
+    if (CMAKE_C_COMPILER_ID MATCHES "XL")
+        GMX_TEST_CFLAG(CFLAGS_OPT "-qarch=auto -qtune=auto" GMXC_CFLAGS)
+        GMX_TEST_CFLAG(CFLAGS_LANG "-qlanglvl=extc99" GMXC_CFLAGS)
+    endif()
+    if (CMAKE_CXX_COMPILER_ID MATCHES "XL")
+        GMX_TEST_CXXFLAG(CFLAGS_OPT "-qarch=auto -qtune=auto" GMXC_CXXFLAGS)
+    endif()
+
+
+    # now actually set the flags:
+    if (NOT DEFINED GMXCFLAGS_SET)
+        set(GMXCFLAGS_SET true CACHE INTERNAL "Whether to reset the C flags" 
+            FORCE)
+        # C
+        set(CMAKE_C_FLAGS "${GMXC_CFLAGS} ${CMAKE_C_FLAGS}" 
+            CACHE STRING "Flags used by the compiler during all build types." 
+            FORCE)
+        set(CMAKE_C_FLAGS_RELEASE "${GMXC_CFLAGS_RELEASE} ${CMAKE_C_FLAGS_RELEASE}" 
+            CACHE STRING "Flags used by the compiler during release builds." 
+            FORCE)
+        set(CMAKE_C_FLAGS_DEBUG "${GMXC_CFLAGS_DEBUG} ${CMAKE_C_FLAGS_DEBUG}" 
+            CACHE STRING "Flags used by the compiler during debug builds." 
+            FORCE)
+        # C++
+        set(CMAKE_CXX_FLAGS "${GMXC_CXXFLAGS} ${CMAKE_CXX_FLAGS}" 
+            CACHE STRING "Flags used by the compiler during all build types." 
+            FORCE)
+        set(CMAKE_CXX_FLAGS_RELEASE 
+            "${GMXC_CXXFLAGS_RELEASE} ${CMAKE_CXX_FLAGS_RELEASE}" 
+            CACHE STRING "Flags used by the compiler during release builds." 
+            FORCE)
+        set(CMAKE_CXX_FLAGS_DEBUG 
+            "${GMXC_CXXFLAGS_DEBUG} ${CMAKE_CXX_FLAGS_DEBUG}" 
+            CACHE STRING "Flags used by the compiler during debug builds." 
+            FORCE)
+    endif()
 ENDMACRO(gmx_c_flags)
+
diff --git a/cmake/gmxCheckGCCVersion.cmake b/cmake/gmxCheckGCCVersion.cmake
new file mode 100644 (file)
index 0000000..70e0764
--- /dev/null
@@ -0,0 +1,47 @@
+# Check GCC version and if any of the 4.1.x family compiler suites is found
+# quit the build system generating process. 
+#
+# The GCC 4.1.x compilers contain an optimization related bug which might 
+# results in code that exhibits incorrect behaviour and often leads to 
+# exploding systems or crashes. 
+#
+# For further details see e.g. 
+# https://bugs.launchpad.net/ubuntu/+source/gcc-4.1/+bug/158799
+#
+# Szilard Pall (pszilard@cbr.su.se)
+#
+
+if(NOT GMX_DISABLE_GCC41_CHECK)
+
+if(CMAKE_COMPILER_IS_GNUCC)
+    # if we have -dumpversion flag use that, otherwise try the --version
+    execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion
+        RESULT_VARIABLE _gcc_dumpversion_res
+        OUTPUT_VARIABLE _gcc_dumpversion_out
+        OUTPUT_STRIP_TRAILING_WHITESPACE)
+    # if gcc returned with error the -dumpversion is not available 
+    if(${_gcc_dumpversion_res} EQUAL 0)
+        if(${_gcc_dumpversion_out} MATCHES ".*4\\.1\\.[0-9]+.*")
+            message(FATAL_ERROR " The GCC compiler in use seems to belong to the 4.1.x 
+                family (detected version: ${_gcc_dumpversion_out}). These compilers 
+                contain an optimization related bug which might results in code that 
+                exhibits incorrect behaviour and often leads to exploding systems or 
+                crashes. To disable this check set GMX_DISABLE_GCC41_CHECK=YES.")
+        endif()
+    else()    
+        message(WARNING " The GCC compiler in use does not support the -dumpversion flag. 
+            Will attempt parsing the version from the \"gcc --version\" output.")        
+        execute_process(COMMAND ${CMAKE_C_COMPILER} --version
+            OUTPUT_VARIABLE _gcc_version_out
+            OUTPUT_STRIP_TRAILING_WHITESPACE)            
+        if("${_gcc_version_out}" MATCHES ".*4\\.1\\.[0-9]+.*")
+            message(FATAL_ERROR " The GCC compiler in use seems to belong to the 4.1.x 
+                family. These compiler  compilers contain an optimization related bug 
+                which might results in code that exhibits incorrect behaviour and 
+                often leads to exploding systems or crashes. To disable this check set 
+                GMX_DISABLE_GCC41_CHECK=YES.")
+        endif()
+    endif()
+endif()
+
+endif()
index dbdd2dc4f523c131c797c9dd1a05a56c4e96630d..e1359cb968b54ec8262a1d34d8e5645ed4d0c5d1 100644 (file)
@@ -47,7 +47,8 @@ endif()
 
 # if git executable xists and it's compatible version
 # build the development version string 
-if(EXISTS ${Git_EXECUTABLE} AND NOT Git_VERSION VERSION_LESS "1.5.1")
+# this should at some point become VERSION_LESS
+if(EXISTS ${Git_EXECUTABLE} AND NOT Git_VERSION STRLESS "1.5.1")
     # refresh git index 
     execute_process(COMMAND ${Git_EXECUTABLE} update-index -q --refresh
         WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
@@ -81,14 +82,19 @@ if(EXISTS ${Git_EXECUTABLE} AND NOT Git_VERSION VERSION_LESS "1.5.1")
 
     # if git is older then 1.5.3 we need to extract the RFC2822 style date 
     # and massage it, otherwise the ISO 8601 format is more trusworthy
-    if (NOT Git_VERSION STREQUAL "" AND Git_VERSION VERSION_LESS "1.5.3")
+    # this should at some point become VERSION_LESS
+    if (NOT Git_VERSION STREQUAL "" AND Git_VERSION STRLESS "1.5.3")
         execute_process(COMMAND ${Git_EXECUTABLE} rev-list -n1 "--pretty=format:%cD" HEAD
             WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
             OUTPUT_VARIABLE HEAD_DATE
             ERROR_VARIABLE EXEC_ERR
             OUTPUT_STRIP_TRAILING_WHITESPACE
         )
-        string(REGEX REPLACE ".*, ([0-9]+) ([A-Z][a-z]+) ([0-9]+).*" "\\3\\2\\1" 
+        # date format: day, D Mmm YYYY  -> YYYY-MM-DD
+        # if the day is single sigit need to insert a "0"
+        string(REGEX REPLACE ".*(, )([0-9] )(.*)" "\\10\\2\\3" 
+            HEAD_DATE ${HEAD_DATE})
+        string(REGEX REPLACE ".*, ([0-9][0-9]) ([A-Z][a-z]+) ([0-9]+).*" "\\3\\2\\1" 
             HEAD_DATE ${HEAD_DATE})
         string(TOUPPER ${HEAD_DATE} HEAD_DATE)
         string(REGEX REPLACE "JAN" "01" HEAD_DATE ${HEAD_DATE})
index 5a343c134d1bb81cf5cba7f018a0a5e9d2a9735f..9aba4699ad3242c2823017cee1751ed192d12457 100644 (file)
@@ -22,6 +22,7 @@ MACRO(GMX_TEST_INLINE_ASM_GCC_X86 VARIABLE)
             set(${VARIABLE} 0 CACHE INTERNAL "Result of test for GCC x86 inline asm" FORCE)
        endif(${VARIABLE})
 
+
     ENDIF(NOT DEFINED ${VARIABLE})
 ENDMACRO(GMX_TEST_INLINE_ASM_GCC_X86 VARIABLE)
 
index 36d311958ac41c3f4840f350dfa7997c1f599853..242b6c072fe253967ac90f76f1e9691d0d00e244 100644 (file)
@@ -14,7 +14,7 @@ AC_PREFIX_DEFAULT(/usr/local/gromacs)
 AM_CONFIG_HEADER(src/config.h)
 dnl This is the version info according to the libtool versioning system.
 dnl It does *not* correspond to the release number.
-SHARED_VERSION_INFO="5:0:0"
+SHARED_VERSION_INFO="6:0:0"
 AC_SUBST(SHARED_VERSION_INFO)
 
 AC_DISABLE_SHARED
@@ -24,10 +24,6 @@ AC_DISABLE_SHARED
 # Simple options and makefile variables
 #######################################################################
 
-# This is currently not defined by CMake, because it's tricky to generate
-# version.h portably (the autoconf rules for it are in src/gmxlib/Makefile.am).
-AC_DEFINE(USE_VERSION_H,,[Use the version string from generated version.h])
-
 ### Single/Double
 AC_ARG_ENABLE(float,
             [AC_HELP_STRING([--disable-float],
@@ -132,12 +128,19 @@ if test "$enable_ppc_altivec" = "undef"; then
   esac
 fi
 
+###################################
+## Detect buggy version of gcc
+###################################
+AC_ARG_ENABLE(gcc41_check,
+              [AC_HELP_STRING([--disable-gcc41-check],
+                              [Disable the check for buggy gcc 4.1])],,enable_gcc41_check=yes)
+
 
 
 ### ia64 assembly code
 AC_ARG_ENABLE(ia64_asm,
-             [AC_HELP_STRING([--disable-ia64-asm],
-                             [Don't build assembly loops on ia64])],,enable_ia64_asm=yes)
+             [AC_HELP_STRING([--enable-ia64-asm],
+                             [Build assembly loops on ia64])],,enable_ia64_asm=no)
 case "${host_cpu}" in
    ia64) ;;
    *) enable_ia64_asm=no ;;
@@ -267,6 +270,15 @@ if test "$with_qmmm_mopac" = "yes"; then
   AC_DEFINE(GMX_QMMM_MOPAC,,[Use (modified) Mopac 7 for QM-MM calculations])
 fi
 
+
+AC_ARG_WITH(qmmm_orca,
+              [AC_HELP_STRING([--without-qmmm-mopac],
+                              [Use ORCA for QM-MM])],,with_qmmm_orca=no)
+if test "$with_qmmm_orca"="yes"; then
+  AC_DEFINE(GMX_QMMM_ORCA,,[Use ORCA for QM-MM calculations])
+fi
+
+
 AC_ARG_WITH(dlopen,
             [AC_HELP_STRING([--without-dlopen],
                             [do not compile with dlopen, needed to read VMD]
@@ -274,8 +286,6 @@ AC_ARG_WITH(dlopen,
 
 
 
-   
-
 ############################################################
 # Add some debug info: Who is building, and on what machine?
 ############################################################
@@ -284,6 +294,28 @@ AC_DEFINE_UNQUOTED([BUILD_USER],["`whoami`@`hostname`"],[User doing build])
 AC_DEFINE_UNQUOTED([BUILD_MACHINE],["`uname -srm`"],[Hardware and OS version for build host])
 
 
+############################################################
+# Checks for requirements for version information generation
+############################################################
+generate_version=no
+if test -d $srcdir/.git ; then
+    AC_CHECK_PROG(have_git, git, yes, no)
+    if test "$have_git" = "yes" ; then
+        AC_MSG_CHECKING(for git >= 1.5.1)
+        if test "`git --version`" \< "git version 1.5.1" ; then
+            AC_MSG_RESULT(no)
+        else
+            AC_MSG_RESULT(yes)
+            generate_version=yes
+            AC_DEFINE(USE_VERSION_H,,[Use generated version info])
+        fi
+    fi
+    if test "$generate_version" = "no" ; then
+        AC_MSG_WARN([No compatible git version found, won't be able to generate proper development version information.])
+    fi
+fi
+AM_CONDITIONAL([USE_VERSION_H],[test "$generate_version" = "yes"])
+
 
 ############################################################
 # Checks for programs
@@ -306,6 +338,18 @@ AC_PROG_CC( $cc_names )
 if test -z "$CC_FOR_BUILD"; then
   CC_FOR_BUILD=$CC
 fi
+
+if test "$enable_gcc41_check" = "yes"; then
+    if $CC --version 2>&1 | grep 'gcc.* 4\.1' > /dev/null 2>&1; then
+        AC_MSG_ERROR([Uh-oh. Your compilers appears to be GCC version 4.1, which unfortunately produces]
+[buggy code at high optimimzation levels. It would be a good idea to update or]
+[use a different compiler. If you are ABSOLUTELY sure what you are doing, you]
+[can override this check with --disable-gcc41-check.])
+    fi
+fi
+
+
+
 AC_SUBST(CC_FOR_BUILD) 
 
 if test "$enable_fortran" = "yes"; then 
@@ -686,6 +730,7 @@ AC_CHECK_HEADERS(unistd.h)
 AC_CHECK_HEADERS(sys/types.h)
 AC_CHECK_HEADERS(sys/time.h)
 AC_CHECK_HEADERS(dirent.h)
+AC_CHECK_HEADERS(copyfile.h)
 AC_CHECK_HEADERS(regex.h,,[AC_MSG_WARN(
 [No regex.h found.
 Regular expression matching in selections will be disabled.
@@ -704,13 +749,22 @@ AM_WITH_DMALLOC
 AC_CHECK_FUNCS(strcasecmp)
 AC_CHECK_FUNCS(strdup)
 AC_CHECK_FUNCS(gettimeofday)
+AC_CHECK_FUNCS(cbrt)
 AC_CHECK_FUNCS(isnan)
 AC_CHECK_FUNCS(_isnan)
 AC_CHECK_FUNCS(isfinite)
 AC_CHECK_FUNCS(_isfinite)
+AC_CHECK_FUNCS(fsync)
+AC_CHECK_FUNCS(fileno)
+AC_CHECK_FUNCS(copyfile)
 
 # check for bool (must come late, since CFLAGS/includes might affect it)
 AC_CHECK_TYPES([bool])
+AC_SEARCH_LIBS(posix_memalign, c, AC_DEFINE(HAVE_POSIX_MEMALIGN, 1, Define to 1 if you have the posix_memalign function))
+AC_SEARCH_LIBS(memalign, c, AC_DEFINE(HAVE_MEMALIGN, 1, Define to 1 if you have the memalign function))
+AC_CHECK_FUNCS(_aligned_malloc)
+#AC_SEARCH_LIBS(_aligned_malloc, c, AC_DEFINE(HAVE__ALIGNED_MALLOC, 1, Define to 1 if you have the _aligned_malloc function))
+
 
 
 
@@ -817,9 +871,26 @@ if test "$with_xml" = "yes"; then
    AC_CHECK_HEADERS([libxml/parser.h],AC_CHECK_LIB(xml2,main))
    if test "$ac_cv_lib_xml2_main" = "yes"; then
      INCLUDES="$INCLUDES -I/usr/include/libxml2"
+     PKG_XML2="libxml-2.0"
+     AC_SUBST(PKG_XML2)
+     if test "$enable_all_static" = "yes"; then
+       LDFLAGS_RET=$LDFLAGS
+       LDFLAGS="-static $LDFLAGS"
+       LIBS_RET="$LIBS"
+       LIBS="$LIBS -lz"
+       AC_MSG_CHECKING(for broken libxml2)
+       AC_TRY_RUN([
+#include <libxml/parser.h>
+main() {
+  xmlInitParser();
+  return 0;
+}],
+       AC_MSG_RESULT([no]),[AC_MSG_RESULT([yes])
+       AC_MSG_ERROR([Your libxml2 is broken for static linking, recompile it without threads or build gromacs without libxml])],[-lz])
+       LDFLAGS=$LDFLAGS_RET
+       LIBS="$LIBS_RET"
+     fi
    fi
-   PKG_XML2="libxml-2.0"
-   AC_SUBST(PKG_XML2)
 # restore CPPFLAGS
    CPPFLAGS="$ac_save_CPPFLAGS"
 fi
index ec3cea0543acb6158710582265b5f4cfbd6c938b..9df08ab85a18b9f848693ff99703d3468fbc3140 100644 (file)
@@ -97,7 +97,7 @@ extern t_3dview *init_view(matrix box);
  */
 
 extern bool zoom_3d(t_3dview *view,real fac);
-/* Zoom in or out with factor fac, returns TRUE when zoom succesful,
+/* Zoom in or out with factor fac, returns TRUE when zoom successful,
  * FALSE otherwise.
  */
 
index f85fe39e655b8c2c5a458ccdfdb298e9fd9aa611..984fef87f8d224e84568a4da2e00409812e02470 100644 (file)
@@ -31,7 +31,6 @@ ebin.h \
 edsam.h \
 enxio.h \
 ffscanf.h \
-fftgrid.h \
 filenm.h \
 force.h \
 futil.h \
@@ -46,8 +45,10 @@ gmx_fatal.h \
 gmx_fft.h \
 gmx_ga2la.h \
 gmx_lapack.h \
+gmx_matrix.h \
 gmx_parallel_3dfft.h \
 gmx_random.h \
+gmx_sort.h \
 gmx_sse2_single.h \
 gmx_statistics.h \
 gmx_system_xdr.h \
@@ -113,6 +114,7 @@ selection.h \
 selmethod.h \
 selparam.h \
 selvalue.h \
+sfactor.h \
 shellfc.h \
 shift.h \
 smalloc.h \
@@ -120,7 +122,6 @@ sortwater.h \
 sparsematrix.h \
 split.h \
 splitter.h \
-statusio.h \
 statutil.h \
 strdb.h \
 string2.h \
index e1d5dad28ab79bf3073ed7f84ac39b5fc70d23c0..57170e6c48921a4e7c08aacb5247ace4f055709b 100644 (file)
@@ -42,11 +42,9 @@ extern "C" {
 
 extern real calc_grid(FILE *fp,
                      matrix box,real gr_sp,
-                     int *nx,int *ny,int *nz,int nnodes);
+                     int *nx,int *ny,int *nz);
 /* Sets the number of grid points for each zero n* to the first reasonable
  * number which gives a spacing equal to or smaller than gr_sp.
- * nx and ny should be divisible by nnodes, an error is generated when this
- * can not be achieved by calc_grid.
  * Returns the maximum grid spacing.
  */
 
index b76bbb85986950003b91a1245de1c512d915d8c6..ec8ec3c150fa6bf334978593fac8e1de2b00511e 100644 (file)
 extern "C" {
 #endif
 
-/* Write a checkpoint to fn */
-extern void write_checkpoint(const char *fn,FILE *fplog,t_commrec *cr,
+/* the name of the environment variable to disable fsync failure checks with */
+#define GMX_IGNORE_FSYNC_FAILURE_ENV "GMX_IGNORE_FSYNC_FAILURE"
+
+/* Write a checkpoint to <fn>.cpt
+ * Appends the _step<step>.cpt with bNumberAndKeep,
+ * otherwise moves the previous <fn>.cpt to <fn>_prev.cpt
+ */
+extern void write_checkpoint(const char *fn,bool bNumberAndKeep,
+                            FILE *fplog,t_commrec *cr,
                             int eIntegrator,int simulation_part,
                             gmx_large_int_t step,double t,
                             t_state *state);
@@ -74,7 +81,7 @@ extern void read_checkpoint_state(const char *fn,int *simulation_part,
                                  gmx_large_int_t *step,double *t,t_state *state);
 
 /* Read everything that can be stored in t_trxframe from a checkpoint file */
-extern void read_checkpoint_trxframe(int fp,t_trxframe *fr);
+extern void read_checkpoint_trxframe(t_fileio *fp,t_trxframe *fr);
 
 /* Print the complete contents of checkpoint file fn to out */
 extern void list_checkpoint(const char *fn,FILE *out);
index 10330fcf7dd235b21b8783f738455b8ff5965443..702a7409f108a39aa42ed6626d5685ea5ad46ca3 100644 (file)
@@ -41,7 +41,7 @@
 #endif
 
 #include <stdio.h>
-#include <types/simple.h>
+#include "types/simple.h"
 
 #ifdef __cplusplus
 extern "C" {
index 2c9210f696f57318fa5b58290d26d31af6a13d2b..601a72b16a7302ce5ffef5ed1d99df9d73d47c7b 100644 (file)
@@ -96,7 +96,7 @@ init_domain_decomposition(FILE *fplog,
                           gmx_mtop_t *mtop,t_inputrec *ir,
                           matrix box,rvec *x,
                           gmx_ddbox_t *ddbox,
-                          int *npme_major);
+                          int *npme_x, int *npme_y);
 
 extern void dd_init_bondeds(FILE *fplog,
                             gmx_domdec_t *dd,gmx_mtop_t *mtop,
@@ -257,7 +257,7 @@ extern void write_dd_pdb(const char *fn,gmx_large_int_t step,const char *title,
 /* In domdec_setup.c */
 
 extern real comm_box_frac(ivec dd_nc,real cutoff,gmx_ddbox_t *ddbox);
-/* Returns the volume fraction of the system communicated by each node */
+/* Returns the volume fraction of the system that is communicated */
 
 extern real dd_choose_grid(FILE *fplog,
                            t_commrec *cr,gmx_domdec_t *dd,t_inputrec *ir,
index d004b96d4c87aa35b4866587f9905b80ba69da3a..6f4f37f7566555a84051624970fb0ce31510ef34 100644 (file)
@@ -103,15 +103,17 @@ dd_scatter(gmx_domdec_t *dd,int nbytes,void *src,void *dest);
 extern void
 dd_gather(gmx_domdec_t *dd,int nbytes,void *src,void *dest);
 
+/* If rcount==0, rbuf is allowed to be NULL */
 extern void
 dd_scatterv(gmx_domdec_t *dd,
-           int *scounts,int *disps,void *sbuf,
-           int rcount,void *rbuf);
+            int *scounts,int *disps,void *sbuf,
+            int rcount,void *rbuf);
 
+/* If scount==0, sbuf is allowed to be NULL */
 extern void
 dd_gatherv(gmx_domdec_t *dd,
-          int scount,void *sbuf,
-          int *rcounts,int *disps,void *rbuf);
+           int scount,void *sbuf,
+           int *rcounts,int *disps,void *rbuf);
 
 #ifdef __cplusplus
 }
index 0d41587d4f3cfc24bd7ea65ecd292b3a8917b45a..c2092c76f60f0094eba43ce79295337ae93c3ebc 100644 (file)
 extern "C" {
 #endif
 
-extern void do_edsam(t_inputrec *ir,int step,t_mdatoms *md,
+extern void do_edsam(t_inputrec *ir,gmx_large_int_t step,t_mdatoms *md,
                      t_commrec *cr,rvec xs[],rvec v[],matrix box,gmx_edsam_t ed);
 /* Essential dynamics constraints, called from constrain() */
 
-extern gmx_edsam_t ed_open(int nfile,const t_filenm fnm[],t_commrec *cr);
+extern gmx_edsam_t ed_open(int nfile,const t_filenm fnm[],unsigned long Flags,t_commrec *cr);
 /* Sets the ED input/output filenames, opens output (.edo) file */
 
 extern void init_edsam(gmx_mtop_t *mtop,t_inputrec *ir,t_commrec *cr,
index 57e612affded4e9f1dbfdc3337fd30de802b83df..04e2677c17b52288d77752f135c230077c9f999f 100644 (file)
@@ -43,6 +43,7 @@
 #include "sysstuff.h"
 #include "typedefs.h"
 #include "pbc.h"
+#include "gmxfio.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -79,9 +80,9 @@ extern "C" {
 
   typedef struct {
     double   t;                    /* Timestamp of this frame                       */
-    gmx_large_int_t step;        /* MD step                                         */
-    gmx_large_int_t nsteps;      /* The number of steps between frames            */
-    gmx_large_int_t nsum;        /* The number of terms for the sums in ener      */
+    gmx_large_int_t step;   /* MD step                                      */
+    gmx_large_int_t nsteps; /* The number of steps between frames            */
+    int      nsum;          /* The number of terms for the sums in ener      */
     int      nre;           /* Number of energies                           */
     int      ndisre;        /* Number of distance restraints                */
     int      nblock;        /* Number of following energy blocks              */
@@ -123,7 +124,7 @@ extern "C" {
 
   extern ener_file_t open_enx(const char *fn,const char *mode);
 
-  extern int enx_file_pointer(const ener_file_t ef);
+  extern t_fileio *enx_file_pointer(const ener_file_t ef);
 
   extern void close_enx(ener_file_t ef);
   
diff --git a/include/fftgrid.h b/include/fftgrid.h
deleted file mode 100644 (file)
index f26eed4..0000000
+++ /dev/null
@@ -1,160 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-
-#ifndef _fftgrid_h
-#define _fftgrid_h
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include "typedefs.h"
-#include "gmxcomplex.h"
-#include "network.h"
-#include "gmx_fft.h"
-
-#ifdef GMX_MPI
-#include "gmx_parallel_3dfft.h"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/* Use FFTW */
-
-#define INDEX(i,j,k)             ((i)*la12+(j)*la2+(k))      
-
-typedef struct {
-  int local_nx,local_x_start,local_ny_after_transpose;
-  int local_y_start_after_transpose;
-} t_parfft;
-
-typedef struct {
-    real *                 ptr;
-    bool                   bParallel;
-    real *                 workspace;    
-    int                    nx,ny,nz,la2r,la2c,la12r,la12c;
-    int                    nptr,nxyz;
-    gmx_fft_t              fft_setup;
-#ifdef GMX_MPI
-    gmx_parallel_3dfft_t   mpi_fft_setup;
-    t_parfft               pfft;
-#endif
-} t_fftgrid;
-
-extern t_fftgrid *mk_fftgrid(int          nx,
-                             int          ny,
-                             int          nz,
-                             int          *node2slab,
-                            int          *slab2grid_x,
-                             t_commrec *  cr,
-                             bool         bReproducible);
-
-/* Create an FFT grid (1 Dimensional), to be indexed by the INDEX macro 
- * Setup FFT plans and extract local sizes for the grid.
- * If the file pointer is given, information is printed to it.
- * If cr is non-NULL and cr->nnodes>1, a parallel grid and FFT will be created.
- * The node2slab array translates to node ids to slab indices,
- * when NULL the slab ids are assumed to be identical to the node ids.
- * The slab2grid_x array determines which grid x-indices beling to which slab
- * (array size nnodes+1), when NULL this is determined automatically.
- * Set bReproducible to avoid FFTW timing and other optimizations that
- * could affect reproducibility of simulations.
- */
-
-extern void pr_fftgrid(FILE *fp,char *title,t_fftgrid *grid);
-/* Dump a grid to a file */
-
-extern void done_fftgrid(t_fftgrid *grid);
-/* And throw it away again */
-
-extern void gmxfft3D(t_fftgrid *grid,enum gmx_fft_direction dir,t_commrec *cr);
-/* Do the FFT, direction may be either 
- * FFTW_FORWARD (sign -1) for real -> complex transform 
- * FFTW_BACKWARD (sign 1) for complex -> real transform
- */
-extern void clear_fftgrid(t_fftgrid *grid);
-/* Set it to zero */
-
-extern void unpack_fftgrid(t_fftgrid *grid,int *nx,int *ny,int *nz,
-                          int *nx2,int *ny2,int *nz2,
-                          int *la2, int *la12,bool bReal, real **ptr);
-
-/* Get the values for the constants into local copies */
-
-
-
-
-/************************************************************************
- * 
- * For backward compatibility (for testing the ewald code vs. PPPM etc)
- * some old grid routines are retained here.
- *
- ************************************************************************/
-extern real ***mk_rgrid(int nx,int ny,int nz);
-
-extern void free_rgrid(real ***grid,int nx,int ny);
-
-extern real print_rgrid(FILE *fp,char *title,int nx,int ny,int nz,
-                       real ***grid);
-
-extern void print_rgrid_pdb(char *fn,int nx,int ny,int nz,real ***grid);
-
-extern t_complex ***mk_cgrid(int nx,int ny,int nz);
-
-extern void free_cgrid(t_complex ***grid,int nx,int ny);
-
-extern t_complex print_cgrid(FILE *fp,char *title,int nx,int ny,int nz,
-                          t_complex ***grid);
-
-extern void clear_cgrid(int nx,int ny,int nz,t_complex ***grid);
-
-extern void clear_rgrid(int nx,int ny,int nz,real ***grid);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-
-
-
-
-
-
index 8a1defdc6874df187fab8ac8d0d4efe992c94328..dca74d33b96c018a28c26f2ae318c96106d8ed74 100644 (file)
@@ -153,6 +153,9 @@ int add_suffix_to_output_names(t_filenm *fnm, int nfile, const char *suffix);
 /* duplicate the filename list (to make a private copy for each thread, 
    for example) */
 t_filenm *dup_tfn(int nf, const t_filenm tfn[]);
+
+/* Free memory allocated for file names by parse_file_args(). */
+void done_filenms(int nf, t_filenm fnm[]);
        
 #ifdef __cplusplus
 }
index f3defa771bcdc3f36e5a32f7a96422f2039bd21f..ce484a0dd45aaf7efedb9c98964b4f13b97824e2 100644 (file)
@@ -126,6 +126,13 @@ forcerec_set_ranges(t_forcerec *fr,
                    int natoms_force,int natoms_f_novirsum);
 /* Set the number of cg's and atoms for the force calculation */
 
+extern bool can_use_allvsall(const t_inputrec *ir, const gmx_mtop_t *mtop,
+                             bool bPrintNote,t_commrec *cr,FILE *fp);
+/* Returns if we can use all-vs-all loops.
+ * If bPrintNote==TRUE, prints a note, if necessary, to stderr
+ * and fp (if !=NULL) on the master node.
+ */
+
 extern void init_forcerec(FILE       *fplog,     
                           const output_env_t oenv,
                          t_forcerec *fr,   
index 70e49e38eb345ea100a3383249f8beb87405bf4f..9beaddca612843e9df9505192503cc00221b5d18 100644 (file)
@@ -88,16 +88,13 @@ extern bool gmx_eof(FILE *fp);
 extern bool is_pipe(FILE *fp);
 /* Check whether the file (opened by ffopen) is a pipe */
 
-extern char *backup_fn(const char *file);
-/* Return a backup name for file (name with # before and after) */
-
 /*  Make a backup of file if necessary.  
     Return false if there was a problem.
 */
 extern bool make_backup(const char * file);
 
 extern FILE *ffopen(const char *file, const char *mode);
-/* Return a valid file pointer when succesfull, exits otherwise 
+/* Return a valid file pointer when successful, exits otherwise 
  * If the file is in compressed format, open a pipe which uncompresses
  * the file! Therefore, files must be closed with ffclose (see below)
  */
@@ -134,8 +131,16 @@ extern FILE *low_libopen(const char *file,bool bFatal);
  */
 extern void gmx_tmpnam(char *buf);
 
-int
-gmx_truncatefile(char *path, off_t length);
+/* truncte the file to the specified length */
+int gmx_truncatefile(char *path, off_t length);
+
+/* rename/move the file (atomically, if the OS makes that available) oldname 
+   to newname */
+int gmx_file_rename(const char *oldname, const char *newname);
+
+/* copy the file (data only) oldname to newname. if copy_if_empty==FALSE,
+   the file won't be copied if it's empty.*/
+int gmx_file_copy(const char *oldname, const char *newname, bool copy_if_empty);
 
 #ifdef __cplusplus
 }
index 48e3fd08ba72871b5bb8e0b588c9d751f7b7213f..3f4bedaf07d2691e34b45a4509d29598102875ff 100644 (file)
@@ -261,6 +261,9 @@ gmx_wheel(int argc,char *argv[]);
 int 
 gmx_xpm2ps(int argc,char *argv[]);
 
+int 
+gmx_membed(int argc,char *argv[]);
+
 #ifdef __cplusplus
 }
 #endif
index a756bf8e0b833c6f344e10e8768f29dc12814737..132ebae998c2b3e75c5ba43790b24393da4888f7 100644 (file)
@@ -87,9 +87,13 @@ gmx_fatal(int fatal_errno,const char *file,int line,const char *fmt,...);
 
 extern void
 gmx_fatal_collective(int f_errno,const char *file,int line,
-                    bool bMaster,
+                    t_commrec *cr,gmx_domdec_t *dd,
                     const char *fmt,...);
-/* As gmx_fatal, but only process with bMaster=TRUE prints the error message.
+/* As gmx_fatal, but only the master process prints the error message.
+ * This should only be called one of the following two situations:
+ * 1) On all nodes in cr->mpi_comm_mysim, with cr!=NULL,dd==NULL.
+ * 2) On all nodes in dd->mpi_comm_all,   with cr==NULL,dd!=NULL.
+ * This will call MPI_Finalize instead of MPI_Abort when possible,
  * This is useful for handling errors in code that is executed identically
  * for all processes.
  */
index b1079902434debe2a51340a2a0247fc8048c3194..2398e6f7bd3d5fc3c7e8d32640dd771cb7f242b3 100644 (file)
@@ -126,6 +126,25 @@ gmx_fft_init_1d        (gmx_fft_t *       fft,
                         gmx_fft_flag      flags);
 
 
+/*! \brief Setup multiple 1-dimensional complex-to-complex transform 
+ *
+ *  \param fft    Pointer to opaque Gromacs FFT datatype
+ *  \param nx     Length of transform 
+ *  \param howmany Howmany 1D FFT
+ *  \param flags  FFT options
+ *
+ *  \return status - 0 or a standard error message.
+ *   
+ *  \note Since some of the libraries (e.g. MKL) store work array data in their 
+ *        handles this datatype should only be used for one thread at a time, 
+ *        i.e. you should create one copy per thread when executing in parallel.
+ */
+int
+gmx_fft_init_many_1d        (gmx_fft_t *       fft,
+                             int               nx,
+                             int               howmany,
+                             gmx_fft_flag      flags);
+
 
 /*! \brief Setup a 1-dimensional real-to-complex transform 
  *
@@ -145,6 +164,26 @@ gmx_fft_init_1d_real        (gmx_fft_t *       fft,
                              gmx_fft_flag      flags);
 
 
+/*! \brief Setup multiple 1-dimensional real-to-complex transform 
+ *
+ *  \param fft    Pointer to opaque Gromacs FFT datatype
+ *  \param nx     Length of transform in real space
+ *  \param howmany Homany 1D FFTs
+ *  \param flags  FFT options
+ *
+ *  \return status - 0 or a standard error message.
+ *   
+ *  \note Since some of the libraries (e.g. MKL) store work array data in their 
+ *        handles this datatype should only be used for one thread at a time, 
+ *        i.e. you should create one copy per thread when executing in parallel.
+ */
+int
+gmx_fft_init_many_1d_real        (gmx_fft_t *       fft,
+                                  int               nx,
+                                  int               howmany,
+                                  gmx_fft_flag      flags);
+
+
 
 /*! \brief Setup a 2-dimensional complex-to-complex transform 
  *
@@ -255,13 +294,38 @@ gmx_fft_init_3d_real   (gmx_fft_t *         fft,
  * \note Data pointers are declared as void, to avoid casting pointers 
  *       depending on your grid type.
  */
-int 
+ int 
 gmx_fft_1d               (gmx_fft_t                  setup,
                           enum gmx_fft_direction     dir,
                           void *                     in_data,
                           void *                     out_data);
 
 
+/*! \brief Perform many 1-dimensional complex-to-complex transforms
+ *
+ *  Performs many instances of a transform previously initiated.
+ *
+ *  \param setup     Setup returned from gmx_fft_init_1d()
+ *  \param dir       Forward or Backward
+ *  \param in_data   Input grid data. This should be allocated with gmx_new()
+ *                   to make it 16-byte aligned for better performance.
+ *  \param out_data  Output grid data. This should be allocated with gmx_new()
+ *                   to make it 16-byte aligned for better performance.
+ *                   You can provide the same pointer for in_data and out_data
+ *                   to perform an in-place transform.
+ *
+ * \return 0 on success, or an error code.
+ *
+ * \note Data pointers are declared as void, to avoid casting pointers 
+ *       depending on your grid type.
+ */
+ int 
+gmx_fft_many_1d          (gmx_fft_t                  setup,
+                          enum gmx_fft_direction     dir,
+                          void *                     in_data,
+                          void *                     out_data);
+
+
 /*! \brief Perform a 1-dimensional real-to-complex transform
  *
  *  Performs an instance of a transform previously initiated.
@@ -290,6 +354,34 @@ gmx_fft_1d_real          (gmx_fft_t                  setup,
                           void *                     in_data,
                           void *                     out_data);
 
+/*! \brief Perform many 1-dimensional real-to-complex transforms
+ *
+ *  Performs many instances of a transform previously initiated.
+ *
+ *  \param setup     Setup returned from gmx_fft_init_1d_real()
+ *  \param dir       Real-to-complex or complex-to-real
+ *  \param in_data   Input grid data. This should be allocated with gmx_new()
+ *                   to make it 16-byte aligned for better performance.
+ *  \param out_data  Output grid data. This should be allocated with gmx_new()
+ *                   to make it 16-byte aligned for better performance.
+ *                   You can provide the same pointer for in_data and out_data
+ *                   to perform an in-place transform.
+ *
+ * If you are doing an in-place transform, the array must be padded up to
+ * an even integer length so n/2 complex numbers can fit. Out-of-place arrays
+ * should not be padded (although it doesn't matter in 1d).
+ *
+ * \return 0 on success, or an error code.
+ *
+ * \note Data pointers are declared as void, to avoid casting pointers 
+ *       depending on transform direction.
+ */
+int 
+gmx_fft_many_1d_real     (gmx_fft_t                  setup,
+                          enum gmx_fft_direction     dir,
+                          void *                     in_data,
+                          void *                     out_data);
+
 
 /*! \brief Perform a 2-dimensional complex-to-complex transform
  *
@@ -424,6 +516,17 @@ gmx_fft_3d_real          (gmx_fft_t                  setup,
 void
 gmx_fft_destroy          (gmx_fft_t                 setup);
 
+/*! \brief Release a many FFT setup structure 
+ *
+ *  Destroy setup and release all allocated memory.
+ *
+ *  \param setup Setup returned from gmx_fft_init_1d(), or one
+ *              of the other initializers.
+ *
+ */
+void
+gmx_many_fft_destroy          (gmx_fft_t                 setup);
+
 
 /*! \brief Transpose 2d complex matrix, in-place or out-of-place.
  * 
diff --git a/include/gmx_matrix.h b/include/gmx_matrix.h
new file mode 100644 (file)
index 0000000..c69bb5b
--- /dev/null
@@ -0,0 +1,62 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ * $Id: gmx_matrix.h,v 1.2 2008/11/26 11:06:21 spoel Exp $
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 4.0.99
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Groningen Machine for Chemical Simulation
+ */
+
+#ifndef _gmx_matrix_h
+#define _gmx_matrix_h
+       
+#include <stdio.h>
+       
+extern double **alloc_matrix(int n,int m);
+
+extern void free_matrix(double **a,int n);
+
+extern void matrix_multiply(FILE *fp,int n,int m,double **x,double **y,double **z);
+
+/* Return 0 if OK or row number where inversion failed otherwise. */
+extern int matrix_invert(FILE *fp,int n,double **a);
+
+extern double multi_regression(FILE *fp,int ny,double *y,
+                               int nx,double **xx,double *a0);
+/* Perform a regression analysis to fit
+ * y' = a0[0] xx[0] + a0[1] xx[1] ... + a0[nx-1] xx[nx-1]
+ * with ny data points in each vector.
+ * The coefficients are returned in vector a0.
+ * The return value of the function is the chi2 value:
+ * sum_{j=0}^{ny-1} (y[j] - y'[j])^2
+ * If fp is not NULL debug information will be written to it.
+ */
+
+#endif
index b5fe72ee554df9ad09cd11760bbf73cc54e17c2d..5dce3c8b954adc0a2c0a81a13c6beb157918b0f1 100644 (file)
 #include <config.h>
 #endif
 
-#ifdef GMX_MPI
 
 #include "types/simple.h"
+#include "types/commrec.h"
 #include "gmxcomplex.h"
 #include "gmx_fft.h"
 
-/* We NEED MPI here. */
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
 typedef struct gmx_parallel_3dfft *
 gmx_parallel_3dfft_t;
 
@@ -73,78 +61,43 @@ gmx_parallel_3dfft_t;
  */
 int
 gmx_parallel_3dfft_init   (gmx_parallel_3dfft_t *    pfft_setup,
-                           int                       ngridx,
-                           int                       ngridy,
-                           int                       ngridz,
-                                                  int                       *node2slab,
-                                                  int                       *slab2grid_x,
-                           MPI_Comm                  comm,
+                           ivec                      ndata,
+                                                  real **                   real_data,
+                                                  t_complex **              complex_data,
+                           MPI_Comm                  comm[2],
+                           int *                     slab2index_major,
+                           int *                     slab2index_minor,
                            bool                      bReproducible);
-                           
+
 
 
 
 
 /*! \brief Get direct space grid index limits
- *
- *  The z dimension is never distributed. In the direct space, the x dimension
- *  is distributed over nodes, and after the real-to-complex FFT we work with
- *  a transposed grid where the y dimension is partitioned over nodes.
- *
- *  The node2slab array translates to node ids to slab indices,
- *  when NULL the slab ids are assumed to be identical to the node ids
- *  in the communicator comm.
  */
 int
-gmx_parallel_3dfft_limits(gmx_parallel_3dfft_t      pfft_setup,
-                          int *                     local_x_start,
-                          int *                     local_nx,
-                          int *                     local_y_start,
-                          int *                     local_ny);
+gmx_parallel_3dfft_real_limits(gmx_parallel_3dfft_t      pfft_setup,
+                                                          ivec                      local_ndata,
+                                                          ivec                      local_offset,
+                                                          ivec                      local_size);
 
 
-int
-gmx_parallel_transpose(t_complex *   data,
-                       t_complex *   work,
-                       int           nx,
-                       int           ny,
-                       int           local_x_start,
-                       int           local_nx,
-                       int           local_y_start,
-                       int           local_ny,
-                       int           nelem,
-                                          int           nnodes,
-                                          int           *node2slab,
-                       MPI_Comm      comm);
-
-
-/*! \brief Perform forward parallel MPI FFT.
- *
- *  Direction is either GMX_FFT_REAL_TO_COMPLEX or GMX_FFT_COMPLEX_TO_REAL.
- *
- *  If input and output arrays are separate there is no packing to consider.
- *  Input is simply nx*ny*nz in real, and output ny*nx*nzc in complex.
- *
- *  In they are identical we need to make sure there is room for the complex
- *  (length nzc=nz/2+1) in the array, so the _real_ space dimensions is
- *  always padded to nzc*2.
- *  In this case, the real dimensions are nx*ny*(nzc*2) while the complex
- *  dimensions is ny*nx*nzc (of type complex).
- *
- *  Note that the X and Y dimensions are transposed in the reciprocal space
- *  to avoid extra communication!
- *
- *  The node2slab array translates to node ids to slab indices,
- *  when NULL the slab ids are assumed to be identical to the node ids
- *  in the communicator comm.
+/*! \brief Get reciprocal space grid index limits
  */
 int
-gmx_parallel_3dfft(gmx_parallel_3dfft_t    pfft_setup,
-                   enum gmx_fft_direction  dir,
-                   void *                  in_data,
-                   void *                  out_data);
+gmx_parallel_3dfft_complex_limits(gmx_parallel_3dfft_t      pfft_setup,
+                                  ivec                      complex_order,
+                                                                 ivec                      local_ndata,
+                                                                 ivec                      local_offset,
+                                                                 ivec                      local_size);
 
 
+int
+gmx_parallel_3dfft_execute(gmx_parallel_3dfft_t    pfft_setup,
+                                                  enum gmx_fft_direction  dir,
+                                                  void *                  in_data,
+                                                  void *                  out_data);
+
 
 /*! \brief Release all data in parallel fft setup
  *
@@ -158,11 +111,8 @@ gmx_parallel_3dfft(gmx_parallel_3dfft_t    pfft_setup,
 int
 gmx_parallel_3dfft_destroy(gmx_parallel_3dfft_t    pfft_setup);
 
-#ifdef __cplusplus
-}
-#endif
 
-#endif /* GMX_MPI */
+
 
 #endif /* _gmx_parallel_3dfft_h_ */
 
index 7ed5c902dba6da83dfc1fbcba2668c563750be21..206bd8cbac70874272162ca56e033107379eb8bb 100644 (file)
@@ -41,7 +41,7 @@
 
 
 #include <stdio.h>
-#include <types/simple.h>
+#include "types/simple.h"
 
 #ifdef __cplusplus
 extern "C" {
diff --git a/include/gmx_sort.h b/include/gmx_sort.h
new file mode 100644 (file)
index 0000000..e58fae7
--- /dev/null
@@ -0,0 +1,76 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ * This file is part of Gromacs        Copyright (c) 1991-2010
+ * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gnomes, ROck Monsters And Chili Sauce
+ */
+#ifndef _GMX_SORT_H_
+#define _GMX_SORT_H_
+
+/** @file gmx_sort.h
+ *
+ *  @brief Portable implementation of thread-safe sort routines.
+ *
+ *
+ *  This module provides a Gromacs version of the qsort() routine defined.
+ *  It is not highly optimized, but it is thread safe, i.e. multiple threads
+ *  can simultaneously call gmx_qsort with different data.
+ */
+
+#include <stdlib.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+#if 0
+} /* fixes auto-indentation problems */
+#endif
+
+
+/*
+ *  @param base    Pointer to first element in list to sort
+ *  @param nmemb   Number of elements in list
+ *  @param size    Size in bytes of each element
+ *  @param compar  Comparison function that takes two pointers to elements
+ *                 being compared as arguments. The function should return an
+ *                 integer less than, equal to, or greater than zero if the 
+ *                 first argument is considered to be respectively less than,
+ *                 equal to, or greater than the second.
+ */
+void
+gmx_qsort(void *           base, 
+          size_t           nmemb, 
+          size_t           size, 
+          int            (*compar)(const void *, const void *));
+
+
+#ifdef GMX_THREADS
+/* Some implementations of qsort are not threadsafe.
+ * For instance qsort in glibc contains a bug which makes it non-threadsafe:
+ * http://sources.redhat.com/bugzilla/show_bug.cgi?id=11655
+ */
+#define qsort_threadsafe gmx_qsort
+#else
+/* System qsort might be faster than our own */
+#define qsort_threadsafe qsort
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _GMX_SORT_H_ */
index 0f1d1b10147d6eee5806fbd3177d32095defcf14..59dd029c0b9460dd27554fd7bd066cafcc92aebc 100644 (file)
 #if (defined (_MSC_VER) || defined(__INTEL_COMPILER))
 #  define gmx_mm_castsi128_ps(a) _mm_castsi128_ps(a)
 #  define gmx_mm_castps_si128(a) _mm_castps_si128(a)
+#  define gmx_mm_castps_ps128(a) (a)
 #elif defined(__GNUC__)
 #  define gmx_mm_castsi128_ps(a) ((__m128)(a))
 #  define gmx_mm_castps_si128(a) ((__m128i)(a))
+#  define gmx_mm_castps_ps128(a) ((__m128)(a))
 #else
 static __m128  gmx_mm_castsi128_ps(__m128i a) { return *(__m128 *) &a;  } 
 static __m128i gmx_mm_castps_si128(__m128 a)  { return *(__m128i *) &a; } 
+static __m128  gmx_mm_castps_ps128(__m128 a) { return *(__m128 *) &a;  } 
 #endif
 
 
@@ -225,34 +228,37 @@ gmx_mm_log_ps(__m128 x)
 }
 
 
-/* This exp-routine has a relative precision of 2^-22.33 bits (essentially single precision :-) ) */
+/* This exp-routine has a relative precision of:
+ *   2^-22.33 bits (essentially single precision :-)
+ * WARNING: no check against over or underflows (x beyond +-87)
+ */
 static __m128 
 gmx_mm_exp_ps(__m128 x)
 {
-    const __m128i half = _mm_set_epi32(0x3F000000, 0x3F000000, 0x3F000000, 0x3F000000);   // 0.5e+0f
-    const __m128i base = _mm_set_epi32(0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F);   // 127
-       const __m128i CC   = _mm_set_epi32(0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B);   // log2(e)
+    const __m128i half = _mm_set_epi32(0x3F000000, 0x3F000000, 0x3F000000, 0x3F000000);   /* 0.5e+0f */
+    const __m128i base = _mm_set_epi32(0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F);   /* 127 */
+    const __m128i CC   = _mm_set_epi32(0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B);   /* log2(e) */
        
-    const __m128i D5   = _mm_set_epi32(0x3AF61905, 0x3AF61905, 0x3AF61905, 0x3AF61905);   // 1.8775767e-3f
-    const __m128i D4   = _mm_set_epi32(0x3C134806, 0x3C134806, 0x3C134806, 0x3C134806);   // 8.9893397e-3f
-    const __m128i D3   = _mm_set_epi32(0x3D64AA23, 0x3D64AA23, 0x3D64AA23, 0x3D64AA23);   // 5.5826318e-2f
-    const __m128i D2   = _mm_set_epi32(0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4);   // 2.4015361e-1f
-    const __m128i D1   = _mm_set_epi32(0x3F31727B, 0x3F31727B, 0x3F31727B, 0x3F31727B);   // 6.9315308e-1f
-    const __m128i D0   = _mm_set_epi32(0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF);   // 9.9999994e-1f
+    const __m128i D5   = _mm_set_epi32(0x3AF61905, 0x3AF61905, 0x3AF61905, 0x3AF61905);   /* 1.8775767e-3f */
+    const __m128i D4   = _mm_set_epi32(0x3C134806, 0x3C134806, 0x3C134806, 0x3C134806);   /* 8.9893397e-3f */
+    const __m128i D3   = _mm_set_epi32(0x3D64AA23, 0x3D64AA23, 0x3D64AA23, 0x3D64AA23);   /* 5.5826318e-2f */
+    const __m128i D2   = _mm_set_epi32(0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4);   /* 2.4015361e-1f */
+    const __m128i D1   = _mm_set_epi32(0x3F31727B, 0x3F31727B, 0x3F31727B, 0x3F31727B);   /* 6.9315308e-1f */
+    const __m128i D0   = _mm_set_epi32(0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF);   /* 9.9999994e-1f */
        
        __m128 xmm0,xmm1;
        __m128i xmm2;
        
        xmm0 = _mm_mul_ps(x,gmx_mm_castsi128_ps(CC));
-       xmm1 = _mm_sub_ps(xmm0, gmx_mm_castsi128_ps(half));
+       xmm1 = _mm_sub_ps(xmm0,gmx_mm_castsi128_ps(half));
        xmm2 = _mm_cvtps_epi32(xmm1); 
        xmm1 = _mm_cvtepi32_ps(xmm2); 
        
-       xmm2 = _mm_add_epi32(xmm2,gmx_mm_castps_si128(base));
+       xmm2 = _mm_add_epi32(xmm2,base);
        xmm2 = _mm_slli_epi32(xmm2,23);
        
        xmm0 = _mm_sub_ps(xmm0,xmm1);
-       xmm1 = _mm_mul_ps(xmm0,gmx_mm_castsi128_ps( D5));
+       xmm1 = _mm_mul_ps(xmm0,gmx_mm_castsi128_ps(D5));
        xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D4));
        xmm1 = _mm_mul_ps(xmm1,xmm0);
        xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D3));
@@ -269,6 +275,54 @@ gmx_mm_exp_ps(__m128 x)
 }
 
 
+/* Same as gmx_mm_exp_ps, but has a lower bound check, such that it can
+ * be safely called with x < -87.33.
+ * WARNING: no check against overflows (x > 87)
+ */
+static __m128 
+gmx_mm_exp_ps_lbc(__m128 x)
+{
+    const __m128i lim  = _mm_set_epi32(0xC2AE0000, 0xC2AE0000, 0xC2AE0000, 0xC2AE0000);   /* -87 */
+    const __m128i half = _mm_set_epi32(0x3F000000, 0x3F000000, 0x3F000000, 0x3F000000);   /* 0.5e+0f */
+    const __m128i base = _mm_set_epi32(0x0000007F, 0x0000007F, 0x0000007F, 0x0000007F);   /* 127 */
+    const __m128i CC   = _mm_set_epi32(0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B, 0x3FB8AA3B);   /* log2(e) */
+       
+    const __m128i D5   = _mm_set_epi32(0x3AF61905, 0x3AF61905, 0x3AF61905, 0x3AF61905);   /* 1.8775767e-3f */
+    const __m128i D4   = _mm_set_epi32(0x3C134806, 0x3C134806, 0x3C134806, 0x3C134806);   /* 8.9893397e-3f */
+    const __m128i D3   = _mm_set_epi32(0x3D64AA23, 0x3D64AA23, 0x3D64AA23, 0x3D64AA23);   /* 5.5826318e-2f */
+    const __m128i D2   = _mm_set_epi32(0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4, 0x3E75EAD4);   /* 2.4015361e-1f */
+    const __m128i D1   = _mm_set_epi32(0x3F31727B, 0x3F31727B, 0x3F31727B, 0x3F31727B);   /* 6.9315308e-1f */
+    const __m128i D0   = _mm_set_epi32(0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF, 0x3F7FFFFF);   /* 9.9999994e-1f */
+       
+       __m128 xmm0,xmm1;
+       __m128i xmm2;
+       
+       xmm1 = _mm_max_ps(x,gmx_mm_castsi128_ps(lim)); /* x<-87 gives exp(-87) */
+       xmm0 = _mm_mul_ps(xmm1,gmx_mm_castsi128_ps(CC));
+       xmm1 = _mm_sub_ps(xmm0,gmx_mm_castsi128_ps(half));
+       xmm2 = _mm_cvtps_epi32(xmm1); 
+       xmm1 = _mm_cvtepi32_ps(xmm2); 
+       
+       xmm2 = _mm_add_epi32(xmm2,base);
+       xmm2 = _mm_slli_epi32(xmm2,23);
+       
+       xmm0 = _mm_sub_ps(xmm0,xmm1);
+       xmm1 = _mm_mul_ps(xmm0,gmx_mm_castsi128_ps(D5));
+       xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D4));
+       xmm1 = _mm_mul_ps(xmm1,xmm0);
+       xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D3));
+       xmm1 = _mm_mul_ps(xmm1,xmm0);
+       xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D2));
+       xmm1 = _mm_mul_ps(xmm1,xmm0);
+       xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D1));
+       xmm1 = _mm_mul_ps(xmm1,xmm0);
+       xmm1 = _mm_add_ps(xmm1,gmx_mm_castsi128_ps(D0));
+       xmm1 = _mm_mul_ps(xmm1,gmx_mm_castsi128_ps(xmm2));
+       
+       /* 19 instructions currently + pipeline latenct after max_ps */
+       return xmm1;
+}
+
 
 #define GMX_MM_SINCOS_PS(x,sinval,cosval)                                                                    \
 {                                                                                                            \
index 4640c78f9f1d0eb9e6d44e773829367b8181b2a8..a41e264420bbb7e38d46ad137565d6451f7f7b3e 100644 (file)
@@ -48,6 +48,8 @@ enum { estatsOK, estatsNO_POINTS, estatsNO_MEMORY, estatsERROR,
 enum { elsqWEIGHT_NONE, elsqWEIGHT_X, elsqWEIGHT_Y, 
        elsqWEIGHT_XY, elsqWEIGHT_NR  };
 
+enum { ehistoX, ehistoY, ehistoNR };
+  
 extern gmx_stats_t gmx_stats_init();
 
 extern int gmx_stats_done(gmx_stats_t stats);
@@ -112,12 +114,15 @@ extern int gmx_stats_dump_xy(gmx_stats_t gstats,FILE *fp);
 
 /* Make a histogram of the data present. Uses either bindwith to
    determine the number of bins, or nbins to determine the binwidth,
-   therefore one of these should be zero, but not the other. If
+   therefore one of these should be zero, but not the other. If *nbins = 0
+   the number of bins will be returned in this variable. ehisto should be one of 
+   ehistoX or ehistoY. If
    normalized not equal to zero, the integral of the histogram will be
    normalized to one. The output is in two arrays, *x and *y, to which
    you should pass a pointer. Memory for the arrays will be allocated
    as needed. Function returns one of the estats codes. */
-extern int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int nbins,
+extern int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int *nbins,
+                                   int ehisto,
                                    int normalized,real **x,real **y);
 
 /* Return message belonging to error code */
index d29a6fe13539b4233fbc6bbd89ff48bcee6c3d1e..c762ff123ad2417eeeed2a6c2a3c7982b31d1789 100644 (file)
@@ -41,24 +41,44 @@ enum { eCPP_OK, eCPP_FILE_NOT_FOUND, eCPP_EOF, eCPP_SYNTAX, eCPP_INTERRUPT,
        eCPP_INVALID_HANDLE,
        eCPP_FILE_NOT_OPEN, eCPP_UNKNOWN, eCPP_NR };
 
+/* THESE FUNCTIONS ARE NOT THREAD SAFE!! */
+
 /* Open the file to be processed. The handle variable holds internal
    info for the cpp emulator. The cppopt variable (null terminated)
-   can hold cpp options like -IXXX and -DXXX. Return integer status. */
+   can hold cpp options like -IXXX and -DXXX. Return integer status. 
+   
+   NOT THREAD SAFE 
+   */
 extern int cpp_open_file(const char *filenm,gmx_cpp_t *handlep, char **cppopts);
 
 /* Return one whole line from the file into buf which holds at most n
-   characters, for subsequent processing. Returns integer status. */
+   characters, for subsequent processing. Returns integer status. 
+   
+   NOT THREAD SAFE 
+   */
 extern int cpp_read_line(gmx_cpp_t *handlep,int n,char buf[]);
 
-/* Return the file currently being read. */
+/* Return the file currently being read. 
+   
+   NOT THREAD SAFE 
+   */
 extern char *cpp_cur_file(const gmx_cpp_t *handlep);
 
-/* Return the current line number. */
+/* Return the current line number. 
+   
+   NOT THREAD SAFE 
+   */
 extern int cpp_cur_linenr(const gmx_cpp_t *handlep);
 
-/* Close the file! Return integer status. */
+/* Close the file! Return integer status. 
+   
+   NOT THREAD SAFE 
+   */
 extern int cpp_close_file(gmx_cpp_t *handlep);
 
 /* Return a string containing the error message coresponding to status
-   variable. */
+   variable. 
+   
+   NOT THREAD SAFE 
+   */
 extern char *cpp_error(gmx_cpp_t *handlep,int status);
index e36de067d259d0f0874d55adb27c695d03416eb6..41955a85aaff99dc68e5f41df483173db8d8ded6 100644 (file)
 #include "typedefs.h"
 #include "xdrf.h"
 
-/* Note that some functions list beow are NOT THREADSAFE
- * when multiple threads use the same file pointer.
- */
-
-/* Highest number of open input/output files. This is usually limited to 1024 by the OS, anyway. */
-#define GMX_MAXFILES    1024
+/* types */
 
 /* Enumerated for different items in files */
 enum { eitemHEADER, eitemIR, eitemBOX, 
@@ -61,21 +56,17 @@ enum { eioREAL, eioDOUBLE, eioINT, eioGMX_LARGE_INT,
        eioUCHAR, eioNUCHAR, eioUSHORT,
        eioRVEC, eioNRVEC, eioIVEC, eioSTRING, eioNR };
 
-/* Functions for reading and writing data */
-typedef bool do_func(void *item,int nitem,int eio,
-                    const char *desc,const char *srcfile,int line);
-                    
-/* Global variables defined in gmxfio.h */
-extern do_func *do_read;
-extern do_func *do_write;
+typedef struct t_fileio t_fileio;
+
 extern const char *itemstr[eitemNR];
 extern const char *comment_str[eitemNR];
 
+
 /********************************************************
  * Open and Close 
  ********************************************************/
 
-int gmx_fio_open(const char *fn,const char *mode);
+t_fileio *gmx_fio_open(const char *fn,const char *mode);
 /* Open a new file for reading or writing.
  * The file type will be deduced from the file name.
  * If fn is NULL, stdin / stdout will be used for Ascii I/O (TPA type)
@@ -85,13 +76,13 @@ int gmx_fio_open(const char *fn,const char *mode);
  * unix, but is important on windows.
  */
  
-int gmx_fio_close(int fp);
+int gmx_fio_close(t_fileio *fp);
 /* Close the file corresponding to fp (if not stdio)
  * The routine will exit when an invalid fio is handled.
  * Returns 0 on success.
  */
 
-int gmx_fio_fp_close(int fp);
+int gmx_fio_fp_close(t_fileio *fp);
 /* Close the file corresponding to fp without closing the FIO entry
  * Needed e.g. for trxio because the FIO entries are used to store 
  * additional data.
@@ -100,72 +91,84 @@ int gmx_fio_fp_close(int fp);
  * Returns 0 on success.
  */
 
-void gmx_fio_select(int fp);
-/* This routine sets the global variables do_read and do_write
- * to point to the correct routines for fp.
- */
+
+/* Open a file, return a stream, record the entry in internal FIO object */
+FILE* gmx_fio_fopen(const char *fn,const char *mode);
+
+/* Close a file previously opened with gmx_fio_fopen. 
+ * Do not mix these calls with standard fopen/fclose ones!
+ * Returns 0 on success.  */
+int gmx_fio_fclose(FILE *fp);
+
+
 
 /********************************************************
  * Change properties of the open file
  ********************************************************/
 
-extern void gmx_fio_setprecision(int fio,bool bDouble);
+extern void gmx_fio_setprecision(t_fileio *fio,bool bDouble);
 /* Select the floating point precision for reading and writing files */
 
-extern char *gmx_fio_getname(int fio);
+extern char *gmx_fio_getname(t_fileio *fio);
 /* Return the filename corresponding to the fio index */
 
-extern int gmx_fio_getftp(int fio);
-/* Return the filetype corresponding to the fio index */
+extern int gmx_fio_getftp(t_fileio *fio);
+/* Return the filetype corresponding to the fio index. 
+    There is as of now no corresponding setftp function because the file
+    was opened as a specific file type and changing that midway is most 
+    likely an evil hack. */
 
-extern void gmx_fio_setftp_fio(int fio,int ftp);
-/* And set it */
-
-extern void gmx_fio_setdebug(int fio,bool bDebug);
+extern void gmx_fio_setdebug(t_fileio *fio,bool bDebug);
 /* Set the debug mode */
 
-extern bool gmx_fio_getdebug(int fio);
+extern bool gmx_fio_getdebug(t_fileio *fio);
 /* Return  whether debug mode is on in fio  */
 
-extern bool gmx_fio_getread(int fio);
+extern bool gmx_fio_getread(t_fileio *fio);
 /* Return  whether read mode is on in fio  */
 
+
+extern void gmx_fio_checktype(t_fileio *fio);
+/* Check whether the fio is of a sane type */
+
 /***************************************************
  * FILE Operations
  ***************************************************/
 
-extern void gmx_fio_rewind(int fio);
+extern void gmx_fio_rewind(t_fileio *fio);
 /* Rewind the tpa file in fio */
 
-int gmx_fio_flush(int fio);
+int gmx_fio_flush(t_fileio *fio);
 /* Flush the fio, returns 0 on success */
 
-extern off_t gmx_fio_ftell(int fio);
+int gmx_fio_fsync(t_fileio *fio);
+/* fsync the fio, returns 0 on success. 
+   NOTE: don't use fsync function unless you're absolutely sure you need it
+   because it deliberately interferes with the OS's caching mechanisms and
+   can cause dramatically slowed down IO performance. Some OSes (Linux, 
+   for example), may implement fsync as a full sync() point. */
+
+extern off_t gmx_fio_ftell(t_fileio *fio);
 /* Return file position if possible */
 
-extern int gmx_fio_seek(int fio,off_t fpos);
+extern int gmx_fio_seek(t_fileio *fio,off_t fpos);
 /* Set file position if possible, quit otherwise */
 
-extern FILE *gmx_fio_getfp(int fio);
+extern FILE *gmx_fio_getfp(t_fileio *fio);
 /* Return the file pointer itself */
 
-extern XDR *gmx_fio_getxdr(int fio);
+extern XDR *gmx_fio_getxdr(t_fileio *fio);
 /* Return the file pointer itself */
 
-/* Open a file, return a stream, record the entry in internal FIO object */
-FILE * gmx_fio_fopen(const char *fn,const char *mode);
 
-/* Close a file previously opened with gmx_fio_fopen. 
- * Do not mix these calls with standard fopen/fclose ones!
- * Returns 0 on success.
- */
-int gmx_fio_fclose(FILE *fp);
+
+
 
 /* Element with information about position in a currently open file.
  * off_t should be defined by autoconf if your system does not have it.
- * If you do not have it on some other platform you do not have largefile support
- * at all, and you can define it to int (or better, find out how to enable large files).
- */
+ * If you do not have it on some other platform you do not have largefile 
+ * support at all, and you can define it to int (or better, find out how to 
+ * enable large files).  */
 typedef struct
 {
        char      filename[STRLEN];
@@ -176,152 +179,253 @@ typedef struct
 gmx_file_position_t;
 
 
-/*
- * Check if the file position is out of the range of off_t.
+int gmx_fio_check_file_position(t_fileio *fio);
+/* Check if the file position is out of the range of off_t.
  * The result is stored along with the other file data of fio.
  */
-int
-gmx_fio_check_file_position(int fio);
 
-/*
- * Return the name and file pointer positions for all currently open
+int gmx_fio_get_output_file_positions(gmx_file_position_t ** outputfiles,
+                                      int *nfiles );
+/* Return the name and file pointer positions for all currently open
  * output files. This is used for saving in the checkpoint files, so we
  * can truncate output files upon restart-with-appending.
  *
  * For the first argument you should use a pointer, which will be set to
  * point to a list of open files.
  */
-int
-gmx_fio_get_output_file_positions (gmx_file_position_t ** outputfiles,
-                                   int *nfiles );
 
-int gmx_fio_get_file_md5(int fio, off_t offset,  unsigned char digest[]);
+t_fileio *gmx_fio_all_output_fsync(void);
+/* fsync all open output files. This is used for checkpointing, where
+   we need to ensure that all output is actually written out to 
+   disk. 
+   This is most important in the case of some networked file systems, 
+   where data is not synced with the file server until close() or 
+   fsync(), so data could remain in cache for days.
+   Note the caveats reported with gmx_fio_fsync(). 
+   
+    returns: NULL if no error occurred, or a pointer to the first file that
+             failed if an error occurred 
+*/
+
 
+int gmx_fio_get_file_md5(t_fileio *fio, off_t offset,  unsigned char digest[]);
 
-extern int xtc_seek_frame(int frame, int fio, int natoms);
 
-extern int xtc_seek_time(real time, int fio, int natoms);
+extern int xtc_seek_frame(t_fileio *fio, int frame, int natoms);
+
+extern int xtc_seek_time(t_fileio *fio, real time, int natoms);
 
        
-extern void set_comment(const char *comment);
 /* Add this to the comment string for debugging */
+extern void gmx_fio_set_comment(t_fileio *fio, const char *comment);
 
-extern void unset_comment(void);
 /* Remove previously set comment */
+extern void gmx_fio_unset_comment(t_fileio *fio);
+
+
 
 
 /********************************************************
- * Dirty C macros... Try this in FORTRAN 
- * (Oh, and you can do structured programming in C too) 
- *********************************************************/
-#define do_real(item)         (bRead ?\
-  do_read ((void *)&(item),1,eioREAL,(#item),__FILE__,__LINE__) : \
-  do_write((void *)&(item),1,eioREAL,(#item),__FILE__,__LINE__))
-
-#define do_double(item)         (bRead ?                                 \
-  do_read ((void *)&(item),1,eioDOUBLE,(#item),__FILE__,__LINE__) : \
-  do_write((void *)&(item),1,eioDOUBLE,(#item),__FILE__,__LINE__))
-#define do_int(item)          (bRead ?\
-  do_read ((void *)&(item),1,eioINT,(#item),__FILE__,__LINE__) :\
-  do_write((void *)&(item),1,eioINT,(#item),__FILE__,__LINE__))
+ * Read and write
+ ********************************************************/
+
+
+/* basic reading & writing */
+bool gmx_fio_reade_real(t_fileio *fio, real *item, 
+                        const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_double(t_fileio *fio, double *item, 
+                          const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_int(t_fileio *fio, int *item, 
+                       const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, 
+                                 const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_uchar(t_fileio *fio, unsigned char *item, 
+                         const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_ushort(t_fileio *fio, unsigned short *item, 
+                         const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_rvec(t_fileio *fio, rvec *item, 
+                        const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_ivec(t_fileio *fio, ivec *item, 
+                        const char *desc, const char *srcfile, int line);
+bool gmx_fio_reade_string(t_fileio *fio, char *item, 
+                          const char *desc, const char *srcfile, int line);
+
+bool gmx_fio_writee_real(t_fileio *fio, real item, 
+                         const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_double(t_fileio *fio, double item, 
+                           const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_int(t_fileio *fio, int item, 
+                        const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_gmx_large_int(t_fileio *fio, gmx_large_int_t item, 
+                                  const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_uchar(t_fileio *fio, unsigned char item, 
+                          const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_ushort(t_fileio *fio, unsigned short item, 
+                          const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_rvec(t_fileio *fio, rvec *item, 
+                         const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_ivec(t_fileio *fio, ivec *item, 
+                         const char *desc, const char *srcfile, int line);
+bool gmx_fio_writee_string(t_fileio *fio, const char *item, 
+                           const char *desc, const char *srcfile, int line);
+
+/* reading or writing, depending on the file's opening mode string */
+bool gmx_fio_doe_real(t_fileio *fio, real *item, 
+                      const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_double(t_fileio *fio, double *item, 
+                        const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_bool(t_fileio *fio, bool *item, 
+                     const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_int(t_fileio *fio, int *item, 
+                     const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, 
+                               const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_uchar(t_fileio *fio, unsigned char *item, 
+                       const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_ushort(t_fileio *fio, unsigned short *item, 
+                       const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_rvec(t_fileio *fio, rvec *item, 
+                      const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_ivec(t_fileio *fio, ivec *item, 
+                      const char *desc, const char *srcfile, int line);
+bool gmx_fio_doe_string(t_fileio *fio, char *item, 
+                        const char *desc, const char *srcfile, int line);
+
+
+
+
+/* array reading & writing */
+bool gmx_fio_nreade_real(t_fileio *fio, real *item, int n, 
+                         const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_double(t_fileio *fio, double *item, int n, 
+                           const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_int(t_fileio *fio, int *item, int n, 
+                        const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n, 
+                                  const char *desc, const char *srcfile, 
+                                  int line);
+bool gmx_fio_nreade_uchar(t_fileio *fio, unsigned char *item, int n, 
+                          const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_ushort(t_fileio *fio, unsigned short *item, int n, 
+                          const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_rvec(t_fileio *fio, rvec *item, int n, 
+                         const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_ivec(t_fileio *fio, ivec *item, int n, 
+                         const char *desc, const char *srcfile, int line);
+bool gmx_fio_nreade_string(t_fileio *fio, char *item[], int n, 
+                           const char *desc, const char *srcfile, int line);
+
+bool gmx_fio_nwritee_real(t_fileio *fio, const real *item, int n, 
+                          const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_double(t_fileio *fio, const double *item, int n, 
+                            const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_int(t_fileio *fio, const int *item, int n, 
+                         const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_gmx_large_int(t_fileio *fio, 
+                                   const gmx_large_int_t *item, int n,
+                                   const char *desc, const char *srcfile, 
+                                   int line);
+bool gmx_fio_nwritee_uchar(t_fileio *fio, const unsigned char *item, int n, 
+                           const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_ushort(t_fileio *fio, const unsigned short *item, int n, 
+                           const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_rvec(t_fileio *fio, const rvec *item, int n, 
+                          const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_ivec(t_fileio *fio, const ivec *item, int n, 
+                          const char *desc, const char *srcfile, int line);
+bool gmx_fio_nwritee_string(t_fileio *fio, const char *item[], int n, 
+                            const char *desc, const char *srcfile, int line);
+
+bool gmx_fio_ndoe_real(t_fileio *fio, real *item, int n, 
+                       const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_double(t_fileio *fio, double *item, int n, 
+                         const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_bool(t_fileio *fio, bool *item, int n, 
+                      const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_int(t_fileio *fio, int *item, int n, 
+                      const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n, 
+                                const char *desc, const char *srcfile, 
+                                int line);
+bool gmx_fio_ndoe_uchar(t_fileio *fio, unsigned char *item, int n, 
+                        const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_ushort(t_fileio *fio, unsigned short *item, int n, 
+                        const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_rvec(t_fileio *fio, rvec *item, int n, 
+                       const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_ivec(t_fileio *fio, ivec *item, int n, 
+                       const char *desc, const char *srcfile, int line);
+bool gmx_fio_ndoe_string(t_fileio *fio, char *item[], int n, 
+                         const char *desc, const char *srcfile, int line);
+
+
+
+/* convenience macros */
+#define gmx_fio_read_real(fio, item)           gmx_fio_reade_real(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_double(fio, item)         gmx_fio_reade_double(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_int(fio, item)            gmx_fio_reade_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_gmx_large_int(fio, item)  gmx_fio_reade_gmx_large_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_uchar(fio, item)          gmx_fio_reade_uchar(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_ushort(fio, item)         gmx_fio_reade_ushort(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_rvec(fio, item)           gmx_fio_reade_rvec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_ivec(fio, item)           gmx_fio_reade_ivec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_read_string(fio, item)         gmx_fio_reade_string(fio, item, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_write_real(fio, item)           gmx_fio_writee_real(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_double(fio, item)         gmx_fio_writee_double(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_int(fio, item)            gmx_fio_writee_int(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_gmx_large_int(fio, item)  gmx_fio_writee_gmx_large_int(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_uchar(fio, item)          gmx_fio_writee_uchar(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_ushort(fio, item)         gmx_fio_writee_ushort(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_rvec(fio, item)           gmx_fio_writee_rvec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_ivec(fio, item)           gmx_fio_writee_ivec(fio, item, (#item), __FILE__, __LINE__)
+#define gmx_fio_write_string(fio, item)         gmx_fio_writee_string(fio, item, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_do_real(fio, item)              gmx_fio_doe_real(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_double(fio, item)            gmx_fio_doe_double(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_bool(fio, item)              gmx_fio_doe_bool(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_int(fio, item)               gmx_fio_doe_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_gmx_large_int(fio, item)     gmx_fio_doe_gmx_large_int(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_uchar(fio, item)             gmx_fio_doe_uchar(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_ushort(fio, item)            gmx_fio_doe_ushort(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_rvec(fio, item)              gmx_fio_doe_rvec(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_ivec(fio, item)              gmx_fio_doe_ivec(fio, &item, (#item), __FILE__, __LINE__)
+#define gmx_fio_do_string(fio, item)            gmx_fio_doe_string(fio, item, (#item), __FILE__, __LINE__)
+
+
+
+
+#define gmx_fio_nread_real(fio, item, n)            gmx_fio_nreade_real(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_double(fio, item, n)          gmx_fio_nreade_double(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_int(fio, item, n)             gmx_fio_nreade_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_gmx_large_int(fio, item, n)   gmx_fio_nreade_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_uchar(fio, item, n)           gmx_fio_nreade_uchar(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_ushort(fio, item, n)          gmx_fio_nreade_ushort(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_rvec(fio, item, n)            gmx_fio_nreade_rvec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_ivec(fio, item, n)            gmx_fio_nreade_ivec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nread_string(fio, item, n)          gmx_fio_nreade_string(fio, item, n, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_nwrite_real(fio, item, n)           gmx_fio_nwritee_real(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_double(fio, item, n)         gmx_fio_nwritee_double(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_int(fio, item, n)            gmx_fio_nwritee_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_gmx_large_int(fio, item, n)  gmx_fio_nwritee_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_uchar(fio, item, n)          gmx_fio_nwritee_uchar(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_ushort(fio, item, n)         gmx_fio_nwritee_ushort(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_rvec(fio, item, n)           gmx_fio_nwritee_rvec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_ivec(fio, item, n)           gmx_fio_nwritee_ivec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_nwrite_string(fio, item, n)         gmx_fio_nwritee_string(fio, item, n, (#item), __FILE__, __LINE__)
+
+#define gmx_fio_ndo_real(fio, item, n)              gmx_fio_ndoe_real(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_double(fio, item, n)            gmx_fio_ndoe_double(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_bool(fio, item, n)              gmx_fio_ndoe_bool(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_int(fio, item, n)               gmx_fio_ndoe_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_gmx_large_int(fio, item, n)     gmx_fio_ndoe_gmx_large_int(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_uchar(fio, item, n)             gmx_fio_ndoe_uchar(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_ushort(fio, item, n)            gmx_fio_ndoe_ushort(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_rvec(fio, item, n)              gmx_fio_ndoe_rvec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_ivec(fio, item, n)              gmx_fio_ndoe_ivec(fio, item, n, (#item), __FILE__, __LINE__)
+#define gmx_fio_ndo_string(fio, item, n)            gmx_fio_ndoe_string(fio, item, n, (#item), __FILE__, __LINE__)
+
 
-#define do_gmx_large_int(item)          (bRead ?                       \
-  do_read ((void *)&(item),1,eioGMX_LARGE_INT,(#item),__FILE__,__LINE__) :\
-  do_write((void *)&(item),1,eioGMX_LARGE_INT,(#item),__FILE__,__LINE__))
-#define do_uchar(item)        (bRead ?\
-  do_read ((void *)&(item),1,eioUCHAR,(#item),__FILE__,__LINE__) :\
-  do_write((void *)&(item),1,eioUCHAR,(#item),__FILE__,__LINE__))
-
-#define do_nuchar(item,n)     (bRead ?\
-  do_read ((void *)(item),n,eioNUCHAR,(#item),__FILE__,__LINE__) :\
-  do_write((void *)(item),n,eioNUCHAR,(#item),__FILE__,__LINE__))
-  
-#define do_ushort(item)          (bRead ?\
-  do_read ((void *)&(item),1,eioUSHORT,(#item),__FILE__,__LINE__) :\
-  do_write((void *)&(item),1,eioUSHORT,(#item),__FILE__,__LINE__))
-  
-#define do_rvec(item)         (bRead ?\
-  do_read ((void *)(item),1,eioRVEC,(#item),__FILE__,__LINE__) :\
-  do_write((void *)(item),1,eioRVEC,(#item),__FILE__,__LINE__))
-  
-#define do_ivec(item)         (bRead ?\
-  do_read ((void *)(item),1,eioIVEC,(#item),__FILE__,__LINE__) :\
-  do_write((void *)(item),1,eioIVEC,(#item),__FILE__,__LINE__))
-  
-#define do_string(item)       (bRead ?\
-  do_read ((void *)(item),1,eioSTRING,(#item),__FILE__,__LINE__) :\
-  do_write((void *)(item),1,eioSTRING,(#item),__FILE__,__LINE__))
-  
-#define ndo_real(item,n,bOK) {\
-  bOK=TRUE;\
-  for(i=0; (i<n); i++) {\
-    char buf[128];\
-    sprintf(buf,"%s[%d]",#item,i);\
-    bOK = bOK && (bRead ?\
-      do_read ((void *)&((item)[i]),1,eioREAL,buf,__FILE__,__LINE__):\
-      do_write((void *)&(item[i]),1,eioREAL,buf,__FILE__,__LINE__));\
-  }\
-}
-
-#define ndo_double(item,n,bOK) {\
-  bOK=TRUE;\
-  for(i=0; (i<n); i++) {\
-    char buf[128];\
-    sprintf(buf,"%s[%d]",#item,i);\
-    bOK = bOK && (bRead ?\
-      do_read ((void *)&((item)[i]),1,eioDOUBLE,buf,__FILE__,__LINE__):\
-      do_write((void *)&(item[i]),1,eioDOUBLE,buf,__FILE__,__LINE__));\
-  }\
-}
-     
-#define ndo_int(item,n,bOK)  {\
-  bOK=TRUE;\
-  for(i=0; (i<n); i++) {\
-    char buf[128];\
-    sprintf(buf,"%s[%d]",#item,i);\
-    bOK = bOK && (bRead ?\
-      do_read ((void *)&(item[i]),1,eioINT,buf,__FILE__,__LINE__):\
-      do_write((void *)&(item[i]),1,eioINT,buf,__FILE__,__LINE__));\
-  }\
-}
-
-#define ndo_nuchar(item,n,bOK)  {\
-  bOK=TRUE;\
-  for(i=0; (i<n); i++) {\
-    char buf[128];\
-    sprintf(buf,"%s[%d]",#item,i);\
-    bOK = bOK && (bRead ?\
-      do_read ((void *)&(item[i]),1,eioNUCHAR,buf,__FILE__,__LINE__):\
-      do_write((void *)&(item[i]),1,eioNUCHAR,buf,__FILE__,__LINE__));\
-  }\
-}
-  
-#define ndo_rvec(item,n)      (bRead ?\
-  do_read ((void *)(item),n,eioNRVEC,(#item),__FILE__,__LINE__) :\
-  do_write((void *)(item),n,eioNRVEC,(#item),__FILE__,__LINE__))
-  
-#define ndo_ivec(item,n,bOK) {\
-  bOK=TRUE;\
-  for(i=0; (i<n); i++) {\
-    char buf[128];\
-    sprintf(buf,"%s[%d]",#item,i);\
-    bOK = bOK && (bRead ?\
-      do_read ((void *)(item)[i],1,eioIVEC,buf,__FILE__,__LINE__):\
-      do_write((void *)(item)[i],1,eioIVEC,buf,__FILE__,__LINE__));\
-  }\
-}
-  
-#define ndo_string(item,n,bOK) {\
-  bOK=TRUE;\
-  for(i=0; (i<n); i++) {\
-    char buf[128];\
-    sprintf(buf,"%s[%d]",#item,i);\
-    bOK = bOK && (bRead ?\
-      do_read ((void *)(item)[i],1,eioSTRING,buf,__FILE__,__LINE__):\
-      do_write((void *)(item)[i],1,eioSTRING,buf,__FILE__,__LINE__));\
-  }\
-}
 
 #endif
index 437a5a4609cc6c28604cdc40e8769493b5361a11..0374926c686ccfc0c847e92ded534e1d4fad6211 100644 (file)
@@ -110,7 +110,7 @@ typedef struct {
 extern bool is_int(double x);
 /* Returns TRUE when x is integer */
 
-extern void print_top_comment(FILE *out,const char *filename,const char *title,bool bITP);
+extern void print_top_comment(FILE *out,const char *filename,const char *generator,bool bITP);
 
 extern void print_top_header(FILE *out,const char *filename,const char *title,bool bITP, 
                             const char *ffdir,real mHmult);
index 8dc0513f08c2d85f4a70bf4e8ad743a84d3d4268..5d3b8f4ab8e785cae356465bc52c1dcc3eb54e35 100644 (file)
@@ -104,6 +104,7 @@ typedef struct {
   int     nctl;     /* How many control atoms there are */
   char           *a[4];    /* Control atoms i,j,k,l      */
   bool    bAlreadyPresent;
+  bool    bXSet;
   rvec    newx;     /* calculated new position    */
   atom_id newi;     /* new atom index number (after additions) */
 } t_hack;
index b368287450d3063ce01f46c9579bc3aae3361570..c739a518d73cb665fe35a9db3bd8a229fb835ab3 100644 (file)
@@ -69,7 +69,7 @@ typedef enum
      *
      * Use gmx_histogram_add_item() or gmx_histogram_add_item_to_bin() to sample.
      */
-    HIST_BINAVER,
+    HIST_BINAVER 
 } e_histogram_t;
 
 /** Whether bins are centered at integer values. */
index ef44c4b4317b56282b845a0ce578dac7fb96fe50..775b2d132c9da002a056cf67118aefab53ee5b34 100644 (file)
@@ -61,9 +61,11 @@ void rd_index(const char *statfile,int ngrps,int isize[],
 /* Assume the group file is generated, so the
  * format need not be user-friendly. The format is:
  * nr of groups, total nr of atoms
- * for each group: name nr of element, elements
- * The function opens a file, reads ngrps groups, puts the
- * sizes in isize, the atom_id s in index and the names of
+ * for each group: name nr of element, elements.
+ *
+ * The function opens a file, reads ngrps groups, asks the 
+ * user for group numbers, and puts the resulting sizes in 
+ * isize, the atom_id s in index and the names of
  * the groups in grpnames.
  *
  * It is also assumed, that when ngrps groups are requested
@@ -102,6 +104,9 @@ extern t_aa_names *get_aa_names(void);
 extern bool is_protein(t_aa_names *aan,char *resnm);
 /* gives true if resnm occurs in aminoacids.dat */
 
+extern bool is_residue(t_aa_names *aan,char *resnm);
+/* gives true if resnm occurs in aminoacids.dat or is DNA or RNA */
+
 extern void done_aa_names(t_aa_names **aan);
 /* Free memory. Pass address of the pointer youget from get_aa_names */
 
index 6312ad908da00c9e5b1f0686777d5aa357644937..4e01d3a6ea73a073120514dec13e01dc6fad8295 100644 (file)
@@ -75,7 +75,7 @@ typedef enum
     INDEX_ATOM,    /**< Each atom in a separate block.*/
     INDEX_RES,     /**< Each residue in a separate block.*/
     INDEX_MOL,     /**< Each molecule in a separate block.*/
-    INDEX_ALL,     /**< All atoms in a single block.*/
+    INDEX_ALL      /**< All atoms in a single block.*/
 } e_index_t;
 
 /*! \brief
@@ -332,10 +332,13 @@ gmx_ana_indexmap_clear(gmx_ana_indexmap_t *m);
 /** Reserves memory for an index group mapping. */
 extern void
 gmx_ana_indexmap_reserve(gmx_ana_indexmap_t *m, int nr, int isize);
-/** Initialize index group mapping. */
+/** Initializes an index group mapping. */
 extern void
 gmx_ana_indexmap_init(gmx_ana_indexmap_t *m, gmx_ana_index_t *g,
                       t_topology *top, e_index_t type);
+/** Sets an index group mapping to be static. */
+extern void
+gmx_ana_indexmap_set_static(gmx_ana_indexmap_t *m, t_blocka *b);
 /** Frees memory allocated for index group mapping. */
 extern void
 gmx_ana_indexmap_deinit(gmx_ana_indexmap_t *m);
index eb3dc325877f2ac8a9f018e499668a4980cfc364..0eba2af8dbdb21ea1c0f0336b0a54b896b10114e 100644 (file)
@@ -76,7 +76,7 @@ extern void check_multi_int(FILE *log,const gmx_multisim_t *ms,
 
 extern void init_multisystem(t_commrec *cr,int nsim,int nfile,
                              const t_filenm fnm[], bool bParFn);
-/* Splits the communication into nsim seperate simulations
+/* Splits the communication into nsim separate simulations
  * and creates a communication structure between the master
  * these simulations.
  * If bParFn is set, the nodeid is appended to the tpx and each output file.
@@ -90,15 +90,12 @@ extern t_commrec *init_par(int *argc,char ***argv_ptr);
  * array of argument strings.
  */
 
-extern t_commrec *init_par_threads(t_commrec *cro);
-/* Initiate the communication records for thread-parallel simulations. 
-   Must be called before any communication takes place by the individual
-   threads. cro is the old shared commrec */
-
-extern void cancel_par_threads(t_commrec *cr);
-/* Cancel threads (for when there is no parallel version of the integration
-   algorithm). Cancels threads (actually, it calls tMPI_Finalize() on them) 
-   and re-writes commrec to new serial situation.  */
+extern t_commrec *init_par_threads(const t_commrec *cro);
+/* Initialize communication records for thread-parallel simulations. 
+   Must be called on all threads before any communication takes place by 
+   the individual threads. Copies the original commrec to 
+   thread-local versions (a small memory leak results because we don't 
+   deallocate the old shared version).  */
 
 extern t_commrec *init_cr_nopar(void);
 /* Returns t_commrec for non-parallel functionality */
index c4b4e783173fb4fa77245fae15e45a7cc815dcf5..13fc174dfd5583746375b7d3329cd11449998948 100644 (file)
 #endif
 
 #include <stdio.h>
+#include <time.h>
 #include "typedefs.h"
 #include "network.h"
 #include "tgroup.h"
 #include "filenm.h"
 #include "mshift.h"
 #include "force.h"
-#include "time.h"
 #include "edsam.h"
 #include "mdebin.h"
 #include "vcm.h"
 extern "C" {
 #endif
 
-#define MD_POLARISE     (1<<2)
-#define MD_IONIZE       (1<<3)
-#define MD_RERUN        (1<<4)
-#define MD_RERUN_VSITE  (1<<5)
-#define MD_FFSCAN       (1<<6)
-#define MD_SEPPOT       (1<<7)
-#define MD_PARTDEC      (1<<9)
-#define MD_DDBONDCHECK  (1<<10)
-#define MD_DDBONDCOMM   (1<<11)
-#define MD_CONFOUT      (1<<12)
-#define MD_REPRODUCIBLE (1<<14)
-#define MD_READ_RNG     (1<<15)
-#define MD_APPENDFILES  (1<<16)
-#define MD_READ_EKIN    (1<<17)
-#define MD_STARTFROMCPT (1<<18)
+#define MD_POLARISE       (1<<2)
+#define MD_IONIZE         (1<<3)
+#define MD_RERUN          (1<<4)
+#define MD_RERUN_VSITE    (1<<5)
+#define MD_FFSCAN         (1<<6)
+#define MD_SEPPOT         (1<<7)
+#define MD_PARTDEC        (1<<9)
+#define MD_DDBONDCHECK    (1<<10)
+#define MD_DDBONDCOMM     (1<<11)
+#define MD_CONFOUT        (1<<12)
+#define MD_REPRODUCIBLE   (1<<13)
+#define MD_READ_RNG       (1<<14)
+#define MD_APPENDFILES    (1<<15)
+#define MD_KEEPANDNUMCPT  (1<<16)
+#define MD_READ_EKIN      (1<<17)
+#define MD_STARTFROMCPT   (1<<18)
 #define MD_RESETCOUNTERSHALFWAY (1<<19)
 
 /* Define a number of flags to better control the information
@@ -126,11 +127,12 @@ typedef struct {
 } gmx_runtime_t;
 
 typedef struct {
-  int  fp_trn;
-  int  fp_xtc;
+  t_fileio *fp_trn;
+  t_fileio *fp_xtc;
   int  xtc_prec;
   ener_file_t fp_ene;
   const char *fn_cpt;
+  bool bKeepAndNumCPT;
   int  eIntegrator;
   int  simulation_part;
   FILE *fp_dhdl;
@@ -145,6 +147,11 @@ extern gmx_large_int_t     deform_init_init_step_tpx;
 extern matrix              deform_init_box_tpx;
 #ifdef GMX_THREADS
 extern tMPI_Thread_mutex_t deform_init_box_mutex;
+
+/* The minimum number of atoms per thread. With fewer atoms than this,
+ * the number of threads will get lowered.
+ */
+#define MIN_ATOMS_PER_THREAD    90
 #endif
 
 
@@ -223,7 +230,7 @@ extern void global_stat(FILE *log,gmx_global_stat_t gs,
 /* Communicate statistics over cr->mpi_comm_mysim */
 
 extern gmx_mdoutf_t *init_mdoutf(int nfile,const t_filenm fnm[],
-                                bool bAppendFiles,
+                                int mdrun_flags,
                                 const t_commrec *cr,const t_inputrec *ir,
                                 const output_env_t oenv);
 /* Returns a pointer to a data structure with all output file pointers
@@ -306,42 +313,19 @@ typedef enum
 extern void check_nnodes_top(char *fn,t_topology *top);
 /* Reset the tpr file to work with one node if necessary */
 
-extern void init_single(FILE *log, t_inputrec *inputrec, const char *tpbfile, 
-                        gmx_mtop_t *mtop, t_state *state);
-     /*
-      * Allocates space for the topology (top), the coordinates x, the
-      * velocities v, masses mass. Reads the parameters, topology,
-      * coordinates and velocities from the file specified in tpbfile
-      */
 
 /* check the version */
 void check_ir_old_tpx_versions(t_commrec *cr,FILE *fplog,
                                t_inputrec *ir,gmx_mtop_t *mtop);
 
+/* Allocate and initialize node-local state entries. */
+void set_state_entries(t_state *state,t_inputrec *ir,int nnodes);
+
+/* Broadcast the data for a simulation, and allocate node-specific settings
+   such as rng generators. */
+extern void init_parallel(FILE *log, t_commrec *cr, t_inputrec *inputrec,
+                          gmx_mtop_t *mtop, t_state *state);
 
-extern void init_parallel(FILE *log,const char *tpxfile, t_commrec *cr,
-                         t_inputrec *inputrec,gmx_mtop_t *mtop,
-                         t_state *state, int list);
-     /*
-      * Loads the data for a simulation from the ring. Parameters, topology
-      * coordinates, velocities, and masses are initialised equal to using
-      * init_single() in the single processor version. The extra argument
-      * f_add is allocated to use for the update of the forces, the load
-      * array specifies in which part of the x and f array the subsystems
-      * of the other processors are located. Homenr0, homenr1, nparts0 and
-      * nparts1 are necessary to calculate the non bonded interaction using
-      * the symmetry and thus calculating every force only once. List is a 
-      * facility for logging (and debugging). One can decide to print none or a 
-      * set of * selected parameters to the file specified by log. Parameters 
-      * are printed by or-ing the corresponding items from t_listitem. A 0 
-      * (zero) specifies that nothing is to be printed on the file. The function
-      * returns the number of shifts over the ring to perform to calculate
-      * all interactions.
-      *
-      * NOTE: for threaded simulations that don't support parallel runs (at
-      * the moment that's only the LBGFS integrator), this function may
-      * cancel them and re-write the commrec.
-      */
 
 extern void do_constrain_first(FILE *log,gmx_constr_t constr,
                               t_inputrec *inputrec,t_mdatoms *md,
@@ -356,29 +340,16 @@ extern void dynamic_load_balancing(bool bVerbose,t_commrec *cr,real capacity[],
  * based on their coordinates in the "dimension" direction.
  */
                                   
-int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
-            const output_env_t oenv, bool bVerbose,bool bCompact,
-            int nstglobalcomm, ivec ddxyz,int dd_node_order,real rdd,
-             real rconstr, const char *dddlb_opt,real dlb_scale,
+int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
+             const t_filenm fnm[], const output_env_t oenv, bool bVerbose,
+             bool bCompact, int nstglobalcomm, ivec ddxyz,int dd_node_order,
+             real rdd, real rconstr, const char *dddlb_opt,real dlb_scale,
             const char *ddcsx,const char *ddcsy,const char *ddcsz,
-            int nstepout, int resetstep, int nmultisim, int repl_ex_nst,int repl_ex_seed,
-            real pforce,real cpt_period,real max_hours,
+            int nstepout, int resetstep, int nmultisim, int repl_ex_nst,
+             int repl_ex_seed, real pforce,real cpt_period,real max_hours,
             const char *deviceOptions, unsigned long Flags);
 /* Driver routine, that calls the different methods */
 
-int mdrunner_threads(int nthreads,
-                     FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
-                     const output_env_t oenv, bool bVerbose,bool bCompact,
-                     int nstglobalcomm, 
-                     ivec ddxyz,int dd_node_order,real rdd,real rconstr,
-                     const char *dddlb_opt,real dlb_scale,
-                     const char *ddcsx,const char *ddcsy,const char *ddcsz,
-                     int nstepout,int resetstep,int nmultisim, int repl_ex_nst,
-                     int repl_ex_seed, real pforce,real cpt_period,
-                     real max_hours, const char *deviceOptions, unsigned long Flags);
-/* initializes nthread threads before running mdrunner: is the preferred
-   way to start a simulation (even if nthreads=1 and no threads are started) */
-
 extern void md_print_warning(const t_commrec *cr,FILE *fplog,const char *buf);
 /* Print a warning message to stderr on the master node
  * and to fplog if fplog!=NULL.
index 14aba773eaa249a9c202d94dae5b0ea0befff9f0..24e792527f581166a55b007b157958245c31d625 100644 (file)
@@ -61,7 +61,7 @@ extern "C" {
 #endif
 
 #ifdef USE_MPE
-#include "mpe.h"
+#include <mpe.h>
      /* Define MPE logging events here */
      /* General events */
      int ev_timestep1,               ev_timestep2;
index a2a535fedd92d740a5e8d89f0ffa7c15425f3db1..45501308e99cb85de09e8d2c7d59543c8a6f3bb1 100644 (file)
@@ -68,6 +68,9 @@ gmx_ana_nbsearch_init(gmx_ana_nbsearch_t *d, t_pbc *pbc, int n, rvec x[]);
 extern int
 gmx_ana_nbsearch_pos_init(gmx_ana_nbsearch_t *d, t_pbc *pbc,
                           struct gmx_ana_pos_t *p);
+/** Sets the exclusions for the next neighborhood search. */
+extern int
+gmx_ana_nbsearch_set_excl(gmx_ana_nbsearch_t *d, int nexcl, int excl[]);
 /** Check whether a point is within a neighborhood. */
 extern bool
 gmx_ana_nbsearch_is_within(gmx_ana_nbsearch_t *d, rvec x);
@@ -82,6 +85,16 @@ gmx_ana_nbsearch_mindist(gmx_ana_nbsearch_t *d, rvec x);
 extern real
 gmx_ana_nbsearch_pos_mindist(gmx_ana_nbsearch_t *d,
                              struct gmx_ana_pos_t *p, int i);
+/** Finds the first reference position within the cutoff. */
+extern bool
+gmx_ana_nbsearch_first_within(gmx_ana_nbsearch_t *d, rvec x, int *jp);
+/** Finds the first reference position within the cutoff. */
+extern bool
+gmx_ana_nbsearch_pos_first_within(gmx_ana_nbsearch_t *d,
+                                  struct gmx_ana_pos_t *p, int i, int *jp);
+/** Finds the next reference position within the cutoff. */
+extern bool
+gmx_ana_nbsearch_next_within(gmx_ana_nbsearch_t *d, int *jp);
 
 #ifdef __cplusplus
 }
index a547ef9de77b16ccbbaf2b096bfc1d8a1461a862..df272599a472c6aef84b78fb46decd7d89188cfa 100644 (file)
 
 #include <stdio.h>
 
-#ifdef GMX_LIB_MPI
-#include <mpi.h>
-#endif
-#ifdef GMX_THREADS
-#include "tmpi.h"
-#endif
-
+#include "types/simple.h"
+#include "types/commrec.h"
 #include "typedefs.h"
 #include "main.h"
 #include "gmx_fatal.h"
@@ -98,13 +93,11 @@ extern void gmx_sumf(int nr,float r[],const t_commrec *cr);
 extern void gmx_sumd(int nr,double r[],const t_commrec *cr);
 /* Calculate the global sum of an array of doubles */
 
-#ifdef GMX_MPI
 extern void gmx_sumf_comm(int nr,float r[],MPI_Comm mpi_comm);
 /* Calculate the global sum of an array of floats */
 
 extern void gmx_sumd_comm(int nr,double r[],MPI_Comm mpi_comm);
 /* Calculate the global sum of an array of doubles */
-#endif
 
 extern void gmx_sumi_sim(int nr,int r[],const gmx_multisim_t *ms);
 /* Calculate the sum over the simulations of an array of ints */
index 09d6f4d6497a3b2eef44dddb75275dc380fb00a3..334c65fda251b9d96cd30d2b1abe99581aecc7c2 100644 (file)
@@ -66,7 +66,7 @@ typedef struct {
   t_dih     *dih;
   int       npp;
   t_phipsi  *pp;
-  int       traj;
+  t_trxstatus *traj;
   int       natoms;
   int       amin,amax;
   real      t;
index 617575a772d6950f2f5818c7cfe7aedeec7231ab..e2f87cd9f49b27a978aef7aba46b1f0eecff6467 100644 (file)
@@ -75,7 +75,7 @@ struct output_env
     int  verbosity; /* The level of verbosity for this program */
     int debug_level; /* the debug level */
 
-    const char *program_name; /* the program name */
+    char *program_name; /* the program name */
     char *cmd_line; /* the re-assembled command line */
 };
 
@@ -92,6 +92,9 @@ void output_env_init_default(output_env_t oenv);
 /* initialize an output_env structure, with reasonable default settings.
     (the time unit is set to time_ps, which means no conversion).  */
 
+extern void output_env_done(output_env_t oenv);
+/* free memory allocated for an output_env structure. */
+
 
 extern int output_env_get_verbosity(const output_env_t oenv);
 /* return the verbosity */
index c05431139eaae6049952204c4597bbc5d17725b9..98c10c69b2b542a150ce6c81a434f97ca6d4fbfe 100644 (file)
@@ -69,11 +69,13 @@ extern void set_pdb_wide_format(bool bSet);
 /* If bSet, use wider format for occupancy and bfactor */
 
 extern void pdb_use_ter(bool bSet);
-/* set read_pdbatoms to read upto 'TER' or 'ENDMDL' (default, bSet=FALSE) */
+/* set read_pdbatoms to read upto 'TER' or 'ENDMDL' (default, bSet=FALSE).
+   This function is fundamentally broken as far as thread-safety is concerned.*/
 
 extern void gmx_write_pdb_box(FILE *out,int ePBC,matrix box);
 /* write the box in the CRYST1 record,
  * with ePBC=-1 the pbc is guessed from the box
+ * This function is fundamentally broken as far as thread-safety is concerned.
  */
 
 extern void write_pdbfile_indexed(FILE *out,const char *title,t_atoms *atoms,
index 83e88e8771c0dea6aaf37035de5b55b1d3b28e30..4aaa12185cc7480654bd8304b906b2785b59c2b4 100644 (file)
@@ -43,7 +43,6 @@
 #include <stdio.h>
 #include "typedefs.h"
 #include "gmxcomplex.h"
-#include "fftgrid.h"
 #include "gmx_wallcycle.h"
 
 #ifdef __cplusplus
@@ -54,14 +53,8 @@ typedef real *splinevec[DIM];
 
 enum { GMX_SUM_QGRID_FORWARD, GMX_SUM_QGRID_BACKWARD };
 
-extern int pme_inconvenient_nnodes(int nkx,int nky,int nnodes);
-/* Checks for FFT + solve_pme load imbalance, returns:
- * 0 when no or negligible load imbalance is expected
- * 1 when a slight load imbalance is expected
- * 2 when using less PME nodes is expected to be faster
- */
-
-extern int gmx_pme_init(gmx_pme_t *pmedata,t_commrec *cr,int nnodes_major,
+extern int gmx_pme_init(gmx_pme_t *pmedata,t_commrec *cr,
+                       int nnodes_major,int nnodes_minor,
                        t_inputrec *ir,int homenr,
                        bool bFreeEnergy, bool bReproducible);
                        
@@ -73,7 +66,8 @@ extern int gmx_pme_destroy(FILE *log,gmx_pme_t *pmedata);
 #define GMX_PME_SPREAD_Q      (1<<0)
 #define GMX_PME_SOLVE         (1<<1)
 #define GMX_PME_CALC_F        (1<<2)
-#define GMX_PME_DO_ALL  (GMX_PME_SPREAD_Q | GMX_PME_SOLVE | GMX_PME_CALC_F)
+#define GMX_PME_CALC_ENER_VIR (1<<3)
+#define GMX_PME_DO_ALL_F  (GMX_PME_SPREAD_Q | GMX_PME_SOLVE | GMX_PME_CALC_F)
 
 extern int gmx_pme_do(gmx_pme_t pme,
                      int start,       int homenr,
@@ -98,9 +92,6 @@ extern int gmx_pmeonly(gmx_pme_t pme,
 /* Called on the nodes that do PME exclusively (as slaves) 
  */
 
-extern void gmx_sum_qgrid(gmx_pme_t pme,t_commrec *cr,t_fftgrid *grid,
-                         int direction);
-
 extern void gmx_pme_calc_energy(gmx_pme_t pme,int n,rvec *x,real *q,real *V);
 /* Calculate the PME grid energy V for n charges with a potential
  * in the pme struct determined before with a call to gmx_pme_do
@@ -123,7 +114,9 @@ extern void gmx_pme_send_q(t_commrec *cr,
 /* Send the charges and maxshift to out PME-only node. */
 
 extern void gmx_pme_send_x(t_commrec *cr, matrix box, rvec *x,
-                          bool bFreeEnergy, real lambda, gmx_large_int_t step);
+                          bool bFreeEnergy, real lambda,
+                          bool bEnerVir,
+                          gmx_large_int_t step);
 /* Send the coordinates to our PME-only node and request a PME calculation */
 
 extern void gmx_pme_finish(t_commrec *cr);
@@ -140,6 +133,7 @@ extern int gmx_pme_recv_q_x(gmx_pme_pp_t pme_pp,
                            matrix box, rvec **x,rvec **f,
                            int *maxshift0,int *maxshift1,
                            bool *bFreeEnergy,real *lambda,
+                           bool *bEnerVir,
                            gmx_large_int_t *step);
 /* Receive charges and/or coordinates from the PP-only nodes.
  * Returns the number of atoms, or -1 when the run is finished.
@@ -148,9 +142,7 @@ extern int gmx_pme_recv_q_x(gmx_pme_pp_t pme_pp,
 extern void gmx_pme_send_force_vir_ener(gmx_pme_pp_t pme_pp,
                                        rvec *f, matrix vir,
                                        real energy, real dvdlambda,
-                                       float cycles,
-                                       bool bGotStopNextStepSignal,
-                                       bool bGotStopNextNbrStepSignal);
+                                       float cycles);
 /* Send the PME mesh force, virial and energy to the PP-only nodes */
 
 #ifdef __cplusplus
index c5fd18ad5e131509053436e14ab330a68d7bee0b..4797bf3bb3a0794e7eae1d9d4133c9b191c1549c 100644 (file)
@@ -118,7 +118,7 @@ typedef enum
     POS_RES,     /**< Calculate center for each residue. */
     POS_MOL,     /**< Calculate center for each molecule. */
     POS_ALL,     /**< Calculate center for the whole group. */
-    POS_ALL_PBC, /**< Calculate center for the whole group with PBC. */
+    POS_ALL_PBC  /**< Calculate center for the whole group with PBC. */
 } e_poscalc_t;
 
 /** Collection of \c gmx_ana_poscalc_t structures for the same topology. */
index f27e1ec0cddf3b1a510d547710a7852c5181b65e..f2a4cee64fa46e8a2547b891dc9193752f5c4fae 100644 (file)
@@ -43,7 +43,6 @@
 #include <stdio.h>
 #include "typedefs.h"
 #include "gmxcomplex.h"
-#include "fftgrid.h"
 
 #ifdef __cplusplus
 extern "C" {
index 51d74bf165bb50f5cc56157f5859c9e1e6d311b7..2e130168f500c25faeec7ec836bf2223636e2573 100644 (file)
@@ -54,6 +54,8 @@ typedef struct {
   bool bSet; /* whether it it has been read out */
   char *name; /* name of the parameter */
   char *value; /* parameter value string */
+  int inp_count; /* number of einps read. Only valid for the first item
+                                          in the inpfile list. */
 } t_inpfile;
 /* entry in input files (like .mdp files). 
  Initally read in with read_inpfile, then filled in with missing values
index 5ed2372fd02623574dfdf559eefd32d14740cb62..f4e547e2ff0a8762cd09487187cfd1e7e6d0db47 100644 (file)
@@ -48,7 +48,7 @@ extern "C" {
 extern t_restp *search_rtp(const char *key,int nrtp,t_restp rtp[]);
 /* Search for an entry in the rtp database */
 
-extern gpp_atomtype_t read_atype(const char *ffdir,t_symtab *tab);
+extern gpp_atomtype_t read_atype(const char *ffdir,bool bAddCWD,t_symtab *tab);
 /* read atom type database(s) */
 
 extern void read_resall(char *resdb, int *nrtp,t_restp **rtp, 
index 576fd13dc928a63fd3f8102be213338911ce473e..006f2c01b69cf70ca3394ab44591c4d2018540a9 100644 (file)
 extern "C" {
 #endif
 
-extern void rm_pbc(t_idef *idef,int ePBC,int natoms,matrix box,rvec x[],
-                  rvec x_s[]);
-/* Correct coordinates for atoms within every molecule for the periodic
- * boundary conditions such that every molecule is whole.
- * (note that mdrun only writes whole molecules)
- * x are the input coordinates, x_s the shifted coordinates where
- * the molecules are whole. x and x_s can be the same array.
- * natoms is the size of x and x_s and can be smaller than the number 
- * of atoms in idef, but should only contain complete molecules.
- * When ePBC=-1, the type of pbc is guessed from the box matrix.
- */
-
-extern void rm_gropbc(t_atoms *atoms,rvec x[],matrix box);
-/* Simple routine for use in analysis tools that just have a pdb or 
- * similar file.
- */
+  typedef struct gmx_rmpbc *gmx_rmpbc_t;
+  
+  extern gmx_rmpbc_t gmx_rmpbc_init(t_idef *idef,int ePBC,int natoms,
+                                   matrix box);
+  
+  extern void gmx_rmpbc_done(gmx_rmpbc_t gpbc);
 
+  extern void gmx_rmpbc(gmx_rmpbc_t gpbc,matrix box,rvec x[],rvec x_s[]);
+  /* Correct coordinates for atoms within every molecule for the periodic
+   * boundary conditions such that every molecule is whole.
+   * (note that mdrun only writes whole molecules)
+   * x are the input coordinates, x_s the shifted coordinates where
+   * the molecules are whole. x and x_s can be the same array.
+   * natoms is the size of x and x_s and can be smaller than the number 
+   * of atoms in idef, but should only contain complete molecules.
+   * When ePBC=-1, the type of pbc is guessed from the box matrix.
+   */
+  
+  /*extern void rm_pbc(t_idef *idef,int ePBC,int natoms,
+    matrix box,rvec x[],rvec x_s[]);*/
+  /* Convenience function that still holds a static variable. */
+  
+  extern void rm_gropbc(t_atoms *atoms,rvec x[],matrix box);
+  /* Simple routine for use in analysis tools that just have a pdb or 
+   * similar file.
+   */
+  
 #ifdef __cplusplus
 }
 #endif
index dad3adda21d37c5fb5e2b332a3fcffc00c37f440..633858adfb16ce3f587f519e66256da549150660 100644 (file)
@@ -55,7 +55,7 @@ struct gmx_ana_poscalc_coll_t;
 typedef enum
 {
     CFRAC_NONE,         /**< No covered fraction (everything covered). */
-    CFRAC_SOLIDANGLE,   /**< Fraction of a solid (3D) angle covered. */
+    CFRAC_SOLIDANGLE    /**< Fraction of a solid (3D) angle covered. */
 } e_coverfrac_t;
 
 /*! \brief
@@ -172,6 +172,9 @@ gmx_ana_selcollection_parse_str(gmx_ana_selcollection_t *sc, const char *str,
                                 gmx_ana_indexgrps_t *grps);
 
 /* In compiler.c */
+/** Set debugging flag for selection compilation. */
+extern void
+gmx_ana_selcollection_set_compile_debug(gmx_ana_selcollection_t *sc, bool bDebug);
 /** Prepares the selections for evaluation and performs some optimizations. */
 extern int
 gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc);
index 0fdcbf421452456a63f77d5a597c6b03bd7f66e4..fdd22412cd99f6539fc28f3b3122960812a5b80f 100644 (file)
  *    number of values.
  *    The number of values is determined based on the values given by the user
  *    to the method parameters (see \ref selmethods_params).
- *
+ *  .
+ * If either of these flags is specified (and the method type is not
+ * \ref GROUP_VALUE), the group passed to the evaluation callback should not
+ * be used as it can be NULL.
  * Currently, the above flags only work (have been tested) for \ref POS_VALUE
  * methods.
  *
  * In general, any of the callbacks can be NULL, but the presence of
  * parameters or other callbacks imposes some restrictions:
  *  - sel_datafunc() should be provided if the method takes parameters.
- *  - sel_initfunc() and sel_freefunc() should be provided if the method takes
+ *  - sel_initfunc() should be provided if the method takes
  *    any parameters with the \ref SPAR_VARNUM or \ref SPAR_ATOMVAL flags,
  *    except if those parameters have a \ref POS_VALUE.
  *  - sel_outinitfunc() should be provided for \ref POS_VALUE methods
  *  - sel_freefunc() should be provided if sel_datafunc() and/or
  *    sel_initfunc() allocate any dynamic memory in addition to the data
  *    structure itself.
- *  - sel_framefunc() and sel_updatefunc_pos() only make sense for methods with
- *    \ref SMETH_DYNAMIC set.
+ *  - sel_updatefunc_pos() only makes sense for methods with \ref SMETH_DYNAMIC
+ *    set.
  *  - At least one update function should be provided unless the method type is
  *    \ref NO_VALUE.
  *
@@ -408,8 +411,8 @@ typedef void  (*sel_posfunc)(struct gmx_ana_poscalc_coll_t *pcc, void *data);
  * If a parameter had the \ref SPAR_VARNUM or \ref SPAR_ATOMVAL flag (and
  * is not \ref POS_VALUE), a pointer to the memory allocated for the values is
  * found in \c gmx_ana_selparam_t::val.
- * The pointer should be stored by this function, otherwise the memory
- * (and the values) are lost.
+ * The pointer should be stored by this function, otherwise the values
+ * cannot be accessed.
  * For \ref SPAR_VARNUM parameters, the number of values can be accessed
  * through \c gmx_ana_selparam_t::val. For parameters with \ref SPAR_DYNAMIC,
  * the number is the maximum number of values (the actual number can be
@@ -474,8 +477,8 @@ typedef int   (*sel_outinitfunc)(t_topology *top, gmx_ana_selvalue_t *out,
  * The data structure itself should not be freed; this is handled automatically.
  * If there is no dynamically allocated data within the structure,
  * this function is not needed.
- * The value pointers for \ref SPAR_VARNUM and \ref SPAR_ATOMVAL parameters
- * stored in sel_initfunc() should also be freed.
+ * Any memory pointers received as values of parameters are managed externally,
+ * and should not be freed.
  * Pointers set as the value pointer of \ref SPAR_ENUMVAL parameters should not
  * be freed.
  */
@@ -500,6 +503,8 @@ typedef void  (*sel_freefunc)(void *data);
  * It is ensured that this function will be called before
  * \p sel_updatefunc_* for each frame, and that it will be called at most
  * once for each frame.
+ * For static methods, it is called once, with \p fr and \p pbc set to
+ * NULL.
  */
 typedef int   (*sel_framefunc)(t_topology *top, t_trxframe *fr, t_pbc *pbc,
                                void *data);
index 380adb34f3137a887b858fbd1a4d2a42012d707e..ebea30a2467287002de3d1b7948803bddf8e2fb0 100644 (file)
@@ -37,7 +37,7 @@
 #ifndef SELVALUE_H
 #define SELVALUE_H
 
-#include <types/simple.h>
+#include "types/simple.h"
 
 #ifdef __cplusplus
 extern "C"
@@ -53,7 +53,7 @@ typedef enum
     REAL_VALUE,         /**< One or more real values. */
     STR_VALUE,          /**< One or more string values. */
     POS_VALUE,          /**< One or more position values. */
-    GROUP_VALUE,        /**< One group of atoms. */
+    GROUP_VALUE         /**< One group of atoms. */
 } e_selvalue_t;
 
 /*! \brief
diff --git a/include/sfactor.h b/include/sfactor.h
new file mode 100644 (file)
index 0000000..ea2e529
--- /dev/null
@@ -0,0 +1,100 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gromacs Runs On Most of All Computer Systems
+ */
+
+#ifndef _sfactor_h
+#define _sfactor_h
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "index.h"
+#include "types/simple.h"
+#include "gmxcomplex.h"
+#include "oenv.h"
+
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+typedef struct gmx_structurefactors gmx_structurefactors_t;
+
+typedef struct structure_factor structure_factor_t;
+
+typedef struct reduced_atom reduced_atom_t;
+
+extern int * create_indexed_atom_type (reduced_atom_t * atm, int size);
+
+extern void compute_structure_factor (structure_factor_t * sft, matrix box,
+                              reduced_atom_t * red, int isize, real start_q,
+                              real end_q, int group,real **sf_table);
+
+extern gmx_structurefactors_t *gmx_structurefactors_init(const char *datfn);
+
+extern void gmx_structurefactors_done(gmx_structurefactors_t *gsf);
+
+extern int gmx_structurefactors_get_sf(gmx_structurefactors_t *gsf, int elem, real a[4], real b[4], real *c);
+
+extern real **gmx_structurefactors_table(gmx_structurefactors_t *gsf,real momentum, real ref_k,
+        real lambda, int n_angles);
+
+extern void save_data (structure_factor_t * sft, const char *file, int ngrps,
+                real start_q, real end_q, const output_env_t oenv);
+
+extern double CMSF (gmx_structurefactors_t *gsf,int type,int nh,double lambda, double sin_theta);
+
+extern int return_atom_type (const char *name,gmx_structurefactors_t *gsf);
+
+extern void rearrange_atoms (reduced_atom_t * positions, t_trxframe *fr, atom_id * index,
+                     int isize, t_topology * top, bool flag,gmx_structurefactors_t *gsf);
+
+extern int do_scattering_intensity (const char* fnTPS, const char* fnNDX,
+                             const char* fnXVG, const char *fnTRX,
+                             const char* fnDAT,
+                             real start_q,real end_q,
+                             real energy,int ng,const output_env_t oenv);
+
+extern t_complex *** rc_tensor_allocation(int x, int y, int z);
+
+extern real **compute_scattering_factor_table (gmx_structurefactors_t *gsf,structure_factor_t * sft,int *nsftable);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
\ No newline at end of file
index 350e0eb9b85aba34c5611ebb8157e8932611d79b..567def49fdfd74b94b78bd53cd3319dee8344c18 100644 (file)
 extern "C" {
 #endif
 
-/* The following two variables and the signal_handler function
- * are used from md.c and pme.c as well 
- *
- * Do not fear these global variables: they represent inherently process-global
- * information that needs to be shared across threads 
- */
+/* NOTE: the terminology is:
+   incoming signals (provided by the operating system, or transmitted from 
+   other nodes) lead to stop conditions. These stop conditions should be 
+   checked for and acted on by the outer loop of the simulation */
 
+/* the stop conditions. They are explicitly allowed to be compared against
+   each other. */
+typedef enum
+{
+    gmx_stop_cond_none=0,
+    gmx_stop_cond_next_ns, /* stop a the next neighbour searching step */
+    gmx_stop_cond_next, /* stop a the next step */
+    gmx_stop_cond_abort  /* stop now. (this should never be seen) */
+} gmx_stop_cond_t;
 
-/* we got a signal to stop in the next step: */
-extern volatile sig_atomic_t bGotStopNextStepSignal;
-/* we got a signal to stop in the next neighbour search step: */
-extern volatile sig_atomic_t bGotStopNextNSStepSignal;
+/* Our names for the stop conditions. 
+   These must match the number given in gmx_stop_cond_t.*/
+extern const char *gmx_stop_cond_name[];
 
-/* our names for the handled signals. These must match the number given
-   in signal_handler.*/
-extern const char *signal_name[];
-/* the last signal received, according to the numbering
-   we use in signal_name. Is set to -1 if no signal has (yet) 
-   been  received */
-extern volatile sig_atomic_t last_signal_number_recvd;
+/* the externally visible functions: */
 
+/* install the signal handlers that can set the stop condition. */
+void signal_handler_install(void);
 
-/* prototype for the signal handler */
-extern RETSIGTYPE signal_handler(int n);
+/* get the current stop condition */
+gmx_stop_cond_t gmx_get_stop_condition(void);
+
+/* set the stop condition upon receiving a remote one */
+void gmx_set_stop_condition(gmx_stop_cond_t recvd_stop_cond);
+
+/* get the signal name that lead to the current stop condition. */
+const char *gmx_get_signal_name(void);
+
+/* check whether we received a USR1 signal. 
+   The condition is reset once a TRUE value is returned, so this function
+   only returns TRUE once for a single signal. */
+bool gmx_got_usr_signal(void);
 
-/* install the signal handlers */
-void signal_handler_install(void);
 
 #ifdef __cplusplus
 }
index fd52bdcdd4de43b238b5b00c9b97db2a4fa07eeb..fee13481ad38daea5e22beeaf8b242c69e0fe4f0 100644 (file)
  * sfree(ptr)
  *    Frees memory referenced by ptr.
  *
+ * snew_aligned(ptr,nelem,alignment)
+ *    Allocates memory for nelem elements and returns this in ptr.
+ *    The allocated memory is initialized to zeroes.
+ *    alignment=n will constrain ptr to be n-byte aligned.
+ *    This pointer should only be freed with sfree_aligned, since
+ *    it may not be the value returned by the underlying malloc.
+ *
+ * sfree_aligned(ptr)
+ *    Frees aligned memory referenced by ptr.
+ *
  ****************************************************************************
  *
  * Functions which are used by the macro's:
  *    the sum of the previously allocated space. As mentioned with maxavail,
  *    it is important that free can undo the effect of a malloc.
  * 
+ * extern void *save_malloc_aligned(char *name,char *file,int line,size_t size,size_t alignment);
+ *    Like alloc, returns a pointer to the allocated space, uses name, file
+ *    and line to generate an error message when allocation failed.
+ *    The returned pointer will be n-byte aligned, where n=alignment.
+ *    The pointer should only be freed with a call to save_free.
+ *
+ * extern void save_free_aligned(char *name,char *file,int line, void *ptr);
+ *    Like free, uses name, file and line to generate an error message when 
+ *    the free failed. This function is intended to be called for
+ *    pointers allocated with save_malloc_aligned, and may not work
+ *    on normal pointers.
  */
 
 #ifdef __cplusplus
@@ -122,36 +143,63 @@ void save_free(const char *name,const char *file,int line, void *ptr);
 size_t maxavail(void);
 size_t memavail(void);
 
+/* Aligned-memory counterparts */
+
+void *save_calloc_aligned(const char *name,const char *file,int line,
+                         unsigned nelem,size_t elsize,size_t alignment); 
+void save_free_aligned(const char *name,const char *file,int line, void *ptr);
+
 #ifdef __cplusplus
 }
 
+/* Use of sizeof(T) in _snew() and _srenew() can cause obscure bugs if
+ * several files define distinct data structures with identical names and
+ * allocate memory for them using the macros below.
+ * For this reason, the size of an element is passed as a parameter.
+ *
+ * The C versions work fine in such cases, but when compiled with a C++
+ * compiler (and if the compiler does not inline the calls), the linker cannot
+ * tell that data structures with identical names are actually different and
+ * links calls to these template functions incorrectly, which can result in
+ * allocation of an incorrect amount of memory if the element size is computed
+ * within the function. Even with the size passed as a parameter, incorrect
+ * linkage will occur, but as the type is now only present in the cast, it
+ * should not cause problems.
+ */
 template <typename T>
-void _snew(const char *name, T *&ptr, int nelem)
+void _snew(const char *name, const char *file, int line,
+           T *&ptr, size_t nelem, size_t elsize)
 {
-    ptr = (T *)save_calloc(name, __FILE__, __LINE__, nelem, sizeof(T));
+    ptr = (T *)save_calloc(name, file, line, nelem, elsize);
 }
 template <typename T>
-void _srenew(const char *name, T *&ptr, int nelem)
+void _srenew(const char *name, const char *file, int line,
+             T *&ptr, size_t nelem, size_t elsize)
 {
-    ptr = (T *)save_realloc(name, __FILE__, __LINE__, ptr, nelem, sizeof(T));
+    ptr = (T *)save_realloc(name, file, line, ptr, nelem, elsize);
 }
 template <typename T>
-void _smalloc(const char *name, T *&ptr, size_t size)
+void _smalloc(const char *name, const char *file, int line, T *&ptr, size_t size)
 {
-    ptr = (T *)save_malloc(name, __FILE__, __LINE__, size);
+    ptr = (T *)save_malloc(name, file, line, size);
 }
 template <typename T>
-void _srealloc(const char *name, T *&ptr, size_t size)
+void _srealloc(const char *name, const char *file, int line, T *&ptr, size_t size)
 {
-    ptr = (T *)save_realloc(name, __FILE__, __LINE__, ptr, size, sizeof(char));
+    ptr = (T *)save_realloc(name, file, line, ptr, size, sizeof(char));
+}
+template <typename T>
+void _snew_aligned(const char *name, const char *file, int line,
+                  T *&ptr, size_t nelem, size_t elsize,size_t alignment)
+{
+  ptr = (T *)save_calloc_aligned(name, file, line, nelem, elsize, alignment);
 }
 
-
-
-#define snew(ptr,nelem) _snew(#ptr,(ptr),(nelem))
-#define srenew(ptr,nelem) _srenew(#ptr,(ptr),(nelem))
-#define smalloc(ptr, size) _smalloc(#ptr,(ptr),(size))
-#define srealloc(ptr, size) _srealloc(#ptr,(ptr),(size))
+#define snew(ptr,nelem) _snew(#ptr,__FILE__,__LINE__,(ptr),(nelem),sizeof(*(ptr)))
+#define srenew(ptr,nelem) _srenew(#ptr,__FILE__,__LINE__,(ptr),(nelem),sizeof(*(ptr)))
+#define smalloc(ptr, size) _smalloc(#ptr,__FILE__,__LINE__,(ptr),(size))
+#define srealloc(ptr, size) _srealloc(#ptr,__FILE__,__LINE__,(ptr),(size))
+#define snew_aligned(ptr,nelem,alignment) _snew_aligned(#ptr,__FILE__,__LINE__,(ptr),(nelem),sizeof(*(ptr)),alignment)
 
 #else
 
@@ -165,8 +213,13 @@ void _srealloc(const char *name, T *&ptr, size_t size)
                (ptr)=save_calloc(#ptr,__FILE__,__LINE__,nelem,elsize)
 #define srealloc(ptr,size) (ptr)=save_realloc(#ptr,__FILE__,__LINE__,\
                        (ptr),size,1)
+#define snew_aligned(ptr,nelem,alignment) (ptr)=save_calloc_aligned(#ptr,__FILE__,__LINE__,(nelem),sizeof(*(ptr)),alignment)
 #endif
 
 #define sfree(ptr) save_free(#ptr,__FILE__,__LINE__,(ptr))
 
+/* call this ONLY with a pointer obtained through snew_aligned or 
+   smalloc_aligned: */
+#define sfree_aligned(ptr) save_free_aligned(#ptr,__FILE__,__LINE__,(ptr))
+
 #endif /* _smalloc_h */
index 31e89a549343df3afdba13903890a1d6bc235b5f..fb78ed4c45ea6d712d52915e651970e1057f9938 100644 (file)
@@ -51,17 +51,20 @@ extern void randwater(int astart,int nwater,int nwatom,
 /* Randomize the order of nwater molecules of length nwatom, the
  * first atom of which is at astart.
  * If v is not NULL it will be shuffled along
+ * IS NOT THREAD SAFE 
  */
 
 
 extern void sortwater(int astart,int nwater,int nwatom,rvec x[],rvec v[]);
 /* Sort the order of nwater molecules of length nwatom on X coordinate
  * If v is not NULL it will be shuffled along
+ * IS NOT THREAD SAFE 
  */
 
 extern void mkcompact(int astart,int nwater,int nwatom,rvec x[],rvec v[],
                      int nnode,matrix box);
-/* Make compact subboxes */
+/* Make compact subboxes 
+ * IS NOT THREAD SAFE  */
 
 #ifdef __cplusplus
 }
diff --git a/include/statusio.h b/include/statusio.h
deleted file mode 100644 (file)
index 575a98b..0000000
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gromacs Runs On Most of All Computer Systems
- */
-
-#ifndef _statusio_h
-#define _statusio_h
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include "typedefs.h"
-#include "sheader.h"
-
-/*
- * This module handles status file io. All read and write operations from
- * and to a status file should use this functions to be independent of the
- * actual file layout (text versus binary file).
- */
-#ifdef __cplusplus
-extern "C" { 
-#endif
-
-extern size_t wr_status(FILE *fp,int step,real t,real lambda,
-                       t_inputrec *ir,rvec *box,rvec *vir,rvec *pres,
-                       int natoms,rvec *x,rvec *v,rvec *f,
-                       int nre,t_energy *e,t_topology *top);
-/*
- * Writes a complete status to the file, specified by fp. NULL pointers
- * indicate that this field should not be written. The function returns
- * the number of bytes written.
- */
-
-extern char *rd_hstatus(FILE *fp,t_statheader *sh,int *step,real *t,
-                        real *lambda,t_inputrec *ir,rvec *box,
-                       rvec *vir,rvec *pres,int *natoms,
-                        rvec *x,rvec *v,rvec *f,int *nre,t_energy *e,
-                        t_topology *top);
-/*
- * Reads a complete status from the file, specified by fp. It uses
- * the status header to find the items in the file, also the file
- * should be positioned right for reading the first item. The function
- * returns the version string from the header.
- */
-
-extern char *rd_status(FILE *fp,int *step,real *t,real *lambda,
-                       t_inputrec *ir,rvec *box,rvec *vir,rvec *pres,
-                      int *natoms,rvec *x,
-                       rvec *v,rvec *f,int *nre,t_energy *e,
-                       t_topology *top);
-/*
- * Reads a complete status from the file, specified by fp. First it
- * reads the header and then invokes rd_hstatus() to read the rest
- * of the status. It returns the version returned from rd_hstatus().
- */
-
-extern void write_status(char *fn,int step,real t,real lambda,t_inputrec *ir,
-                         rvec *box,rvec *vir,rvec *pres,
-                        int natoms,rvec *x,rvec *v,rvec *f,
-                         int nre,t_energy *e,t_topology *top);
-/*
- * Writes a complete status to the file, specified by fn. NULL pointers
- * indicate that this field should not be written.
- */
-
-extern char *read_status(char *fn,int *step,real *t,real *lambda,
-                         t_inputrec *ir,rvec *box,rvec *vir,rvec *pres,
-                        int *natoms,rvec *x,
-                         rvec *v,rvec *f,int *nre,t_energy *e,
-                         t_topology *top);
-/*
- * Reads a complete status from the file, specified by fn. It returns
- * the version returned from rd_hstatus().
- */
-
-extern void read_status_header(char *fn,t_statheader *header);
-/*
- * Reads a (status) header from the file, specified by fn. If
- * available, it returns the version string from the file, else
- * it returns a version string from the statusio module.
- */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _statusio_h */
index 44344c3a2a680526d40bd5f34726c42ef42918d2..abae7ce538a571a66f8e7f965ee1f71b2ee32364 100644 (file)
@@ -48,6 +48,7 @@
 #include "wman.h"
 #include "pdbio.h"
 #include "oenv.h"
+#include "gmxfio.h"
 
 
 #ifdef __cplusplus
@@ -71,10 +72,15 @@ extern real rTimeValue(int tcontrol);
 extern void setTimeValue(int tcontrol,real value);
 
 /* End trajectory time control */
+
+/* a dedicated status type contains fp, etc. */
+typedef struct t_trxstatus t_trxstatus;
   
-typedef int t_first_x(int *status,const char *fn,real *t,rvec **x,matrix box);
+typedef int t_first_x(t_trxstatus **status,const char *fn,real *t,rvec **x,
+                      matrix box);
 
-typedef bool t_next_x(int status,real *t,int natoms,rvec x[],matrix box);
+typedef bool t_next_x(t_trxstatus *status,real *t,int natoms,rvec x[],
+                      matrix box);
 
 /* I/O function types */
 
@@ -116,14 +122,14 @@ extern void clear_trxframe(t_trxframe *fr,bool bFirst);
 extern void set_trxframe_ePBC(t_trxframe *fr,int ePBC);
 /* Set the type of periodic boundary conditions, ePBC=-1 is not set */
 
-extern int nframes_read(void);
+extern int nframes_read(t_trxstatus *status);
 /* Returns the number of frames read from the trajectory */
 
-int write_trxframe_indexed(int status,t_trxframe *fr,int nind,atom_id *ind,
-                           gmx_conect gc);
+int write_trxframe_indexed(t_trxstatus *status,t_trxframe *fr,int nind,
+                           atom_id *ind, gmx_conect gc);
 /* Write an indexed frame to a TRX file, see write_trxframe. gc may be NULL */
 
-int write_trxframe(int status,t_trxframe *fr,gmx_conect gc);
+int write_trxframe(t_trxstatus *status,t_trxframe *fr,gmx_conect gc);
 /* Write a frame to a TRX file. 
  * Only entries for which the boolean is TRUE will be written,
  * except for step, time, lambda and/or box, which may not be
@@ -133,7 +139,7 @@ int write_trxframe(int status,t_trxframe *fr,gmx_conect gc);
  * gc is important for pdb file writing only and may be NULL.
  */
 
-int write_trx(int status,int nind,atom_id *ind,t_atoms *atoms,
+int write_trx(t_trxstatus *status,int nind,atom_id *ind,t_atoms *atoms,
               int step,real time,matrix box,rvec x[],rvec *v,
               gmx_conect gc);
 /* Write an indexed frame to a TRX file.
@@ -141,13 +147,17 @@ int write_trx(int status,int nind,atom_id *ind,t_atoms *atoms,
  * atoms can be NULL for file types which don't need atom names.
  */ 
 
-void close_trx(int status);
+void close_trx(t_trxstatus *status);
 /* Close trj file as opened with read_first_x, read_frist_frame
  * or open_trx. Identical to close_trj.
  */
 
-int open_trx(const char *outfile,const char *filemode);
-/* Open a TRX file and return the file number */
+t_trxstatus *open_trx(const char *outfile,const char *filemode);
+/* Open a TRX file and return an allocated status pointer */
+
+/* get a fileio from a trxstatus */
+t_fileio *trx_get_fileio(t_trxstatus *status);
+
 
 extern bool bRmod_fd(double a, double b, double c,bool bDouble);
 /* Returns TRUE when (a - b) MOD c = 0, using a margin which is slightly
@@ -201,8 +211,8 @@ extern int check_times(real t);
 #define DATA_NOT_OK   (1<<1)
 #define FRAME_NOT_OK  (HEADER_NOT_OK | DATA_NOT_OK)
 
-extern int read_first_frame(const output_env_t oenv,int *status,const char *fn,
-                            t_trxframe *fr,int flags);
+extern int read_first_frame(const output_env_t oenv,t_trxstatus **status,
+                            const char *fn, t_trxframe *fr,int flags);
   /* Read the first frame which is in accordance with flags, which are
    * defined further up in this file. 
    * Returns natoms when succeeded, 0 otherwise.
@@ -211,32 +221,33 @@ extern int read_first_frame(const output_env_t oenv,int *status,const char *fn,
    * Returns TRUE when succeeded, FALSE otherwise.
    */
 
-extern bool read_next_frame(const output_env_t oenv,int status,t_trxframe *fr);
+extern bool read_next_frame(const output_env_t oenv,t_trxstatus *status,
+                            t_trxframe *fr);
   /* Reads the next frame which is in accordance with fr->flags.
    * Returns TRUE when succeeded, FALSE otherwise.
    */
 
-extern int read_first_x(const output_env_t oenv,int *status,const char *fn,
-                        real *t,rvec **x,matrix box);
+extern int read_first_x(const output_env_t oenv,t_trxstatus **status,
+                        const char *fn, real *t,rvec **x,matrix box);
 /* These routines read first coordinates and box, and allocates 
  * memory for the coordinates, for a trajectory file.
  * The routine returns the number of atoms, or 0 when something is wrong.
  * The integer in status should be passed to calls of read_next_x
  */
 
-extern bool read_next_x(const output_env_t oenv,int status,real *t,int natoms,
-                        rvec x[],matrix box);
+extern bool read_next_x(const output_env_t oenv,t_trxstatus *status,real *t,
+                        int natoms, rvec x[],matrix box);
 /* Read coordinates and box from a trajectory file. Return TRUE when all well,
  * or FALSE when end of file (or last frame requested by user).
  * status is the integer set in read_first_x.
  */
 
-extern void close_trj(int status);
+extern void close_trj(t_trxstatus *status);
 /* Close trj file as opened with read_first_x, read_frist_frame
  * or open_trx. Identical to close_trx.
  */
 
-extern void rewind_trj(int status);
+extern void rewind_trj(t_trxstatus *status);
 /* Rewind trj file as opened with read_first_x */
 
 extern t_topology *read_top(const char *fn,int *ePBC);
index e02c98a42224bd0ff692992423ce5be384f69b4a..017afccc178900db0a872a057ddcc1d73d31dcb6 100644 (file)
@@ -8,8 +8,8 @@ SUBDIRS = . atomic
 pkgincludethread_mpidir = ${pkgincludedir}/thread_mpi
 
 pkgincludethread_mpi_HEADERS = \
-       atomic.h       list.h         nothreads.h    threads.h      \
-       winthreads.h   collective.h   mpi_bindings.h pthreads.h     \
-       tmpi.h
-       
+       atomic.h       hwinfo.h       nothreads.h    wait.h         \
+       barrier.h      list.h         pthreads.h     winthreads.h   \
+       collective.h   lock.h         threads.h      \
+       event.h        mpi_bindings.h tmpi.h
 
index 77b9eb42ccc526e2549ce0ba9ebfe6da01ab095b..c3e80730fa9ef5940d33d9ee977d916d5ca8e19d 100644 (file)
@@ -566,7 +566,7 @@ void tMPI_Spinlock_unlock( tMPI_Spinlock_t &x);
  *
  *  \return 1 if the spinlock is locked, 0 otherwise.
  */
-static inline int tMPI_Spinlock_islocked(tMPI_Spinlock_t *x)
+static inline int tMPI_Spinlock_islocked(const tMPI_Spinlock_t *x)
 {
     int rc;
     
@@ -645,113 +645,8 @@ static inline void *tMPI_Atomic_ptr_swap(tMPI_Atomic_ptr_t *a, void *b)
 
 #endif
 
-
-#if 0
-/** Spinlock-based barrier type
- *
- *  This barrier has the same functionality as the standard
- *  tMPI_Thread_barrier_t, but since it is based on spinlocks
- *  it provides faster synchronization at the cost of busy-waiting.
- *
- *  Variables of this type should be initialized by calling
- *  tMPI_Spinlock_barrier_init() to set the number of threads
- *  that should be synchronized.
- * 
- * \see
- * - tMPI_Spinlock_barrier_init
- * - tMPI_Spinlock_barrier_wait
- */
-typedef struct tMPI_Spinlock_barrier
-{
-        tMPI_Atomic_t      count;     /*!< Number of threads remaining     */
-        int               threshold; /*!< Total number of threads         */
-        volatile int      cycle;     /*!< Current cycle (alternating 0/1) */
-}
-tMPI_Spinlock_barrier_t;
-
-
-
-/** Initialize spinlock-based barrier
- *
- *  \param barrier  Pointer to _spinlock_ barrier. Note that this is not
- *                  the same datatype as the full, thread based, barrier.
- *  \param count    Number of threads to synchronize. All threads
- *                  will be released after \a count calls to 
- *                  tMPI_Spinlock_barrier_wait().  
- */
-static inline void tMPI_Spinlock_barrier_init(tMPI_Spinlock_barrier_t *barrier,
-                                              int count)
-{
-    barrier->threshold = count;
-    barrier->cycle     = 0;
-    tMPI_Atomic_set(&(barrier->count),count);
-}
-
-
-
-
-/** Perform busy-waiting barrier synchronization
-*
-*  This routine blocks until it has been called N times,
-*  where N is the count value the barrier was initialized with.
-*  After N total calls all threads return. The barrier automatically
-*  cycles, and thus requires another N calls to unblock another time.
-*
-*  Note that spinlock-based barriers are completely different from
-*  standard ones (using mutexes and condition variables), only the 
-*  functionality and names are similar.
-*
-*  \param barrier  Pointer to previously create barrier.
-*
-*  \return The last thread returns -1, all the others 0.
-*/
-static inline int tMPI_Spinlock_barrier_wait(tMPI_Spinlock_barrier_t *barrier)
-{
-    int    cycle;
-    int    status;
-    /*int    i;*/
-
-    /* We don't need to lock or use atomic ops here, since the cycle index 
-     * cannot change until after the last thread has performed the check
-     * further down. Further, they cannot reach this point in the next 
-     * barrier iteration until all of them have been released, and that 
-     * happens after the cycle value has been updated.
-     *
-     * No synchronization == fast synchronization.
-     */
-    cycle = barrier->cycle;
-
-    /* Decrement the count atomically and check if it is zero.
-     * This will only be true for the last thread calling us.
-     */
-    if( tMPI_Atomic_add_return( &(barrier->count), -1 ) <= 0)
-    { 
-        tMPI_Atomic_set(&(barrier->count), barrier->threshold);
-        barrier->cycle = !barrier->cycle;
-
-        status = -1;
-    }
-    else
-    {
-        /* Wait until the last thread changes the cycle index.
-         * We are both using a memory barrier, and explicit
-         * volatile pointer cast to make sure the compiler
-         * doesn't try to be smart and cache the contents.
-         */
-        do
-        { 
-            tMPI_Atomic_memory_barrier();
-        } 
-        while( *(volatile int *)(&(barrier->cycle)) == cycle);
-
-        status = 0;
-    }
-    return status;
-}
-#endif
-
-
+/* this allows us to use the inline keyword without breaking support for 
+   some compilers that don't support it: */
 #ifdef inline_defined_in_atomic
 #undef inline
 #endif
index cc3e085b90dc8d057bae833b8ae28f7a5429e58a..c860d84a69497eb36d7409f4e7042691f8ee0b46 100644 (file)
@@ -268,6 +268,7 @@ static inline void tMPI_Spinlock_wait(tMPI_Spinlock_t *x)
                          "\tpause\n"              /* otherwise: small pause
                                                      as recommended by Intel */
                          "\tjmp 1b\n"             /* and jump back */  
+                         "2:\n"
                          : "=m"(x->lock)         /* input & output var */
                          : 
                          : "memory"/* we changed memory */
index 77af73a24ee1f3585f9f9145461c382358fb5772..8ed154e395b3c02678f85763013e465d31cf780e 100644 (file)
@@ -41,7 +41,14 @@ files.
  * particular when it comes to clobbered variables. Since this implementation
  * _could_ be buggy, we have separated it from the known-to-be-working gcc
  * one above.
+ *
+ * For now, we just disable the inline keyword if we're compiling C code:
  */
+#ifndef __cplusplus
+#define inline_defined_in_atomic 1
+#define inline
+#endif
+
 
 #define tMPI_Atomic_memory_barrier()  { __asm__ __volatile__("\t eieio\n"\
                                                              : : :"memory" ); }
index 3e278ae60ca3c669b8059e67facc611d184ee457..f2215106000af44c7bbcb7b48b3bf70cfe0dd05c 100644 (file)
@@ -38,6 +38,8 @@ files.
 #ifndef _TMPI_BARRIER_H_
 #define _TMPI_BARRIER_H_
 
+#include "wait.h"
+
 /** Fast (possibly busy-wait-based) barrier type
  *
  *  This barrier has the same functionality as the standard
@@ -48,14 +50,23 @@ files.
  *  barrier for when waits are expected to be reasonably short.
  *
  *  Variables of this type should be initialized by calling
- *  tMPI_Spinlock_barrier_init() to set the number of threads
+ *  tMPI_Barrier_init() to set the number of threads
  *  that should be synchronized.
  * 
  * \see
- * - tMPI_Spinlock_barrier_init
- * - tMPI_Spinlock_barrier_wait
+ * - tMPI_Barrier_init
+ * - tMPI_Barrier_wait
  */
-typedef struct tMPI_Spinlock_barrier tMPI_Spinlock_barrier_t;
+typedef struct tMPI_Barrier_t tMPI_Barrier_t;
+struct tMPI_Barrier_t
+{
+    tMPI_Atomic_t     count;     /*!< Number of threads remaining     */
+    int               threshold; /*!< Total number of threads         */
+    volatile int      cycle;     /*!< Current cycle (alternating 0/1) */
+    TMPI_YIELD_WAIT_DATA
+};
+
+
 
 /** Initialize barrier
  *
@@ -63,9 +74,9 @@ typedef struct tMPI_Spinlock_barrier tMPI_Spinlock_barrier_t;
  *                  the same datatype as the full, thread based, barrier.
  *  \param count    Number of threads to synchronize. All threads
  *                  will be released after \a count calls to 
- *                  tMPI_Spinlock_barrier_wait().  
+ *                  tMPI_Barrier_wait().  
  */
-void tMPI_Spinlock_barrier_init(tMPI_Spinlock_barrier_t *barrier, int count);
+void tMPI_Barrier_init(tMPI_Barrier_t *barrier, int count);
 
 
 /** Perform yielding, busy-waiting barrier synchronization
@@ -79,7 +90,7 @@ void tMPI_Spinlock_barrier_init(tMPI_Spinlock_barrier_t *barrier, int count);
   *
   *  \return The last thread returns -1, all the others 0.
   */
-int tMPI_Spinlock_barrier_wait(tMPI_Spinlock_barrier_t *barrier);
+int tMPI_Barrier_wait(tMPI_Barrier_t *barrier);
 
 
 #ifdef DOXYGEN
@@ -92,9 +103,9 @@ int tMPI_Spinlock_barrier_wait(tMPI_Spinlock_barrier_t *barrier);
   *
   *  \return the number of threads to synchronize
   */
-int tMPI_Spinlock_barrier_N(tMPI_Spinlock_barrier_t *barrier);
+int tMPI_Barrier_N(tMPI_Barrier_t *barrier);
 #else
-#define tMPI_Spinlock_barrier_N(barrier)  ((barrier)->threshold)
+#define tMPI_Barrier_N(barrier)  ((barrier)->threshold)
 #endif
 
 #endif
index 58795c2fde61e606c67e98bc06cc79e309be250e..ec13f76c2ae5b5a69b6f053ab4ae09fa3369785a 100644 (file)
@@ -104,7 +104,7 @@ void* tMPI_Shmalloc(tMPI_Comm comm, size_t size);
 
 
 
-#include "thread_mpi/atomic.h" 
+#include "atomic.h" 
 
 typedef struct
 {
index a72ae6d0502016158c5afca51eb1db80438bca04..fb8a136cca32b384c67f73c65e999c2e822f10e2 100644 (file)
@@ -38,6 +38,8 @@ files.
 #ifndef _TMPI_EVENT_H_
 #define _TMPI_EVENT_H_
 
+#include "wait.h"
+
 /*! \file
 
   \brief Event notification wait and signaling functions.
@@ -59,7 +61,14 @@ files.
    
    This structure allows notification of a single thread by any number of 
    threads*/
-typedef struct tMPI_Event tMPI_Event;
+typedef struct tMPI_Event_t tMPI_Event;
+struct tMPI_Event_t
+{
+    tMPI_Atomic_t sync; /* the event sync counter */
+    int last_sync; /* the last sync event looked at */
+    TMPI_YIELD_WAIT_DATA   /* data associated with yielding */
+};
+
 
 
 /*! \brief Initialize the event object.
index 7028b4fc712317e16b1ba4e9023a4cfefed1d2cb..779b770cb66a7e15ef5c0567f5cf80b45fde5f2f 100644 (file)
@@ -38,7 +38,7 @@ files.
 #ifndef _TMPI_LIST_H_
 #define _TMPI_LIST_H_
 
-#include "thread_mpi/atomic.h"
+#include "atomic.h"
 
 
 /** \file 
similarity index 56%
rename from src/gmxlib/thread_mpi/event.h
rename to include/thread_mpi/lock.h
index 8b838d553a30d126b1bfa0506f4430e8632c8e0d..d2567cb713b24eefa5536295ffbf6c5adfd0a0e6 100644 (file)
@@ -35,12 +35,66 @@ be called official thread_mpi. Details are found in the README & COPYING
 files.
 */
 
+#ifndef _TMPI_FASTLOCK_H_
+#define _TMPI_FASTLOCK_H_
 
-struct tMPI_Event
+#include "wait.h"
+
+/** Fast (possibly busy-wait-based) lock type
+ *
+ *  This lock type forms an intermediate between the spinlocks and mutexes:
+ *  it is based on a busy-wait loop, but yields to the scheduler if the lock
+ *  is locked.  This is therefore the preferred type of  lock for when waits 
+ *  are expected to be reasonably short.
+ *
+ *  Variables of this type should be initialized by calling
+ *  tMPI_Lock_init().  
+ * 
+ * \see
+ * - tMPI_Lock_init
+ * - tMPI_Lock_lock
+ */
+typedef struct tMPI_Lock tMPI_Lock_t;
+struct tMPI_Lock
 {
-    tMPI_Atomic_t sync; /* the event sync counter */
-    int last_sync; /* the last sync event looked at */
-    TMPI_YIELD_WAIT_DATA   /* data associated with yielding */
+    tMPI_Spinlock_t   lock;      /*!< The underlying spin lock */
+    TMPI_YIELD_WAIT_DATA
 };
 
 
+/** Initialize lock
+ *
+ *  \param lock     Pointer to the new lock. 
+ */
+void tMPI_Lock_init(tMPI_Lock_t *lock);
+
+
+/** Perform yielding, busy-waiting locking 
+  *
+  *  This function blocks until the lock is locked.
+  *
+  *  \param lock  Pointer to previously created lock.
+  */
+void tMPI_Lock_lock(tMPI_Lock_t *lock);
+
+/** Unlock the lock
+  *
+  *  \param lock  Pointer to previously created lock.
+  */
+void tMPI_Lock_unlock(tMPI_Lock_t *lock);
+
+/** Try to lock the lock but don't block if it is locked.
+  *
+  *  \param lock  Pointer to previously created lock.
+  */
+int tMPI_Lock_trylock(tMPI_Lock_t *lock);
+
+/** Check the status of the lock without affecting its state
+  *
+  *  \param lock  Pointer to previously created lock.
+  */
+int tMPI_Lock_islocked(const tMPI_Lock_t *lock);
+
+
+
+#endif
index 2608de0b0acbcc22fb8afd0be22c2a1ac065e452..40153f8ad2bc972fe436e17c7e58362e4a7d301f 100644 (file)
@@ -134,6 +134,13 @@ typedef struct tmpi_datatype_ *MPI_Datatype;
 #define MPI_ANY_SOURCE          TMPI_ANY_SOURCE
 #define MPI_ANY_TAG             TMPI_ANY_TAG
 
+/* comm_compare defines */
+#define MPI_IDENT               TMPI_IDENT
+#define MPI_CONGRUENT           TMPI_CONGRUENT
+#define MPI_SIMILAR             TMPI_SIMILAR
+#define MPI_UNEQUAL             TMPI_UNEQUAL
+
+
 /* topology test defines */
 #define MPI_CART                TMPI_CART
 #define MPI_GRAPH               TMPI_GRAPH
@@ -200,6 +207,7 @@ typedef struct tmpi_datatype_ *MPI_Datatype;
 
 #define MPI_Comm_size               tMPI_Comm_size
 #define MPI_Comm_rank               tMPI_Comm_rank
+#define MPI_Comm_compare            tMPI_Comm_compare
 #define MPI_Comm_free               tMPI_Comm_free
 #define MPI_Comm_create             tMPI_Comm_create
 #define MPI_Comm_split              tMPI_Comm_split
index 72c8611aa987c63c4dfd167bf25d60b80426ff34..143b3cb3663e668a9a6fd571f96836af76cb2fb5 100644 (file)
@@ -69,7 +69,7 @@ files.
 
 #include <stdio.h>
 
-#include "thread_mpi/atomic.h"
+#include "atomic.h"
 
 
 #ifdef __cplusplus
index f9d7d02670810edc88fb0bd19fca6226709768f7..1a1ffe93096ae6bbea168b3136a58f0b93d6ed08 100644 (file)
@@ -63,8 +63,6 @@ extern "C"
 } /* Avoids screwing up auto-indentation */
 #endif
 
-/*#include "thread_mpi/threads.h"
-#include "thread_mpi/atomic.h"*/
 
 
 /** tMPI Communicator
@@ -170,6 +168,18 @@ extern tMPI_Errhandler TMPI_ERRORS_ARE_FATAL;
 /** pre-defined error handler that tries to continue on every error */
 extern tMPI_Errhandler TMPI_ERRORS_RETURN;
 
+/*! \name tMPI_Comm_compare() return codes */
+/*! \{ */
+/** Identical comms*/
+#define TMPI_IDENT 0
+/** Comms with the same members in the same order*/
+#define TMPI_CONGRUENT 1
+/** Comms with the same members in the different order*/
+#define TMPI_SIMILAR 2
+/** Comms with the different  members */
+#define TMPI_UNEQUAL 3
+/*! \} */
+
 
 /** Source number wildcard so tMPI_Recv(), etc. can receive from 
            any source. */
@@ -298,29 +308,34 @@ int tMPI_Init(int *argc, char ***argv);
     If N==0, the number of threads will be the recommended number of 
     threads for this platform as obtained from tMPI_Get_recommended_ntreads(). 
 
-    
-    \param[in] N                The number of threads to start (or 0 to
-                                automatically determine this).
-    \param[in] start_function   The function to start threads at (including 
-                                main thread). 
-    \param[in] arg              An optional argument for start_function().
-
-    \return  TMPI_FAILURE on failure, TMPI_SUCCESS on succes, after all
-             threads have finished.
-    */
-int tMPI_Init_fn(int N, void (*start_function)(void*), void *arg);
+    \param[in]  main_thread_returns   whether the control in the main thread 
+                                      should return immediately (if true), or 
+                                      the start_function() should be called 
+                                      from the main thread, too (if false).
+    \param[in] N                      The number of threads to start (or 0 to
+                                      automatically determine this).
+    \param[in] start_function         The function to start threads at 
+                                      (including main thread if 
+                                      main_thread_returns). 
+    \param[in] arg                    An optional argument for start_function().
+
+    \return  TMPI_FAILURE on failure, TMPI_SUCCESS on succes (after all
+             threads have finished if main_thread_returns=true).  */
+int tMPI_Init_fn(int main_thread_returns, int N, 
+                 void (*start_function)(void*), void *arg);
 
 /** get the number of threads from the command line
   
     can be called before tMPI_Init() 
 
-    \param[in]  argc            argc from main()
-    \param[in]  argv            argv from main()
-    \param[in]  optname         name of the argument specifying the number of 
-                                threads to run. If this is NULL, this function
-                                will read the first argument and interpret
-                                it as the number of threads.
-    \param[out] nthreads        the number of threads
+    \param[in]  argc                    argc from main()
+    \param[in]  argv                    argv from main()
+    \param[in]  optname                 name of the argument specifying the 
+                                        number of threads to run. If this is 
+                                        NULL, this function will read the first 
+                                        argument and interpret it as the number 
+                                        of threads.
+    \param[out] nthreads                the number of threads
     
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
 int tMPI_Get_N(int *argc, char ***argv, const char *optname, int *nthreads);
@@ -532,6 +547,20 @@ int tMPI_Comm_size(tMPI_Comm comm, int *size);
     \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
 int tMPI_Comm_rank(tMPI_Comm comm, int *rank);
 
+/** Compare two comms. Returns TMPI_IDENT if the two comms point to
+    the same underlying comm structure, TMPI_CONGRUENT if all 
+    members appear in the both comms in the same order, TMPI_SIMILAR
+    if both comms have the smae members but not in the same order, or
+    TMPI_UNEQUAL if the comms have different members.
+
+    \param[in]  comm1        The first comm to compare.
+    \param[in]  comm2        The second comm to compare.
+    \param[out] result       The output result, one of the values
+                             described above. 
+    \return  TMPI_SUCCESS on success, TMPI_FAILURE on failure.  */
+int tMPI_Comm_compare(tMPI_Comm comm1, tMPI_Comm comm2, int *result);
+
+
 /** De-allocate a comm 
 
     Collective function.
index 48bd7e35e12f2b977b7a8dafaa6669decb40746a..47ca78188f16eefdeb178f8a12e091be510e754a 100644 (file)
@@ -49,6 +49,7 @@
    *
    **************************************************************/
 #include "typedefs.h"
+#include "gmxfio.h"
 
 #ifdef __cplusplus 
 extern "C" {
@@ -81,11 +82,11 @@ typedef struct
  * but double and single precision can be read by either.
  */
 
-extern int open_tpx(const char *fn, const char *mode);
-/* Return an integer corresponding to the file you have just opened */
+extern t_fileio *open_tpx(const char *fn, const char *mode);
+/* Return an file pointer corresponding to the file you have just opened */
   
-extern void close_tpx(int fp);
-/*  Close the file corresponding to fp */
+extern void close_tpx(t_fileio *fio);
+/*  Close the file corresponding to fio */
   
 extern void read_tpxheader(const char *fn, t_tpxheader *tpx, bool TopOnlyOK,
                            int *version, int *generation);
@@ -136,8 +137,7 @@ extern bool read_tps_conf(const char *infile,char *title,t_topology *top,
  * else if bMass=TRUE, read the masses into top.atoms from the mass database.
  */
 
-void
-tpx_make_chain_identifiers(t_atoms *atoms,t_block *mols);
+void tpx_make_chain_identifiers(t_atoms *atoms,t_block *mols);
        
 #ifdef __cplusplus
 }
index 5e25e76a8a3784f9848feb71d3506d7eac66e06f..01ee5a0ad72d8dc97c4ec328bfab36dfaa1ff56b 100644 (file)
@@ -56,6 +56,7 @@
  **************************************************************/
        
 #include "typedefs.h"
+#include "gmxfio.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -83,13 +84,13 @@ typedef struct              /* This struct describes the order and the      */
   real lambda;         /* Current value of lambda                      */
 } t_trnheader;
 
-extern int open_trn(const char *fn,const char *mode);
+extern t_fileio *open_trn(const char *fn,const char *mode);
 /* Open a trj / trr file */
 
-extern void close_trn(int fp);
+extern void close_trn(t_fileio *fio);
 /* Close it */
 
-extern bool fread_trnheader(int fp,t_trnheader *trn,bool *bOK);
+extern bool fread_trnheader(t_fileio *fio,t_trnheader *trn,bool *bOK);
 /* Read the header of a trn file. Return FALSE if there is no frame.
  * bOK will be FALSE when the header is incomplete.
  */
@@ -106,18 +107,18 @@ extern bool is_trn(FILE *fp);
  * afterwards.
  */
 
-extern void fwrite_trn(int fp,int step,real t,real lambda,
+extern void fwrite_trn(t_fileio *fio,int step,real t,real lambda,
                       rvec *box,int natoms,rvec *x,rvec *v,rvec *f);
 /* Write a trn frame to file fp, box, x, v, f may be NULL */
 
-extern bool fread_htrn(int fp,t_trnheader *sh,
+extern bool fread_htrn(t_fileio *fio,t_trnheader *sh,
                       rvec *box,rvec *x,rvec *v,rvec *f);
 /* Extern read a frame except the header (that should be pre-read,
  * using routine read_trnheader, see above) from a trn file.
  * Return FALSE on error
  */
  
-extern bool fread_trn(int fp,int *step,real *t,real *lambda,
+extern bool fread_trn(t_fileio *fio,int *step,real *t,real *lambda,
                      rvec *box,int *natoms,rvec *x,rvec *v,rvec *f);
 /* Read a trn frame, including the header from fp. box, x, v, f may
  * be NULL, in which case the data will be skipped over.
index 11204eda7c6578b5b30e1659d50da9ea3891e678..2095f5f65b25ba65067831ce78a41373f3cb48fd 100644 (file)
 
 #include <sys/types.h>
 #include <sysstuff.h>
-#include <types/simple.h>
-#include <types/enums.h>
-#include <types/block.h>
-#include <types/symtab.h>
-#include <types/idef.h>
-#include <types/atoms.h>
-#include <types/trx.h>
-#include <types/topology.h>
-#include <types/energy.h>
-#include <types/inputrec.h>
-#include <types/ishift.h>
-#include <types/graph.h>
-#include <types/nrnb.h>
-#include <types/nblist.h>
-#include <types/nsgrid.h>
-#include <types/commrec.h>
-#include <types/forcerec.h>
-#include <types/fcdata.h>
-#include <types/mdatom.h>
-#include <types/pbc.h>
-#include <types/ifunc.h>
-#include <types/filenm.h>
-#include <types/group.h>
-#include <types/state.h>
-#include <types/shellfc.h>
-#include <types/constr.h>
-#include <types/matrix.h>
-#include <types/oenv.h>
+#include "types/simple.h"
+#include "types/enums.h"
+#include "types/block.h"
+#include "types/symtab.h"
+#include "types/idef.h"
+#include "types/atoms.h"
+#include "types/trx.h"
+#include "types/topology.h"
+#include "types/energy.h"
+#include "types/inputrec.h"
+#include "types/ishift.h"
+#include "types/graph.h"
+#include "types/nrnb.h"
+#include "types/nblist.h"
+#include "types/nsgrid.h"
+#include "types/commrec.h"
+#include "types/forcerec.h"
+#include "types/fcdata.h"
+#include "types/mdatom.h"
+#include "types/pbc.h"
+#include "types/ifunc.h"
+#include "types/filenm.h"
+#include "types/group.h"
+#include "types/state.h"
+#include "types/shellfc.h"
+#include "types/constr.h"
+#include "types/matrix.h"
+#include "types/oenv.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -186,7 +186,10 @@ extern void t_atoms_set_resinfo(t_atoms *atoms,int atom_ind,t_symtab *symtab,
  */
 
 void free_t_atoms(t_atoms *atoms,bool bFreeNames);
-/* free all the arrays and set the nr and nres to 0 */
+/* Free all the arrays and set the nr and nres to 0.
+ * bFreeNames tells if to free the atom and residue name strings,
+ * don't free them if they still need to be used in e.g. the topology struct.
+ */
 
 t_atoms *mtop2atoms(gmx_mtop_t *mtop);
 /* generate a t_atoms struct for the system from gmx_mtop_t */ 
index d51d47d2d9c3da9ca7a8ee5e182a95a91b4df3cb..725d508178c305be370eab7cf7535d9cf9f84937 100644 (file)
  * And Hey:
  * GRoups of Organic Molecules in ACtion for Science
  */
+#ifndef _commrec_h
+#define _commrec_h
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 
 #ifdef GMX_LIB_MPI
 #include <mpi.h>
-#endif
+#else
 #ifdef GMX_THREADS
-#include "tmpi.h"
+#include "../tmpi.h"
+#else
+typedef void* MPI_Comm;
+typedef void* MPI_Request;
+typedef void* MPI_Group;
+#endif
 #endif
 
 #include "idef.h"
@@ -105,7 +113,6 @@ typedef struct {
 } gmx_ddbox_t;
 
 
-#if defined(GMX_MPI) && !defined(GMX_THREADS) && !defined(MPI_IN_PLACE_EXISTS)
 typedef struct {
   /* these buffers are used as destination buffers if MPI_IN_PLACE isn't
      supported.*/
@@ -118,7 +125,6 @@ typedef struct {
   double *dbuf; /* for doubles */
   int dbuf_alloc;
 } mpi_in_place_buf_t;
-#endif
 
 
 typedef struct {
@@ -127,9 +133,7 @@ typedef struct {
    * defined in dd->comm in domdec.c
    */
   int  nnodes;
-#ifdef GMX_MPI
   MPI_Comm mpi_comm_all;
-#endif
   /* Use MPI_Sendrecv communication instead of non-blocking calls */
   bool bSendRecv2;
   /* The local DD cell index and rank */
@@ -141,10 +145,8 @@ typedef struct {
   int  pme_nodeid;
   bool pme_receive_vir_ener;
   gmx_pme_comm_n_box_p_t cnb;
-#ifdef GMX_MPI
   int  nreq_pme;
   MPI_Request req_pme[4];
-#endif
   
 
   /* The communication setup, identical for each cell, cartesian index */
@@ -223,15 +225,11 @@ typedef struct gmx_partdec *gmx_partdec_p_t;
 typedef struct {
   int nsim;
   int sim;
-#ifdef GMX_MPI
   MPI_Group mpi_group_masters;
   MPI_Comm mpi_comm_masters;
-#if !defined(GMX_THREADS) && !defined(MPI_IN_PLACE_EXISTS)
   /* these buffers are used as destination buffers if MPI_IN_PLACE isn't
      supported.*/
   mpi_in_place_buf_t *mpb;
-#endif
-#endif
 } gmx_multisim_t;
 
 #define DUTY_PP  (1<<0)
@@ -239,11 +237,9 @@ typedef struct {
 
 typedef struct {
   int      bUse;
-#ifdef GMX_MPI
   MPI_Comm comm_intra;
   int      rank_intra;
   MPI_Comm comm_inter;
-#endif
   
 } gmx_nodecomm_t;
 
@@ -252,18 +248,18 @@ typedef struct {
 } gmx_commrec_thread_t;
 
 typedef struct {
-  /* The nodids in one sim are numbered sequentially from 0.
+  /* The nodeids in one sim are numbered sequentially from 0.
    * All communication within some simulation should happen
    * in mpi_comm_mysim, or its subset mpi_comm_mygroup.
    */
   int sim_nodeid,nnodes,npmenodes;
-  int threadid,nthreads;
+
+  /* thread numbers: */
+  int threadid, nthreads;
   /* The nodeid in the PP/PME, PP or PME group */
   int nodeid;
-#ifdef GMX_MPI
   MPI_Comm mpi_comm_mysim;
   MPI_Comm mpi_comm_mygroup;
-#endif
 
 #ifdef GMX_THREAD_SHM_FDECOMP
   gmx_commrec_thread_t thread;
@@ -282,11 +278,9 @@ typedef struct {
 
   gmx_multisim_t *ms;
 
-#if defined(GMX_MPI) && !defined(GMX_THREADS) && !defined(MPI_IN_PLACE_EXISTS)
   /* these buffers are used as destination buffers if MPI_IN_PLACE isn't
      supported.*/
   mpi_in_place_buf_t *mpb;
-#endif
 } t_commrec;
 
 #define MASTERNODE(cr)     ((cr)->nodeid == 0)
@@ -314,4 +308,4 @@ typedef struct {
 #ifdef __cplusplus
 }
 #endif
-
+#endif
index da947909fde8e4029e401e322114673c0cc11f25..e4f0d959fb56d119d774ece1928e7df455cb8b56 100644 (file)
@@ -36,6 +36,8 @@
 #include <config.h>
 #endif
 
+#include <types/commrec.h>
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -63,9 +65,7 @@ typedef struct {
   real *Rt_6;         /* The calculated inst. ens. averaged r^-6 (nr)     */
   real *Rtav_6;       /* The calculated time and ens. averaged r^-6 (nr)  */
   int  nsystems;      /* The number of systems for ensemble averaging     */
-#ifdef GMX_MPI
   MPI_Comm mpi_comm_ensemble; /* For ensemble averaging                   */
-#endif
 } t_disresdata;
 
 
@@ -93,6 +93,11 @@ typedef struct {
   rvec5  *tmp;        /* An array of temporary 5-vectors (nex);             */ 
   real   ***TMP;      /* An array of temporary 5x5 matrices (nex);          */
   real   *eig;        /* Eigenvalues/vectors, for output only (nex x 12)    */
+
+  /* variables for diagonalization with diagonalize_orires_tensors()*/
+  double **M;
+  double *eig_diag;
+  double **v;
 } t_oriresdata;
 
 /* 
index c44eb8b03e25ed4c68dae9329f1541f2cf1d8c0e..ced0766c4ea2b5f1a7f10fad77457dde7c04dc8d 100644 (file)
@@ -281,10 +281,17 @@ typedef struct
  *      function to use. Every "bond" with the same function but different 
  *     force parameters is a different force type. The type identifier in the 
  *     forceatoms[] array is an index in this array.
-     t_iparams *iparams;
+ *   t_iparams *iparams
  *     array of length ntypes, defines the parameters for every interaction
  *      type. The type identifier in the actual interaction list
- *      (bondeds.iatoms[] or shakes.iatoms[]) is an index in this array.
+ *      (ilist[ftype].iatoms[]) is an index in this array.
+ *   gmx_cmap_t cmap_grid
+ *      the grid for the dihedral pair correction maps.
+ *   t_iparams *iparams_posres
+ *     defines the parameters for position restraints only.
+ *      Position restraints are the only interactions that have different
+ *      parameters (reference positions) for different molecules
+ *      of the same type. ilist[F_POSRES].iatoms[] is an index in this array.
  *   t_ilist il[F_NRE]
  *      The list of interactions for each type. Note that some,
  *      such as LJ and COUL will have 0 entries.
index 2646d5d1e14e2047fcf74fa6bec84743ba4f051e..f0f05b3abccca968d0ef58fab9946973f228f401 100644 (file)
@@ -41,7 +41,7 @@
 #endif
 
 
-#include "types/simple.h"
+#include "simple.h"
 
 #ifdef __cplusplus
 extern "C" {
index 56bd84bdf7ee15798518afbddf5335fb32e38cef..09aaa816b9b60ec98a93dec60fc78c3c6a3a9d4b 100644 (file)
@@ -41,44 +41,45 @@ extern "C" {
 #endif
 
 typedef struct {
-  int           nrQMatoms;      /* total nr of QM atoms              */
-  rvec          *xQM;           /* shifted to center of box          */  
-  int           *indexQM;       /* atom i = atom indexQM[i] in mdrun */
-  int           *atomicnumberQM;/* atomic numbers of QM atoms        */  
-  real          *QMcharges;     /* atomic charges of QM atoms(ONIOM) */
-  int           *shiftQM;
-  int           QMcharge;       /* charge of the QM system           */
-  int           multiplicity;   /* multipicity (no of unpaired eln)  */
-  int           QMmethod;       /* see enums.h for all methods       */
-  int           QMbasis;        /* see enums.h for all bases         */
-  int           nelectrons;     /* total number of elecs in QM region*/
-  bool          bTS;            /* Optimize a TS, only steep, no md  */
-  bool          bOPT;          /* Optimize QM subsys, only steep, no md  */
-  bool          *frontatoms;   /* qm atoms on the QM side of a QM-MM bond */
-  /* Gaussian specific stuff */
-  int           nQMcpus;        /* no. of CPUs used for the QM calc. */
-  int           QMmem;          /* memory for the gaussian calc.     */
-  int           accuracy;       /* convergence criterium (E(-x))     */
-  bool          cpmcscf;        /* using cpmcscf(l1003)*/
-  char          *gauss_dir;
-  char          *gauss_exe;
-  char          *devel_dir;
-  real          *c6;
-  real          *c12;
-  /* Surface hopping stuff */
-  bool          bSH;            /* surface hopping (diabatic only)   */
-  real          SAon;           /* at which energy gap the SA starts */
-  real          SAoff;          /* at which energy gap the SA stops  */
-  int           SAsteps;        /* stepwise switchinng on the SA     */
-  int           SAstep;         /* current state of SA               */
-  int           CIdim;
-  real          *CIvec1;
-  real          *CIvec2;
-  real          *CIvec1old;
-  real          *CIvec2old;
-  ivec          SHbasis;
-  int           CASelectrons;
-  int           CASorbitals;
+ int           nrQMatoms;      /* total nr of QM atoms              */
+ rvec          *xQM;           /* shifted to center of box          */  
+ int           *indexQM;       /* atom i = atom indexQM[i] in mdrun */
+ int           *atomicnumberQM;/* atomic numbers of QM atoms        */  
+ real          *QMcharges;     /* atomic charges of QM atoms(ONIOM) */
+ int           *shiftQM;
+ int           QMcharge;       /* charge of the QM system           */
+ int           multiplicity;   /* multipicity (no of unpaired eln)  */
+ int           QMmethod;       /* see enums.h for all methods       */
+ int           QMbasis;        /* see enums.h for all bases         */
+ int           nelectrons;     /* total number of elecs in QM region*/
+ bool          bTS;            /* Optimize a TS, only steep, no md  */
+ bool          bOPT;          /* Optimize QM subsys, only steep, no md  */
+ bool          *frontatoms;   /* qm atoms on the QM side of a QM-MM bond */
+ /* Gaussian specific stuff */
+ int           nQMcpus;        /* no. of CPUs used for the QM calc. */
+ int           QMmem;          /* memory for the gaussian calc.     */
+ int           accuracy;       /* convergence criterium (E(-x))     */
+ bool          cpmcscf;        /* using cpmcscf(l1003)*/
+ char          *gauss_dir;
+ char          *gauss_exe;
+ char          *devel_dir;
+ char          *orca_basename; /* basename for I/O with orca        */
+ real          *c6;
+ real          *c12;
+ /* Surface hopping stuff */
+ bool          bSH;            /* surface hopping (diabatic only)   */
+ real          SAon;           /* at which energy gap the SA starts */
+ real          SAoff;          /* at which energy gap the SA stops  */
+ int           SAsteps;        /* stepwise switchinng on the SA     */
+ int           SAstep;         /* current state of SA               */
+ int           CIdim;
+ real          *CIvec1;
+ real          *CIvec2;
+ real          *CIvec1old;
+ real          *CIvec2old;
+ ivec          SHbasis;
+ int           CASelectrons;
+ int           CASorbitals;
 } t_QMrec;
 
 typedef struct {
index 825c006060ce70fdb0e0bea2bae26270760976b9..307c8a1f03d60a38dd562cdd85a5064d5549f6d6 100644 (file)
@@ -50,7 +50,7 @@ extern "C" {
  */
 
 /* for now, define the length of the NH chains here */
-#define NHCHAINLENGTH 5
+#define NHCHAINLENGTH 10
 
 /* These enums are used in flags as (1<<est...).
  * The order of these enums should not be changed,
index 7842953178f3f1b7604a8e326bea49061d27fdcf..43afeda757b64d3fa1bb6fcbad1ad7a9eaba279a 100644 (file)
@@ -79,7 +79,7 @@ typedef struct {
  */
 #define ggrpnr(groups,egc,i) ((groups)->grpnr[egc] ? (groups)->grpnr[egc][i] : 0)
 
-/* The global topology struct, based on molecule types */
+/* The global, complete system topology struct, based on molecule types */
 typedef struct {
   char           **name;       /* Name of the topology                 */
   gmx_ffparams_t ffparams;
@@ -96,7 +96,7 @@ typedef struct {
   t_symtab      symtab;        /* The symbol table                     */
 } gmx_mtop_t;
 
-/* The mdrun local topology struct, completely written out */
+/* The mdrun node-local topology struct, completely written out */
 typedef struct {
   t_idef       idef;           /* The interaction function definition  */
   t_atomtypes   atomtypes;      /* Atomtype properties                  */
index cb56e10e43a4cc90cf81eb5610569cd4512df8ef..622f97fcc1fb0c684f4eb9bed8ffd318950f8fe0 100644 (file)
@@ -41,8 +41,8 @@
  * not be allocated.
  */ 
 
-#include "molfile_plugin.h"
-#include "vmdio.h"
+#include "../molfile_plugin.h"
+#include "../vmdio.h"
 
 #ifdef __cplusplus
 extern "C" {
index 128871fb187a9f29bd23e233c8395918dc12f2df..3c47ff57f1edde2383e9af11e4dbe5708542b60a 100644 (file)
@@ -185,7 +185,8 @@ extern t_state *init_bufstate(const t_state *template_state);
 
 extern void destroy_bufstate(t_state *state);
 
-extern void trotter_update(t_inputrec *ir,gmx_ekindata_t *ekind, gmx_enerdata_t *enerd, 
+extern void trotter_update(t_inputrec *ir,gmx_large_int_t step,
+                          gmx_ekindata_t *ekind, gmx_enerdata_t *enerd, 
                           t_state *state, tensor vir, t_mdatoms *md, 
                           t_extmass *MassQ, int *trotter_seq);
 
index eaa56bf4cea4d1e9d82203b1b5a7e66619d902a2..54519a0f197a04159509379ccd68f979fe1e7fac 100644 (file)
@@ -264,11 +264,7 @@ extern void vecrecip(real in[],real out[],int n);
  * versions if your hardware supports it.
  *
  * To use those routines, your memory HAS TO BE CACHE-ALIGNED.
- * Start by allocating 31 bytes more than you need, put
- * this in a temp variable (e.g. _buf, so you can free it later), and
- * create your aligned array buf with
- * 
- *  buf=(real *) ( ( (unsigned long int)_buf + 31 ) & (~0x1f) );
+ * Use snew_aligned(ptr,size,32) to allocate and sfree_aligned to free.
  */
 
 
@@ -627,7 +623,7 @@ static inline real
 gmx_angle(const rvec a, const rvec b)
 {
     rvec w;
-    real wlen,s,theta;
+    real wlen,s;
     
     cprod(a,b,w);
     
index b1b91592d2f854eebf8804ea450d4114ce4210af..f9f0df8aa014f020ad1fd047f9ccc2079b1d8d12 100644 (file)
@@ -36,7 +36,7 @@ typedef struct
     bool bV;
 } t_gmxvmdplugin;
     
-int read_first_vmd_frame(int *status,const char *fn, struct trxframe *fr,int flags);
+int read_first_vmd_frame(int  *status,const char *fn, struct trxframe *fr,int flags);
 bool read_next_vmd_frame(int status,struct trxframe *fr);
 int load_vmd_library(const char *fn, t_gmxvmdplugin *vmdplugin);
 
index c9fb61ac6082ce198f3763afb459315fe6db51bc..0b62dd222d2b07bd584aeb3a806e04f63f36cbd8 100644 (file)
 extern "C" {
 #endif
 
-int xdropen(XDR *xdrs, const char *filename, const char *type);
-
 
+/* THESE 3 FUNCTIONS (xdropen, xdrclose and xdr_get_fp) ARE NOW OBSOLETE 
+   AND ONLY PROVIDED FOR BACKWARD COMPATIBILITY OF 3D PARTY TOOLS. 
+   THEY SHOULD NOT BE USED ANYWHERE IN GROMACS ITSELF. 
+int xdropen(XDR *xdrs, const char *filename, const char *type);
 int xdrclose(XDR *xdrs);
+*/
 
-FILE * xdr_get_fp(int xdrid);
 
 
 /* Read or write reduced precision *float* coordinates */
-int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision);
+int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision, bool bRead);
 
 
 /* Read or write a *real* value (stored as float) */
@@ -75,7 +77,7 @@ int xdr_real(XDR *xdrs,real *r);
 
 
 /* Read or write reduced precision *real* coordinates */
-int xdr3drcoord(XDR *xdrs,real *fp,int *size,real *precision);
+int xdr3drcoord(XDR *xdrs,real *fp,int *size,real *precision, bool bRead);
 
 
 extern int xdr_gmx_large_int(XDR *xdrs,gmx_large_int_t *i,const char *warn);
index f6929b076cdf2e8c4c9671a4dc0c325d03cda3a3..56f0c924eb7191fff0eec9d08475c60faeabad31 100644 (file)
 
 
 #include "typedefs.h"
+#include "gmxfio.h"
 #include "xdrf.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/* All functions return 1 if succesfull, 0 otherwise 
+/* All functions return 1 if successful, 0 otherwise 
  * bOK tells if a frame is not corrupted 
  */  
 
-extern int open_xtc(const char *filename,const char *mode);
+extern t_fileio *open_xtc(const char *filename,const char *mode);
 /* Open a file for xdr I/O */
   
-extern void close_xtc(int fp);
+extern void close_xtc(t_fileio *fio);
 /* Close the file for xdr I/O */
   
-extern int read_first_xtc(int fp,
+extern int read_first_xtc(t_fileio *fio,
                          int *natoms,int *step,real *time,
                          matrix box,rvec **x,real *prec,bool *bOK);
 /* Open xtc file, read xtc file first time, allocate memory for x */
 
-extern int read_next_xtc(int fp,
+extern int read_next_xtc(t_fileio *fio,
                         int natoms,int *step,real *time,
                         matrix box,rvec *x,real *prec,bool *bOK);
 /* Read subsequent frames */
 
-extern int write_xtc(int fp,
+extern int write_xtc(t_fileio *fio,
                     int natoms,int step,real time,
                     matrix box,rvec *x,real prec);
 /* Write a frame to xtc file */
index 173156601dd12453bc4a7b001b337628697b392e..19f9f415aa6d10a91b1f81a80f45a1da919c92db 100755 (executable)
@@ -13,9 +13,9 @@
 # taken directly from ifp43a1.dat. For a description of what the numbers
 # mean, see the GROMOS96 manual and the fie ifp43a1.dat
 
-# set the input seperator to #--- so we read one atom entry at a time
-# make sure the records are actually seperated by #---\n and not by say #--\n!!
-# don't put a seperator at the end of the file, only between records
+# set the input separator to #--- so we read one atom entry at a time
+# make sure the records are actually separated by #---\n and not by say #--\n!!
+# don't put a separator at the end of the file, only between records
 $/= "#---\n"; 
 
 # start arrays with 1 instead of 0
index 3dd338dafc052c7402dd7d721b68ebdd8bf77e31..c672c2a2ac6675a334de6f2f06a01b577cf34860 100755 (executable)
@@ -253,7 +253,7 @@ for resnum in range(start,stop):    # loop through all residues
     f.getRESname(f.all[resnum])                # residue name
     f.getNATOM  (f.all[resnum])                # number of atoms
 
-    if f.nlin != 0:                    # 0 for a seperate molecule
+    if f.nlin != 0:                    # 0 for a separate molecule
           f.getEXCLUS(f.all[resnum])   # number of exclusions
 
     f.getATOM   (f.all[resnum])                # atoms                 => f.atoms
index b4c7af71153a2d1abf9309c3acc0321400056363..b22c0b91e305d90f3248e3865315c19d13f85582 100644 (file)
@@ -108,6 +108,25 @@ topology, this can be useful for normal mode analysis.</dd>
 <dt><b>md</b></dt>
 <dd>A <!--Idx-->leap-frog<!--EIdx--> algorithm for integrating Newton's
 equations of motion.</dd>
+<dt><b>md-vv</b></dt>
+<dd>A velocity Verlet algorithm for integrating Newton's equations of motion.
+For constant NVE simulations started from corresponding points in the same trajectory, the trajectories 
+are analytically, but not binary, identical to the <b>md</b> leap-frog integrator.  The the kinetic
+energy, which is determined from the whole step velocities and is therefore
+slightly too high. The advantage of this integrator is more accurate,
+reversible Nose-Hoover and Parrinello-Rahman coupling integration
+based on Trotter expansion, as well as (slightly too small) full step velocity
+output. This all comes at the cost off extra computation, especially with
+constraints and extra communication in parallel. Note that for nearly all
+production simulations the <b>md</b> integrator is accurate enough.
+</dd>
+<dt><b>md-vv-avek</b></dt>
+<dd>A velocity Verlet algorithm identical to <b>md-vv</b>, except that
+the kinetic energy is determined as the average of
+the two half step kinetic energies as in the <b>md</b> integrator, and this thus more accurate.
+With Nose-Hoover and/or Parrinello-Rahman coupling this comes with
+a slight increase in computational cost.
+</dd>
 <dt><b>sd</b></dt>
 <dd> An accurate leap-frog stochastic dynamics integrator.
 Four Gaussian random number are required
@@ -220,7 +239,7 @@ Parallel tpic gives identical results to single node tpic.
 <dd>time step for integration (only makes sense for integrators <tt>md</tt>,
 <tt>sd</tt> and <tt>bd</tt>)</dd>
 <dt><h4>nsteps: (0)</h4></dt>
-<dd>maximum number of steps to integrate</dd>
+<dd>maximum number of steps to integrate or minimize, -1 is no maximum</dd>
 <dt><h4>init_step: (0)</h4></dt>
 <dd>The starting step.
 The time at an step i in a run is calculated as: t = <tt>tinit</tt> + <tt>dt</tt>*(<tt>init_step</tt> + i).
@@ -230,7 +249,7 @@ Thus for exact restarts or redoing part of a run it might be necessary to
 set <tt>init_step</tt> to the step number of the restart frame.
 <tt>tpbconv</tt> does this automatically.
 </dd>
-<dt><h4>nstcalcenergy: (1)</h4></dt>
+<dt><h4>nstcalcenergy: (-1)</h4></dt>
 <dd>The frequency for calculating the energies, including the temperature
 and the pressure, 0 is never.
 This option is only relevant with dynamics.
@@ -241,7 +260,10 @@ because calculating energies requires global communication between all
 processes which can become a bottleneck at high parallelization.
 With global temperature and/or pressure coupling the time step for
 the coupling algorithm is <b>nstcalcenergy</b>*<b>dt</b>.
-Take this into account when setting <b>tau_t</b> and/or <b>tau_p</b>.</dd>
+Take this into account when setting <b>tau_t</b> and/or <b>tau_p</b>.
+The default value of -1 sets <b>nstcalcenergy</b> equal to <b>nstlist</b>,
+unless <b>nstlist</b> &le 0, then a value of 10 is used;
+for velocity Verlet integrators <b>nstcalcenergy</b> is set to 1.</dd>
 <dt><h4>comm_mode:</h4></dt>
 <dd><dl compact>
 <dt><b>Linear</b></dt>
@@ -252,7 +274,7 @@ Take this into account when setting <b>tau_t</b> and/or <b>tau_p</b>.</dd>
 <dt><b>No</b></dt>
 <dd>No restriction on the center of mass motion
 </dl></dd>
-<dt><h4>nstcomm: (1) [steps]</h4></dt>
+<dt><h4>nstcomm: (10) [steps]</h4></dt>
 <dd>frequency for center of mass motion removal</dd>
 <dt><h4>comm_grps:</h4></dt>
 <dd>group(s) for center of mass motion removal, default is the whole system</dd>
@@ -342,8 +364,7 @@ the last velocities are always written</dd>
 <dd>frequency to write forces to output trajectory.</dd>
 <dt><h4>nstlog: (100) [steps]</h4></dt>
 <dd>frequency to write energies to <!--Idx-->log file<!--EIdx-->,
-the last energies are always written,
-should be a multiple of <b>nstcalcenergy</b></dd>
+the last energies are always written</dd>
 <dt><h4>nstenergy: (100) [steps]</h4></dt>
 <dd>frequency to write energies to energy file,
 the last energies are always written,
@@ -494,7 +515,8 @@ The grid dimensions are controlled by <b>fourierspacing</b>.
 Reasonable grid spacing for PPPM is 0.05-0.1 nm.
 See <tt>Shift</tt> for the details of the particle-particle potential.
 <br>
-NOTE: the pressure in incorrect when using PPPM.</dd>
+NOTE: PPPM is not functional in the current version, we plan to implement
+PPPM through a small modification of the PME code.</dd>
 
 <dt><b><!--Idx-->Reaction-Field<!--EIdx--></b></dt>
 <dd>Reaction field with Coulomb cut-off <b>rcoulomb</b>,
@@ -790,7 +812,7 @@ temperature <b>ref_t</b> [K], with time constant <b>tau_t</b> [ps].
 Several groups can be coupled separately, these are specified in the
 <b>tc_grps</b> field separated by spaces.</dd>
 <dt><b>nose-hoover</b></dt>
-<dd>Temperature coupling with a by using a Nose-Hoover extended
+<dd>Temperature coupling using a Nose-Hoover extended
 ensemble. The reference temperature and coupling groups are selected
 as above, but in this case <b>tau_t</b> [ps] controls the period
 of the temperature fluctuations at equilibrium, which is slightly
@@ -808,7 +830,8 @@ This thermostat works correctly even for <b>tau_t</b>=0.
 For NVT simulations the conserved energy quantity is written
 to the energy and log file.</dd>
 </dl>
-
+<dt><h4>nh-chain-length (10)</h4></dt>
+<dd>the number of chained Nose-Hoover thermostats for velocity Verlet integrators, the leap-frog <b>md</b> integrator only supports 1.  Data for the NH chain variables is not printed to the .edr, but can be using the GMX_NOSEHOOVER_CHAINS environment variable</dd>
 <dt><h4>tc_grps:</h4></dt>
 <dd>groups to couple separately to temperature bath</dd>
 <dt><h4>tau_t: [ps]</h4></dt>
@@ -834,14 +857,27 @@ argued that this does not yield a correct thermodynamic ensemble,
 but it is the most efficient way to scale a box at the beginning
 of a run.</dd>
 <dt><b>Parrinello-Rahman</b></dt>
-<dd>Extended-ensemble pressure coupling where the box vectors
-are subject to an equation of motion. The equation of motion for
-the atoms is coupled to this. No instantaneous scaling takes place.
+<dd>Extended-ensemble pressure coupling where the box vectors are
+subject to an equation of motion. The equation of motion for the atoms
+is coupled to this. No instantaneous scaling takes place.  As for
+Nose-Hoover temperature coupling the time constant <b>tau_p</b> [ps]
+is the period of pressure fluctuations at equilibrium. This is
+probably a better method when you want to apply pressure scaling
+during data collection, but beware that you can get very large
+oscillations if you are starting from a different pressure. For
+simulations where the exact fluctation of the NPT ensemble are
+important, or if the pressure coupling time is very short,it may not
+be appropriate, as the previous time step pressure is used in some
+steps of the gromacs implementation for the current time step pressure.</dd>
+</dl></dd>
+<dt><b>MTTK</b></dt>
+<dd>Martyna-Tuckerman-Tobias-Klein implementation, only useable with <b>md-vv</b>
+or <b>md-vv-avek</b>, very similar to Parinello-Raphman.  
 As for Nose-Hoover temperature coupling the time constant <b>tau_p</b>
 [ps] is the period of pressure fluctuations at equilibrium. This is
 probably a better method when you want to apply pressure scaling
 during data collection, but beware that you can get very large
-oscillations if you are starting from a different pressure.</dd>
+oscillations if you are starting from a different pressure. Currently only supports isotropic scaling.</dd>
 </dl></dd>
 </dl>
 
@@ -1218,7 +1254,10 @@ is larger than half the shortest box vector.
 For determining the COM, all atoms in the group are put at their periodic image
 which is closest to <b>pull_pbcatom1</b>.
 A value of 0 means that the middle atom (number wise) is used.
-This parameter is not used with geometry <b>cylinder</b>.</dd>
+This parameter is not used with geometry <b>cylinder</b>.
+A value of -1 turns on cosine weighting, which is useful for a group
+of molecules in a periodic system, e.g. a water slab (see Engin et al.
+J. Chem. Phys. B 2010).</dd>
 <dt><h4>pull_vec1: (0.0 0.0 0.0)</h4></dt>
 <dd>The pull direction. <tt>grompp</tt> normalizes the vector.</dd>
 <dt><h4>pull_init1: (0.0) / (0.0 0.0 0.0) [nm]</h4></dt>
@@ -1248,10 +1287,13 @@ The force constant is then (1 - lambda)*<b>pull_k1</b> + lambda*<b>pull_kB1</b>.
 restraint information in topology file)</dd>
 <dt><b>simple</b></dt>
 <dd>simple (per-molecule) distance restraints,
-ensemble averaging can be performed with <tt>mdrun -multi</tt></dd>
+ensemble averaging can be performed with <tt>mdrun -multi</tt>
+where the environment variable GMX_DISRE_ENSEMBLE_SIZE sets the number
+of systems within each ensemble (usually equal to the mdrun -multi value)</dd>
 <dt><b>ensemble</b></dt>
 <dd>distance restraints over an ensemble of molecules in one simulation box,
-should only be used for special cases, such as dimers</dd>
+should only be used for special cases, such as dimers
+(this option is not fuctional in the current version of GROMACS)</dd>
 </dl></dd>
 <dt><h4>disre_weighting:</h4></dt>
 <dd><dl compact>
@@ -1679,6 +1721,7 @@ reals to your subroutine. Check the inputrec definition in
 <A HREF="#bond2">morse</A><br>
 <A HREF="#em">nbfgscorr</A><br>
 <A HREF="#xmdrun">niter</A><br>
+<A HREF="#tc">nh-chain-length</A><br>
 <A HREF="#em">nstcgsteep</A><br>
 <A HREF="#run">nstcalcenergy</A><br>
 <A HREF="#run">nstcomm</A><br>
index 7fff1a6481c376c420e5c323352538fda58031f5..09bea49f3c4a3c8addebf77917487a820ad6cd5e 100644 (file)
@@ -20,7 +20,7 @@ performed, for instance making use of the fact that atoms close
 in sequence are usually close in space too (e.g. a water molecule).
 To this end, the <i>xdr</i> library is extended with a special routine
 to write 3-D float coordinates. This routine was written by Frans van Hoesel
-as part of an Europort project, and can be obtianed through <a href="http://hpcv100.rc.rug.nl/xdrf.html">this link</a>.
+as part of an Europort project, and can be obtained through <a href="http://hpcv100.rc.rug.nl/xdrf.html">this link</a>.
 <p>
 All the data is stored using calls to <i>xdr</i> routines.
 
@@ -46,7 +46,7 @@ All the data is stored using calls to <i>xdr</i> routines.
 <h3>Using xtc in your "C" programs</h3>
 To read and write these files the following "C" routines are available:
 <pre>
-/* All functions return 1 if succesfull, 0 otherwise */  
+/* All functions return 1 if successful, 0 otherwise */  
 
 extern int open_xtc(XDR *xd,char *filename,char *mode);
 /* Open a file for xdr I/O */
index af75cde6a2a035a9f5b08adb304d4b132c2a1a64..e400469b7513be0d48bb122771ea3b54ad1bffd2 100644 (file)
@@ -18,15 +18,11 @@ oplsaa.ff \
 charmm27.ff
 
 topol_DATA = \
-       1mlg.itp        2mlg.itp        benzamide.itp   bondadd.itp     \
-       buck.itp        decane.itp      dlg.itp         dmso.itp        \
-       fa.itp          ff_dum.itp      flexspc.itp     flexspce.itp    \
-       flexwat-ferguson.itp            h2p4o13.itp     h2p8o25.itp     \
-       h2po4.itp       ions.itp        methanol.itp    spc.itp         \
-       spce.itp        tfe.itp         tip3p.itp       tip4p.itp       \
-       urea.itp        dgsolv.dat      electroneg.dat                  \
-       dec50.gro       dmso.gro        spc216.gro      tip4p.gro       \
-       urea+h2o.gro    \
+       ff_dum.itp      flexspc.itp     \
+       flexspce.itp    flexwat-ferguson.itp            ions.itp        \
+       spc.itp         spce.itp        tip3p.itp       tip4p.itp       \
+       dgsolv.dat      electroneg.dat  \
+       spc216.gro      tip4p.gro       \
        aminoacids.dat  atommass.dat    bromacs.dat     ca-shift.dat    \
        cb-shift.dat    co-shift.dat    edissoc.dat                     \
        gurgle.dat      ha-shift.dat    links.dat       phbres.dat      \
diff --git a/share/top/benzamide.itp b/share/top/benzamide.itp
deleted file mode 100644 (file)
index 6ca4e2b..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-[ moleculetype ]
-; Name  nrexcl
-Benz   3
-
-[ atoms ]
-;   nr    type   resnr  residu    atom    cgnr        charge          mass
-     1      CB       1     BEN      C1       1             0   ; qtot: 0
-     2     CR6       1     BEN      C2       2         -0.14   ; qtot: -0.14
-     3     HCR       1     BEN      H2       2          0.14   ; qtot: 0
-     4     CR6       1     BEN      C3       3         -0.14   ; qtot: -0.14
-     5     HCR       1     BEN      H3       3          0.14   ; qtot: 0
-     6     CR6       1     BEN      C4       4         -0.14   ; qtot: -0.14
-     7     HCR       1     BEN      H4       4          0.14   ; qtot: 0
-     8     CR6       1     BEN      C5       5         -0.14   ; qtot: -0.14
-     9     HCR       1     BEN      H5       5          0.14   ; qtot: 0
-    10     CR6       1     BEN      C6       6         -0.14   ; qtot: -0.14
-    11     HCR       1     BEN      H6       6          0.14   ; qtot: 0
-    12       C       1     BEN      C7       7          0.56   ; qtot: 0.56
-    13      NZ       1     BEN      N1       7         -0.26   ; qtot: 0.3
-    14       H       1     BEN     H11       7          0.24   ; qtot: 0.54
-    15       H       1     BEN     H12       7          0.24   ; qtot: 0.78
-    16      NZ       1     BEN      N2       7         -0.26   ; qtot: 0.52
-    17       H       1     BEN     H21       7          0.24   ; qtot: 0.76
-    18       H       1     BEN     H22       7          0.24   ; qtot: 1
-
-[ bonds ]
-;  ai    aj funct
-    1     2     1 
-    1    10     1 
-    1    12     1 
-    2     3     1 
-    2     4     1 
-    4     5     1 
-    4     6     1 
-    6     7     1 
-    6     8     1 
-    8     9     1 
-    8    10     1 
-   10    11     1 
-   12    13     1 
-   12    16     1 
-   13    14     1 
-   13    15     1 
-   16    17     1 
-   16    18     1 
-
-[ pairs ]
-;  ai    aj funct
-    1     5     1 
-    1     6     1 
-    1     9     1 
-    1    14     1 
-    1    15     1 
-    1    17     1 
-    1    18     1 
-    2     7     1 
-    2     8     1 
-    2    11     1 
-    2    13     1 
-    2    16     1 
-    3     6     1 
-    3    10     1 
-    3    12     1 
-    4     9     1 
-    4    10     1 
-    4    12     1 
-    5     8     1 
-    6    11     1 
-    7    10     1 
-    8    12     1 
-   10    13     1 
-   10    16     1 
-   11    12     1 
-   13    17     1 
-   13    18     1 
-   14    16     1 
-   15    16     1 
-
-[ angles ]
-;  ai    aj    ak funct
-    2     1    10     1 
-    2     1    12     1 
-   10     1    12     1 
-    1     2     3     1 
-    1     2     4     1 
-    3     2     4     1 
-    2     4     5     1 
-    2     4     6     1 
-    5     4     6     1 
-    4     6     7     1 
-    4     6     8     1 
-    7     6     8     1 
-    6     8     9     1 
-    6     8    10     1 
-    9     8    10     1 
-    1    10     8     1 
-    1    10    11     1 
-    8    10    11     1 
-    1    12    13     1        120.    400.
-    1    12    16     1        120.    400.
-   13    12    16     1 
-   12    13    14     1 
-   12    13    15     1 
-   14    13    15     1 
-   12    16    17     1 
-   12    16    18     1 
-   17    16    18     1 
-
-[ dihedrals ]
-;  ai    aj    ak    al funct
-    1    12    13    14     1 
-    1    12    16    17     1 
-
-[ dihedrals ]
-;  ai    aj    ak    al funct
-    1     2     4     6     2 
-    1    10     2    12     2 
-    2     1     4     3     2 
-    2     1    10     8     2 
-    2     4     6     8     2 
-    2     1    12    13     2  0.0     167.0
-    4     2     6     5     2 
-    4     6     8    10     2 
-    6     8    10     1     2 
-    6     4     8     7     2 
-    8    10     1     2     2 
-    8     6    10     9     2 
-   10     1     2     4     2 
-   10     8     1    11     2 
-   10     1    12    16     2  0.0     167.0
-   12    13    16     1     2 
-   13    14    15    12     2 
-   16    17    18    12     2 
-
diff --git a/share/top/bondadd.itp b/share/top/bondadd.itp
deleted file mode 100644 (file)
index 6bce7ee..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-[ dihedraltypes ]
-CP2 CP2  3   9.2789   12.156  -13.120 -3.0597 26.240 -31.495
-CH2 CH2  3   9.2789   12.156  -13.120 -3.0597 26.240 -31.495
diff --git a/share/top/buck.itp b/share/top/buck.itp
deleted file mode 100644 (file)
index c2a180e..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-[ nonbond_params ]
-; ai    aj             funct   a       b       c
-#ifdef MM3
-; Parameters from MM3
-C       C       2 2.07861e+04   2.94117e+01   1.17244e-03
-C       H       2 1.77067e+04   3.37078e+01   4.40743e-04
-H       H       2 1.53971e+04   3.70370e+01   2.17819e-04
-#else
-; Parameters from Dauchez et. al. (JCC Vol 14 No. 3 1992)
-C       C       2 3.49908e+05   3.60000e+01   2.37651e-03
-C       O       2 1.59912e+05   3.88100e+01   1.10709e-03
-C       H       2 3.66769e+04   3.67000e+01   5.23000e-04
-O       O       2 4.03756e+05   4.33300e+01   1.44766e-03
-O       H       2 2.40580e+05   4.72700e+01   5.10448e-04
-H       H       2 1.11043e+04   3.74000e+01   1.14223e-04
-#endif
index 6a32b23c42e57c465a6ff1929e55c21f1815ae87..e966d6a7ebe7e0203c9323afbaeb3d4a84d7d6cd 100644 (file)
@@ -10,7 +10,8 @@ aminoacids.c.tdb atomtypes.atp    ffnb.itp         lipids.rtp \
 aminoacids.hdb   cmap.itp         forcefield.doc   rna.rtp     \
 aminoacids.n.tdb dna.rtp          forcefield.itp   spc.itp     \
 aminoacids.r2b   ffbon.itp        gb.itp           tip3p.itp   \
-aminoacids.rtp   ffnabon.itp      ions.itp         tip4p.itp
+aminoacids.rtp   ffnabon.itp      ions.itp         tip4p.itp   \
+spce.itp       tips3p.itp      watermodels.dat
 
 EXTRA_DIST = ${topol_DATA}
 
index 9f5b2c9521717734c6be44c032ea36260242ec1f..b0870caf1b3175e87205b497d3b841d08ef6bba9 100644 (file)
 [ impropers ]
  C     CA      OT2     OT1      
 
-; Not part of CHARMM27, created by Michel Cuendet.
+; Created by Cuendet and Bjelkmar.
 [ COOH ]
 [ replace ]
- C             CD              12.011  0.72
+ C     C       CD              12.011  0.72
+ O     OT1     OB              15.9994 -0.55 
+ OXT   OT2     OH              15.9994 -0.61
 [ add ]
  2     8       OT      C       CA      N
        OB      15.9994 -0.55
  1     2       HT2     OT2     C       CA
        H       1.008   0.44
 [ replace ]
- OT2           OH1             15.9994 -0.61
-[ delete ]
- O
+ OT2   OT2     OH1             15.9994 -0.61
 [ impropers ]
  C     CA      OT2     OT1
 
index fe9bfdb51505c060359dc6fdd958bcce57009874..1bde28e0162e572c1fe325ef33022f7f106a98ee 100644 (file)
@@ -1,8 +1,7 @@
-HISA   HSD
-HISB   HSE
+HISD   HSD
+HISE   HSE
 HISH   HSP
-CYSH   CYS
-LYS    LSN
-LYSH   LYS
+HIS1   HSD
+LYSN   LSN
 ASPH   ASPP
 GLUH   GLUP
index 293fe8098e64fcefd4c8f66fd9bf8f752336bd74..926144fdcf8caeeb1754553d720dd336bc7e4814 100644 (file)
        OH2     H1
        OH2     H2
 
+[ HO4 ] 
+; TIP4P
+ [ atoms ]
+       OW      OWT4    0.00    0
+       HW1     HWT4    0.52    0
+       HW2     HWT4    0.52    0
+       MW      MWT4    -1.04   0
+ [ bonds ]
+       OW      HW1
+       OW      HW2
+
 [ SOD ]
  [ atoms ]
        SOD     SOD     1.00    0
index 2d501431f869deec93c61fe118353587b7a45dd6..e9954d0f23212367d09b9e3c266ceef8fc63b24c 100644 (file)
@@ -2,6 +2,7 @@ H       1.00800 ;       polar H
 HC     1.00800 ;       N-ter H 
 HA     1.00800 ;       nonpolar H 
 HT     1.00800 ;       TIPS3P WATER HYDROGEN 
+HT0    1.00800 ;       TIP3P WATER HYDROGEN 
 HP     1.00800 ;       aromatic H 
 HB     1.00800 ;       backbone H 
 HR1    1.00800 ;       his he1, (+) his HG,HD2 
@@ -189,15 +190,6 @@ ON6B       15.999400 ;     Nucleic acid ribose ring oxygen  ### For DNA
 ON2B   15.999400 ;     Nucleic acid phosphate ester oxygen (pres tp1/tp2, toppar_tyr_ser_thr_phosphate.str)  ### For DNA 
 FN1    18.998400 ;     Fluorine for sugar derivatives (NF)  ### For DNA 
 FNA    18.998400 ;     Aromatic fluorine  ### For DNA 
-CC1A   12.011000 ;     alkene conjugation  ### For DNA 
-CC1B   12.011000 ;     alkene conjugation  ### For DNA 
-CC2    12.011000 ;     alkene conjugation  ### For DNA 
-NS1    14.007000 ;     N for deprotonated Schiff's base  ### For DNA 
-NS2    14.007000 ;     N for protonated Schiff's base  ### For DNA 
-SP     32.060000 ;     positive Sulphur, S-adenosylmethionine (SAM)  ### For DNA 
-CPH1   12.011000 ;     For imidazole model compound (NF) 
-CPH2   12.011000 ;     For imidazole model compound (NF) 
-HR3    1.008000 ;      For imidazole model compound (NF) 
-HR1    1.008000 ;      For imidazole model compound (NF) 
-NR1    14.007000 ;     For nitrogen in imidazol (NF) 
-NR2    14.007000 ;     For nitrogen in imidazol (NF) 
+OWT4   15.999400 ;     For TIP4P
+HWT4   1.008000 ;      For TIP4P
+MWT4   0.000000 ;      For TIP4P
index 1aed2b2ba65cf94cf58cff3e2093509b527d3497..aa31bba4c7a7eb96cf51e2aa9d8c69bae36f037f 100644 (file)
@@ -37,21 +37,19 @@ HR1 1       1.008000        0.13    A       0.160361769265  0.192464
 HR2    1       1.008000        0.18    A       0.12472582054   0.192464 
 HR3    1       1.008000        0.09    A       0.261567863646  0.0326352 
 HS     1       1.008000        0.16    A       0.0801808846326 0.4184 
-#ifdef CHARMM_TIP3P
+; CHARMM_TIP3P
 #ifdef HEAVY_H
-HT     1       4.032   0.417   A       0.0400013524445 0.192464 
+HT     1       4.032           0.417   A       0.0400013524445 0.192464 
 #else 
-; CHARMM_TIP3P, but not HEAVY_H 
+; CHARMM_TIP3P, but not HEAVY_H
 HT     1       1.008000        0.417   A       0.0400013524445 0.192464 
 #endif
-#else 
 ; normal TIP3p 
 #ifdef HEAVY_H
-HT     1       4.032   0.417   A       0.0     0.0 
+HT0    1       4.032           0.417   A       0.0     0.0 
 #else 
-; normal TIP3P, but not HEAVY_H 
-HT     1       1.008000        0.417   A       0.0     0.0 
-#endif
+; normal TIP3P, but not HEAVY_H
+HT0    1       1.008000        0.417   A       0.0     0.0 
 #endif
 HA1    1       1.008000        0.000   A       0.235197261589  0.092048 ; partial charge def not found
 HA2    1       1.008000        0.000   A       0.238760856462  0.117152 ; partial charge def not found
@@ -211,7 +209,6 @@ CP1 HR1     1       0.249451641079  0.0897368027066
 CP1    HR2     1       0.231633666716  0.0897368027066
 CP1    HR3     1       0.300054688269  0.0369520874647
 CP1    HS      1       0.209361198763  0.132309697301
-CP1    HT      1       0.189271432669  0.0897368027066
 CP1    HA1     1       0.286869387241  0.06205874894
 CP1    HA2     1       0.288651184678  0.0700117110204
 CP1    HA3     1       0.288651184678  0.0648182492821
@@ -329,7 +326,6 @@ CP2 HR1     1       0.249451641079  0.0897368027066
 CP2    HR2     1       0.231633666716  0.0897368027066
 CP2    HR3     1       0.300054688269  0.0369520874647
 CP2    HS      1       0.209361198763  0.132309697301
-CP2    HT      1       0.189271432669  0.0897368027066
 CP2    HA1     1       0.286869387241  0.06205874894
 CP2    HA2     1       0.288651184678  0.0700117110204
 CP2    HA3     1       0.288651184678  0.0648182492821
@@ -446,7 +442,6 @@ CP3 HR1     1       0.249451641079  0.0897368027066
 CP3    HR2     1       0.231633666716  0.0897368027066
 CP3    HR3     1       0.300054688269  0.0369520874647
 CP3    HS      1       0.209361198763  0.132309697301
-CP3    HT      1       0.189271432669  0.0897368027066
 CP3    HA1     1       0.286869387241  0.06205874894
 CP3    HA2     1       0.288651184678  0.0700117110204
 CP3    HA3     1       0.288651184678  0.0648182492821
@@ -562,7 +557,6 @@ CPT HR1     1       0.249451641079  0.26921040812
 CPT    HR2     1       0.231633666716  0.26921040812
 CPT    HR3     1       0.300054688269  0.110856262394
 CPT    HS      1       0.209361198763  0.396929091904
-CPT    HT      1       0.189271432669  0.26921040812
 CPT    HA1     1       0.286869387241  0.18617624682
 CPT    HA2     1       0.288651184678  0.210035133061
 CPT    HA3     1       0.288651184678  0.194454747846
@@ -677,7 +671,6 @@ CT1 HR1     1       0.249451641079  0.0897368027066
 CT1    HR2     1       0.231633666716  0.0897368027066
 CT1    HR3     1       0.300054688269  0.0369520874647
 CT1    HS      1       0.209361198763  0.132309697301
-CT1    HT      1       0.189271432669  0.0897368027066
 CT1    HA1     1       0.286869387241  0.06205874894
 CT1    HA2     1       0.288651184678  0.0700117110204
 CT1    HA3     1       0.288651184678  0.0648182492821
@@ -791,7 +784,6 @@ CT2 HR1     1       0.249451641079  0.0897368027066
 CT2    HR2     1       0.231633666716  0.0897368027066
 CT2    HR3     1       0.300054688269  0.0369520874647
 CT2    HS      1       0.209361198763  0.132309697301
-CT2    HT      1       0.189271432669  0.0897368027066
 CT2    HA1     1       0.286869387241  0.06205874894
 CT2    HA2     1       0.288651184678  0.0700117110204
 CT2    HA3     1       0.288651184678  0.0648182492821
@@ -904,7 +896,6 @@ CT3 HR1     1       0.249451641079  0.0897368027066
 CT3    HR2     1       0.231633666716  0.0897368027066
 CT3    HR3     1       0.300054688269  0.0369520874647
 CT3    HS      1       0.209361198763  0.132309697301
-CT3    HT      1       0.189271432669  0.0897368027066
 CT3    HA1     1       0.286869387241  0.06205874894
 CT3    HA2     1       0.288651184678  0.0700117110204
 CT3    HA3     1       0.288651184678  0.0648182492821
@@ -1016,7 +1007,6 @@ CT        HR1     1       0.249451641079  0.0897368027066
 CT     HR2     1       0.231633666716  0.0897368027066
 CT     HR3     1       0.300054688269  0.0369520874647
 CT     HS      1       0.209361198763  0.132309697301
-CT     HT      1       0.189271432669  0.0897368027066
 CT     HA1     1       0.286869387241  0.06205874894
 CT     HA2     1       0.288651184678  0.0700117110204
 CT     HA3     1       0.288651184678  0.0648182492821
@@ -1127,7 +1117,6 @@ CT1x      HR1     1       0.249451641079  0.0897368027066
 CT1x   HR2     1       0.231633666716  0.0897368027066
 CT1x   HR3     1       0.300054688269  0.0369520874647
 CT1x   HS      1       0.209361198763  0.132309697301
-CT1x   HT      1       0.189271432669  0.0897368027066
 CT1x   HA1     1       0.286869387241  0.06205874894
 CT1x   HA2     1       0.288651184678  0.0700117110204
 CT1x   HA3     1       0.288651184678  0.0648182492821
@@ -1237,7 +1226,6 @@ CT2x      HR1     1       0.249451641079  0.0897368027066
 CT2x   HR2     1       0.231633666716  0.0897368027066
 CT2x   HR3     1       0.300054688269  0.0369520874647
 CT2x   HS      1       0.209361198763  0.132309697301
-CT2x   HT      1       0.189271432669  0.0897368027066
 CT2x   HA1     1       0.286869387241  0.06205874894
 CT2x   HA2     1       0.288651184678  0.0700117110204
 CT2x   HA3     1       0.288651184678  0.0648182492821
@@ -1346,7 +1334,6 @@ CT3x      HR1     1       0.249451641079  0.0897368027066
 CT3x   HR2     1       0.231633666716  0.0897368027066
 CT3x   HR3     1       0.300054688269  0.0369520874647
 CT3x   HS      1       0.209361198763  0.132309697301
-CT3x   HT      1       0.189271432669  0.0897368027066
 CT3x   HA1     1       0.286869387241  0.06205874894
 CT3x   HA2     1       0.288651184678  0.0700117110204
 CT3x   HA3     1       0.288651184678  0.0648182492821
@@ -1454,7 +1441,6 @@ HP        HR1     1       0.20118274853   0.155428701597
 HP     HR2     1       0.183364774168  0.155428701597
 HP     HR3     1       0.251785795721  0.0640028929346
 HP     HS      1       0.161092306214  0.22916711806
-HP     HT      1       0.14100254012   0.155428701597
 HP     HA1     1       0.238600494692  0.107488906218
 HP     HA2     1       0.240382292129  0.121263840612
 HP     HA3     1       0.240382292129  0.112268501014
@@ -1561,7 +1547,6 @@ N HR1     1       0.244997147489  0.00897368027066
 N      HR2     1       0.227179173126  0.00897368027066
 N      HR3     1       0.295600194679  0.00369520874647
 N      HS      1       0.204906705172  0.0132309697301
-N      HT      1       0.184816939078  0.00897368027066
 N      HA1     1       0.28241489365   0.006205874894
 N      HA2     1       0.284196691087  0.00700117110204
 N      HA3     1       0.284196691087  0.00648182492821
@@ -1667,7 +1652,6 @@ NH1       HR1     1       0.218270185945  0.401315181871
 NH1    HR2     1       0.200452211582  0.401315181871
 NH1    HR3     1       0.268873233135  0.165254758963
 NH1    HS      1       0.178179743628  0.591706954497
-NH1    HT      1       0.158089977534  0.401315181871
 NH1    HA1     1       0.255687932106  0.277535162457
 NH1    HA2     1       0.257469729543  0.313101890125
 NH1    HA3     1       0.257469729543  0.289876023155
@@ -1772,7 +1756,6 @@ O HR1     1       0.204906705172  0.310857403193
 O      HR2     1       0.18708873081   0.310857403193
 O      HR3     1       0.255509752363  0.128005785869
 O      HS      1       0.164816262856  0.45833423612
-O      HT      1       0.144726496762  0.310857403193
 O      HA1     1       0.242324451334  0.214977812437
 O      HA2     1       0.24410624877   0.242527681224
 O      HA3     1       0.24410624877   0.224537002029
@@ -1876,7 +1859,6 @@ OB        HR1     1       0.204906705172  0.310857403193
 OB     HR2     1       0.18708873081   0.310857403193
 OB     HR3     1       0.255509752363  0.128005785869
 OB     HS      1       0.164816262856  0.45833423612
-OB     HT      1       0.144726496762  0.310857403193
 OB     HA1     1       0.242324451334  0.214977812437
 OB     HA2     1       0.24410624877   0.242527681224
 OB     HA3     1       0.24410624877   0.224537002029
@@ -1979,7 +1961,6 @@ OCA       HR1     1       0.204906705172  0.310857403193
 OCA    HR2     1       0.18708873081   0.310857403193
 OCA    HR3     1       0.255509752363  0.128005785869
 OCA    HS      1       0.164816262856  0.45833423612
-OCA    HT      1       0.144726496762  0.310857403193
 OCA    HA1     1       0.242324451334  0.214977812437
 OCA    HA2     1       0.24410624877   0.242527681224
 OCA    HA3     1       0.24410624877   0.224537002029
@@ -2081,7 +2062,6 @@ CTL1      HR1     1       0.249451641079  0.0897368027066
 CTL1   HR2     1       0.231633666716  0.0897368027066
 CTL1   HR3     1       0.300054688269  0.0369520874647
 CTL1   HS      1       0.209361198763  0.132309697301
-CTL1   HT      1       0.189271432669  0.0897368027066
 CTL1   HA1     1       0.286869387241  0.06205874894
 CTL1   HA2     1       0.288651184678  0.0700117110204
 CTL1   HA3     1       0.288651184678  0.0648182492821
@@ -2182,7 +2162,6 @@ CTL2      HR1     1       0.249451641079  0.0897368027066
 CTL2   HR2     1       0.231633666716  0.0897368027066
 CTL2   HR3     1       0.300054688269  0.0369520874647
 CTL2   HS      1       0.209361198763  0.132309697301
-CTL2   HT      1       0.189271432669  0.0897368027066
 CTL2   HA1     1       0.286869387241  0.06205874894
 CTL2   HA2     1       0.288651184678  0.0700117110204
 CTL2   HA3     1       0.288651184678  0.0648182492821
@@ -2282,7 +2261,6 @@ CTL3      HR1     1       0.249451641079  0.0897368027066
 CTL3   HR2     1       0.231633666716  0.0897368027066
 CTL3   HR3     1       0.300054688269  0.0369520874647
 CTL3   HS      1       0.209361198763  0.132309697301
-CTL3   HT      1       0.189271432669  0.0897368027066
 CTL3   HA1     1       0.286869387241  0.06205874894
 CTL3   HA2     1       0.288651184678  0.0700117110204
 CTL3   HA3     1       0.288651184678  0.0648182492821
@@ -2381,7 +2359,6 @@ CTL5      HR1     1       0.249451641079  0.0897368027066
 CTL5   HR2     1       0.231633666716  0.0897368027066
 CTL5   HR3     1       0.300054688269  0.0369520874647
 CTL5   HS      1       0.209361198763  0.132309697301
-CTL5   HT      1       0.189271432669  0.0897368027066
 CTL5   HA1     1       0.286869387241  0.06205874894
 CTL5   HA2     1       0.288651184678  0.0700117110204
 CTL5   HA3     1       0.288651184678  0.0648182492821
@@ -2479,7 +2456,6 @@ OBL       HR1     1       0.204906705172  0.310857403193
 OBL    HR2     1       0.18708873081   0.310857403193
 OBL    HR3     1       0.255509752363  0.128005785869
 OBL    HS      1       0.164816262856  0.45833423612
-OBL    HT      1       0.144726496762  0.310857403193
 OBL    HA1     1       0.242324451334  0.214977812437
 OBL    HA2     1       0.24410624877   0.242527681224
 OBL    HA3     1       0.24410624877   0.224537002029
index a4f29e117c2fb5b4d99ef3949085394730fb4e95..473e594fbc123f2f9818365125a2bac5a96b05f7 100644 (file)
@@ -2,9 +2,9 @@
 
 ; Atom type    sar     st      pi      gbr      hct
  NH1            0.155   1       1.028   0.17063  0.79 ; N
- N             0.155   1       1       0.155    0.79 ; Proline backbone N
- NP            0.155   1       1       0.155    0.79 ; Proline backbone N for Proline N-terminus
- H              0.1     1       1       0.115    0.85 ; H
+ N             0.155   1       1       0.17063  0.79 ; Proline backbone N
+ NP            0.155   1       1       0.17063  0.79 ; Proline backbone N-termini
+ H              0.1     1       1       0.115    0.85 ; Should be 0.105 when hydroxyl or carboxylic hydrogen
  CT1            0.180   1       1.276   0.190    0.72 ; C
  HB             0.1     1       1       0.125    0.85 ; H
  CT3            0.200   1       0.880   0.190    0.72 ; C
@@ -28,7 +28,7 @@
  HR1            0.1     1       1       0.125    0.85 ; H
  HR2            0.1     1       1       0.125    0.85 ; H
  NR2            0.155   1       1.215   0.17063  0.79 ; N
- HR3            0.1     1       1       0.115    0.85 ; H
+ HR3            0.1     1       1       0.125    0.85 ; H
  NR3            0.155   1       1.215   0.17063  0.79 ; N
  NH3            0.160   1       1.215   0.1625   0.79 ; N
  HP             0.1     1       1       0.125    0.85 ; H
diff --git a/share/top/charmm27.ff/spce.itp b/share/top/charmm27.ff/spce.itp
new file mode 100644 (file)
index 0000000..7267e3d
--- /dev/null
@@ -0,0 +1,29 @@
+[ moleculetype ]
+; molname      nrexcl
+SOL            2
+
+[ atoms ]
+;   nr   type  resnr residue  atom   cgnr     charge       mass
+     1     OW   1    SOL     OW      1      -0.8476
+     2     HW   1    SOL    HW1      1       0.4238
+     3     HW   1    SOL    HW2      1       0.4238
+
+#ifndef FLEXIBLE
+[ settles ]
+; OW   funct   doh     dhh
+1      1       0.1     0.16330
+
+[ exclusions ]
+1      2       3
+2      1       3
+3      1       2
+#else
+[ bonds ]
+; i    j       funct   length  force.c.
+1      2       1       0.1     345000  0.1     345000
+1      3       1       0.1     345000  0.1     345000
+       
+[ angles ]
+; i    j       k       funct   angle   force.c.
+2      1       3       1       109.47  383     109.47  383
+#endif
index a7366eb41e29d381186c6a44e9761bd083441139..9c3baac59df1c923907a32dea63714619de46d6f 100644 (file)
@@ -4,24 +4,19 @@ SOL           2
 
 [ atoms ]
 ; id   at type res nr  residu name     at name         cg nr   charge
-#ifdef _FF_CHARMM
 1       OT      1       SOL              OW             1       -0.834
-2       HT      1       SOL             HW1             1        0.417
-3       HT      1       SOL             HW2             1        0.417
-#endif
-
+2       HT0     1       SOL             HW1             1        0.417
+3       HT0     1       SOL             HW2             1        0.417
 
-#ifdef FLEXIBLE
+#ifndef FLEXIBLE
+[ settles ]
+; i      j     funct   length
+1        1     0.09572 0.15139
 
-#ifdef CHARMM_TIP3P 
-[ bonds ]
-; i    j       funct   length  force.c.
-1      2       1       0.09572 376560.0 0.09572        376560.0 
-1      3       1       0.09572 376560.0 0.09572        376560.0 
-  
-[ angles ]
-; i     j      k       funct   angle   force.c.
-2       1      3       1       104.52  460.24  104.52  460.24  
+[ exclusions ]
+1 2 3
+2 1 3
+3 1 2
 #else
 [ bonds ]
 ; i    j       funct   length  force.c.
@@ -32,15 +27,3 @@ SOL          2
 ; i     j      k       funct   angle   force.c.
 2       1      3       1       104.52  628.02  104.52  628.02  
 #endif
-
-
-#else
-[ settles ]
-; i      j     funct   length
-1        1     0.09572 0.15139
-
-[ exclusions ]
-1 2 3
-2 1 3
-3 1 2
-#endif
diff --git a/share/top/charmm27.ff/tips3p.itp b/share/top/charmm27.ff/tips3p.itp
new file mode 100644 (file)
index 0000000..3f6a424
--- /dev/null
@@ -0,0 +1,29 @@
+[ moleculetype ]
+; molname      nrexcl
+SOL            2
+
+[ atoms ]
+; id   at type res nr  residu name     at name         cg nr   charge
+1       OT      1       SOL              OW             1       -0.834
+2       HT      1       SOL             HW1             1        0.417
+3       HT      1       SOL             HW2             1        0.417
+
+#ifndef FLEXIBLE
+[ settles ]
+; i      j     funct   length
+1        1     0.09572 0.15139
+
+[ exclusions ]
+1 2 3
+2 1 3
+3 1 2
+#else
+[ bonds ]
+; i    j       funct   length  force.c.
+1      2       1       0.09572 376560.0 0.09572        376560.0 
+1      3       1       0.09572 376560.0 0.09572        376560.0 
+  
+[ angles ]
+; i     j      k       funct   angle   force.c.
+2       1      3       1       104.52  460.24  104.52  460.24  
+#endif
diff --git a/share/top/charmm27.ff/watermodels.dat b/share/top/charmm27.ff/watermodels.dat
new file mode 100644 (file)
index 0000000..671895f
--- /dev/null
@@ -0,0 +1,6 @@
+tip3p   TIP3P   TIP 3-point, recommended
+tip4p   TIP4P   TIP 4-point
+tip5p   TIP5P   TIP 5-point
+tips3p  TIPS3P  CHARMM TIP 3-point with LJ on H's (note: twice as slow in GROMACS)
+spc     SPC     simple point charge
+spce    SPC/E   extended simple point charge
index 4180ac5840fed146c9002f1acb25dba9343e349c..784d19cbedcbb9a586ceb87174fa93498793623c 100644 (file)
@@ -8,9 +8,9 @@ protein = resname ABU ACE AIB ALA ARG ARGN ASN ASN1 ASP ASP1 ASPH
 "Protein-H"      protein and not name "H*" "[0-9]?H.*";
 "C-alpha"        protein and name CA;
 "Backbone"       protein and name N CA C;
-"MainChain"      protein and name N CA C O O1 O2 OXT;
-"MainChain+Cb"   protein and name N CA CB C O O1 O2 OXT;
-"MainChain+H"    protein and name N CA C O O1 O2 OT OXT H1 H2 H3 H "[0-9]?H";
+"MainChain"      protein and name N CA C O O1 O2 OC1 OC2 OT OXT;
+"MainChain+Cb"   protein and name N CA CB C O O1 O2 OC1 OC2 OT OXT;
+"MainChain+H"    protein and name N CA C O O1 O2 OC1 OC2 OT OXT H1 H2 H3 H "[0-9]?H";
 "SideChain"      protein and not name N CA C O O1 O2 OT OXT H1 H2 H3 H "[0-9]?H";
 "SideChain-H"    protein and not name N CA C O O1 O2 OT OXT "H*" "[0-9]?H.*";
 "Prot-Masses"    protein and not name MN1 MN2 MCB1 MCB2 MCG1 MCG2 MCD1 MCD2 MCE1 MCE2 MNZ1 MNZ2;
diff --git a/share/top/dmso.gro b/share/top/dmso.gro
deleted file mode 100644 (file)
index 42649dc..0000000
+++ /dev/null
@@ -1,835 +0,0 @@
-Pure DMSO, 200 ps Equilibration run at 300 K. DvdS 26/02/95
-  832
-    1DMSO    SD    1   2.915   1.878   2.580 -0.2435  0.1688 -0.2164
-    1DMSO   CD1    2   2.764   1.908   2.461 -0.0608  0.4317 -0.3840
-    1DMSO    OD    3   2.852   1.844   2.715 -0.1943 -0.6301 -0.3887
-    1DMSO   CD2    4   2.964   1.705   2.506 -0.8067 -0.2363  0.3290
-    2DMSO    SD    5   2.893   0.696   1.134  0.1596  0.0027  0.2853
-    2DMSO   CD1    6   2.787   0.578   1.020 -0.3099  0.3434  0.3729
-    2DMSO    OD    7   2.839   0.838   1.116 -0.0463 -0.1506 -0.3567
-    2DMSO   CD2    8   2.843   0.624   1.308  0.5615  0.0386  0.4130
-    3DMSO    SD    9   0.620   1.691   1.180  0.1682 -0.0369 -0.0753
-    3DMSO   CD1   10   0.718   1.778   1.036 -0.1599 -0.0405 -0.3042
-    3DMSO    OD   11   0.584   1.563   1.104  0.0159 -0.0079 -0.0551
-    3DMSO   CD2   12   0.767   1.654   1.303 -0.3406  0.0902  0.5836
-    4DMSO    SD   13   2.264   2.260   2.008  0.2096  0.0293  0.1754
-    4DMSO   CD1   14   2.186   2.165   1.857  0.3713  0.3718 -0.1247
-    4DMSO    OD   15   2.283   2.409   1.979 -0.1800  0.0529  0.0423
-    4DMSO   CD2   16   2.093   2.260   2.102  0.1315  0.0484  0.0353
-    5DMSO    SD   17   1.725   2.836   1.513 -0.0783 -0.1507 -0.2909
-    5DMSO   CD1   18   1.854   2.798   1.654 -0.2961 -0.0955 -0.0768
-    5DMSO    OD   19   1.591   2.798   1.576 -0.1178  0.3079 -0.0997
-    5DMSO   CD2   20   1.745   3.029   1.521  0.5401 -0.2434  0.4994
-    6DMSO    SD   21   1.005   0.466   0.330 -0.3035 -0.4799  0.1949
-    6DMSO   CD1   22   0.860   0.373   0.420 -0.6714 -0.1368 -0.0370
-    6DMSO    OD   23   0.955   0.490   0.188 -0.1032 -0.7419  0.0758
-    6DMSO   CD2   24   0.974   0.633   0.425 -0.2182 -0.2018 -0.2728
-    7DMSO    SD   25   0.187   1.467   0.054 -0.0656 -0.2666  0.1195
-    7DMSO   CD1   26   0.091   1.589  -0.065  0.4751 -0.2864 -0.3392
-    7DMSO    OD   27   0.159   1.326   0.002  0.4067 -0.2758 -0.1154
-    7DMSO   CD2   28   0.375   1.507   0.020 -0.0589 -0.6598 -0.3131
-    8DMSO    SD   29   0.117   0.736   1.833 -0.0278 -0.1966 -0.0829
-    8DMSO   CD1   30   0.063   0.899   1.924 -0.6302 -0.3517 -0.1602
-    8DMSO    OD   31   0.132   0.627   1.940 -0.4293 -0.1368  0.0324
-    8DMSO   CD2   32  -0.050   0.691   1.745  0.0488 -0.2570 -0.2059
-    9DMSO    SD   33   1.222   1.472   0.491 -0.4523  0.3486 -0.4296
-    9DMSO   CD1   34   1.122   1.343   0.384 -0.3135 -0.2618  0.1527
-    9DMSO    OD   35   1.196   1.448   0.640  0.3825  0.3794 -0.2733
-    9DMSO   CD2   36   1.402   1.409   0.448 -0.3399  0.6361 -0.3836
-   10DMSO    SD   37   0.850   0.792   2.553  0.0360  0.1920 -0.1967
-   10DMSO   CD1   38   0.885   0.605   2.594  0.0380  0.1875 -0.2160
-   10DMSO    OD   39   0.751   0.830   2.663  0.2662 -0.1098  0.1159
-   10DMSO   CD2   40   1.028   0.857   2.597  0.2414 -0.3881 -0.1625
-   11DMSO    SD   41   1.151   0.225   0.819 -0.2380 -0.1951  0.2490
-   11DMSO   CD1   42   1.166   0.189   0.628 -0.3387  0.1023  0.1884
-   11DMSO    OD   43   1.030   0.315   0.844 -0.0672  0.1090  0.0015
-   11DMSO   CD2   44   1.095   0.044   0.862  0.0251 -0.2353  0.4298
-   12DMSO    SD   45   2.787   1.781   1.382 -0.1556 -0.0358 -0.0186
-   12DMSO   CD1   46   2.697   1.845   1.222 -0.2487 -0.2713 -0.0663
-   12DMSO    OD   47   2.938   1.772   1.359 -0.1462  0.5978 -0.2086
-   12DMSO   CD2   48   2.753   1.936   1.495  1.0564  0.3097 -0.1110
-   13DMSO    SD   49   2.146   1.962   0.831 -0.4005  0.0201 -0.2676
-   13DMSO   CD1   50   2.000   1.843   0.782 -0.1510 -0.3073 -0.2163
-   13DMSO    OD   51   2.085   2.100   0.860  0.0322  0.0772  0.4092
-   13DMSO   CD2   52   2.187   1.897   1.010  0.3011  0.4826 -0.2452
-   14DMSO    SD   53   1.687   1.547   0.674  0.1017 -0.2890 -0.2877
-   14DMSO   CD1   54   1.685   1.660   0.833 -0.2577 -0.2230 -0.3375
-   14DMSO    OD   55   1.838   1.528   0.653  0.2129 -0.0980  0.3211
-   14DMSO   CD2   56   1.619   1.394   0.774  0.1941 -0.1277  0.0257
-   15DMSO    SD   57   2.630   2.290   2.069 -0.1191 -0.7534 -0.0608
-   15DMSO   CD1   58   2.689   2.453   2.159  0.4199 -0.8949 -0.1525
-   15DMSO    OD   59   2.724   2.271   1.950 -0.1684  1.0946 -0.4280
-   15DMSO   CD2   60   2.672   2.144   2.191 -0.1770 -0.5909  0.1558
-   16DMSO    SD   61   2.228   0.713   2.313 -0.2089  0.0723 -0.0471
-   16DMSO   CD1   62   2.156   0.567   2.204  0.3440 -0.4807  0.3076
-   16DMSO    OD   63   2.143   0.739   2.438 -0.2857  0.2572 -0.1374
-   16DMSO   CD2   64   2.386   0.614   2.370 -0.4013 -0.2731 -0.1012
-   17DMSO    SD   65   1.452   1.450   2.681 -0.2099 -0.2486  0.1148
-   17DMSO   CD1   66   1.501   1.630   2.626 -0.3949 -0.1878  0.1452
-   17DMSO    OD   67   1.464   1.438   2.833  0.3079 -0.3054  0.0714
-   17DMSO   CD2   68   1.262   1.472   2.645 -0.1256 -0.3092 -0.3765
-   18DMSO    SD   69   2.729   0.530   0.123  0.1503  0.2629  0.0744
-   18DMSO   CD1   70   2.881   0.650   0.148  0.2716  0.0883  0.2315
-   18DMSO    OD   71   2.766   0.434   0.010  0.0451  0.0851  0.1925
-   18DMSO   CD2   72   2.757   0.416   0.278 -0.1110  0.7131  0.4579
-   19DMSO    SD   73   2.528   2.660   0.691  0.1116  0.1910  0.3180
-   19DMSO   CD1   74   2.709   2.710   0.638 -0.0274  0.3599 -0.0084
-   19DMSO    OD   75   2.516   2.509   0.674 -0.3023  0.2384  0.1575
-   19DMSO   CD2   76   2.552   2.712   0.877 -0.1496  0.2762  0.3304
-   20DMSO    SD   77   2.179   2.187   0.519 -0.1965 -0.1237  0.2664
-   20DMSO   CD1   78   1.993   2.244   0.508 -0.1430 -0.0480 -0.3707
-   20DMSO    OD   79   2.251   2.260   0.405 -0.1152 -0.4990  0.0734
-   20DMSO   CD2   80   2.213   2.300   0.674  0.1804  0.4423 -0.2325
-   21DMSO    SD   81   1.170   1.582   0.971  0.0536  0.4675 -0.1386
-   21DMSO   CD1   82   1.213   1.630   1.155 -0.5253  0.1177  0.0956
-   21DMSO    OD   83   1.039   1.658   0.946 -0.3586 -0.2832 -0.3068
-   21DMSO   CD2   84   1.307   1.696   0.894  0.2375  0.3996  0.0844
-   22DMSO    SD   85   0.243   0.353   1.218  0.1199  0.0907 -0.0836
-   22DMSO   CD1   86   0.395   0.282   1.316  0.1801  0.4442  0.0911
-   22DMSO    OD   87   0.249   0.506   1.224  0.1678  0.0862 -0.0075
-   22DMSO   CD2   88   0.288   0.276   1.044 -0.1555  0.3827 -0.2864
-   23DMSO    SD   89   1.880   1.177   0.518  0.1186  0.1922 -0.0372
-   23DMSO   CD1   90   1.931   1.188   0.706 -0.1752  0.1760  0.0474
-   23DMSO    OD   91   1.729   1.202   0.513 -0.0308 -0.6801 -0.0132
-   23DMSO   CD2   92   1.968   1.332   0.440 -0.3749  0.5990  0.2067
-   24DMSO    SD   93   2.535   2.684   1.838 -0.4172 -0.2809  0.0905
-   24DMSO   CD1   94   2.396   2.721   1.970  0.0463  0.3810  0.4055
-   24DMSO    OD   95   2.493   2.772   1.720 -0.5212 -0.0112  0.3241
-   24DMSO   CD2   96   2.679   2.784   1.925 -0.2818 -0.2048 -0.2268
-   25DMSO    SD   97   2.676   1.166   1.779  0.3963  0.2202 -0.1794
-   25DMSO   CD1   98   2.496   1.091   1.785  0.4791  0.0060 -0.2478
-   25DMSO    OD   99   2.727   1.154   1.923 -0.3194 -0.0958  0.0564
-   25DMSO   CD2  100   2.757   1.028   1.667  0.9429  0.3781  0.0297
-   26DMSO    SD  101   2.834   1.188   1.352 -0.0298  0.3201  0.0668
-   26DMSO   CD1  102   2.861   1.240   1.165  0.2325  0.4812  0.1479
-   26DMSO    OD  103   2.701   1.115   1.374  0.3037 -0.2467  0.1999
-   26DMSO   CD2  104   2.966   1.045   1.354  0.2112  0.5428  0.3179
-   27DMSO    SD  105   0.061   2.744   0.984 -0.0076  0.0200  0.2086
-   27DMSO   CD1  106   0.035   2.556   1.029  0.0623 -0.0079  0.1476
-   27DMSO    OD  107  -0.046   2.797   0.888  0.0888 -0.4305 -0.1425
-   27DMSO   CD2  108   0.039   2.846   1.149 -0.2318 -0.4628  0.4843
-   28DMSO    SD  109   2.103   1.229   2.460 -0.2184  0.1146  0.1781
-   28DMSO   CD1  110   2.205   1.064   2.473 -0.0373  0.2396  0.3573
-   28DMSO    OD  111   2.021   1.203   2.333  0.3576  0.4179 -0.2679
-   28DMSO   CD2  112   1.985   1.209   2.614 -0.6566 -0.3816 -0.2209
-   29DMSO    SD  113   0.509   0.613   1.474 -0.0756 -0.5906  0.0699
-   29DMSO   CD1  114   0.316   0.621   1.503 -0.0190  0.5901  0.1457
-   29DMSO    OD  115   0.558   0.470   1.496 -0.0174 -0.4771  0.7317
-   29DMSO   CD2  116   0.491   0.655   1.285  0.1436 -0.7317  0.0241
-   30DMSO    SD  117   2.708   0.540   2.137 -0.1059  0.1653  0.3879
-   30DMSO   CD1  118   2.820   0.691   2.187  0.3035  0.0754 -0.2382
-   30DMSO    OD  119   2.645   0.567   2.000  0.4600  0.2983  0.1484
-   30DMSO   CD2  120   2.852   0.410   2.112 -0.5324 -0.1613 -0.3995
-   31DMSO    SD  121   2.590   1.296   2.570 -0.0598 -0.3898  0.3481
-   31DMSO   CD1  122   2.679   1.277   2.742  0.2285 -0.2792  0.2065
-   31DMSO    OD  123   2.442   1.262   2.584 -0.2216  0.1888  0.1075
-   31DMSO   CD2  124   2.607   1.490   2.558 -0.2594 -0.4079 -0.3246
-   32DMSO    SD  125   1.315   2.657   2.830 -0.0496 -0.0017  0.0106
-   32DMSO   CD1  126   1.444   2.790   2.891 -0.1667  0.1978 -0.1781
-   32DMSO    OD  127   1.177   2.706   2.872 -0.1373 -0.2564  0.0252
-   32DMSO   CD2  128   1.325   2.692   2.638  0.7142  0.2966  0.0972
-   33DMSO    SD  129   2.376   0.240   0.119  0.5156  0.1365  0.1799
-   33DMSO   CD1  130   2.552   0.169   0.072  0.2991 -0.6268  0.5352
-   33DMSO    OD  131   2.393   0.303   0.258  0.0978 -0.4506  0.5026
-   33DMSO   CD2  132   2.387   0.388  -0.006  0.3366  0.0488  0.0593
-   34DMSO    SD  133   0.087   2.526   1.935  0.0499 -0.4439  0.3131
-   34DMSO   CD1  134   0.168   2.356   1.985  0.2730 -0.1661  0.9006
-   34DMSO    OD  135   0.195   2.628   1.899 -0.4533 -0.3138 -0.8676
-   34DMSO   CD2  136   0.019   2.467   1.762  0.2806  0.3664 -0.0616
-   35DMSO    SD  137   1.780   1.497   0.093  0.0308 -0.0973 -0.0447
-   35DMSO   CD1  138   1.760   1.616   0.247  0.0917  0.1693 -0.2531
-   35DMSO    OD  139   1.927   1.458   0.087  0.2242  0.4259  0.9654
-   35DMSO   CD2  140   1.674   1.352   0.171 -0.6565  0.6431  0.4416
-   36DMSO    SD  141   1.713   1.039   2.399 -0.1739 -0.4488 -0.1576
-   36DMSO   CD1  142   1.731   1.163   2.250 -0.3588  0.4050  0.5288
-   36DMSO    OD  143   1.565   1.000   2.405 -0.4125  0.3701 -0.5449
-   36DMSO   CD2  144   1.808   0.895   2.307  0.4724 -0.2579  0.2197
-   37DMSO    SD  145   1.205   2.088   1.233  0.2683 -0.3870  0.0229
-   37DMSO   CD1  146   1.219   2.050   1.424  0.6694  0.0153  0.0862
-   37DMSO    OD  147   1.325   2.025   1.163  0.6024  0.3748 -0.0996
-   37DMSO   CD2  148   1.045   1.987   1.186 -0.1242  0.1562  0.1702
-   38DMSO    SD  149   1.527   1.063   0.771 -0.2351  0.0684  0.2590
-   38DMSO   CD1  150   1.673   0.948   0.712 -0.9106 -0.6749  0.0169
-   38DMSO    OD  151   1.430   1.063   0.652  0.3864 -0.1877 -0.2604
-   38DMSO   CD2  152   1.471   0.934   0.906 -0.0202 -0.3912 -0.0900
-   39DMSO    SD  153   0.742   0.518   0.825  0.1332 -0.1282 -0.0785
-   39DMSO   CD1  154   0.579   0.603   0.888  0.2281  0.0497 -0.0545
-   39DMSO    OD  155   0.723   0.503   0.674  0.6199 -0.0676 -0.1493
-   39DMSO   CD2  156   0.890   0.635   0.876  0.0991 -0.3299  0.5023
-   40DMSO    SD  157   2.501   1.735   0.818  0.0200 -0.1881 -0.2182
-   40DMSO   CD1  158   2.462   1.906   0.733  0.0687 -0.1470 -0.1642
-   40DMSO    OD  159   2.370   1.656   0.833 -0.4013  0.5568  0.0647
-   40DMSO   CD2  160   2.618   1.659   0.682  0.5548  0.1726  0.0259
-   41DMSO    SD  161   2.135   0.930   0.503  0.7237 -0.2773 -0.3028
-   41DMSO   CD1  162   2.232   0.794   0.605  0.0737  0.0629  0.8043
-   41DMSO    OD  163   2.190   0.935   0.360  0.5485  0.1016 -0.3583
-   41DMSO   CD2  164   1.968   0.829   0.501  0.5520 -0.0004 -0.0949
-   42DMSO    SD  165   2.674   0.651   0.543  0.2518  0.0202  0.0833
-   42DMSO   CD1  166   2.589   0.711   0.708  0.4877 -0.2151  0.2990
-   42DMSO    OD  167   2.709   0.503   0.564  0.0927 -0.0817 -0.3501
-   42DMSO   CD2  168   2.508   0.646   0.442  0.2481 -0.1867  0.0972
-   43DMSO    SD  169   1.788   0.630   1.010  0.1339  0.4230 -0.0259
-   43DMSO   CD1  170   1.657   0.489   1.038  0.1867  0.4944  0.6152
-   43DMSO    OD  171   1.900   0.624   1.115  0.2049  0.3765 -0.1029
-   43DMSO   CD2  172   1.858   0.565   0.840 -0.4005  0.5273 -0.2863
-   44DMSO    SD  173   0.541   2.392   2.832 -0.1214 -0.3109  0.3017
-   44DMSO   CD1  174   0.458   2.547   2.915 -0.3363  0.0163 -0.5013
-   44DMSO    OD  175   0.595   2.306   2.947  0.0372 -0.3303  0.2128
-   44DMSO   CD2  176   0.367   2.322   2.776 -0.0279  0.0421 -0.4390
-   45DMSO    SD  177   2.335   0.683   1.898  0.1493  0.2021  0.4730
-   45DMSO   CD1  178   2.389   0.722   1.715 -0.3334 -0.0426  0.2762
-   45DMSO    OD  179   2.184   0.705   1.895  0.0653 -0.3931  0.1720
-   45DMSO   CD2  180   2.362   0.490   1.884 -0.7851  0.0895  0.1001
-   46DMSO    SD  181   1.028   0.932   0.142  0.0263  0.2181 -0.2843
-   46DMSO   CD1  182   0.888   0.997   0.261 -0.2457 -0.9359  0.0400
-   46DMSO    OD  183   1.119   0.852   0.236  0.0628  0.2312 -0.3083
-   46DMSO   CD2  184   0.916   0.793   0.065  0.4231 -0.0945 -0.3031
-   47DMSO    SD  185   0.481   2.641   1.065  0.1310 -0.0900  0.0108
-   47DMSO   CD1  186   0.531   2.582   1.244 -0.0782  0.0188  0.1020
-   47DMSO    OD  187   0.340   2.699   1.068  0.1002 -0.1658  0.0779
-   47DMSO   CD2  188   0.609   2.786   1.043  0.2021 -0.2059 -0.3592
-   48DMSO    SD  189   0.844   2.651   2.727  0.3758  0.2468 -0.0340
-   48DMSO   CD1  190   0.953   2.543   2.606  0.1400  0.3682 -0.3618
-   48DMSO    OD  191   0.694   2.628   2.705  0.4326 -0.1438 -0.0323
-   48DMSO   CD2  192   0.877   2.536   2.881  0.7531  0.0874 -0.2322
-   49DMSO    SD  193   2.244   2.120   1.388  0.3070  0.2701  0.0923
-   49DMSO   CD1  194   2.408   2.046   1.315 -0.2396 -0.6592 -0.2165
-   49DMSO    OD  195   2.263   2.135   1.539  0.2594  0.0875  0.1165
-   49DMSO   CD2  196   2.232   2.284   1.283 -0.0486 -0.0700 -0.4088
-   50DMSO    SD  197   1.290   2.161   0.048 -0.3284  0.1788  0.0095
-   50DMSO   CD1  198   1.329   2.307   0.171 -0.7131  0.1776  0.1218
-   50DMSO    OD  199   1.162   2.099   0.106  0.3246 -0.2261  1.0687
-   50DMSO   CD2  200   1.242   2.277  -0.101 -0.9757  0.1800  0.2196
-   51DMSO    SD  201   1.850   2.733   2.166 -0.2294  0.3676  0.1750
-   51DMSO   CD1  202   1.982   2.696   2.027 -0.3343  0.1036  0.1525
-   51DMSO    OD  203   1.861   2.629   2.277  0.1549  0.0234 -0.1775
-   51DMSO   CD2  204   1.925   2.896   2.244 -0.0744  0.2626  0.2499
-   52DMSO    SD  205   0.128   2.273   1.430 -0.1938  0.2382  0.1840
-   52DMSO   CD1  206   0.145   2.085   1.381  0.3888  0.2348  0.3961
-   52DMSO    OD  207   0.257   2.345   1.390 -0.2507  0.2283 -0.0374
-   52DMSO   CD2  208  -0.016   2.335   1.314 -0.3275 -0.3250  0.0557
-   53DMSO    SD  209   1.673   2.548   0.776  0.1001 -0.2487  0.2280
-   53DMSO   CD1  210   1.617   2.539   0.962  0.2773  0.2156  0.3070
-   53DMSO    OD  211   1.822   2.582   0.767 -0.0104  0.4432  0.8765
-   53DMSO   CD2  212   1.678   2.359   0.730 -0.4963 -0.1650 -0.1914
-   54DMSO    SD  213   0.683   1.094   0.577  0.0528  0.4805 -0.0152
-   54DMSO   CD1  214   0.488   1.098   0.580  0.0367  0.2320 -0.5618
-   54DMSO    OD  215   0.723   1.155   0.711 -0.0961 -0.0114  0.2564
-   54DMSO   CD2  216   0.710   0.901   0.577  0.3510  0.5205  0.0795
-   55DMSO    SD  217   2.404   1.765   2.187 -0.0769 -0.0402  0.4017
-   55DMSO   CD1  218   2.431   1.901   2.050 -0.3313 -0.2591  0.1333
-   55DMSO    OD  219   2.328   1.651   2.118  0.1788  0.0130  0.0238
-   55DMSO   CD2  220   2.592   1.713   2.173 -0.1342 -0.1092 -0.1576
-   56DMSO    SD  221   1.039   0.776   1.361 -0.1611 -0.0454 -0.5522
-   56DMSO   CD1  222   1.078   0.887   1.206  0.1819  0.4723 -0.0845
-   56DMSO    OD  223   1.119   0.835   1.476  0.4097 -0.3068 -0.8124
-   56DMSO   CD2  224   0.854   0.836   1.373  0.0628  0.4897  0.2574
-   57DMSO    SD  225   0.267   2.743   0.525 -0.2281 -0.2874 -0.2623
-   57DMSO   CD1  226   0.291   2.812   0.705  0.3034  0.0577 -0.4574
-   57DMSO    OD  227   0.142   2.814   0.473 -0.1143  0.1209  0.0354
-   57DMSO   CD2  228   0.418   2.813   0.423 -0.1113 -0.2099 -0.0377
-   58DMSO    SD  229   1.910  -0.014   0.189  0.3568  0.2791 -0.1395
-   58DMSO   CD1  230   2.049   0.103   0.118  0.0381  0.6681 -0.1254
-   58DMSO    OD  231   1.786   0.076   0.188 -0.1907 -0.4617 -0.1746
-   58DMSO   CD2  232   1.878  -0.122   0.030  0.0827  0.5195 -0.2504
-   59DMSO    SD  233   1.692   2.575   2.635  0.1422 -0.1786  0.1876
-   59DMSO   CD1  234   1.873   2.501   2.623  0.2931  0.2272 -0.1829
-   59DMSO    OD  235   1.635   2.569   2.776 -0.8243  0.7250 -0.1569
-   59DMSO   CD2  236   1.762   2.754   2.602 -0.4378  0.0502  0.1825
-   60DMSO    SD  237   0.247   2.755   1.466  0.1361 -0.1887  0.0088
-   60DMSO   CD1  238   0.071   2.708   1.537  0.2185 -0.2666  0.1698
-   60DMSO    OD  239   0.280   2.901   1.497 -0.0577 -0.0489 -0.4091
-   60DMSO   CD2  240   0.351   2.664   1.603  0.2560  0.1873  0.1707
-   61DMSO    SD  241   0.919   2.885   0.362 -0.2171 -0.2644  0.2843
-   61DMSO   CD1  242   0.772   2.758   0.349 -0.7689  0.3806  0.1106
-   61DMSO    OD  243   0.993   2.860   0.493  0.2020 -0.4638  0.0117
-   61DMSO   CD2  244   1.036   2.820   0.220  0.3204  0.5897  0.3255
-   62DMSO    SD  245   1.765   1.899   1.954  0.0621 -0.3148  0.0089
-   62DMSO   CD1  246   1.878   1.942   2.108 -0.7523  0.1355  0.4848
-   62DMSO    OD  247   1.624   1.880   2.009  0.0783  0.1917  0.2342
-   62DMSO   CD2  248   1.791   2.064   1.852 -1.5073  0.0695  0.2115
-   63DMSO    SD  249   0.531   1.552   2.394  0.2963  0.1261 -0.0898
-   63DMSO   CD1  250   0.563   1.613   2.576  0.5276 -0.2019 -0.0191
-   63DMSO    OD  251   0.402   1.470   2.392  0.2330  0.2112  0.3945
-   63DMSO   CD2  252   0.486   1.733   2.335  0.2668  0.1490  0.0008
-   64DMSO    SD  253   0.999   2.503   1.238  0.2144 -0.5212 -0.0845
-   64DMSO   CD1  254   0.854   2.397   1.161 -0.3054  0.1355 -0.0237
-   64DMSO    OD  255   1.122   2.417   1.267  0.1835 -0.4257  0.3394
-   64DMSO   CD2  256   1.028   2.601   1.072 -0.2681 -0.0793  0.0970
-   65DMSO    SD  257   0.186   1.451   1.396 -0.2131  0.0928  0.4137
-   65DMSO   CD1  258   0.302   1.608   1.401 -0.0843  0.0273 -0.0657
-   65DMSO    OD  259   0.267   1.327   1.432  0.0049  0.0107 -0.3290
-   65DMSO   CD2  260   0.087   1.502   1.556  0.0208  0.5463  0.4175
-   66DMSO    SD  261   2.584   2.762   2.532  0.0846  0.0029  0.0567
-   66DMSO   CD1  262   2.757   2.701   2.465 -0.3510 -0.1628 -0.9489
-   66DMSO    OD  263   2.600   2.797   2.680 -0.3105  0.0340  0.0936
-   66DMSO   CD2  264   2.577   2.921   2.419  0.2614 -0.0024  0.0334
-   67DMSO    SD  265   2.417   0.985   1.260  0.1395  0.3214  0.0216
-   67DMSO   CD1  266   2.510   0.894   1.115  0.3184  0.6994 -0.1033
-   67DMSO    OD  267   2.271   0.944   1.236  0.1918  0.0140  0.2282
-   67DMSO   CD2  268   2.496   0.871   1.396 -0.2905  0.4508  0.3903
-   68DMSO    SD  269   0.886   2.113   1.621  0.0093 -0.1189 -0.2469
-   68DMSO   CD1  270   0.912   2.194   1.446 -0.4310  0.7362  0.0771
-   68DMSO    OD  271   0.839   2.218   1.722  0.5566 -0.2197  0.1193
-   68DMSO   CD2  272   0.722   2.023   1.566 -0.2488  0.1260  0.1121
-   69DMSO    SD  273   2.009   2.448   1.779  0.3434 -0.0230 -0.2909
-   69DMSO   CD1  274   2.137   2.554   1.677  0.5728 -0.4838 -0.4928
-   69DMSO    OD  275   1.884   2.530   1.809  0.2027 -0.2877 -0.1338
-   69DMSO   CD2  276   1.978   2.342   1.618  0.1452  0.0366 -0.2931
-   70DMSO    SD  277   1.024   1.926   0.531  0.1133  0.1842  0.2663
-   70DMSO   CD1  278   0.941   1.756   0.485  0.3126  0.2754 -0.4282
-   70DMSO    OD  279   0.917   2.035   0.526 -0.0725  0.0153  0.5167
-   70DMSO   CD2  280   1.044   1.881   0.720  0.4977  0.3526  0.2698
-   71DMSO    SD  281   0.043   1.269   2.428 -0.2869  0.1290 -0.0142
-   71DMSO   CD1  282   0.189   1.356   2.522 -0.1204 -0.4742  0.2903
-   71DMSO    OD  283  -0.027   1.383   2.353 -0.4144  0.0752  0.0160
-   71DMSO   CD2  284   0.165   1.185   2.302 -0.4993 -0.3822  0.1168
-   72DMSO    SD  285   2.350   1.191   0.640 -0.0370 -0.0751 -0.3322
-   72DMSO   CD1  286   2.454   1.093   0.773 -0.6264 -0.1031  0.1093
-   72DMSO    OD  287   2.226   1.243   0.713  0.2837  0.4143 -0.1299
-   72DMSO   CD2  288   2.479   1.326   0.586  0.2970 -0.1690  0.2111
-   73DMSO    SD  289   2.770   0.363   2.525 -0.2007  0.1757  0.0142
-   73DMSO   CD1  290   2.783   0.207   2.642 -0.2736 -0.0916 -0.3176
-   73DMSO    OD  291   2.746   0.309   2.384  0.2942 -0.1436  0.0507
-   73DMSO   CD2  292   2.615   0.453   2.604 -0.1944  0.2067 -0.0068
-   74DMSO    SD  293   2.236   0.060   1.634 -0.0874 -0.0814 -0.3781
-   74DMSO   CD1  294   2.191   0.207   1.755  0.7511 -0.3038  0.2145
-   74DMSO    OD  295   2.120   0.053   1.535 -0.4038 -0.1388 -0.0029
-   74DMSO   CD2  296   2.398   0.136   1.555 -0.0920  0.6115  0.2649
-   75DMSO    SD  297   2.844   0.143   1.695  0.1931  0.2422  0.1509
-   75DMSO   CD1  298   2.973   0.244   1.589  0.1241  0.1849  0.0098
-   75DMSO    OD  299   2.906   0.114   1.832 -0.4973 -0.8505  0.2448
-   75DMSO   CD2  300   2.706   0.278   1.720 -0.4525 -0.3423 -0.2191
-   76DMSO    SD  301   0.238   1.014   0.844 -0.2510  0.1348 -0.0107
-   76DMSO   CD1  302   0.074   0.909   0.846 -0.3869  0.3133 -0.5234
-   76DMSO    OD  303   0.209   1.154   0.898  0.4028 -0.0007  0.6925
-   76DMSO   CD2  304   0.336   0.925   0.987  0.2843 -0.1254 -0.5163
-   77DMSO    SD  305   0.470   1.189   1.255 -0.2774  0.1474  0.1152
-   77DMSO   CD1  306   0.447   1.275   1.081 -0.1172 -0.5935 -0.2787
-   77DMSO    OD  307   0.558   1.066   1.233 -0.1954  0.2735 -0.2705
-   77DMSO   CD2  308   0.576   1.337   1.325 -0.0882  0.2734 -0.4421
-   78DMSO    SD  309   1.977   1.814  -0.014  0.0196 -0.1883 -0.0596
-   78DMSO   CD1  310   2.011   1.846   0.175 -0.2822  0.0025 -0.0287
-   78DMSO    OD  311   1.831   1.771  -0.029 -0.0557  0.0163  0.0835
-   78DMSO   CD2  312   1.988   1.995  -0.088  0.2347 -0.1885 -0.0276
-   79DMSO    SD  313   1.440   0.411   1.485 -0.4680  0.0041 -0.1350
-   79DMSO   CD1  314   1.274   0.510   1.506 -0.1648  0.4558  0.1441
-   79DMSO    OD  315   1.508   0.430   1.349  0.2066  0.2558  0.2307
-   79DMSO   CD2  316   1.535   0.529   1.607  0.4519 -0.7171 -0.1454
-   80DMSO    SD  317   1.406   1.032   2.777  0.3337  0.0059 -0.1681
-   80DMSO   CD1  318   1.591   1.081   2.738  0.1922  0.5690 -0.1050
-   80DMSO    OD  319   1.410   0.885   2.821  0.1883  0.2067  0.5331
-   80DMSO   CD2  320   1.385   1.131   2.944  0.3617 -0.4594  0.1105
-   81DMSO    SD  321   0.202   1.473   2.062  0.1886 -0.2555  0.0201
-   81DMSO   CD1  322   0.134   1.325   1.954  0.6196 -0.5666  0.1863
-   81DMSO    OD  323   0.276   1.576   1.976 -0.3531  0.1094 -0.0125
-   81DMSO   CD2  324   0.022   1.533   2.105  0.2148 -0.3192  0.2404
-   82DMSO    SD  325   1.252   0.717   2.313  0.3641  0.0143 -0.4423
-   82DMSO   CD1  326   1.312   0.634   2.147 -0.3322 -0.6231 -0.3810
-   82DMSO    OD  327   1.165   0.615   2.387  0.2760  0.4267  0.0285
-   82DMSO   CD2  328   1.425   0.711   2.402  0.0280  0.0236  0.2171
-   83DMSO    SD  329   2.854   1.414   0.696  0.0873  0.4357 -0.1701
-   83DMSO   CD1  330   3.038   1.394   0.757 -0.0544  0.1824  0.1825
-   83DMSO    OD  331   2.859   1.430   0.544 -0.0007 -0.2717 -0.2508
-   83DMSO   CD2  332   2.800   1.233   0.746 -0.2836  0.5877  0.0022
-   84DMSO    SD  333   0.458   1.141   2.882  0.0406  0.1368 -0.5473
-   84DMSO   CD1  334   0.571   0.982   2.883 -0.2845 -0.0915 -0.5729
-   84DMSO    OD  335   0.559   1.256   2.876  0.3446 -0.1031 -0.0927
-   84DMSO   CD2  336   0.375   1.120   2.706 -0.1355 -0.0858 -0.4311
-   85DMSO    SD  337   1.326   2.068   1.838 -0.4710  0.1070  0.1613
-   85DMSO   CD1  338   1.470   2.134   1.952  0.1499 -0.1132 -0.4902
-   85DMSO    OD  339   1.360   2.101   1.693  0.1074 -0.1674  0.2357
-   85DMSO   CD2  340   1.347   1.876   1.868 -0.5788 -0.0064 -0.4247
-   86DMSO    SD  341   0.507   0.812   2.131 -0.3622  0.1311  0.0973
-   86DMSO   CD1  342   0.506   0.743   1.949  1.0399  0.1046  0.0828
-   86DMSO    OD  343   0.509   0.965   2.129 -0.4392  0.1337  0.1599
-   86DMSO   CD2  344   0.326   0.777   2.194 -0.6060  0.1135 -0.6088
-   87DMSO    SD  345   1.878   0.137   0.737 -0.3480 -0.0439  0.0104
-   87DMSO   CD1  346   1.794  -0.018   0.821 -0.0744 -0.1608  0.0694
-   87DMSO    OD  347   1.794   0.252   0.793 -0.3597  0.2386 -0.5780
-   87DMSO   CD2  348   2.048   0.146   0.832 -0.5044  0.8185  0.2198
-   88DMSO    SD  349   1.287   2.246   0.704  0.3400 -0.1291 -0.0172
-   88DMSO   CD1  350   1.134   2.286   0.817 -0.1205 -0.3798 -0.5398
-   88DMSO    OD  351   1.387   2.359   0.682  0.6020 -0.3512  0.0114
-   88DMSO   CD2  352   1.380   2.128   0.828  0.1035 -0.4888 -0.1783
-   89DMSO    SD  353   1.076   1.778   1.603 -0.0350 -0.2041  0.0272
-   89DMSO   CD1  354   1.194   1.656   1.508 -0.4932 -0.3460 -0.3662
-   89DMSO    OD  355   1.009   1.858   1.491  0.3567  0.2618  0.1228
-   89DMSO   CD2  356   0.944   1.653   1.674 -0.7520  0.4644 -0.1072
-   90DMSO    SD  357   0.096   0.179   0.764  0.5645  0.0202  0.2037
-   90DMSO   CD1  358  -0.009   0.176   0.600  0.2315  0.2899  0.3994
-   90DMSO    OD  359   0.175   0.310   0.776  0.0274  0.3736  0.0298
-   90DMSO   CD2  360  -0.050   0.208   0.890 -0.0480  0.2204 -0.5428
-   91DMSO    SD  361   0.060   1.781   0.893 -0.0520 -0.2076 -0.0605
-   91DMSO   CD1  362   0.113   1.871   1.058 -0.3251  0.2745 -0.2362
-   91DMSO    OD  363  -0.049   1.677   0.921 -0.3295 -0.0305 -0.4673
-   91DMSO   CD2  364  -0.045   1.931   0.827 -1.1358 -0.4189  1.1207
-   92DMSO    SD  365   0.428   2.194   1.795 -0.0482 -0.0398  0.2562
-   92DMSO   CD1  366   0.473   2.277   1.625  0.5035 -0.1042  0.3673
-   92DMSO    OD  367   0.349   2.067   1.763  0.0886 -0.1346  0.2623
-   92DMSO   CD2  368   0.598   2.122   1.857 -0.1521 -0.5822 -0.0796
-   93DMSO    SD  369   2.024   2.825   1.273  0.0652 -0.1376  0.2408
-   93DMSO   CD1  370   2.052   3.018   1.282 -0.3660 -0.0825  0.5839
-   93DMSO    OD  371   1.963   2.799   1.135 -0.6171  0.7119  0.3720
-   93DMSO   CD2  372   2.217   2.797   1.268  0.1040  0.1566 -0.0515
-   94DMSO    SD  373   0.345   0.670   2.675 -0.0395  0.1156 -0.1345
-   94DMSO   CD1  374   0.525   0.606   2.714  0.1072 -0.0335 -1.0145
-   94DMSO    OD  375   0.296   0.763   2.786 -0.4529 -0.2473 -0.0075
-   94DMSO   CD2  376   0.390   0.799   2.536  0.4865 -0.2826 -0.3409
-   95DMSO    SD  377   1.476   0.189   2.634  0.4367  0.0356  0.2774
-   95DMSO   CD1  378   1.421   0.371   2.591 -0.2664 -0.2371  0.0148
-   95DMSO    OD  379   1.387   0.099   2.548  0.6624 -0.6973  0.8047
-   95DMSO   CD2  380   1.651   0.186   2.549  0.4637 -1.1716  0.3566
-   96DMSO    SD  381   1.462   1.887   0.497  0.1601  0.0265  0.4470
-   96DMSO   CD1  382   1.654   1.921   0.510  0.2173 -0.0352 -0.1064
-   96DMSO    OD  383   1.407   1.849   0.634 -0.0871 -0.2783  0.2656
-   96DMSO   CD2  384   1.407   2.068   0.451 -0.0868 -0.1509  0.0441
-   97DMSO    SD  385   0.961   1.195   2.706  0.0539  0.0910  0.1299
-   97DMSO   CD1  386   0.913   1.328   2.572  0.9387  0.2065 -0.0843
-   97DMSO    OD  387   1.112   1.171   2.693 -0.0243 -0.1685 -0.3172
-   97DMSO   CD2  388   0.938   1.303   2.868  0.3846 -0.1615  0.3418
-   98DMSO    SD  389   2.585   1.470   1.402 -0.2832  0.2655  0.1449
-   98DMSO   CD1  390   2.442   1.602   1.396 -0.2198  0.3372  0.3468
-   98DMSO    OD  391   2.678   1.520   1.512 -0.0324  0.7367 -0.2652
-   98DMSO   CD2  392   2.488   1.315   1.469 -0.1997  0.1020 -0.1314
-   99DMSO    SD  393   2.038   0.874   0.934  0.0099  0.1452  0.0585
-   99DMSO   CD1  394   1.911   0.971   1.046 -0.3307 -0.1245 -0.0809
-   99DMSO    OD  395   1.986   0.886   0.791 -0.3915 -0.5618  0.1344
-   99DMSO   CD2  396   2.176   1.009   0.955  0.2420 -0.1675  0.5711
-  100DMSO    SD  397   0.608   0.068   2.360  0.2726 -0.2182 -0.2080
-  100DMSO   CD1  398   0.738  -0.070   2.406  0.0656 -0.2271  0.3965
-  100DMSO    OD  399   0.464   0.017   2.344  0.0339  0.2191  0.5265
-  100DMSO   CD2  400   0.619   0.187   2.513  0.0178 -0.8021  0.2797
-  101DMSO    SD  401   2.541   0.968   2.291  0.0963  0.1489 -0.1637
-  101DMSO   CD1  402   2.490   0.919   2.109  0.2565 -0.0835 -0.1403
-  101DMSO    OD  403   2.597   0.847   2.367 -0.4964  0.0572  0.1389
-  101DMSO   CD2  404   2.707   1.050   2.232  0.3061 -0.1277  0.0346
-  102DMSO    SD  405   0.629   1.973   0.719  0.3509 -0.0200  0.5390
-  102DMSO   CD1  406   0.676   2.162   0.714  0.3938 -0.0401  0.1071
-  102DMSO    OD  407   0.515   1.961   0.821 -0.1986 -0.4479 -0.1136
-  102DMSO   CD2  408   0.553   1.967   0.539  0.4058 -0.2096  0.5117
-  103DMSO    SD  409   2.039   0.982   0.029  0.1833  0.0424 -0.1325
-  103DMSO   CD1  410   2.010   0.834   0.152  0.0457 -0.1040 -0.3238
-  103DMSO    OD  411   1.906   0.998  -0.045  0.2686  0.1808 -0.2516
-  103DMSO   CD2  412   2.057   1.129   0.155  0.3392 -0.2314  0.1656
-  104DMSO    SD  413   0.876   2.324   0.384 -0.2570 -0.0049 -0.0039
-  104DMSO   CD1  414   0.878   2.214   0.224  0.2622 -0.5095  0.3540
-  104DMSO    OD  415   0.925   2.464   0.347 -0.6843  0.0747 -0.2733
-  104DMSO   CD2  416   0.682   2.341   0.400 -0.2055  0.5763  0.0523
-  105DMSO    SD  417   1.597   0.932   0.372  0.1206  0.2313  0.0519
-  105DMSO   CD1  418   1.412   0.872   0.349  0.2772 -0.0461 -0.5012
-  105DMSO    OD  419   1.663   0.797   0.399 -0.4849 -0.1604 -0.3926
-  105DMSO   CD2  420   1.647   0.973   0.188  0.4992  0.6778  0.2516
-  106DMSO    SD  421   2.606   1.658   0.232 -0.1397 -0.1376 -0.1464
-  106DMSO   CD1  422   2.738   1.514   0.234 -0.2130 -0.2158 -0.1342
-  106DMSO    OD  423   2.628   1.751   0.352 -0.5670 -0.6492  0.3407
-  106DMSO   CD2  424   2.690   1.766   0.093  0.1366 -0.2356 -0.0564
-  107DMSO    SD  425   2.613   2.220   1.658  0.0119  0.0243  0.0181
-  107DMSO   CD1  426   2.531   2.053   1.717 -0.1463  0.2493  0.4400
-  107DMSO    OD  427   2.626   2.234   1.506 -0.0278  0.2090  0.0312
-  107DMSO   CD2  428   2.476   2.344   1.719 -0.2533 -0.2320 -0.0536
-  108DMSO    SD  429   1.733   0.864   1.841 -0.1562 -0.2969 -0.0235
-  108DMSO   CD1  430   1.858   0.777   1.962  0.0554 -0.0410 -0.0588
-  108DMSO    OD  431   1.718   0.774   1.718  0.2288 -0.0845 -0.2297
-  108DMSO   CD2  432   1.586   0.813   1.958 -0.2254 -0.2918 -0.1063
-  109DMSO    SD  433   1.224   0.496   0.028 -0.1609  0.0779  0.2900
-  109DMSO   CD1  434   1.205   0.608  -0.131  0.0134 -0.0909  0.1495
-  109DMSO    OD  435   1.341   0.403  -0.003 -0.0598  0.2145  0.2596
-  109DMSO   CD2  436   1.302   0.642   0.131  0.3869  0.3299 -0.4742
-  110DMSO    SD  437   2.282   2.546   2.809  0.2257  0.0805 -0.2098
-  110DMSO   CD1  438   2.168   2.522   2.966 -0.3378  0.5472 -0.5387
-  110DMSO    OD  439   2.183   2.558   2.693  0.0147  0.2780 -0.0086
-  110DMSO   CD2  440   2.320   2.732   2.854 -0.2651  0.2164 -0.3520
-  111DMSO    SD  441   0.804   2.723   1.491  0.0517  0.3680 -0.5189
-  111DMSO   CD1  442   0.699   2.570   1.552  0.0996  0.2953 -0.6139
-  111DMSO    OD  443   0.818   2.735   1.339  0.3318  0.3542 -0.4953
-  111DMSO   CD2  444   0.668   2.852   1.548  0.3761  0.5181 -0.0781
-  112DMSO    SD  445   1.181   0.519   1.099 -0.0826 -0.0729  0.4382
-  112DMSO   CD1  446   1.278   0.360   1.156  0.1448 -0.1238 -0.0911
-  112DMSO    OD  447   1.061   0.533   1.193  0.0809 -0.0790  0.6515
-  112DMSO   CD2  448   1.318   0.648   1.148  0.2776 -0.3487  0.1354
-  113DMSO    SD  449   0.457   2.509   2.383  0.1696  0.3233  0.0752
-  113DMSO   CD1  450   0.641   2.458   2.422 -0.1013 -0.0961  0.8221
-  113DMSO    OD  451   0.370   2.385   2.407  0.2973  0.1611 -0.2936
-  113DMSO   CD2  452   0.422   2.622   2.538 -0.8641  0.0554  0.0463
-  114DMSO    SD  453   2.401   0.836   2.808 -0.2128 -0.1463 -0.0981
-  114DMSO   CD1  454   2.248   0.759   2.716 -0.2328  0.1590 -0.3216
-  114DMSO    OD  455   2.496   0.727   2.858 -0.4117 -0.5898 -0.6822
-  114DMSO   CD2  456   2.489   0.887   2.641 -0.0253  0.4162  0.1670
-  115DMSO    SD  457   1.770   2.585   0.424 -0.0344  0.4057  0.2767
-  115DMSO   CD1  458   1.617   2.622   0.308 -0.0173 -0.8045 -0.1565
-  115DMSO    OD  459   1.896   2.556   0.342 -0.4847 -0.3446 -0.1652
-  115DMSO   CD2  460   1.781   2.767   0.491 -0.2077  0.3592  0.4356
-  116DMSO    SD  461   1.048   2.513   2.212  0.4781  0.2156  0.1028
-  116DMSO   CD1  462   0.964   2.358   2.294  0.1961  0.4278  0.2207
-  116DMSO    OD  463   0.973   2.633   2.271 -0.3278 -0.2685  0.0908
-  116DMSO   CD2  464   1.218   2.490   2.305  0.4885  0.3585  0.1330
-  117DMSO    SD  465   0.309   0.273   2.710 -0.4076  0.2875 -0.2674
-  117DMSO   CD1  466   0.218   0.283   2.882  0.1233 -0.2716  0.0488
-  117DMSO    OD  467   0.452   0.311   2.747 -0.3140 -0.6537  0.3729
-  117DMSO   CD2  468   0.299   0.081   2.681 -0.1564  0.2214  0.0721
-  118DMSO    SD  469   2.140   2.505   0.996  0.0912 -0.1371 -0.3457
-  118DMSO   CD1  470   2.117   2.638   0.855  0.1457 -0.2322 -0.4480
-  118DMSO    OD  471   2.221   2.561   1.112  0.0943  0.0021 -0.4066
-  118DMSO   CD2  472   1.958   2.484   1.064  0.2792  0.3482  0.2983
-  119DMSO    SD  473   1.142   1.579   2.039  0.0294 -0.2290 -0.1878
-  119DMSO   CD1  474   1.096   1.433   1.918  0.3358 -0.2270 -0.2993
-  119DMSO    OD  475   1.097   1.710   1.973  0.4293  0.0516  0.0982
-  119DMSO   CD2  476   1.001   1.555   2.171  0.2286  0.1365  0.0964
-  120DMSO    SD  477   0.324   1.059   1.605  0.2198  0.0240 -0.4507
-  120DMSO   CD1  478   0.502   1.014   1.537  0.3518  0.4225 -0.3698
-  120DMSO    OD  479   0.242   0.930   1.610  0.3337 -0.0506 -0.4857
-  120DMSO   CD2  480   0.368   1.108   1.788  0.4653 -0.9913 -0.2319
-  121DMSO    SD  481   0.880   0.411   2.249 -0.0859  0.1027 -0.4500
-  121DMSO   CD1  482   0.774   0.562   2.187 -0.2706  0.0611 -0.2542
-  121DMSO    OD  483   0.815   0.278   2.213  0.3090 -0.0896 -0.4612
-  121DMSO   CD2  484   1.032   0.440   2.131 -0.0434 -0.5380 -0.5579
-  122DMSO    SD  485   1.772   1.961   1.094 -0.1146  0.1997 -0.0458
-  122DMSO   CD1  486   1.700   2.005   0.918  0.2429  0.7871 -0.0506
-  122DMSO    OD  487   1.861   1.836   1.087 -0.3834  0.0174 -0.1813
-  122DMSO   CD2  488   1.888   2.117   1.108  0.0931  0.0578 -0.0269
-  123DMSO    SD  489   1.420   1.356   1.780 -0.1739 -0.1670  0.0523
-  123DMSO   CD1  490   1.467   1.325   1.594  0.8104 -0.5050  0.3452
-  123DMSO    OD  491   1.546   1.313   1.855 -0.0606 -0.4869 -0.3185
-  123DMSO   CD2  492   1.440   1.550   1.769 -0.3335 -0.1727 -0.3403
-  124DMSO    SD  493   1.602   1.608   2.313  0.4085 -0.2796  0.0905
-  124DMSO   CD1  494   1.616   1.549   2.127  0.1305 -0.7141  0.2055
-  124DMSO    OD  495   1.732   1.683   2.343  0.4296 -0.2294 -0.1166
-  124DMSO   CD2  496   1.441   1.715   2.291  0.7070  0.2418  0.4127
-  125DMSO    SD  497   0.549   1.608   0.734 -0.1525 -0.0255  0.5367
-  125DMSO   CD1  498   0.547   1.416   0.766  0.0623 -0.1228 -0.0210
-  125DMSO    OD  499   0.483   1.644   0.601  0.5245  0.2849  0.2742
-  125DMSO   CD2  500   0.410   1.666   0.858 -0.9275 -0.2114 -0.2482
-  126DMSO    SD  501   0.718   1.491   0.375 -0.2052 -0.3118  0.6995
-  126DMSO   CD1  502   0.607   1.347   0.305  0.5428 -0.5009 -0.1221
-  126DMSO    OD  503   0.854   1.479   0.305 -0.1991 -0.0021  0.6538
-  126DMSO   CD2  504   0.632   1.634   0.275 -0.4927 -0.6809  0.4176
-  127DMSO    SD  505   0.903   2.163   2.683  0.2428  0.0757 -0.4779
-  127DMSO   CD1  506   0.963   2.020   2.801 -0.3007  0.0693 -0.2046
-  127DMSO    OD  507   1.012   2.219   2.591  0.0249  0.5391 -0.4580
-  127DMSO   CD2  508   0.778   2.077   2.560  0.0112 -0.4252  0.1084
-  128DMSO    SD  509   1.434   2.617   1.971 -0.0859  0.1283 -0.3023
-  128DMSO   CD1  510   1.299   2.736   1.895 -0.3933 -0.0947 -0.1116
-  128DMSO    OD  511   1.359   2.489   2.010  0.0457  0.2286  0.2792
-  128DMSO   CD2  512   1.517   2.590   1.796  0.0374 -0.1441 -0.2023
-  129DMSO    SD  513   2.504   0.201   0.746 -0.3364 -0.0633 -0.0937
-  129DMSO   CD1  514   2.459   0.388   0.783  0.1093 -0.1392  0.8600
-  129DMSO    OD  515   2.374   0.121   0.762  0.1032 -0.8447 -0.3458
-  129DMSO   CD2  516   2.533   0.209   0.553 -0.4621  0.3827 -0.0963
-  130DMSO    SD  517   2.757   2.190   0.393 -0.1574  0.3281 -0.3412
-  130DMSO   CD1  518   2.687   2.365   0.441 -0.6692 -0.0163  0.1980
-  130DMSO    OD  519   2.865   2.159   0.497 -0.0507  0.3532 -0.4407
-  130DMSO   CD2  520   2.608   2.078   0.448  0.5738 -0.3141  0.3603
-  131DMSO    SD  521   0.682   1.250   2.266  0.1973  0.0018  0.3190
-  131DMSO   CD1  522   0.663   1.082   2.363  0.4996 -0.4440 -0.3847
-  131DMSO    OD  523   0.769   1.241   2.140 -0.1852 -0.3345  0.0728
-  131DMSO   CD2  524   0.499   1.249   2.196  0.2899  0.6675  0.0545
-  132DMSO    SD  525   1.504   0.058   2.159  0.0986 -0.1232 -0.2844
-  132DMSO   CD1  526   1.402   0.196   2.252  0.3875  0.1905 -0.4296
-  132DMSO    OD  527   1.649   0.099   2.182  0.1503 -0.1545 -0.5521
-  132DMSO   CD2  528   1.450  -0.094   2.269 -0.3381  0.3558  0.1695
-  133DMSO    SD  529   1.551   0.907   1.301  0.0302  0.4445 -0.1303
-  133DMSO   CD1  530   1.586   0.976   1.480 -0.0725 -0.2787  0.1624
-  133DMSO    OD  531   1.597   1.015   1.204 -0.2682  0.5460 -0.1608
-  133DMSO   CD2  532   1.676   0.757   1.283  0.2005  0.6067 -0.3126
-  134DMSO    SD  533   0.376   0.408   2.352  0.1977 -0.1167  0.4029
-  134DMSO   CD1  534   0.348   0.382   2.161 -0.2598  0.2795  0.4078
-  134DMSO    OD  535   0.428   0.552   2.363 -0.0606  0.0324 -0.1992
-  134DMSO   CD2  536   0.189   0.400   2.406 -0.0780 -0.3566 -0.5636
-  135DMSO    SD  537   2.878   2.311   2.551 -0.1371  0.2657 -0.0181
-  135DMSO   CD1  538   2.961   2.479   2.604  0.5002  0.1187 -0.5305
-  135DMSO    OD  539   2.728   2.342   2.544 -0.2185 -0.1299 -0.1708
-  135DMSO   CD2  540   2.938   2.341   2.368  0.4312  0.0793  0.1359
-  136DMSO    SD  541   0.699   2.552   0.789 -0.3341 -0.2693 -0.1130
-  136DMSO   CD1  542   0.531   2.543   0.691 -0.3915  0.1928 -0.0456
-  136DMSO    OD  543   0.745   2.423   0.857 -0.3594  0.0057  0.4315
-  136DMSO   CD2  544   0.815   2.616   0.645 -0.0451  0.2491  0.3449
-  137DMSO    SD  545   1.472   0.291   0.325 -0.1886  0.2542  0.1314
-  137DMSO   CD1  546   1.370   0.139   0.257  0.3951  0.0895 -0.3888
-  137DMSO    OD  547   1.374   0.382   0.399 -0.6422 -0.2500  0.1591
-  137DMSO   CD2  548   1.576   0.209   0.468 -0.0191  0.5139  0.1521
-  138DMSO    SD  549   0.476   0.126   1.872  0.3415 -0.0462  0.2664
-  138DMSO   CD1  550   0.316   0.024   1.917  0.2154 -0.0807 -0.2612
-  138DMSO    OD  551   0.585   0.028   1.828  0.5961  0.5114 -0.3713
-  138DMSO   CD2  552   0.407   0.207   1.708  0.3921  0.5502  0.5344
-  139DMSO    SD  553   2.116   0.912   1.635  0.1312 -0.1593 -0.0031
-  139DMSO   CD1  554   2.034   0.920   1.459 -0.0192  0.0382  0.0739
-  139DMSO    OD  555   2.254   0.973   1.610 -0.1758  0.6495  0.2151
-  139DMSO   CD2  556   2.007   1.059   1.703 -0.5409 -0.8247  0.3789
-  140DMSO    SD  557   0.493   2.206   1.247 -0.4223 -0.0542  0.0498
-  140DMSO   CD1  558   0.478   2.014   1.275  0.0058 -0.1650 -0.4512
-  140DMSO    OD  559   0.643   2.228   1.271 -0.3654 -0.0491 -0.3284
-  140DMSO   CD2  560   0.460   2.187   1.056 -0.1231 -0.2276  0.0098
-  141DMSO    SD  561   1.367   0.380   1.932 -0.1687 -0.5778 -0.1172
-  141DMSO   CD1  562   1.491   0.258   1.844  0.2418 -0.0939 -0.2013
-  141DMSO    OD  563   1.429   0.520   1.920 -0.1027 -0.6343 -0.4107
-  141DMSO   CD2  564   1.215   0.360   1.812 -0.1037  0.2856 -0.3650
-  142DMSO    SD  565   1.355   2.628   0.550 -0.0999 -0.0832  0.0556
-  142DMSO   CD1  566   1.198   2.550   0.465 -0.2682 -0.1349  0.4175
-  142DMSO    OD  567   1.396   2.758   0.480 -0.6365  0.2184  0.3019
-  142DMSO   CD2  568   1.273   2.665   0.723 -0.1094  0.2233 -0.0039
-  143DMSO    SD  569   1.054   1.283   1.460  0.3902  0.1688 -0.4272
-  143DMSO   CD1  570   0.886   1.186   1.476  0.2590  0.4657  0.0056
-  143DMSO    OD  571   1.087   1.366   1.584  0.2149  0.0923 -0.3287
-  143DMSO   CD2  572   1.166   1.123   1.460 -0.2174 -0.2652  0.5351
-  144DMSO    SD  573   1.761   2.339   2.246 -0.4389  0.1733 -0.2614
-  144DMSO   CD1  574   1.570   2.310   2.276 -0.2967 -0.1323  0.3738
-  144DMSO    OD  575   1.823   2.200   2.237  0.4928  0.5481  0.2193
-  144DMSO   CD2  576   1.730   2.416   2.070 -0.0901  0.5084 -0.1719
-  145DMSO    SD  577   1.817   0.364   2.133 -0.4628 -0.2088 -0.0437
-  145DMSO   CD1  578   1.668   0.484   2.171 -0.4804 -0.0461 -0.6171
-  145DMSO    OD  579   1.912   0.457   2.058 -0.2502 -0.1616  0.2826
-  145DMSO   CD2  580   1.895   0.350   2.311  0.2323  0.0226 -0.3303
-  146DMSO    SD  581   2.246   2.018   2.400 -0.3376  0.0613  0.2552
-  146DMSO   CD1  582   2.110   2.152   2.441 -0.1727  0.3195 -0.0336
-  146DMSO    OD  583   2.350   2.073   2.302 -0.4981 -0.1498 -0.0324
-  146DMSO   CD2  584   2.333   1.986   2.571 -0.0744  0.7261  0.2563
-  147DMSO    SD  585   0.259   2.042   2.281  0.2419  0.0130 -0.0623
-  147DMSO   CD1  586   0.258   1.940   2.115  0.2771  0.1321 -0.1373
-  147DMSO    OD  587   0.252   1.959   2.409  0.0100  0.4371  0.2050
-  147DMSO   CD2  588   0.445   2.099   2.279  0.0476  0.6331  0.0665
-  148DMSO    SD  589   1.048   2.460   1.697  0.1255  0.0430  0.0201
-  148DMSO   CD1  590   1.127   2.351   1.838  0.3987  0.2525  0.0355
-  148DMSO    OD  591   1.037   2.608   1.735  0.1327  0.0515 -0.0086
-  148DMSO   CD2  592   1.198   2.456   1.572 -0.0175 -0.0880 -0.1489
-  149DMSO    SD  593   2.504   1.655   1.792 -0.0640 -0.2806 -0.0496
-  149DMSO   CD1  594   2.681   1.575   1.812  0.1608  0.1786 -0.1236
-  149DMSO    OD  595   2.501   1.731   1.659  0.6272 -0.2788 -0.0716
-  149DMSO   CD2  596   2.399   1.494   1.765  0.2910 -0.3886 -0.8544
-  150DMSO    SD  597   2.096   1.612   2.556  0.2447 -0.0497 -0.0682
-  150DMSO   CD1  598   2.071   1.696   2.382  0.2567  1.0148  0.4405
-  150DMSO    OD  599   2.174   1.710   2.644 -0.3421 -0.1163  0.5318
-  150DMSO   CD2  600   1.912   1.604   2.619  0.3438  0.1645  0.2525
-  151DMSO    SD  601   1.215   0.081   1.571 -0.5589  0.0651 -0.2396
-  151DMSO   CD1  602   1.175  -0.069   1.452  0.1236 -0.1781 -0.1634
-  151DMSO    OD  603   1.181   0.212   1.501 -0.0402  0.1105 -0.4187
-  151DMSO   CD2  604   1.082   0.041   1.708 -0.3162  0.7320  0.1859
-  152DMSO    SD  605   2.293   0.605   1.038  0.1429 -0.4849  0.1823
-  152DMSO   CD1  606   2.203   0.661   1.202  0.8484  0.1564  0.3499
-  152DMSO    OD  607   2.425   0.539   1.079  0.3471 -0.1771  0.0331
-  152DMSO   CD2  608   2.155   0.473   0.996 -0.2997 -0.0333  0.1661
-  153DMSO    SD  609   1.172   2.044   2.366 -0.0449  0.1729  0.1518
-  153DMSO   CD1  610   1.259   2.010   2.537 -0.2338  0.1899  0.2526
-  153DMSO    OD  611   1.288   2.070   2.270  0.1103 -0.2843  0.2080
-  153DMSO   CD2  612   1.107   1.861   2.347  0.2508  0.0072  0.7309
-  154DMSO    SD  613   1.320   1.742   0.029 -0.0595 -0.3656  0.0203
-  154DMSO   CD1  614   1.186   1.799   0.159 -0.0817 -0.2133 -0.0686
-  154DMSO    OD  615   1.263   1.794  -0.103 -0.4796 -0.2233  0.2549
-  154DMSO   CD2  616   1.471   1.848   0.092  0.0985 -0.2867 -0.4825
-  155DMSO    SD  617   1.150   0.996   0.772  0.0993  0.2196 -0.2073
-  155DMSO   CD1  618   1.123   1.173   0.849 -0.6772 -0.0474  0.1523
-  155DMSO    OD  619   1.071   0.889   0.847  0.1662  0.0500 -0.3701
-  155DMSO   CD2  620   1.067   1.030   0.599 -0.3142  0.1968 -0.0091
-  156DMSO    SD  621   0.778   0.517   1.777  0.3797  0.0661  0.0544
-  156DMSO   CD1  622   0.799   0.325   1.805  0.3310  0.0080 -0.2983
-  156DMSO    OD  623   0.846   0.599   1.886  0.3763 -0.2121  0.2657
-  156DMSO   CD2  624   0.886   0.536   1.615 -0.1285 -0.6314 -0.3843
-  157DMSO    SD  625   0.480   1.548   1.713 -0.0474 -0.0907 -0.1302
-  157DMSO   CD1  626   0.499   1.725   1.792 -0.0201  0.2339 -0.8574
-  157DMSO    OD  627   0.567   1.548   1.588  0.3403  0.2287  0.1374
-  157DMSO   CD2  628   0.570   1.443   1.850 -0.4316 -0.2750 -0.0154
-  158DMSO    SD  629   0.856   2.065   2.111 -0.1651 -0.0590 -0.0391
-  158DMSO   CD1  630   0.839   1.879   2.056 -0.0812  0.1094 -0.6167
-  158DMSO    OD  631   0.850   2.081   2.263  0.2694 -0.0854 -0.0191
-  158DMSO   CD2  632   1.035   2.085   2.037 -0.0659  1.5751  0.6037
-  159DMSO    SD  633   2.838   0.900   2.619  0.2990 -0.0475 -0.3719
-  159DMSO   CD1  634   2.875   0.950   2.804  0.1332 -0.4595 -0.2259
-  159DMSO    OD  635   2.938   0.961   2.520  0.2830  0.5296 -0.0333
-  159DMSO   CD2  636   2.871   0.709   2.646  0.0858 -0.0978 -0.3972
-  160DMSO    SD  637   0.729   1.039   1.855  0.4033 -0.3943  0.3485
-  160DMSO   CD1  638   0.855   1.188   1.852  0.1356 -0.1763  0.2640
-  160DMSO    OD  639   0.734   0.962   1.723 -0.2241 -0.2957  0.2627
-  160DMSO   CD2  640   0.816   0.925   1.987 -0.0295 -0.9507  0.1513
-  161DMSO    SD  641   1.068   0.016   2.096 -0.0591  0.0677 -0.1827
-  161DMSO   CD1  642   0.884   0.018   2.031  0.0347  0.0448 -0.4495
-  161DMSO    OD  643   1.139   0.140   2.041 -0.3527  0.2661 -0.1240
-  161DMSO   CD2  644   1.038   0.068   2.282 -0.4505  0.5552 -0.3757
-  162DMSO    SD  645   2.070   1.404   0.961  0.2323 -0.6975  0.0547
-  162DMSO   CD1  646   2.265   1.413   0.958  0.1705  0.8047  0.4531
-  162DMSO    OD  647   2.039   1.315   1.082 -0.7955 -0.0415  0.2867
-  162DMSO   CD2  648   2.035   1.591   1.001 -0.0895 -0.7003 -0.2125
-  163DMSO    SD  649   1.961   1.936   1.562 -0.4267  0.3436  0.4410
-  163DMSO   CD1  650   2.001   1.831   1.403 -0.2991  0.4544  0.3989
-  163DMSO    OD  651   1.830   1.891   1.626 -0.2833  0.7110  1.0046
-  163DMSO   CD2  652   2.108   1.850   1.659 -0.2323 -0.1017 -0.2518
-  164DMSO    SD  653   1.188   0.944   1.911 -0.2782 -0.2675  0.1878
-  164DMSO   CD1  654   1.135   0.758   1.880  0.8256 -0.7036  0.8622
-  164DMSO    OD  655   1.263   0.936   2.044  0.0089 -0.1018  0.0347
-  164DMSO   CD2  656   1.319   0.971   1.770  0.0026  0.1839  0.5326
-  165DMSO    SD  657   1.791   0.450   0.154  0.0215  0.3325 -0.2383
-  165DMSO   CD1  658   1.703   0.339   0.020 -0.5234 -0.0636  0.4493
-  165DMSO    OD  659   1.918   0.505   0.090  0.0240  0.5022 -0.0794
-  165DMSO   CD2  660   1.645   0.578   0.173 -0.0378  0.1825  0.4341
-  166DMSO    SD  661   2.064   1.503   1.486 -0.0331 -0.0087  0.4572
-  166DMSO   CD1  662   2.094   1.311   1.484 -0.0302 -0.0043  0.1865
-  166DMSO    OD  663   2.148   1.581   1.384  0.1960 -0.5856  0.1940
-  166DMSO   CD2  664   1.885   1.499   1.410 -0.0712 -1.3472  0.6192
-  167DMSO    SD  665   2.263   2.122   0.108 -0.2297  0.1813  0.1929
-  167DMSO   CD1  666   2.403   2.255   0.132 -0.3150  0.3548 -0.2026
-  167DMSO    OD  667   2.265   2.084  -0.041  0.4679  0.2043  0.1915
-  167DMSO   CD2  668   2.363   1.982   0.200  0.4052  0.2834 -0.3283
-  168DMSO    SD  669   0.117   2.269   0.737 -0.1346 -0.0546 -0.3640
-  168DMSO   CD1  670   0.305   2.223   0.712 -0.1321 -0.0391 -0.3489
-  168DMSO    OD  671   0.085   2.255   0.886 -0.4892 -0.3039 -0.4624
-  168DMSO   CD2  672   0.119   2.460   0.694  0.0889  0.1445  0.5230
-  169DMSO    SD  673   0.596   0.146   0.132  0.0566  0.3260 -0.3020
-  169DMSO   CD1  674   0.649   0.017  -0.004  0.1754 -0.2245  0.2572
-  169DMSO    OD  675   0.639   0.097   0.270 -0.1787 -0.6318 -0.5615
-  169DMSO   CD2  676   0.733   0.268   0.066  0.1099  0.3647 -0.1238
-  170DMSO    SD  677   0.538   1.880   2.809  0.4107 -0.1246  0.0415
-  170DMSO   CD1  678   0.617   2.006   2.935  0.3454  0.2421 -0.2837
-  170DMSO    OD  679   0.569   1.749   2.883 -0.4922 -0.4225 -0.0924
-  170DMSO   CD2  680   0.351   1.926   2.837  0.2746 -0.2459 -0.6329
-  171DMSO    SD  681   2.566   2.694   1.307 -0.1653 -0.0415 -0.1119
-  171DMSO   CD1  682   2.632   2.826   1.435 -0.3651 -0.0646  0.0175
-  171DMSO    OD  683   2.679   2.630   1.227  0.5546  0.7292  0.2639
-  171DMSO   CD2  684   2.501   2.568   1.441 -0.1863  0.0849 -0.0005
-  172DMSO    SD  685   1.675   2.096   2.529 -0.3535  0.1203 -0.1738
-  172DMSO   CD1  686   1.607   1.982   2.671 -0.4500  0.4515  0.0430
-  172DMSO    OD  687   1.762   2.205   2.591  0.0834 -0.3155 -0.0107
-  172DMSO   CD2  688   1.822   1.980   2.474 -0.3094  0.1946 -0.2161
-  173DMSO    SD  689   1.266   1.260   2.274 -0.0234  0.2192 -0.1372
-  173DMSO   CD1  690   1.256   1.126   2.414 -0.2467  0.3253 -0.0511
-  173DMSO    OD  691   1.332   1.385   2.332  0.0195  0.0229  0.2428
-  173DMSO   CD2  692   1.382   1.191   2.132  0.6480  0.8817  0.0812
-  174DMSO    SD  693   2.343   1.339   2.089 -0.2559  0.2204  0.1801
-  174DMSO   CD1  694   2.375   1.381   2.277  0.0271 -0.1672  0.2233
-  174DMSO    OD  695   2.475   1.293   2.026 -0.3816  0.3194 -0.1596
-  174DMSO   CD2  696   2.223   1.188   2.116  0.2451 -0.1707  0.2670
-  175DMSO    SD  697   2.127   0.392   0.495  0.0122  0.3820  0.3899
-  175DMSO   CD1  698   2.162   0.494   0.333 -0.6112 -0.3095 -0.1854
-  175DMSO    OD  699   2.140   0.488   0.614  0.4100  0.5191  0.2433
-  175DMSO   CD2  700   1.935   0.375   0.470  0.0303  0.1945  0.4298
-  176DMSO    SD  701   0.239   1.785   0.401 -0.5069  0.2832  0.0894
-  176DMSO   CD1  702   0.230   1.590   0.391  0.0746  0.2518  0.1275
-  176DMSO    OD  703   0.231   1.817   0.252 -0.9473 -0.3318 -0.0230
-  176DMSO   CD2  704   0.064   1.799   0.485 -0.2960  0.5595  0.4891
-  177DMSO    SD  705   1.396   0.016   1.071 -0.1144  0.1569  0.0587
-  177DMSO   CD1  706   1.503   0.128   0.953  0.1135 -0.0272  0.0886
-  177DMSO    OD  707   1.365  -0.107   0.986  0.3799  0.0701  0.0062
-  177DMSO   CD2  708   1.553  -0.023   1.181  0.3381 -0.1884 -0.7117
-  178DMSO    SD  709   2.319   0.193   2.237 -0.2670  0.0102  0.3959
-  178DMSO   CD1  710   2.471   0.275   2.147 -0.4940 -0.4100 -0.3750
-  178DMSO    OD  711   2.272   0.280   2.354 -0.1281  0.1917  0.3198
-  178DMSO   CD2  712   2.201   0.220   2.085  0.7844  0.0157 -0.4319
-  179DMSO    SD  713   0.230   0.620   0.617  0.1583 -0.2518 -0.1791
-  179DMSO   CD1  714   0.130   0.664   0.456  0.0641  0.6493  0.1216
-  179DMSO    OD  715   0.271   0.765   0.647 -0.1482 -0.0426 -0.7612
-  179DMSO   CD2  716   0.069   0.585   0.720  0.0834  0.3038 -0.1042
-  180DMSO    SD  717   2.359   2.527   2.307 -0.1165 -0.0396 -0.2913
-  180DMSO   CD1  718   2.200   2.601   2.392  0.1767 -0.0575  0.2958
-  180DMSO    OD  719   2.464   2.638   2.298  0.0850 -0.2782 -0.9689
-  180DMSO   CD2  720   2.414   2.407   2.451  0.2623 -0.1531 -0.5156
-  181DMSO    SD  721   1.881   1.433   1.866  0.3126  0.0091 -0.0188
-  181DMSO   CD1  722   1.831   1.593   1.767 -0.1053  0.1206  0.3704
-  181DMSO    OD  723   1.982   1.363   1.775  0.3560 -0.4274  0.3566
-  181DMSO   CD2  724   1.981   1.517   2.012  0.3822  0.4205 -0.3030
-  182DMSO    SD  725   0.326   2.397   0.306 -0.0782  0.0883  0.0799
-  182DMSO   CD1  726   0.136   2.374   0.344 -0.0743 -0.0801  0.0063
-  182DMSO    OD  727   0.385   2.412   0.446  0.2287 -0.5969  0.0220
-  182DMSO   CD2  728   0.350   2.211   0.254 -0.4572 -0.0446  0.3519
-  183DMSO    SD  729   0.067   1.084   0.291 -0.1385 -0.2201 -0.2065
-  183DMSO   CD1  730   0.171   1.086   0.456  0.4652 -0.1882 -0.5817
-  183DMSO    OD  731   0.016   0.942   0.268  0.0739 -0.1577 -1.1117
-  183DMSO   CD2  732  -0.082   1.192   0.354  0.3045  0.4748 -0.3061
-  184DMSO    SD  733   0.039   2.149  -0.022 -0.1551  0.5456 -0.1496
-  184DMSO   CD1  734  -0.155   2.168  -0.033 -0.1401  0.7730 -0.0391
-  184DMSO    OD  735   0.100   2.275   0.038  0.3040  0.5380 -0.5956
-  184DMSO   CD2  736   0.065   2.013   0.116  0.2010  0.7491 -0.0147
-  185DMSO    SD  737   0.809   0.351   1.104  0.0639 -0.1681  0.2080
-  185DMSO   CD1  738   0.888   0.181   1.158 -0.0080 -0.1683  0.3252
-  185DMSO    OD  739   0.658   0.331   1.088  0.0164 -0.0265  0.4699
-  185DMSO   CD2  740   0.820   0.443   1.276 -0.1125  0.4117 -0.0879
-  186DMSO    SD  741   1.582   1.429   1.178 -0.0836 -0.3788  0.2447
-  186DMSO   CD1  742   1.724   1.321   1.098  0.0486 -0.3623  0.4322
-  186DMSO    OD  743   1.517   1.509   1.066  0.0144 -0.0023  0.4566
-  186DMSO   CD2  744   1.458   1.283   1.218 -0.4545 -0.1671 -0.1037
-  187DMSO    SD  745   0.026   2.726  -0.025  0.0808  0.1849 -0.1883
-  187DMSO   CD1  746   0.014   2.816   0.147 -0.1929  0.3271 -0.2842
-  187DMSO    OD  747   0.172   2.681  -0.029  0.0264  0.0114 -0.2821
-  187DMSO   CD2  748  -0.097   2.576  -0.000  0.2227  0.1327  0.2141
-  188DMSO    SD  749   2.308   1.625   0.476  0.1520  0.1563  0.1143
-  188DMSO   CD1  750   2.287   1.526   0.309  0.0827  0.2038  0.0899
-  188DMSO    OD  751   2.276   1.772   0.449 -0.0720  0.2359  0.7602
-  188DMSO   CD2  752   2.158   1.568   0.587  0.2636 -0.8618 -0.2621
-  189DMSO    SD  753   2.593   0.288   1.271  0.1819 -0.2789 -0.4347
-  189DMSO   CD1  754   2.546   0.457   1.356  1.4617 -0.1239  0.0028
-  189DMSO    OD  755   2.637   0.211   1.396 -0.3781 -0.0059 -0.0657
-  189DMSO   CD2  756   2.410   0.237   1.227  0.0538  0.2526 -0.5684
-  190DMSO    SD  757   2.393   1.477  -0.043  0.0426 -0.5414  0.0704
-  190DMSO   CD1  758   2.340   1.662  -0.015  0.4222 -0.3593 -0.3541
-  190DMSO    OD  759   2.475   1.438   0.080  0.0837 -0.1082  0.1761
-  190DMSO   CD2  760   2.222   1.386  -0.019 -0.2866 -0.0182 -0.2640
-  191DMSO    SD  761   1.426   0.509   0.682 -0.1246  0.0377  0.1999
-  191DMSO   CD1  762   1.565   0.603   0.583 -0.0945 -0.5540 -0.3254
-  191DMSO    OD  763   1.431   0.544   0.831  0.9135  0.4520  0.0736
-  191DMSO   CD2  764   1.271   0.612   0.624  0.3751  0.4102 -0.4852
-  192DMSO    SD  765   0.458   0.771   0.309  0.2015  0.3997 -0.2951
-  192DMSO   CD1  766   0.554   0.660   0.181  0.1738 -0.3338  0.3085
-  192DMSO    OD  767   0.527   0.905   0.329  0.5907  0.1408  0.1112
-  192DMSO   CD2  768   0.309   0.815   0.191 -0.0749 -0.3164 -0.2203
-  193DMSO    SD  769   0.141   2.931   2.317 -0.2157 -0.2062 -0.0861
-  193DMSO   CD1  770   0.016   2.899   2.171  0.0250  0.0049 -0.3403
-  193DMSO    OD  771   0.065   2.969   2.444 -0.5411 -0.5072 -0.1906
-  193DMSO   CD2  772   0.208   2.748   2.326 -0.0677 -0.1434  0.1048
-  194DMSO    SD  773   2.525   2.209   0.910  0.1612 -0.1880 -0.0201
-  194DMSO   CD1  774   2.688   2.182   1.013  0.0767  0.7284  0.3851
-  194DMSO    OD  775   2.414   2.123   0.971  0.1267  0.0851  0.2987
-  194DMSO   CD2  776   2.485   2.384   0.987  0.7945  0.0585 -0.2435
-  195DMSO    SD  777   2.050   0.204   2.586  0.1599 -0.0480  0.2195
-  195DMSO   CD1  778   2.217   0.127   2.651  0.0037  0.3714  1.1371
-  195DMSO    OD  779   1.949   0.129   2.673  0.4907 -0.3491  0.3453
-  195DMSO   CD2  780   2.085   0.383   2.655 -0.4045  0.2899 -0.3580
-  196DMSO    SD  781   1.744   0.642   2.585  0.0504  0.0463 -0.5525
-  196DMSO   CD1  782   1.910   0.717   2.655  0.3088 -1.0352  0.0215
-  196DMSO    OD  783   1.731   0.490   2.596  0.5257  0.0490  0.1210
-  196DMSO   CD2  784   1.628   0.688   2.735  0.4828 -0.0142 -0.1985
-  197DMSO    SD  785   2.479   0.980   0.366 -0.1036 -0.1347  0.2435
-  197DMSO   CD1  786   2.603   0.920   0.228  0.0702 -0.4369  0.5299
-  197DMSO    OD  787   2.555   1.019   0.493 -0.0647 -0.0442  0.1936
-  197DMSO   CD2  788   2.394   1.121   0.260  0.2174 -0.4294 -0.4146
-  198DMSO    SD  789   2.073   0.553   1.652 -0.2987  0.3349  0.0174
-  198DMSO   CD1  790   1.953   0.439   1.754 -0.3820  0.1532 -0.2817
-  198DMSO    OD  791   2.185   0.466   1.594 -0.2211  0.3388  0.1617
-  198DMSO   CD2  792   1.942   0.585   1.511  0.0405 -0.7390 -0.5612
-  199DMSO    SD  793   2.348   2.792   0.411 -0.0739 -0.1142  0.1751
-  199DMSO   CD1  794   2.248   2.627   0.439 -0.2279 -0.0411  0.0694
-  199DMSO    OD  795   2.329   2.857   0.274  0.7038 -0.2502  0.0011
-  199DMSO   CD2  796   2.226   2.897   0.522 -0.0331  0.6099 -0.4490
-  200DMSO    SD  797   0.605   0.134   0.647 -0.0462 -0.2846  0.0058
-  200DMSO   CD1  798   0.796   0.155   0.680 -0.0575 -0.4839  0.2066
-  200DMSO    OD  799   0.579  -0.014   0.677  0.6258 -0.4649 -0.2767
-  200DMSO   CD2  800   0.542   0.228   0.805 -0.0580 -0.0760 -0.1219
-  201DMSO    SD  801   1.585   1.731   1.446 -0.1947 -0.0247  0.3547
-  201DMSO   CD1  802   1.530   1.888   1.547  0.5073  0.5125 -0.0998
-  201DMSO    OD  803   1.506   1.607   1.491 -0.4009  0.2261  0.6904
-  201DMSO   CD2  804   1.515   1.781   1.271  0.1125 -0.6604  0.0497
-  202DMSO    SD  805  -0.037   1.908   1.848  0.3234  0.0831  0.1783
-  202DMSO   CD1  806   0.113   1.787   1.816  0.3056  0.1751 -0.2702
-  202DMSO    OD  807  -0.040   1.937   1.998  0.3274 -0.8189  0.3496
-  202DMSO   CD2  808   0.037   2.055   1.743 -0.2584  0.1357 -0.1816
-  203DMSO    SD  809   0.613   2.508   2.047 -0.1770 -0.1717 -0.5288
-  203DMSO   CD1  810   0.537   2.641   1.927 -0.1501  0.2539 -0.0802
-  203DMSO    OD  811   0.523   2.385   2.034 -0.1143 -0.2151 -0.5655
-  203DMSO   CD2  812   0.783   2.488   1.953  0.5404  0.5641  0.5760
-  204DMSO    SD  813   1.037   0.098   2.608  0.3241 -0.2840 -0.2910
-  204DMSO   CD1  814   1.140   0.139   2.768  0.0354 -0.5712 -0.0290
-  204DMSO    OD  815   0.894   0.060   2.647  0.1065  0.2757 -0.5254
-  204DMSO   CD2  816   1.027   0.284   2.550 -0.6331 -0.3315 -0.3341
-  205DMSO    SD  817   0.396   0.367   0.319 -0.2819 -0.1180 -0.0154
-  205DMSO   CD1  818   0.276   0.281   0.446  0.0777  0.1885  0.5338
-  205DMSO    OD  819   0.303   0.473   0.261 -0.6565 -0.1986  0.4438
-  205DMSO   CD2  820   0.517   0.439   0.453  0.2228 -0.5648 -0.2129
-  206DMSO    SD  821   0.816   1.213   1.124 -0.4610  0.0448  0.0922
-  206DMSO   CD1  822   0.766   1.082   0.988 -0.2183  0.0845 -0.0384
-  206DMSO    OD  823   0.950   1.149   1.159 -0.0710  0.6546 -0.2924
-  206DMSO   CD2  824   0.837   1.363   1.001  0.5192  0.0666  0.2725
-  207DMSO    SD  825   1.541   2.288   1.281  0.1023  0.1094  0.0821
-  207DMSO   CD1  826   1.483   2.469   1.325 -0.1763  0.1235 -0.3533
-  207DMSO    OD  827   1.659   2.317   1.187  0.2348 -0.3310  0.1077
-  207DMSO   CD2  828   1.602   2.207   1.447 -0.1681  0.0018  0.1306
-  208DMSO    SD  829   1.691   2.239   0.183 -0.4203 -0.0751  0.3402
-  208DMSO   CD1  830   1.648   2.274  -0.004  0.1103  0.0923  0.2410
-  208DMSO    OD  831   1.653   2.094   0.216  0.0492 -0.2086  0.2908
-  208DMSO   CD2  832   1.881   2.242   0.139 -0.6149  0.8721 -0.4796
-   2.89162   2.89162   2.89162
diff --git a/share/top/dmso.itp b/share/top/dmso.itp
deleted file mode 100644 (file)
index ed262d7..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-[ moleculetype ]
-; name  nrexcl
-DMSO   2
-
-[ atoms ]
-;   nr    type   resnr  residu  atom    cgnr    charge
-    1     SD     1     DMSO    SD      1        0.139
-    2     CD     1     DMSO    CD1     1        0.16
-    3     OD     1     DMSO    OD      1       -0.459
-    4     CD     1     DMSO    CD2     1        0.16
-
-[ bonds ]
-;  ai    aj funct          b0       kb
-    1     2     1      0.195   376560  ; kb from Methionine
-    1     3     1      0.153   502080  ; kb from C=O bond      
-    1     4     1      0.195   376560
-
-[ angles ]
-;  ai    aj    ak   funct        theta      kt
-3      1       2       1       106.75  460.240
-3      1       4       1       106.75  460.240
-2      1       4       1        97.40  460.240 ; kt from Methionine
-
-[ dihedrals ]
-;  ai  aj      ak      al   funct     xi         kxi   
-1      2       4       3       2 35.264     334.720    ; default params
index f6b6b4bbfa71566a64733a1e7e9a8a7f5ca99ab3..2b6d26872d97ea8fd6d3253b0f55868aafea5ce3 100644 (file)
@@ -9,7 +9,7 @@ aminoacids.c.tdb        atomtypes.atp           f3c.itp \
 aminoacids.hdb         ffbonded.itp            \
 aminoacids.n.tdb       ffnonbonded.itp         \
 aminoacids.rtp         forcefield.doc          \
-forcefield.itp 
+aminoacids.r2b         forcefield.itp          watermodels.dat
 
 EXTRA_DIST = ${topol_DATA}
 
index e15265a672b71000ac5c7591c95ab93e38a164e7..b06deead13f21024e14f9a67d2626a1e37e1f001 100644 (file)
@@ -2,12 +2,12 @@
 
 [ COO- ]
 [ replace ]
-C              Abis    12.011  0.84
+C      C       Abis    12.011   0.84
+O      O1      Obis    15.9994 -0.92
+OXT    O2      Obis    15.9994 -0.92
 [ add ]
 2      8       O       C       CA      N
        Obis    15.9994 -0.92
-[ delete ]
-O
 [ dihedrals ]
 N      CA      C       O2      
 [ impropers ]
@@ -16,12 +16,12 @@ N   C       CA      CB      improper_X_X_C_X
 
 [ Gly-COO- ]
 [ replace ]
-C              Abis    12.011  0.84
+C      C       Abis    12.011   0.84
+O      O       Obis    15.9994 -0.92
+OXT    O2      Obis    15.9994 -0.92
 [ add ]
 2      8       O       C       CA      N
        Obis    15.9994 -0.92
-[ delete ]
-O
 [ dihedrals ]
 N      CA      C       O2      
 [ impropers ]
@@ -29,15 +29,16 @@ CA  O2      C       O1      improper_X_X_A_X
 
 [ COOH ]
 [ replace ]
-C              Aprime  12.011  0.38
-O              OH      15.9994 -0.38
+C      C       Aprime  12.011   0.38
+O      O       OH      15.9994 -0.38
+OXT    OT      O       15.9994 -0.433
 [ add ]
 1      2       OT      C       CA      N
        O       15.9994 -0.433
 1      2       HO      O       C       CA
        HO      1.008   0.433
 [ dihedrals ]
-N      CA      C       O1      
+N      CA      C       O       
 [ impropers ]
-O2     CA      C       O1      improper_X_X_A_X
+OT     CA      C       O       improper_X_X_A_X
 
diff --git a/share/top/encads.ff/aminoacids.r2b b/share/top/encads.ff/aminoacids.r2b
new file mode 100644 (file)
index 0000000..823db90
--- /dev/null
@@ -0,0 +1,7 @@
+; rtp residue to rtp building block table
+;GMX   Force-field
+CYS    CYSH
+HISD   HISA
+HISE   HISB
+LYS    LYSH
+LYSN   LYS
index b7ce94d19b1c5a734728cabf77111d2deabf07e0..35c5b999a376b308a4e3eeee50d6a3b1dc5e1da2 100644 (file)
@@ -1 +1 @@
-Encad all-atom force field, using full solvent charges
+[DEPRECATED] Encad all-atom force field, using full solvent charges
diff --git a/share/top/encads.ff/watermodels.dat b/share/top/encads.ff/watermodels.dat
new file mode 100644 (file)
index 0000000..592e150
--- /dev/null
@@ -0,0 +1 @@
+f3c  F3C  flexible three-centered water model
index a157da128c812c3b86b84dba08d5a9d143c5b9d5..45c62b8c13e50334be97f9938009ee76a8c833a9 100644 (file)
@@ -9,7 +9,7 @@ aminoacids.c.tdb        atomtypes.atp           \
 aminoacids.hdb         ffbonded.itp            \
 aminoacids.n.tdb       ffnonbonded.itp         \
 aminoacids.rtp         forcefield.doc          \
-forcefield.itp 
+aminoacids.r2b         forcefield.itp          watermodels.dat
 
 EXTRA_DIST = ${topol_DATA}
 
index b60855dbaa400e6b362b4a495ca5535256a02518..918adc33c6432460b00c083d21df432e8d7bb189 100644 (file)
@@ -2,12 +2,12 @@
 
 [ COO- ]
 [ replace ]
-C              Abis    12.011  0.64
+C      C       Abis    12.011   0.64
+O      O1      Obis    15.9994 -0.42
+OXT    O2      Obis    15.9994 -0.42
 [ add ]
 2      8       O       C       CA      N
-       Obis    15.9994 -0.42
-[ delete ]
-O
+       Obis    15.9994 -0.92
 [ dihedrals ]
 N      CA      C       O2      
 [ impropers ]
@@ -16,15 +16,16 @@ N   C       CA      CB      improper_X_X_C_X
 
 [ COOH ]
 [ replace ]
-C              Aprime  12.011  0.38
-O              OH      15.9994 -0.38
+C      C       Aprime  12.011   0.38
+O      O       OH      15.9994 -0.38
+OXT    OT      O       15.9994 -0.433
 [ add ]
 1      2       OT      C       CA      N
        O       15.9994 -0.433
 1      2       HO      O       C       CA
        HO      1.008   0.433
 [ dihedrals ]
-N      CA      C       O1      
+N      CA      C       O       
 [ impropers ]
-O2     CA      C       O1      improper_X_X_A_X
+OT     CA      C       O       improper_X_X_A_X
 
diff --git a/share/top/encadv.ff/aminoacids.r2b b/share/top/encadv.ff/aminoacids.r2b
new file mode 100644 (file)
index 0000000..823db90
--- /dev/null
@@ -0,0 +1,7 @@
+; rtp residue to rtp building block table
+;GMX   Force-field
+CYS    CYSH
+HISD   HISA
+HISE   HISB
+LYS    LYSH
+LYSN   LYS
index 9de72a5a3ab90f9bede070446ef77e63b231380e..778b023fb85b07c5143f145017bffe641e20aca3 100644 (file)
@@ -1 +1 @@
-Encad all-atom force field, using scaled-down vacuum charges
+[DEPRECATED] Encad all-atom force field, using scaled-down vacuum charges
diff --git a/share/top/encadv.ff/watermodels.dat b/share/top/encadv.ff/watermodels.dat
new file mode 100644 (file)
index 0000000..592e150
--- /dev/null
@@ -0,0 +1 @@
+f3c  F3C  flexible three-centered water model
similarity index 100%
rename from share/top/1mlg.itp
rename to share/top/gmx.ff/1mlg.itp
similarity index 100%
rename from share/top/2mlg.itp
rename to share/top/gmx.ff/2mlg.itp
index 4470028fe075c0c384eaa113502dc79743bde14f..9da5c2721a940ece4c5cbbc6c1fa42b5e4b02e60 100644 (file)
@@ -9,7 +9,11 @@ aminoacids.c.tdb       atomtypes.atp           ions.itp        \
 aminoacids.hdb         ffbonded.itp            spc.itp         \
 aminoacids.n.tdb       ffnonbonded.itp         spce.itp        \
 aminoacids.rtp         forcefield.doc          tip3p.itp       \
-aminoacids.vsd         forcefield.itp          tip4p.itp
+aminoacids.vsd         forcefield.itp          tip4p.itp       \
+h2p4o13.itp            h2p8o25.itp             h2po4.itp       \
+1mlg.itp               2mlg.itp                decane.itp      \
+dlg.itp                        fa.itp                  tfe.itp         \
+decane50.gro           watermodels.dat
 
 EXTRA_DIST = ${topol_DATA}
 
index 7e57c3e6acde60c5c607ad147f1932fa3f6eabcf..daa9356449db604bebec57ca4cb5b8fc35b8f522 100644 (file)
    OW  OWT4    0.0      0
   HW1    HW    0.52     0
   HW2    HW    0.52     0
-  HW3    IW   -1.04     0
+   MW    IW   -1.04     0
  [ bonds ]
    OW   HW1    gb_35
    OW   HW2    gb_35
-   OW   HW3    gb_35
 
 [ HYP ]
  [ atoms ]
similarity index 100%
rename from share/top/dlg.itp
rename to share/top/gmx.ff/dlg.itp
similarity index 100%
rename from share/top/fa.itp
rename to share/top/gmx.ff/fa.itp
similarity index 100%
rename from share/top/tfe.itp
rename to share/top/gmx.ff/tfe.itp
diff --git a/share/top/gmx.ff/watermodels.dat b/share/top/gmx.ff/watermodels.dat
new file mode 100644 (file)
index 0000000..834a93a
--- /dev/null
@@ -0,0 +1,4 @@
+spc    SPC    simple point charge, recommended
+spce   SPC/E  extended simple point charge
+tip3p  TIP3P  TIP 3-point
+tip4p  TIP4P  TIP 4-point
index 94ecd2080753e1310f27db701eeabaf1e945ca57..94408a1f8d6ff4752435e207513432044d354c57 100644 (file)
@@ -9,7 +9,8 @@ aminoacids.c.tdb        atomtypes.atp           ions.itp        \
 aminoacids.hdb         ffbonded.itp            spc.itp         \
 aminoacids.n.tdb       ffnonbonded.itp         spce.itp        \
 aminoacids.rtp         forcefield.doc          tip3p.itp       \
-aminoacids.vsd         forcefield.itp          tip4p.itp
+aminoacids.vsd         forcefield.itp          tip4p.itp       \
+watermodels.dat
 
 EXTRA_DIST = ${topol_DATA}
 
index 20e955c73f475ac90c35693263b952a35538e343..301cc3733995a3506cc681701d144e388c331121 100644 (file)
    OW  OWT4    0.0     0
   HW1     H    0.52     0
   HW2     H    0.52     0
-  HW3    IW   -1.04     0
+   MW    IW   -1.04     0
  [ bonds ]
    OW   HW1
    OW   HW2
-   OW   HW3
 
 [ HYP ]
  [ atoms ]
diff --git a/share/top/gmx2.ff/watermodels.dat b/share/top/gmx2.ff/watermodels.dat
new file mode 100644 (file)
index 0000000..834a93a
--- /dev/null
@@ -0,0 +1,4 @@
+spc    SPC    simple point charge, recommended
+spce   SPC/E  extended simple point charge
+tip3p  TIP3P  TIP 3-point
+tip4p  TIP4P  TIP 4-point
index c4e302b2ca1388057c6a864e3d3a907dc501b4bb..d09a8a867476ad5be4f8b9fae87779bf1276553e 100644 (file)
@@ -9,7 +9,9 @@ aminoacids.c.tdb        atomtypes.atp           ions.itp        \
 aminoacids.hdb         ffbonded.itp            spc.itp         \
 aminoacids.n.tdb       ffnonbonded.itp         spce.itp        \
 aminoacids.rtp         forcefield.doc          tip3p.itp       \
-aminoacids.vsd         forcefield.itp          tip4p.itp
+aminoacids.vsd         forcefield.itp          tip4p.itp       \
+aminoacids.r2b         methanol.itp            methanol216.gro \
+watermodels.dat
 
 EXTRA_DIST = ${topol_DATA}
 
diff --git a/share/top/gromos43a1.ff/aminoacids.r2b b/share/top/gromos43a1.ff/aminoacids.r2b
new file mode 100644 (file)
index 0000000..823db90
--- /dev/null
@@ -0,0 +1,7 @@
+; rtp residue to rtp building block table
+;GMX   Force-field
+CYS    CYSH
+HISD   HISA
+HISE   HISB
+LYS    LYSH
+LYSN   LYS
index 7765ff651e6bca325640577514bb406ee66ffd27..1b01ede52c4d6e9efee7d06c7ac87880d36ef05c 100644 (file)
@@ -10,7 +10,6 @@
 ; bonds  angles  dihedrals  impropers all_dihedrals nrexcl HH14 RemoveDih
      2      2         1          2         0           3     0     1
 
-
 [ ACE ]
  [ atoms ]
     CA   CH3   0.000     0
@@ -21,6 +20,7 @@
      C     O   gb_4
      C    +N   gb_9
  [ angles ]
+   CA     C     O    ga_30
    CA     C    +N    ga_18
     O     C    +N    ga_32
  [ impropers ]
@@ -9217,11 +9217,10 @@ AO3PB   APG AO3PG AH3PG     gd_9
    OW  OWT4    0.0     0
   HW1     H    0.52     0
   HW2     H    0.52     0
-  HW3    IW   -1.04     0
+   MW    IW   -1.04     0
  [ bonds ]
    OW   HW1    gb_35
    OW   HW2    gb_35
-   OW   HW3    gb_35
  [ angles ]
 ;   ai    aj    ak  gromos type
  [ impropers ]
@@ -9247,11 +9246,11 @@ AO3PB   APG AO3PG AH3PG     gd_9
 
 [ CHCL3 ]
  [ atoms ]
- CChl  CCHL     0.17900     0
- HChl  HCHL     0.08200     0
-CLCh1 CLCHL    -0.08700     0
-CLCh2 CLCHL    -0.08700     0
-CLCh3 CLCHL    -0.08700     0
+ CChl  CChl     0.17900     0
+ HChl  HChl     0.08200     0
+CLCh1 CLChl    -0.08700     0
+CLCh2 CLChl    -0.08700     0
+CLCh3 CLChl    -0.08700     0
  [ bonds ]
  CChl CLCh1    gb_37   
  CChl CLCh2    gb_37   
@@ -9271,10 +9270,10 @@ CLCh2 CLCh3    gb_43
 
 [ DMSO ]
  [ atoms ]
-SDmso SDMSO     0.13900     0
-ODmso ODMSO    -0.45900     0
-CDms1 CDMSO     0.16000     0
-CDms2 CDMSO     0.16000     0
+SDmso SDmso     0.13900     0
+ODmso ODmso    -0.45900     0
+CDms1 CDmso     0.16000     0
+CDms2 CDmso     0.16000     0
  [ bonds ]
 SDmso ODmso    gb_38   
 SDmso CDms1    gb_39   
@@ -9291,9 +9290,9 @@ CDms1 CDms2    gb_45
 
 [ CH3OH ]
  [ atoms ]
- Omet  OMET    -0.57400     0
+ Omet  OMet    -0.57400     0
  HMet     H     0.39800     0
- CMet  CMET     0.17600     0
+ CMet  CMet     0.17600     0
  [ bonds ]
  Omet  HMet    gb_1    
  Omet  CMet    gb_17   
@@ -9307,11 +9306,11 @@ CDms1 CDms2    gb_45
 
 [ CCL4 ]
  [ atoms ]
- CCl4  CCL4     0.00000     0
-CLCl1 CLCL4     0.00000     0
-CLCl2 CLCL4     0.00000     0
-CLCl3 CLCL4     0.00000     0
-CLCl4 CLCL4     0.00000     0
+ CCl4  CCl4     0.00000     0
+CLCl1 CLCl4     0.00000     0
+CLCl2 CLCl4     0.00000     0
+CLCl3 CLCl4     0.00000     0
+CLCl4 CLCl4     0.00000     0
  [ bonds ]
  CCl4 CLCl1    gb_40   
  CCl4 CLCl2    gb_40   
index 3fa34e288501fda3bf79434a9e8872b5456cbc01..127d88473edf4d88c3e7d8a9a55bbaaabd088989 100644 (file)
     F  18.99840 ;     fluor (non-ionic)
    CL  35.45300 ;     chlorine (non-ionic)
    BR  79.90400 ;     bromine (non-ionic)
- CMET  15.035   ;     CH3-group in methanol (solvent)
- OMET  15.9994  ;     oxygen in methanol (solvent)
+ CMet  15.035   ;     CH3-group in methanol (solvent)
+ OMet  15.9994  ;     oxygen in methanol (solvent)
   NA+  22.9898  ;     sodium (charge 1+)
   CL-  35.45300 ;     chlorine (charge 1-)
- CCHL  12.011   ;     carbon in chloroform (solvent)
-CLCHL  35.453   ;     chloride in chloroform (solvent)
- HCHL  1.008    ;     hydrogen in chloroform (solvent)
-SDMSO  32.06000 ;     DMSO Sulphur (solvent)
-CDMSO  15.03500 ;     DMSO Carbon (solvent)
-ODMSO  15.99940 ;     DMSO Oxygen (solvent)
- CCL4  12.011   ;     carbon in carbontetrachloride (solvent)
-CLCL4  35.453   ;     chloride in carbontetrachloride (solvent)
+ CChl  12.011   ;     carbon in chloroform (solvent)
+CLChl  35.453   ;     chloride in chloroform (solvent)
+ HChl  1.008    ;     hydrogen in chloroform (solvent)
+SDmso  32.06000 ;     DMSO Sulphur (solvent)
+CDmso  15.03500 ;     DMSO Carbon (solvent)
+ODmso  15.99940 ;     DMSO Oxygen (solvent)
+ CCl4  12.011   ;     carbon in carbontetrachloride (solvent)
+CLCl4  35.453   ;     chloride in carbontetrachloride (solvent)
    SI  28.08   ;     silicon
  MNH3   0       ;     Dummy mass in rigid tetraedrical NH3 group
    MW   0       ;     Dummy mass in rigid tyrosine rings
index 759cb0aca19af40e0ff620a4b7d7a341dd9d44ae..eb5c995afeaaa8636c6bf9317c0b53c78b304d83 100644 (file)
     F    9     0.000      0.000     A  0.0011778624  7.6073284e-07
    CL   17     0.000      0.000     A  0.0087647044  1.5295921e-05
    BR   35     0.000      0.000     A  0.0011792356  6.5480464e-05
- CMET    6     0.000      0.000     A  0.0088755241  2.0852922e-05
- OMET    8     0.000      0.000     A  0.0022619536  1.505529e-06
+ CMet    6     0.000      0.000     A  0.0088755241  2.0852922e-05
+ OMet    8     0.000      0.000     A  0.0022619536  1.505529e-06
   NA+   11     0.000      0.000     A  7.2063121e-05  2.1025e-08
   CL-   17     0.000      0.000     A  0.01380625  0.0001069156
- CCHL    6     0.000      0.000     A  0.0026308693  4.064256e-06
-CLCHL   17     0.000      0.000     A  0.0083066819  1.3764842e-05
- HCHL    1     0.000      0.000     A  3.76996e-05  4.2999495e-09
-SDMSO   16     0.000      0.000     A  0.010561673  2.149806e-05
-CDMSO    6     0.000      0.000     A  0.0090514293  2.175756e-05
-ODMSO    8     0.000      0.000     A  0.0022707131  7.5144626e-07
- CCL4    6     0.000      0.000     A  0.0026308693  7.5999462e-06
-CLCL4   17     0.000      0.000     A  0.0076040144  1.2767758e-05
+ CChl    6     0.000      0.000     A  0.0026308693  4.064256e-06
+CLChl   17     0.000      0.000     A  0.0083066819  1.3764842e-05
+ HChl    1     0.000      0.000     A  3.76996e-05  4.2999495e-09
+SDmso   16     0.000      0.000     A  0.010561673  2.149806e-05
+CDmso    6     0.000      0.000     A  0.0090514293  2.175756e-05
+ODmso    8     0.000      0.000     A  0.0022707131  7.5144626e-07
+ CCl4    6     0.000      0.000     A  0.0026308693  7.5999462e-06
+CLCl4   17     0.000      0.000     A  0.0076040144  1.2767758e-05
    SI   14     0.000      0.000     A  0.01473796  2.2193521e-05
  MNH3    0     0.000      0.000     A   0.0           0.0
  OWT3    8     15.9994     0.000     A   0.24889E-02   0.24352E-05
@@ -517,69 +517,69 @@ CLCL4   17        0.000      0.000     A  0.0076040144  1.2767758e-05
       BR       AR  1  0.002718011  2.5392696e-05
       BR        F  1  0.0011785488  7.0578424e-06
       BR       CL  1  0.0032149108  3.1647812e-05
-    CMET        O  1  0.0044806276  3.9322131e-06
-    CMET       OM  1  0.0044806276  3.9322131e-06
-    CMET       OA  1  0.0044806276  5.1373125e-06
-    CMET       OW  1  0.0048197836  7.050676e-06
-    CMET        N  1  0.0046502056  5.9410165e-06
-    CMET       NT  1  0.0046502056  5.9410165e-06
-    CMET       NL  1  0.0046502056  5.9410165e-06
-    CMET       NR  1  0.0046502056  5.9410165e-06
-    CMET       NZ  1  0.0046502056  5.9410165e-06
-    CMET       NE  1  0.0046502056  5.9410165e-06
-    CMET        C  1  0.0045578798  8.3886605e-06
-    CMET      CH1  1  0.0057920308  1.5402804e-05
-    CMET      CH2  1  0.0079409609  2.318412e-05
-    CMET      CH3  1  0.0093814318  2.6458301e-05
-    CMET      CH4  1  0.010815308  2.6768823e-05
-    CMET      CR1  1  0.0069950925  1.7754552e-05
-    CMET       HC  1  0.000866732  5.616795e-07
-    CMET        H  1           0           0
-    CMET      DUM  1           0           0
-    CMET        S  1  0.0094134632  1.6512464e-05
-    CMET     CU1+  1  0.0019265945  3.2691574e-07
-    CMET     CU2+  1  0.0019265945  3.2691574e-07
-    CMET       FE  1           0           0
-    CMET     ZN2+  1  0.0019265945  4.4368114e-07
-    CMET     MG2+  1  0.0007612168  2.6659227e-07
-    CMET     CA2+  1  0.002986457  3.222579e-06
-    CMET        P  1  0.011437094  2.1512782e-05
-    CMET       AR  1  0.0074567215  1.4329677e-05
-    CMET        F  1  0.0032332872  3.9829013e-06
-    CMET       CL  1  0.0088199402  1.7859582e-05
-    CMET       BR  1  0.0032351714  3.6952118e-05
-    OMET        O  1  0.0022619536  1.380375e-06
-    OMET       OM  1  0.0022619536  2.258907e-06
-    OMET       OA  1  0.0022619536  1.505529e-06
-    OMET       OW  1  0.0024331696  1.991421e-06
-    OMET        N  1  0.0023475616  2.384061e-06
-    OMET       NT  1  0.0023475616  2.76075e-06
-    OMET       NL  1  0.0023475616  3.764436e-06
-    OMET       NR  1  0.0023475616  2.258907e-06
-    OMET       NZ  1  0.0023475616  2.635596e-06
-    OMET       NE  1  0.0023475616  2.434368e-06
-    OMET        C  1  0.0023009528  2.066625e-06
-    OMET      CH1  1  0.0029239888  3.794625e-06
-    OMET      CH2  1  0.0040088324  5.711625e-06
-    OMET      CH3  1  0.0047360248  6.51825e-06
-    OMET      CH4  1  0.005459888  6.59475e-06
-    OMET      CR1  1  0.00353133   4.374e-06
-    OMET       HC  1  0.000437552  1.38375e-07
-    OMET        H  1           0           0
-    OMET      DUM  1           0           0
-    OMET        S  1  0.0047521952   4.068e-06
-    OMET     CU1+  1  0.000972602  2.76075e-07
-    OMET     CU2+  1  0.000972602  5.019657e-07
-    OMET       FE  1           0           0
-    OMET     ZN2+  1  0.000972602  1.1921532e-07
-    OMET     MG2+  1  0.0003842848  7.163226e-08
-    OMET     CA2+  1  0.001507652  8.658939e-07
-    OMET        P  1  0.005773784  5.780397e-06
-    OMET       AR  1  0.003764374  3.53025e-06
-    OMET        F  1  0.0016322592  1.505529e-06
-    OMET       CL  1  0.0044525672  4.798797e-06
-    OMET       BR  1  0.0016332104  9.928884e-06
-    OMET     CMET  1  0.0044806276  5.1373125e-06
+    CMet        O  1  0.0044806276  3.9322131e-06
+    CMet       OM  1  0.0044806276  3.9322131e-06
+    CMet       OA  1  0.0044806276  5.1373125e-06
+    CMet       OW  1  0.0048197836  7.050676e-06
+    CMet        N  1  0.0046502056  5.9410165e-06
+    CMet       NT  1  0.0046502056  5.9410165e-06
+    CMet       NL  1  0.0046502056  5.9410165e-06
+    CMet       NR  1  0.0046502056  5.9410165e-06
+    CMet       NZ  1  0.0046502056  5.9410165e-06
+    CMet       NE  1  0.0046502056  5.9410165e-06
+    CMet        C  1  0.0045578798  8.3886605e-06
+    CMet      CH1  1  0.0057920308  1.5402804e-05
+    CMet      CH2  1  0.0079409609  2.318412e-05
+    CMet      CH3  1  0.0093814318  2.6458301e-05
+    CMet      CH4  1  0.010815308  2.6768823e-05
+    CMet      CR1  1  0.0069950925  1.7754552e-05
+    CMet       HC  1  0.000866732  5.616795e-07
+    CMet        H  1           0           0
+    CMet      DUM  1           0           0
+    CMet        S  1  0.0094134632  1.6512464e-05
+    CMet     CU1+  1  0.0019265945  3.2691574e-07
+    CMet     CU2+  1  0.0019265945  3.2691574e-07
+    CMet       FE  1           0           0
+    CMet     ZN2+  1  0.0019265945  4.4368114e-07
+    CMet     MG2+  1  0.0007612168  2.6659227e-07
+    CMet     CA2+  1  0.002986457  3.222579e-06
+    CMet        P  1  0.011437094  2.1512782e-05
+    CMet       AR  1  0.0074567215  1.4329677e-05
+    CMet        F  1  0.0032332872  3.9829013e-06
+    CMet       CL  1  0.0088199402  1.7859582e-05
+    CMet       BR  1  0.0032351714  3.6952118e-05
+    OMet        O  1  0.0022619536  1.380375e-06
+    OMet       OM  1  0.0022619536  2.258907e-06
+    OMet       OA  1  0.0022619536  1.505529e-06
+    OMet       OW  1  0.0024331696  1.991421e-06
+    OMet        N  1  0.0023475616  2.384061e-06
+    OMet       NT  1  0.0023475616  2.76075e-06
+    OMet       NL  1  0.0023475616  3.764436e-06
+    OMet       NR  1  0.0023475616  2.258907e-06
+    OMet       NZ  1  0.0023475616  2.635596e-06
+    OMet       NE  1  0.0023475616  2.434368e-06
+    OMet        C  1  0.0023009528  2.066625e-06
+    OMet      CH1  1  0.0029239888  3.794625e-06
+    OMet      CH2  1  0.0040088324  5.711625e-06
+    OMet      CH3  1  0.0047360248  6.51825e-06
+    OMet      CH4  1  0.005459888  6.59475e-06
+    OMet      CR1  1  0.00353133   4.374e-06
+    OMet       HC  1  0.000437552  1.38375e-07
+    OMet        H  1           0           0
+    OMet      DUM  1           0           0
+    OMet        S  1  0.0047521952   4.068e-06
+    OMet     CU1+  1  0.000972602  2.76075e-07
+    OMet     CU2+  1  0.000972602  5.019657e-07
+    OMet       FE  1           0           0
+    OMet     ZN2+  1  0.000972602  1.1921532e-07
+    OMet     MG2+  1  0.0003842848  7.163226e-08
+    OMet     CA2+  1  0.001507652  8.658939e-07
+    OMet        P  1  0.005773784  5.780397e-06
+    OMet       AR  1  0.003764374  3.53025e-06
+    OMet        F  1  0.0016322592  1.505529e-06
+    OMet       CL  1  0.0044525672  4.798797e-06
+    OMet       BR  1  0.0016332104  9.928884e-06
+    OMet     CMet  1  0.0044806276  5.1373125e-06
      NA+        O  1  0.00040373684  1.63125e-07
      NA+       OM  1  0.00040373684  4.4486e-07
      NA+       OA  1  0.00040373684  1.77915e-07
@@ -611,8 +611,8 @@ CLCL4   17          0.000      0.000     A  0.0076040144  1.2767758e-05
      NA+        F  1  0.00029134248  1.77915e-07
      NA+       CL  1  0.00079474018  5.67095e-07
      NA+       BR  1  0.00029151226  1.17334e-06
-     NA+     CMET  1  0.00079974869  6.621425e-07
-     NA+     OMET  1  0.00040373684  1.77915e-07
+     NA+     CMet  1  0.00079974869  6.621425e-07
+     NA+     OMet  1  0.00040373684  1.77915e-07
      CL-        O  1   0.0055883  8.903774e-06
      CL-       OM  1   0.0055883  8.903774e-06
      CL-       OA  1   0.0055883  1.268718e-05
@@ -644,317 +644,317 @@ CLCL4   17      0.000      0.000     A  0.0076040144  1.2767758e-05
      CL-        F  1   0.0040326  9.018548e-06
      CL-       CL  1  0.01100035  4.043974e-05
      CL-       BR  1  0.00403495  8.367128e-05
-     CL-     CMET  1  0.011069675  4.721761e-05
-     CL-     OMET  1   0.0055883  1.268718e-05
+     CL-     CMet  1  0.011069675  4.721761e-05
+     CL-     OMet  1   0.0055883  1.268718e-05
      CL-      NA+  1  0.0009974575  1.4993e-06
-    CCHL        O  1  0.0024394475  1.7359776e-06
-    CCHL       OM  1  0.0024394475  1.7359776e-06
-    CCHL       OA  1  0.0024394475   2.268e-06
-    CCHL       OW  1  0.0026240987  3.112704e-06
-    CCHL        N  1  0.0025317731  2.622816e-06
-    CCHL       NT  1  0.0025317731  2.622816e-06
-    CCHL       NL  1  0.0025317731  2.622816e-06
-    CCHL       NR  1  0.0025317731  2.622816e-06
-    CCHL       NZ  1  0.0025317731  2.622816e-06
-    CCHL       NE  1  0.0025317731  2.622816e-06
-    CCHL        C  1  0.002481507  3.703392e-06
-    CCHL      CH1  1  0.0031534322  6.799968e-06
-    CCHL      CH2  1  0.0043234027  1.0235232e-05
-    CCHL      CH3  1  0.0051076574  1.1680704e-05
-    CCHL      CH4  1  0.0058883216  1.1817792e-05
-    CCHL      CR1  1  0.003808431  7.838208e-06
-    CCHL       HC  1  0.0004718864  2.47968e-07
-    CCHL        H  1           0           0
-    CCHL      DUM  1           0           0
-    CCHL        S  1  0.0051250966  7.289856e-06
-    CCHL     CU1+  1  0.0010489214  1.4432544e-07
-    CCHL     CU2+  1  0.0010489214  1.4432544e-07
-    CCHL       FE  1           0           0
-    CCHL     ZN2+  1  0.0010489214  1.9587456e-07
-    CCHL     MG2+  1  0.00041443936  1.1769408e-07
-    CCHL     CA2+  1  0.0016259564  1.4226912e-06
-    CCHL        P  1  0.0062268488  9.497376e-06
-    CCHL       AR  1  0.0040597618  6.326208e-06
-    CCHL        F  1  0.0017603414  1.7583552e-06
-    CCHL       CL  1  0.004801957  7.884576e-06
-    CCHL       BR  1  0.0017613673  1.6313472e-05
-    CCHL     CMET  1  0.0048322193  9.206064e-06
-    CCHL     OMET  1  0.0024394475   2.268e-06
-    CCHL      NA+  1  0.00043541779  2.9232e-07
-    CCHL      CL-  1  0.00602681  2.084544e-05
-   CLCHL        O  1  0.004334666  3.1947671e-06
-   CLCHL       OM  1  0.004334666  3.1947671e-06
-   CLCHL       OA  1  0.004334666  4.1738625e-06
-   CLCHL       OW  1  0.0046627736  5.7283944e-06
-   CLCHL        N  1  0.0044987198  4.8268401e-06
-   CLCHL       NT  1  0.0044987198  4.8268401e-06
-   CLCHL       NL  1  0.0044987198  4.8268401e-06
-   CLCHL       NR  1  0.0044987198  4.8268401e-06
-   CLCHL       NZ  1  0.0044987198  4.8268401e-06
-   CLCHL       NE  1  0.0044987198  4.8268401e-06
-   CLCHL        C  1  0.0044094016  6.8154537e-06
-   CLCHL      CH1  1  0.0056033487  1.2514167e-05
-   CLCHL      CH2  1  0.0076822749  1.8836178e-05
-   CLCHL      CH3  1  0.0090758208  2.1496319e-05
-   CLCHL      CH4  1  0.010462987  2.1748606e-05
-   CLCHL      CR1  1  0.0067672192  1.4424869e-05
-   CLCHL       HC  1  0.0008384972  4.563423e-07
-   CLCHL        H  1           0           0
-   CLCHL      DUM  1           0           0
-   CLCHL        S  1  0.0091068087  1.3415722e-05
-   CLCHL     CU1+  1  0.0018638335  2.6560606e-07
-   CLCHL     CU2+  1  0.0018638335  2.6560606e-07
-   CLCHL       FE  1           0           0
-   CLCHL     ZN2+  1  0.0018638335  3.6047332e-07
-   CLCHL     MG2+  1  0.00073641928  2.1659564e-07
-   CLCHL     CA2+  1  0.0028891697  2.6182176e-06
-   CLCHL        P  1  0.011064517  1.7478281e-05
-   CLCHL       AR  1  0.0072138101  1.1642294e-05
-   CLCHL        F  1  0.0031279591  3.2359492e-06
-   CLCHL       CL  1  0.0085326204  1.4510201e-05
-   CLCHL       BR  1  0.0031297819  3.0022129e-05
-   CLCHL     CMET  1  0.0085863936  1.6942172e-05
-   CLCHL     OMET  1  0.004334666  4.1738625e-06
-   CLCHL      NA+  1  0.00077369595  5.379645e-07
-   CLCHL      CL-  1  0.010709067  3.8362434e-05
-   CLCHL     CCHL  1  0.0046754       7.4813E-6
-    HCHL        O  1  0.0002920184  5.6465771e-08
-    HCHL       OM  1  0.0002920184  5.6465771e-08
-    HCHL       OA  1  0.0002920184  7.377075e-08
-    HCHL       OW  1  0.0003141224  1.0124626e-07
-    HCHL        N  1  0.0003030704  8.5311774e-08
-    HCHL       NT  1  0.0003030704  8.5311774e-08
-    HCHL       NL  1  0.0003030704  8.5311774e-08
-    HCHL       NR  1  0.0003030704  8.5311774e-08
-    HCHL       NZ  1  0.0003030704  8.5311774e-08
-    HCHL       NE  1  0.0003030704  8.5311774e-08
-    HCHL        C  1  0.0002970532  1.2045944e-07
-    HCHL      CH1  1  0.0003774872  2.211811e-07
-    HCHL      CH2  1  0.0005175406  3.329192e-07
-    HCHL      CH3  1  0.0006114212  3.7993576e-07
-    HCHL      CH4  1  0.000704872  3.8439479e-07
-    HCHL      CR1  1  0.000455895  2.5495171e-07
-    HCHL       HC  1  5.6488e-05  8.065602e-09
-    HCHL        H  1           0           0
-    HCHL      DUM  1           0           0
-    HCHL        S  1  0.0006135088  2.3711558e-07
-    HCHL     CU1+  1  0.000125563  4.6944427e-09
-    HCHL     CU2+  1  0.000125563  4.6944427e-09
-    HCHL       FE  1           0           0
-    HCHL     ZN2+  1  0.000125563  6.3711698e-09
-    HCHL     MG2+  1  4.96112e-05  3.8282101e-09
-    HCHL     CA2+  1  0.000194638  4.6275572e-08
-    HCHL        P  1  0.000745396  3.0891911e-07
-    HCHL       AR  1  0.000485981  2.0577121e-07
-    HCHL        F  1  0.0002107248  5.7193643e-08
-    HCHL       CL  1  0.0005748268  2.5645991e-07
-    HCHL       BR  1  0.0002108476  5.3062481e-07
-    HCHL     CMET  1  0.0005784494  2.9944367e-07
-    HCHL     OMET  1  0.0002920184  7.377075e-08
-    HCHL      NA+  1  5.212246e-05  9.50823e-09
-    HCHL      CL-  1  0.00072145  6.7803516e-07
-    HCHL     CCHL  1  0.0003622       0.1745E-6
-    HCHL    CLCHL  1  0.0006493       0.3266E-6
-   SDMSO        O  1  0.0048877412  3.9925763e-06
-   SDMSO       OM  1  0.0048877412  3.9925763e-06
-   SDMSO       OA  1  0.0048877412  5.216175e-06
-   SDMSO       OW  1  0.0052577132  7.1589104e-06
-   SDMSO        N  1  0.0050727272  6.0322166e-06
-   SDMSO       NT  1  0.0050727272  6.0322166e-06
-   SDMSO       NL  1  0.0050727272  6.0322166e-06
-   SDMSO       NR  1  0.0050727272  6.0322166e-06
-   SDMSO       NZ  1  0.0050727272  6.0322166e-06
-   SDMSO       NE  1  0.0050727272  6.0322166e-06
-   SDMSO        C  1  0.0049720126  8.5174342e-06
-   SDMSO      CH1  1  0.0063182996  1.5639252e-05
-   SDMSO      CH2  1  0.0086624833  2.3540018e-05
-   SDMSO      CH3  1  0.010233837  2.686446e-05
-   SDMSO      CH4  1  0.011797996  2.7179749e-05
-   SDMSO      CR1  1  0.0076306725  1.8027101e-05
-   SDMSO       HC  1  0.000945484  5.703018e-07
-   SDMSO        H  1           0           0
-   SDMSO      DUM  1           0           0
-   SDMSO        S  1  0.010268778  1.6765946e-05
-   SDMSO     CU1+  1  0.0021016465  3.3193419e-07
-   SDMSO     CU2+  1  0.0021016465  3.3193419e-07
-   SDMSO       FE  1           0           0
-   SDMSO     ZN2+  1  0.0021016465  4.5049206e-07
-   SDMSO     MG2+  1  0.0008303816  2.7068471e-07
-   SDMSO     CA2+  1  0.003257809  3.2720486e-06
-   SDMSO        P  1  0.012476278  2.1843023e-05
-   SDMSO       AR  1  0.0081342455  1.4549651e-05
-   SDMSO        F  1  0.0035270664  4.0440425e-06
-   SDMSO       CL  1  0.0096213274  1.8133743e-05
-   SDMSO       BR  1  0.0035291218  3.7519367e-05
-   SDMSO     CMET  1  0.0096819617  2.1173034e-05
-   SDMSO     OMET  1  0.0048877412  5.216175e-06
-   SDMSO      NA+  1  0.00087241453  6.72307e-07
-   SDMSO      CL-  1  0.012075475  4.7942444e-05
-   SDMSO     CCHL  1  0.0052712788  9.3473856e-06
-   SDMSO    CLCHL  1  0.0093665606  1.720225e-05
-   SDMSO     HCHL  1  0.0006310078  3.0404041e-07
-   CDMSO        O  1  0.0045248108  4.016601e-06
-   CDMSO       OM  1  0.0045248108  4.016601e-06
-   CDMSO       OA  1  0.0045248108  5.2475625e-06
-   CDMSO       OW  1  0.0048673112  7.201988e-06
-   CDMSO        N  1  0.004696061  6.0685145e-06
-   CDMSO       NT  1  0.004696061  6.0685145e-06
-   CDMSO       NL  1  0.004696061  6.0685145e-06
-   CDMSO       NR  1  0.004696061  6.0685145e-06
-   CDMSO       NZ  1  0.004696061  6.0685145e-06
-   CDMSO       NE  1  0.004696061  6.0685145e-06
-   CDMSO        C  1  0.0046028248  8.5686865e-06
-   CDMSO      CH1  1  0.0058491457  1.5733359e-05
-   CDMSO      CH2  1  0.0080192663  2.3681667e-05
-   CDMSO      CH3  1  0.0094739416  2.7026113e-05
-   CDMSO      CH4  1  0.010921957  2.7343299e-05
-   CDMSO      CR1  1  0.0070640708  1.8135576e-05
-   CDMSO       HC  1  0.0008752788  5.737335e-07
-   CDMSO        H  1           0           0
-   CDMSO      DUM  1           0           0
-   CDMSO        S  1  0.0095062889  1.6866832e-05
-   CDMSO     CU1+  1  0.0019455925  3.3393156e-07
-   CDMSO     CU2+  1  0.0019455925  3.3393156e-07
-   CDMSO       FE  1           0           0
-   CDMSO     ZN2+  1  0.0019455925  4.5320282e-07
-   CDMSO     MG2+  1  0.00076872312  2.7231351e-07
-   CDMSO     CA2+  1  0.0030159063  3.2917377e-06
-   CDMSO        P  1  0.011549875  2.197446e-05
-   CDMSO       AR  1  0.0075302519  1.4637201e-05
-   CDMSO        F  1  0.0032651705  4.0683769e-06
-   CDMSO       CL  1  0.0089069132  1.824286e-05
-   CDMSO       BR  1  0.0032670733  3.7745134e-05
-   CDMSO     CMET  1  0.0089630452  2.1300439e-05
-   CDMSO     OMET  1  0.0045248108  5.2475625e-06
-   CDMSO      NA+  1  0.00080763497  6.763525e-07
-   CDMSO      CL-  1  0.011178832  4.823093e-05
-   CDMSO     CCHL  1  0.0048798696  9.403632e-06
-   CDMSO    CLCHL  1  0.0086710636  1.7305761e-05
-   CDMSO     HCHL  1  0.00058415346  3.0586992e-07
-   CDMSO    SDMSO  1  0.0097827      21.6523E-6
-   ODMSO        O  1  0.0022663291  7.4645315e-07
-   ODMSO       OM  1  0.0022663291  7.4645315e-07
-   ODMSO       OA  1  0.0022663291  1.380375e-06
-   ODMSO       OW  1  0.0024378763  1.825875e-06
-   ODMSO        N  1  0.0023521027  2.185875e-06
-   ODMSO       NT  1  0.0023521027  2.53125e-06
-   ODMSO       NL  1  0.0023521027  3.4515e-06
-   ODMSO       NR  1  0.0023521027  2.071125e-06
-   ODMSO       NZ  1  0.0023521027  2.4165e-06
-   ODMSO       NE  1  0.0023521027   2.232e-06
-   ODMSO        C  1  0.0023054038  1.5924218e-06
-   ODMSO      CH1  1  0.002929645  2.9239188e-06
-   ODMSO      CH2  1  0.0040165871  4.4010482e-06
-   ODMSO      CH3  1  0.0047451862  5.0225868e-06
-   ODMSO      CH4  1  0.0054704496  5.0815333e-06
-   ODMSO      CR1  1  0.003538161  3.3703517e-06
-   ODMSO       HC  1  0.0004383984  1.0662378e-07
-   ODMSO        H  1           0           0
-   ODMSO      DUM  1           0           0
-   ODMSO        S  1  0.0047613878  3.1345658e-06
-   ODMSO     CU1+  1  0.0009744834  2.53125e-07
-   ODMSO     CU2+  1  0.0009744834  4.602375e-07
-   ODMSO       FE  1           0           0
-   ODMSO     ZN2+  1  0.0009744834  1.09305e-07
-   ODMSO     MG2+  1  0.00038502816  6.56775e-08
-   ODMSO     CA2+  1  0.0015105684  7.939125e-07
-   ODMSO        P  1  0.0057849528  5.299875e-06
-   ODMSO       AR  1  0.0037716558  2.7202067e-06
-   ODMSO        F  1  0.0016354166  7.5607529e-07
-   ODMSO       CL  1  0.0044611802  3.3902895e-06
-   ODMSO       BR  1  0.0016363697  7.0146311e-06
-   ODMSO     CMET  1  0.0044892949  3.9585162e-06
-   ODMSO     OMET  1  0.0022663291  1.380375e-06
-   ODMSO      NA+  1  0.00040451783  1.63125e-07
-   ODMSO      CL-  1  0.00559911  8.9633324e-06
-   ODMSO     CCHL  1  0.0024441664  1.7475898e-06
-   ODMSO    CLCHL  1  0.0043430509  3.2161373e-06
-   ODMSO     HCHL  1  0.00029258328  5.6843478e-08
-   ODMSO    SDMSO  1  0.0052442       4.6094E-6
-   ODMSO    CDMSO  1  0.0049187       4.7597E-6
-    CCL4        O  1  0.0024394475  2.3738805e-06
-    CCL4       OM  1  0.0024394475  2.3738805e-06
-    CCL4       OA  1  0.0024394475  3.1014e-06
-    CCL4       OW  1  0.0026240987  4.2564992e-06
-    CCL4        N  1  0.0025317731  3.5865968e-06
-    CCL4       NT  1  0.0025317731  3.5865968e-06
-    CCL4       NL  1  0.0025317731  3.5865968e-06
-    CCL4       NR  1  0.0025317731  3.5865968e-06
-    CCL4       NZ  1  0.0025317731  3.5865968e-06
-    CCL4       NE  1  0.0025317731  3.5865968e-06
-    CCL4        C  1  0.002481507  5.0642416e-06
-    CCL4      CH1  1  0.0031534322  9.2986864e-06
-    CCL4      CH2  1  0.0043234027  1.3996274e-05
-    CCL4      CH3  1  0.0051076574  1.5972899e-05
-    CCL4      CH4  1  0.0058883216  1.6160362e-05
-    CCL4      CR1  1  0.003808431  1.0718438e-05
-    CCL4       HC  1  0.0004718864  3.390864e-07
-    CCL4        H  1           0           0
-    CCL4      DUM  1           0           0
-    CCL4        S  1  0.0051250966  9.9685888e-06
-    CCL4     CU1+  1  0.0010489214  1.9735931e-07
-    CCL4     CU2+  1  0.0010489214  1.9735931e-07
-    CCL4       FE  1           0           0
-    CCL4     ZN2+  1  0.0010489214  2.6785069e-07
-    CCL4     MG2+  1  0.00041443936  1.6094198e-07
-    CCL4     CA2+  1  0.0016259564  1.9454738e-06
-    CCL4        P  1  0.0062268488  1.2987285e-05
-    CCL4       AR  1  0.0040597618  8.6508384e-06
-    CCL4        F  1  0.0017603414  2.404481e-06
-    CCL4       CL  1  0.004801957  1.0781845e-05
-    CCL4       BR  1  0.0017613673  2.2308026e-05
-    CCL4     CMET  1  0.0048322193  1.2588927e-05
-    CCL4     OMET  1  0.0024394475  3.1014e-06
-    CCL4      NA+  1  0.00043541779  3.99736e-07
-    CCL4      CL-  1  0.00602681  2.8505312e-05
-    CCL4     CCHL  1  0.0026308693  5.5577088e-06
-    CCL4    CLCHL  1  0.0046748042  1.0228004e-05
-    CCL4     HCHL  1  0.00031493288  1.807744e-07
-    CCL4    SDMSO  1  0.0052712788  1.2782179e-05
-    CCL4    CDMSO  1  0.0048798696  1.2859094e-05
-    CCL4    ODMSO  1  0.0024441664  2.3897596e-06
-   CLCL4        O  1  0.0041472796  3.0768825e-06
-   CLCL4       OM  1  0.0041472796  3.0768825e-06
-   CLCL4       OA  1  0.0041472796  4.01985e-06
-   CLCL4       OW  1  0.0044612032  5.5170208e-06
-   CLCL4        N  1  0.0043042414  4.6487332e-06
-   CLCL4       NT  1  0.0043042414  4.6487332e-06
-   CLCL4       NL  1  0.0043042414  4.6487332e-06
-   CLCL4       NR  1  0.0043042414  4.6487332e-06
-   CLCL4       NZ  1  0.0043042414  4.6487332e-06
-   CLCL4       NE  1  0.0043042414  4.6487332e-06
-   CLCL4        C  1  0.0042187844  6.5639684e-06
-   CLCL4      CH1  1  0.0053611175  1.2052404e-05
-   CLCL4      CH2  1  0.0073501723  1.8141136e-05
-   CLCL4      CH3  1  0.0086834756  2.0703121e-05
-   CLCL4      CH4  1  0.010010675  2.0946098e-05
-   CLCL4      CR1  1  0.0064746742  1.3892602e-05
-   CLCL4       HC  1  0.0008022492  4.395036e-07
-   CLCL4        H  1           0           0
-   CLCL4      DUM  1           0           0
-   CLCL4        S  1  0.0087131239  1.2920691e-05
-   CLCL4     CU1+  1  0.0017832604  2.5580539e-07
-   CLCL4     CU2+  1  0.0017832604  2.5580539e-07
-   CLCL4       FE  1           0           0
-   CLCL4     ZN2+  1  0.0017832604  3.4717211e-07
-   CLCL4     MG2+  1  0.00070458408  2.0860342e-07
-   CLCL4     CA2+  1  0.0027642717  2.5216072e-06
-   CLCL4        P  1  0.010586201  1.6833345e-05
-   CLCL4       AR  1  0.0069019592  1.1212702e-05
-   CLCL4        F  1  0.0029927383  3.116545e-06
-   CLCL4       CL  1  0.0081637576  1.3974785e-05
-   CLCL4       BR  1  0.0029944823  2.8914334e-05
-   CLCL4     CMET  1  0.0082152062  1.6317018e-05
-   CLCL4     OMET  1  0.0041472796  4.01985e-06
-   CLCL4      NA+  1  0.00074024929  5.18114e-07
-   CLCL4      CL-  1  0.010246117  3.6946888e-05
-   CLCL4     CCHL  1  0.0044727137  7.2035712e-06
-   CLCL4    CLCHL  1  0.0079475863  1.3256929e-05
-   CLCL4     HCHL  1  0.00053541414  2.3430902e-07
-   CLCL4    SDMSO  1  0.0089616468  1.6567499e-05
-   CLCL4    CDMSO  1  0.0082962159  1.6667191e-05
-   CLCL4    ODMSO  1  0.0041553021  3.0974642e-06
-   CLCL4     CCL4  1  0.0044727137  9.8505978e-06
+    CChl        O  1  0.0024394475  1.7359776e-06
+    CChl       OM  1  0.0024394475  1.7359776e-06
+    CChl       OA  1  0.0024394475   2.268e-06
+    CChl       OW  1  0.0026240987  3.112704e-06
+    CChl        N  1  0.0025317731  2.622816e-06
+    CChl       NT  1  0.0025317731  2.622816e-06
+    CChl       NL  1  0.0025317731  2.622816e-06
+    CChl       NR  1  0.0025317731  2.622816e-06
+    CChl       NZ  1  0.0025317731  2.622816e-06
+    CChl       NE  1  0.0025317731  2.622816e-06
+    CChl        C  1  0.002481507  3.703392e-06
+    CChl      CH1  1  0.0031534322  6.799968e-06
+    CChl      CH2  1  0.0043234027  1.0235232e-05
+    CChl      CH3  1  0.0051076574  1.1680704e-05
+    CChl      CH4  1  0.0058883216  1.1817792e-05
+    CChl      CR1  1  0.003808431  7.838208e-06
+    CChl       HC  1  0.0004718864  2.47968e-07
+    CChl        H  1           0           0
+    CChl      DUM  1           0           0
+    CChl        S  1  0.0051250966  7.289856e-06
+    CChl     CU1+  1  0.0010489214  1.4432544e-07
+    CChl     CU2+  1  0.0010489214  1.4432544e-07
+    CChl       FE  1           0           0
+    CChl     ZN2+  1  0.0010489214  1.9587456e-07
+    CChl     MG2+  1  0.00041443936  1.1769408e-07
+    CChl     CA2+  1  0.0016259564  1.4226912e-06
+    CChl        P  1  0.0062268488  9.497376e-06
+    CChl       AR  1  0.0040597618  6.326208e-06
+    CChl        F  1  0.0017603414  1.7583552e-06
+    CChl       CL  1  0.004801957  7.884576e-06
+    CChl       BR  1  0.0017613673  1.6313472e-05
+    CChl     CMet  1  0.0048322193  9.206064e-06
+    CChl     OMet  1  0.0024394475   2.268e-06
+    CChl      NA+  1  0.00043541779  2.9232e-07
+    CChl      CL-  1  0.00602681  2.084544e-05
+   CLChl        O  1  0.004334666  3.1947671e-06
+   CLChl       OM  1  0.004334666  3.1947671e-06
+   CLChl       OA  1  0.004334666  4.1738625e-06
+   CLChl       OW  1  0.0046627736  5.7283944e-06
+   CLChl        N  1  0.0044987198  4.8268401e-06
+   CLChl       NT  1  0.0044987198  4.8268401e-06
+   CLChl       NL  1  0.0044987198  4.8268401e-06
+   CLChl       NR  1  0.0044987198  4.8268401e-06
+   CLChl       NZ  1  0.0044987198  4.8268401e-06
+   CLChl       NE  1  0.0044987198  4.8268401e-06
+   CLChl        C  1  0.0044094016  6.8154537e-06
+   CLChl      CH1  1  0.0056033487  1.2514167e-05
+   CLChl      CH2  1  0.0076822749  1.8836178e-05
+   CLChl      CH3  1  0.0090758208  2.1496319e-05
+   CLChl      CH4  1  0.010462987  2.1748606e-05
+   CLChl      CR1  1  0.0067672192  1.4424869e-05
+   CLChl       HC  1  0.0008384972  4.563423e-07
+   CLChl        H  1           0           0
+   CLChl      DUM  1           0           0
+   CLChl        S  1  0.0091068087  1.3415722e-05
+   CLChl     CU1+  1  0.0018638335  2.6560606e-07
+   CLChl     CU2+  1  0.0018638335  2.6560606e-07
+   CLChl       FE  1           0           0
+   CLChl     ZN2+  1  0.0018638335  3.6047332e-07
+   CLChl     MG2+  1  0.00073641928  2.1659564e-07
+   CLChl     CA2+  1  0.0028891697  2.6182176e-06
+   CLChl        P  1  0.011064517  1.7478281e-05
+   CLChl       AR  1  0.0072138101  1.1642294e-05
+   CLChl        F  1  0.0031279591  3.2359492e-06
+   CLChl       CL  1  0.0085326204  1.4510201e-05
+   CLChl       BR  1  0.0031297819  3.0022129e-05
+   CLChl     CMet  1  0.0085863936  1.6942172e-05
+   CLChl     OMet  1  0.004334666  4.1738625e-06
+   CLChl      NA+  1  0.00077369595  5.379645e-07
+   CLChl      CL-  1  0.010709067  3.8362434e-05
+   CLChl     CChl  1  0.0046754       7.4813E-6
+    HChl        O  1  0.0002920184  5.6465771e-08
+    HChl       OM  1  0.0002920184  5.6465771e-08
+    HChl       OA  1  0.0002920184  7.377075e-08
+    HChl       OW  1  0.0003141224  1.0124626e-07
+    HChl        N  1  0.0003030704  8.5311774e-08
+    HChl       NT  1  0.0003030704  8.5311774e-08
+    HChl       NL  1  0.0003030704  8.5311774e-08
+    HChl       NR  1  0.0003030704  8.5311774e-08
+    HChl       NZ  1  0.0003030704  8.5311774e-08
+    HChl       NE  1  0.0003030704  8.5311774e-08
+    HChl        C  1  0.0002970532  1.2045944e-07
+    HChl      CH1  1  0.0003774872  2.211811e-07
+    HChl      CH2  1  0.0005175406  3.329192e-07
+    HChl      CH3  1  0.0006114212  3.7993576e-07
+    HChl      CH4  1  0.000704872  3.8439479e-07
+    HChl      CR1  1  0.000455895  2.5495171e-07
+    HChl       HC  1  5.6488e-05  8.065602e-09
+    HChl        H  1           0           0
+    HChl      DUM  1           0           0
+    HChl        S  1  0.0006135088  2.3711558e-07
+    HChl     CU1+  1  0.000125563  4.6944427e-09
+    HChl     CU2+  1  0.000125563  4.6944427e-09
+    HChl       FE  1           0           0
+    HChl     ZN2+  1  0.000125563  6.3711698e-09
+    HChl     MG2+  1  4.96112e-05  3.8282101e-09
+    HChl     CA2+  1  0.000194638  4.6275572e-08
+    HChl        P  1  0.000745396  3.0891911e-07
+    HChl       AR  1  0.000485981  2.0577121e-07
+    HChl        F  1  0.0002107248  5.7193643e-08
+    HChl       CL  1  0.0005748268  2.5645991e-07
+    HChl       BR  1  0.0002108476  5.3062481e-07
+    HChl     CMet  1  0.0005784494  2.9944367e-07
+    HChl     OMet  1  0.0002920184  7.377075e-08
+    HChl      NA+  1  5.212246e-05  9.50823e-09
+    HChl      CL-  1  0.00072145  6.7803516e-07
+    HChl     CChl  1  0.0003622       0.1745E-6
+    HChl    CLChl  1  0.0006493       0.3266E-6
+   SDmso        O  1  0.0048877412  3.9925763e-06
+   SDmso       OM  1  0.0048877412  3.9925763e-06
+   SDmso       OA  1  0.0048877412  5.216175e-06
+   SDmso       OW  1  0.0052577132  7.1589104e-06
+   SDmso        N  1  0.0050727272  6.0322166e-06
+   SDmso       NT  1  0.0050727272  6.0322166e-06
+   SDmso       NL  1  0.0050727272  6.0322166e-06
+   SDmso       NR  1  0.0050727272  6.0322166e-06
+   SDmso       NZ  1  0.0050727272  6.0322166e-06
+   SDmso       NE  1  0.0050727272  6.0322166e-06
+   SDmso        C  1  0.0049720126  8.5174342e-06
+   SDmso      CH1  1  0.0063182996  1.5639252e-05
+   SDmso      CH2  1  0.0086624833  2.3540018e-05
+   SDmso      CH3  1  0.010233837  2.686446e-05
+   SDmso      CH4  1  0.011797996  2.7179749e-05
+   SDmso      CR1  1  0.0076306725  1.8027101e-05
+   SDmso       HC  1  0.000945484  5.703018e-07
+   SDmso        H  1           0           0
+   SDmso      DUM  1           0           0
+   SDmso        S  1  0.010268778  1.6765946e-05
+   SDmso     CU1+  1  0.0021016465  3.3193419e-07
+   SDmso     CU2+  1  0.0021016465  3.3193419e-07
+   SDmso       FE  1           0           0
+   SDmso     ZN2+  1  0.0021016465  4.5049206e-07
+   SDmso     MG2+  1  0.0008303816  2.7068471e-07
+   SDmso     CA2+  1  0.003257809  3.2720486e-06
+   SDmso        P  1  0.012476278  2.1843023e-05
+   SDmso       AR  1  0.0081342455  1.4549651e-05
+   SDmso        F  1  0.0035270664  4.0440425e-06
+   SDmso       CL  1  0.0096213274  1.8133743e-05
+   SDmso       BR  1  0.0035291218  3.7519367e-05
+   SDmso     CMet  1  0.0096819617  2.1173034e-05
+   SDmso     OMet  1  0.0048877412  5.216175e-06
+   SDmso      NA+  1  0.00087241453  6.72307e-07
+   SDmso      CL-  1  0.012075475  4.7942444e-05
+   SDmso     CChl  1  0.0052712788  9.3473856e-06
+   SDmso    CLChl  1  0.0093665606  1.720225e-05
+   SDmso     HChl  1  0.0006310078  3.0404041e-07
+   CDmso        O  1  0.0045248108  4.016601e-06
+   CDmso       OM  1  0.0045248108  4.016601e-06
+   CDmso       OA  1  0.0045248108  5.2475625e-06
+   CDmso       OW  1  0.0048673112  7.201988e-06
+   CDmso        N  1  0.004696061  6.0685145e-06
+   CDmso       NT  1  0.004696061  6.0685145e-06
+   CDmso       NL  1  0.004696061  6.0685145e-06
+   CDmso       NR  1  0.004696061  6.0685145e-06
+   CDmso       NZ  1  0.004696061  6.0685145e-06
+   CDmso       NE  1  0.004696061  6.0685145e-06
+   CDmso        C  1  0.0046028248  8.5686865e-06
+   CDmso      CH1  1  0.0058491457  1.5733359e-05
+   CDmso      CH2  1  0.0080192663  2.3681667e-05
+   CDmso      CH3  1  0.0094739416  2.7026113e-05
+   CDmso      CH4  1  0.010921957  2.7343299e-05
+   CDmso      CR1  1  0.0070640708  1.8135576e-05
+   CDmso       HC  1  0.0008752788  5.737335e-07
+   CDmso        H  1           0           0
+   CDmso      DUM  1           0           0
+   CDmso        S  1  0.0095062889  1.6866832e-05
+   CDmso     CU1+  1  0.0019455925  3.3393156e-07
+   CDmso     CU2+  1  0.0019455925  3.3393156e-07
+   CDmso       FE  1           0           0
+   CDmso     ZN2+  1  0.0019455925  4.5320282e-07
+   CDmso     MG2+  1  0.00076872312  2.7231351e-07
+   CDmso     CA2+  1  0.0030159063  3.2917377e-06
+   CDmso        P  1  0.011549875  2.197446e-05
+   CDmso       AR  1  0.0075302519  1.4637201e-05
+   CDmso        F  1  0.0032651705  4.0683769e-06
+   CDmso       CL  1  0.0089069132  1.824286e-05
+   CDmso       BR  1  0.0032670733  3.7745134e-05
+   CDmso     CMet  1  0.0089630452  2.1300439e-05
+   CDmso     OMet  1  0.0045248108  5.2475625e-06
+   CDmso      NA+  1  0.00080763497  6.763525e-07
+   CDmso      CL-  1  0.011178832  4.823093e-05
+   CDmso     CChl  1  0.0048798696  9.403632e-06
+   CDmso    CLChl  1  0.0086710636  1.7305761e-05
+   CDmso     HChl  1  0.00058415346  3.0586992e-07
+   CDmso    SDmso  1  0.0097827      21.6523E-6
+   ODmso        O  1  0.0022663291  7.4645315e-07
+   ODmso       OM  1  0.0022663291  7.4645315e-07
+   ODmso       OA  1  0.0022663291  1.380375e-06
+   ODmso       OW  1  0.0024378763  1.825875e-06
+   ODmso        N  1  0.0023521027  2.185875e-06
+   ODmso       NT  1  0.0023521027  2.53125e-06
+   ODmso       NL  1  0.0023521027  3.4515e-06
+   ODmso       NR  1  0.0023521027  2.071125e-06
+   ODmso       NZ  1  0.0023521027  2.4165e-06
+   ODmso       NE  1  0.0023521027   2.232e-06
+   ODmso        C  1  0.0023054038  1.5924218e-06
+   ODmso      CH1  1  0.002929645  2.9239188e-06
+   ODmso      CH2  1  0.0040165871  4.4010482e-06
+   ODmso      CH3  1  0.0047451862  5.0225868e-06
+   ODmso      CH4  1  0.0054704496  5.0815333e-06
+   ODmso      CR1  1  0.003538161  3.3703517e-06
+   ODmso       HC  1  0.0004383984  1.0662378e-07
+   ODmso        H  1           0           0
+   ODmso      DUM  1           0           0
+   ODmso        S  1  0.0047613878  3.1345658e-06
+   ODmso     CU1+  1  0.0009744834  2.53125e-07
+   ODmso     CU2+  1  0.0009744834  4.602375e-07
+   ODmso       FE  1           0           0
+   ODmso     ZN2+  1  0.0009744834  1.09305e-07
+   ODmso     MG2+  1  0.00038502816  6.56775e-08
+   ODmso     CA2+  1  0.0015105684  7.939125e-07
+   ODmso        P  1  0.0057849528  5.299875e-06
+   ODmso       AR  1  0.0037716558  2.7202067e-06
+   ODmso        F  1  0.0016354166  7.5607529e-07
+   ODmso       CL  1  0.0044611802  3.3902895e-06
+   ODmso       BR  1  0.0016363697  7.0146311e-06
+   ODmso     CMet  1  0.0044892949  3.9585162e-06
+   ODmso     OMet  1  0.0022663291  1.380375e-06
+   ODmso      NA+  1  0.00040451783  1.63125e-07
+   ODmso      CL-  1  0.00559911  8.9633324e-06
+   ODmso     CChl  1  0.0024441664  1.7475898e-06
+   ODmso    CLChl  1  0.0043430509  3.2161373e-06
+   ODmso     HChl  1  0.00029258328  5.6843478e-08
+   ODmso    SDmso  1  0.0052442       4.6094E-6
+   ODmso    CDmso  1  0.0049187       4.7597E-6
+    CCl4        O  1  0.0024394475  2.3738805e-06
+    CCl4       OM  1  0.0024394475  2.3738805e-06
+    CCl4       OA  1  0.0024394475  3.1014e-06
+    CCl4       OW  1  0.0026240987  4.2564992e-06
+    CCl4        N  1  0.0025317731  3.5865968e-06
+    CCl4       NT  1  0.0025317731  3.5865968e-06
+    CCl4       NL  1  0.0025317731  3.5865968e-06
+    CCl4       NR  1  0.0025317731  3.5865968e-06
+    CCl4       NZ  1  0.0025317731  3.5865968e-06
+    CCl4       NE  1  0.0025317731  3.5865968e-06
+    CCl4        C  1  0.002481507  5.0642416e-06
+    CCl4      CH1  1  0.0031534322  9.2986864e-06
+    CCl4      CH2  1  0.0043234027  1.3996274e-05
+    CCl4      CH3  1  0.0051076574  1.5972899e-05
+    CCl4      CH4  1  0.0058883216  1.6160362e-05
+    CCl4      CR1  1  0.003808431  1.0718438e-05
+    CCl4       HC  1  0.0004718864  3.390864e-07
+    CCl4        H  1           0           0
+    CCl4      DUM  1           0           0
+    CCl4        S  1  0.0051250966  9.9685888e-06
+    CCl4     CU1+  1  0.0010489214  1.9735931e-07
+    CCl4     CU2+  1  0.0010489214  1.9735931e-07
+    CCl4       FE  1           0           0
+    CCl4     ZN2+  1  0.0010489214  2.6785069e-07
+    CCl4     MG2+  1  0.00041443936  1.6094198e-07
+    CCl4     CA2+  1  0.0016259564  1.9454738e-06
+    CCl4        P  1  0.0062268488  1.2987285e-05
+    CCl4       AR  1  0.0040597618  8.6508384e-06
+    CCl4        F  1  0.0017603414  2.404481e-06
+    CCl4       CL  1  0.004801957  1.0781845e-05
+    CCl4       BR  1  0.0017613673  2.2308026e-05
+    CCl4     CMet  1  0.0048322193  1.2588927e-05
+    CCl4     OMet  1  0.0024394475  3.1014e-06
+    CCl4      NA+  1  0.00043541779  3.99736e-07
+    CCl4      CL-  1  0.00602681  2.8505312e-05
+    CCl4     CChl  1  0.0026308693  5.5577088e-06
+    CCl4    CLChl  1  0.0046748042  1.0228004e-05
+    CCl4     HChl  1  0.00031493288  1.807744e-07
+    CCl4    SDmso  1  0.0052712788  1.2782179e-05
+    CCl4    CDmso  1  0.0048798696  1.2859094e-05
+    CCl4    ODmso  1  0.0024441664  2.3897596e-06
+   CLCl4        O  1  0.0041472796  3.0768825e-06
+   CLCl4       OM  1  0.0041472796  3.0768825e-06
+   CLCl4       OA  1  0.0041472796  4.01985e-06
+   CLCl4       OW  1  0.0044612032  5.5170208e-06
+   CLCl4        N  1  0.0043042414  4.6487332e-06
+   CLCl4       NT  1  0.0043042414  4.6487332e-06
+   CLCl4       NL  1  0.0043042414  4.6487332e-06
+   CLCl4       NR  1  0.0043042414  4.6487332e-06
+   CLCl4       NZ  1  0.0043042414  4.6487332e-06
+   CLCl4       NE  1  0.0043042414  4.6487332e-06
+   CLCl4        C  1  0.0042187844  6.5639684e-06
+   CLCl4      CH1  1  0.0053611175  1.2052404e-05
+   CLCl4      CH2  1  0.0073501723  1.8141136e-05
+   CLCl4      CH3  1  0.0086834756  2.0703121e-05
+   CLCl4      CH4  1  0.010010675  2.0946098e-05
+   CLCl4      CR1  1  0.0064746742  1.3892602e-05
+   CLCl4       HC  1  0.0008022492  4.395036e-07
+   CLCl4        H  1           0           0
+   CLCl4      DUM  1           0           0
+   CLCl4        S  1  0.0087131239  1.2920691e-05
+   CLCl4     CU1+  1  0.0017832604  2.5580539e-07
+   CLCl4     CU2+  1  0.0017832604  2.5580539e-07
+   CLCl4       FE  1           0           0
+   CLCl4     ZN2+  1  0.0017832604  3.4717211e-07
+   CLCl4     MG2+  1  0.00070458408  2.0860342e-07
+   CLCl4     CA2+  1  0.0027642717  2.5216072e-06
+   CLCl4        P  1  0.010586201  1.6833345e-05
+   CLCl4       AR  1  0.0069019592  1.1212702e-05
+   CLCl4        F  1  0.0029927383  3.116545e-06
+   CLCl4       CL  1  0.0081637576  1.3974785e-05
+   CLCl4       BR  1  0.0029944823  2.8914334e-05
+   CLCl4     CMet  1  0.0082152062  1.6317018e-05
+   CLCl4     OMet  1  0.0041472796  4.01985e-06
+   CLCl4      NA+  1  0.00074024929  5.18114e-07
+   CLCl4      CL-  1  0.010246117  3.6946888e-05
+   CLCl4     CChl  1  0.0044727137  7.2035712e-06
+   CLCl4    CLChl  1  0.0079475863  1.3256929e-05
+   CLCl4     HChl  1  0.00053541414  2.3430902e-07
+   CLCl4    SDmso  1  0.0089616468  1.6567499e-05
+   CLCl4    CDmso  1  0.0082962159  1.6667191e-05
+   CLCl4    ODmso  1  0.0041553021  3.0974642e-06
+   CLCl4     CCl4  1  0.0044727137  9.8505978e-06
       SI        O  1  0.005773784  5.299875e-06
       SI       OM  1  0.005773784  1.4453348e-05
       SI       OA  1  0.005773784  5.780397e-06
@@ -986,18 +986,18 @@ CLCL4   17        0.000      0.000     A  0.0076040144  1.2767758e-05
       SI        F  1  0.004166448  5.780397e-06
       SI       CL  1  0.011365468  1.8424721e-05
       SI       BR  1  0.004168876  3.8121412e-05
-      SI     CMET  1  0.011437094  2.1512782e-05
-      SI     OMET  1  0.005773784  5.780397e-06
+      SI     CMet  1  0.011437094  2.1512782e-05
+      SI     OMet  1  0.005773784  5.780397e-06
       SI      NA+  1  0.0010305646  6.83095e-07
       SI      CL-  1   0.0142645  4.871174e-05
-      SI     CCHL  1  0.0062268488  9.497376e-06
-      SI    CLCHL  1  0.011064517  1.7478281e-05
-      SI     HCHL  1  0.000745396  3.0891911e-07
-      SI    SDMSO  1  0.012476278  2.1843023e-05
-      SI    CDMSO  1  0.011549875  2.197446e-05
-      SI    ODMSO  1  0.0057849528  5.299875e-06
-      SI     CCL4  1  0.0062268488  1.2987285e-05
-      SI    CLCL4  1  0.010586201  1.6833345e-05
+      SI     CChl  1  0.0062268488  9.497376e-06
+      SI    CLChl  1  0.011064517  1.7478281e-05
+      SI     HChl  1  0.000745396  3.0891911e-07
+      SI    SDmso  1  0.012476278  2.1843023e-05
+      SI    CDmso  1  0.011549875  2.197446e-05
+      SI    ODmso  1  0.0057849528  5.299875e-06
+      SI     CCl4  1  0.0062268488  1.2987285e-05
+      SI    CLCl4  1  0.010586201  1.6833345e-05
 
 [ pairtypes ]
 ; i    j func          c6           c12
@@ -1497,71 +1497,71 @@ CLCL4   17      0.000      0.000     A  0.0076040144  1.2767758e-05
       BR        F  1  0.0011785488  7.0578424e-06
       BR       CL  1  0.0032149108  3.1647812e-05
       BR       BR  1  0.0011792356  6.5480464e-05
-    CMET        O  1  0.0044806276  3.9322131e-06
-    CMET       OM  1  0.0044806276  3.9322131e-06
-    CMET       OA  1  0.0044806276  5.1373125e-06
-    CMET       OW  1  0.0048197836  7.050676e-06
-    CMET        N  1  0.0046502056  5.9410165e-06
-    CMET       NT  1  0.0046502056  5.9410165e-06
-    CMET       NL  1  0.0046502056  5.9410165e-06
-    CMET       NR  1  0.0046502056  5.9410165e-06
-    CMET       NZ  1  0.0046502056  5.9410165e-06
-    CMET       NE  1  0.0046502056  5.9410165e-06
-    CMET        C  1  0.0045578798  8.3886605e-06
-    CMET      CH1  1  0.0050835716  8.8270445e-06
-    CMET      CH2  1  0.0064750533  1.2178856e-05
-    CMET      CH3  1  0.0077987038  1.5859455e-05
-    CMET      CH4  1  0.010815308  2.6768823e-05
-    CMET      CR1  1  0.0070045135  1.3178919e-05
-    CMET       HC  1  0.000866732  5.616795e-07
-    CMET        H  1           0           0
-    CMET      DUM  1           0           0
-    CMET        S  1  0.0094134632  1.6512464e-05
-    CMET     CU1+  1  0.0019265945  3.2691574e-07
-    CMET     CU2+  1  0.0019265945  3.2691574e-07
-    CMET       FE  1           0           0
-    CMET     ZN2+  1  0.0019265945  4.4368114e-07
-    CMET     MG2+  1  0.0007612168  2.6659227e-07
-    CMET     CA2+  1  0.002986457  3.222579e-06
-    CMET        P  1  0.011437094  2.1512782e-05
-    CMET       AR  1  0.0074567215  1.4329677e-05
-    CMET        F  1  0.0032332872  3.9829013e-06
-    CMET       CL  1  0.0088199402  1.7859582e-05
-    CMET       BR  1  0.0032351714  3.6952118e-05
-    CMET     CMET  1  0.0088755241  2.0852922e-05
-    OMET        O  1  0.0022619536  9.687375e-07
-    OMET       OM  1  0.0022619536  9.687375e-07
-    OMET       OA  1  0.0022619536  1.265625e-06
-    OMET       OW  1  0.0024331696   1.737e-06
-    OMET        N  1  0.0023475616  1.463625e-06
-    OMET       NT  1  0.0023475616  1.463625e-06
-    OMET       NL  1  0.0023475616  1.463625e-06
-    OMET       NR  1  0.0023475616  1.463625e-06
-    OMET       NZ  1  0.0023475616  1.463625e-06
-    OMET       NE  1  0.0023475616  1.463625e-06
-    OMET        C  1  0.0023009528  2.066625e-06
-    OMET      CH1  1  0.0025663376  2.174625e-06
-    OMET      CH2  1  0.0032687988  3.000375e-06
-    OMET      CH3  1  0.0039370168  3.907125e-06
-    OMET      CH4  1  0.005459888  6.59475e-06
-    OMET      CR1  1  0.003536086  3.24675e-06
-    OMET       HC  1  0.000437552  1.38375e-07
-    OMET        H  1           0           0
-    OMET      DUM  1           0           0
-    OMET        S  1  0.0047521952   4.068e-06
-    OMET     CU1+  1  0.000972602  8.053875e-08
-    OMET     CU2+  1  0.000972602  8.053875e-08
-    OMET       FE  1           0           0
-    OMET     ZN2+  1  0.000972602  1.09305e-07
-    OMET     MG2+  1  0.0003842848  6.56775e-08
-    OMET     CA2+  1  0.001507652  7.939125e-07
-    OMET        P  1  0.005773784  5.299875e-06
-    OMET       AR  1  0.003764374  3.53025e-06
-    OMET        F  1  0.0016322592  9.81225e-07
-    OMET       CL  1  0.0044525672  4.399875e-06
-    OMET       BR  1  0.0016332104  9.1035e-06
-    OMET     CMET  1  0.0044806276  5.1373125e-06
-    OMET     OMET  1  0.0022619536  1.265625e-06
+    CMet        O  1  0.0044806276  3.9322131e-06
+    CMet       OM  1  0.0044806276  3.9322131e-06
+    CMet       OA  1  0.0044806276  5.1373125e-06
+    CMet       OW  1  0.0048197836  7.050676e-06
+    CMet        N  1  0.0046502056  5.9410165e-06
+    CMet       NT  1  0.0046502056  5.9410165e-06
+    CMet       NL  1  0.0046502056  5.9410165e-06
+    CMet       NR  1  0.0046502056  5.9410165e-06
+    CMet       NZ  1  0.0046502056  5.9410165e-06
+    CMet       NE  1  0.0046502056  5.9410165e-06
+    CMet        C  1  0.0045578798  8.3886605e-06
+    CMet      CH1  1  0.0050835716  8.8270445e-06
+    CMet      CH2  1  0.0064750533  1.2178856e-05
+    CMet      CH3  1  0.0077987038  1.5859455e-05
+    CMet      CH4  1  0.010815308  2.6768823e-05
+    CMet      CR1  1  0.0070045135  1.3178919e-05
+    CMet       HC  1  0.000866732  5.616795e-07
+    CMet        H  1           0           0
+    CMet      DUM  1           0           0
+    CMet        S  1  0.0094134632  1.6512464e-05
+    CMet     CU1+  1  0.0019265945  3.2691574e-07
+    CMet     CU2+  1  0.0019265945  3.2691574e-07
+    CMet       FE  1           0           0
+    CMet     ZN2+  1  0.0019265945  4.4368114e-07
+    CMet     MG2+  1  0.0007612168  2.6659227e-07
+    CMet     CA2+  1  0.002986457  3.222579e-06
+    CMet        P  1  0.011437094  2.1512782e-05
+    CMet       AR  1  0.0074567215  1.4329677e-05
+    CMet        F  1  0.0032332872  3.9829013e-06
+    CMet       CL  1  0.0088199402  1.7859582e-05
+    CMet       BR  1  0.0032351714  3.6952118e-05
+    CMet     CMet  1  0.0088755241  2.0852922e-05
+    OMet        O  1  0.0022619536  9.687375e-07
+    OMet       OM  1  0.0022619536  9.687375e-07
+    OMet       OA  1  0.0022619536  1.265625e-06
+    OMet       OW  1  0.0024331696   1.737e-06
+    OMet        N  1  0.0023475616  1.463625e-06
+    OMet       NT  1  0.0023475616  1.463625e-06
+    OMet       NL  1  0.0023475616  1.463625e-06
+    OMet       NR  1  0.0023475616  1.463625e-06
+    OMet       NZ  1  0.0023475616  1.463625e-06
+    OMet       NE  1  0.0023475616  1.463625e-06
+    OMet        C  1  0.0023009528  2.066625e-06
+    OMet      CH1  1  0.0025663376  2.174625e-06
+    OMet      CH2  1  0.0032687988  3.000375e-06
+    OMet      CH3  1  0.0039370168  3.907125e-06
+    OMet      CH4  1  0.005459888  6.59475e-06
+    OMet      CR1  1  0.003536086  3.24675e-06
+    OMet       HC  1  0.000437552  1.38375e-07
+    OMet        H  1           0           0
+    OMet      DUM  1           0           0
+    OMet        S  1  0.0047521952   4.068e-06
+    OMet     CU1+  1  0.000972602  8.053875e-08
+    OMet     CU2+  1  0.000972602  8.053875e-08
+    OMet       FE  1           0           0
+    OMet     ZN2+  1  0.000972602  1.09305e-07
+    OMet     MG2+  1  0.0003842848  6.56775e-08
+    OMet     CA2+  1  0.001507652  7.939125e-07
+    OMet        P  1  0.005773784  5.299875e-06
+    OMet       AR  1  0.003764374  3.53025e-06
+    OMet        F  1  0.0016322592  9.81225e-07
+    OMet       CL  1  0.0044525672  4.399875e-06
+    OMet       BR  1  0.0016332104  9.1035e-06
+    OMet     CMet  1  0.0044806276  5.1373125e-06
+    OMet     OMet  1  0.0022619536  1.265625e-06
      NA+        O  1  0.00040373684  1.248595e-07
      NA+       OM  1  0.00040373684  1.248595e-07
      NA+       OA  1  0.00040373684  1.63125e-07
@@ -1593,8 +1593,8 @@ CLCL4   17        0.000      0.000     A  0.0076040144  1.2767758e-05
      NA+        F  1  0.00029134248  1.26469e-07
      NA+       CL  1  0.00079474018  5.67095e-07
      NA+       BR  1  0.00029151226  1.17334e-06
-     NA+     CMET  1  0.00079974869  6.621425e-07
-     NA+     OMET  1  0.00040373684  1.63125e-07
+     NA+     CMet  1  0.00079974869  6.621425e-07
+     NA+     OMet  1  0.00040373684  1.63125e-07
      NA+      NA+  1  7.2063121e-05  2.1025e-08
      CL-        O  1   0.0055883  8.903774e-06
      CL-       OM  1   0.0055883  8.903774e-06
@@ -1627,326 +1627,326 @@ CLCL4   17    0.000      0.000     A  0.0076040144  1.2767758e-05
      CL-        F  1   0.0040326  9.018548e-06
      CL-       CL  1  0.01100035  4.043974e-05
      CL-       BR  1  0.00403495  8.367128e-05
-     CL-     CMET  1  0.011069675  4.721761e-05
-     CL-     OMET  1   0.0055883  1.16325e-05
+     CL-     CMet  1  0.011069675  4.721761e-05
+     CL-     OMet  1   0.0055883  1.16325e-05
      CL-      NA+  1  0.0009974575  1.4993e-06
      CL-      CL-  1  0.01380625  0.0001069156
-    CCHL        O  1  0.0024394475  1.7359776e-06
-    CCHL       OM  1  0.0024394475  1.7359776e-06
-    CCHL       OA  1  0.0024394475   2.268e-06
-    CCHL       OW  1  0.0026240987  3.112704e-06
-    CCHL        N  1  0.0025317731  2.622816e-06
-    CCHL       NT  1  0.0025317731  2.622816e-06
-    CCHL       NL  1  0.0025317731  2.622816e-06
-    CCHL       NR  1  0.0025317731  2.622816e-06
-    CCHL       NZ  1  0.0025317731  2.622816e-06
-    CCHL       NE  1  0.0025317731  2.622816e-06
-    CCHL        C  1  0.002481507  3.703392e-06
-    CCHL      CH1  1  0.0027677163  3.896928e-06
-    CCHL      CH2  1  0.0035252992  5.376672e-06
-    CCHL      CH3  1  0.0042459518  7.001568e-06
-    CCHL      CH4  1  0.0058883216  1.1817792e-05
-    CCHL      CR1  1  0.0038135602  5.818176e-06
-    CCHL       HC  1  0.0004718864  2.47968e-07
-    CCHL        H  1           0           0
-    CCHL      DUM  1           0           0
-    CCHL        S  1  0.0051250966  7.289856e-06
-    CCHL     CU1+  1  0.0010489214  1.4432544e-07
-    CCHL     CU2+  1  0.0010489214  1.4432544e-07
-    CCHL       FE  1           0           0
-    CCHL     ZN2+  1  0.0010489214  1.9587456e-07
-    CCHL     MG2+  1  0.00041443936  1.1769408e-07
-    CCHL     CA2+  1  0.0016259564  1.4226912e-06
-    CCHL        P  1  0.0062268488  9.497376e-06
-    CCHL       AR  1  0.0040597618  6.326208e-06
-    CCHL        F  1  0.0017603414  1.7583552e-06
-    CCHL       CL  1  0.004801957  7.884576e-06
-    CCHL       BR  1  0.0017613673  1.6313472e-05
-    CCHL     CMET  1  0.0048322193  9.206064e-06
-    CCHL     OMET  1  0.0024394475   2.268e-06
-    CCHL      NA+  1  0.00043541779  2.9232e-07
-    CCHL      CL-  1  0.00602681  2.084544e-05
-    CCHL     CCHL  1  0.0026308693  4.064256e-06
-   CLCHL        O  1  0.004334666  3.1947671e-06
-   CLCHL       OM  1  0.004334666  3.1947671e-06
-   CLCHL       OA  1  0.004334666  4.1738625e-06
-   CLCHL       OW  1  0.0046627736  5.7283944e-06
-   CLCHL        N  1  0.0044987198  4.8268401e-06
-   CLCHL       NT  1  0.0044987198  4.8268401e-06
-   CLCHL       NL  1  0.0044987198  4.8268401e-06
-   CLCHL       NR  1  0.0044987198  4.8268401e-06
-   CLCHL       NZ  1  0.0044987198  4.8268401e-06
-   CLCHL       NE  1  0.0044987198  4.8268401e-06
-   CLCHL        C  1  0.0044094016  6.8154537e-06
-   CLCHL      CH1  1  0.0049179684  7.1716233e-06
-   CLCHL      CH2  1  0.0062641209  9.8948367e-06
-   CLCHL      CH3  1  0.007544652  1.2885177e-05
-   CLCHL      CH4  1  0.010462987  2.1748606e-05
-   CLCHL      CR1  1  0.0067763334  1.0707349e-05
-   CLCHL       HC  1  0.0008384972  4.563423e-07
-   CLCHL        H  1           0           0
-   CLCHL      DUM  1           0           0
-   CLCHL        S  1  0.0091068087  1.3415722e-05
-   CLCHL     CU1+  1  0.0018638335  2.6560606e-07
-   CLCHL     CU2+  1  0.0018638335  2.6560606e-07
-   CLCHL       FE  1           0           0
-   CLCHL     ZN2+  1  0.0018638335  3.6047332e-07
-   CLCHL     MG2+  1  0.00073641928  2.1659564e-07
-   CLCHL     CA2+  1  0.0028891697  2.6182176e-06
-   CLCHL        P  1  0.011064517  1.7478281e-05
-   CLCHL       AR  1  0.0072138101  1.1642294e-05
-   CLCHL        F  1  0.0031279591  3.2359492e-06
-   CLCHL       CL  1  0.0085326204  1.4510201e-05
-   CLCHL       BR  1  0.0031297819  3.0022129e-05
-   CLCHL     CMET  1  0.0085863936  1.6942172e-05
-   CLCHL     OMET  1  0.004334666  4.1738625e-06
-   CLCHL      NA+  1  0.00077369595  5.379645e-07
-   CLCHL      CL-  1  0.010709067  3.8362434e-05
-   CLCHL     CCHL  1  0.0046754       7.4813E-6
-   CLCHL    CLCHL  1  0.0083066819  1.3764842e-05
-    HCHL        O  1  0.0002920184  5.6465771e-08
-    HCHL       OM  1  0.0002920184  5.6465771e-08
-    HCHL       OA  1  0.0002920184  7.377075e-08
-    HCHL       OW  1  0.0003141224  1.0124626e-07
-    HCHL        N  1  0.0003030704  8.5311774e-08
-    HCHL       NT  1  0.0003030704  8.5311774e-08
-    HCHL       NL  1  0.0003030704  8.5311774e-08
-    HCHL       NR  1  0.0003030704  8.5311774e-08
-    HCHL       NZ  1  0.0003030704  8.5311774e-08
-    HCHL       NE  1  0.0003030704  8.5311774e-08
-    HCHL        C  1  0.0002970532  1.2045944e-07
-    HCHL      CH1  1  0.0003313144  1.2675454e-07
-    HCHL      CH2  1  0.0004220022  1.7488586e-07
-    HCHL      CH3  1  0.0005082692  2.277385e-07
-    HCHL      CH4  1  0.000704872  3.8439479e-07
-    HCHL      CR1  1  0.000456509  1.8924656e-07
-    HCHL       HC  1  5.6488e-05  8.065602e-09
-    HCHL        H  1           0           0
-    HCHL      DUM  1           0           0
-    HCHL        S  1  0.0006135088  2.3711558e-07
-    HCHL     CU1+  1  0.000125563  4.6944427e-09
-    HCHL     CU2+  1  0.000125563  4.6944427e-09
-    HCHL       FE  1           0           0
-    HCHL     ZN2+  1  0.000125563  6.3711698e-09
-    HCHL     MG2+  1  4.96112e-05  3.8282101e-09
-    HCHL     CA2+  1  0.000194638  4.6275572e-08
-    HCHL        P  1  0.000745396  3.0891911e-07
-    HCHL       AR  1  0.000485981  2.0577121e-07
-    HCHL        F  1  0.0002107248  5.7193643e-08
-    HCHL       CL  1  0.0005748268  2.5645991e-07
-    HCHL       BR  1  0.0002108476  5.3062481e-07
-    HCHL     CMET  1  0.0005784494  2.9944367e-07
-    HCHL     OMET  1  0.0002920184  7.377075e-08
-    HCHL      NA+  1  5.212246e-05  9.50823e-09
-    HCHL      CL-  1  0.00072145  6.7803516e-07
-    HCHL     CCHL  1  0.0003622       0.1745E-6
-    HCHL    CLCHL  1  0.0006493       0.3266E-6
-    HCHL     HCHL  1  3.76996e-05  4.2999495e-09
-   SDMSO        O  1  0.0048877412  3.9925763e-06
-   SDMSO       OM  1  0.0048877412  3.9925763e-06
-   SDMSO       OA  1  0.0048877412  5.216175e-06
-   SDMSO       OW  1  0.0052577132  7.1589104e-06
-   SDMSO        N  1  0.0050727272  6.0322166e-06
-   SDMSO       NT  1  0.0050727272  6.0322166e-06
-   SDMSO       NL  1  0.0050727272  6.0322166e-06
-   SDMSO       NR  1  0.0050727272  6.0322166e-06
-   SDMSO       NZ  1  0.0050727272  6.0322166e-06
-   SDMSO       NE  1  0.0050727272  6.0322166e-06
-   SDMSO        C  1  0.0049720126  8.5174342e-06
-   SDMSO      CH1  1  0.0055454692  8.9625478e-06
-   SDMSO      CH2  1  0.0070633821  1.2365812e-05
-   SDMSO      CH3  1  0.0085073006  1.6102912e-05
-   SDMSO      CH4  1  0.011797996  2.7179749e-05
-   SDMSO      CR1  1  0.0076409495  1.3381228e-05
-   SDMSO       HC  1  0.000945484  5.703018e-07
-   SDMSO        H  1           0           0
-   SDMSO      DUM  1           0           0
-   SDMSO        S  1  0.010268778  1.6765946e-05
-   SDMSO     CU1+  1  0.0021016465  3.3193419e-07
-   SDMSO     CU2+  1  0.0021016465  3.3193419e-07
-   SDMSO       FE  1           0           0
-   SDMSO     ZN2+  1  0.0021016465  4.5049206e-07
-   SDMSO     MG2+  1  0.0008303816  2.7068471e-07
-   SDMSO     CA2+  1  0.003257809  3.2720486e-06
-   SDMSO        P  1  0.012476278  2.1843023e-05
-   SDMSO       AR  1  0.0081342455  1.4549651e-05
-   SDMSO        F  1  0.0035270664  4.0440425e-06
-   SDMSO       CL  1  0.0096213274  1.8133743e-05
-   SDMSO       BR  1  0.0035291218  3.7519367e-05
-   SDMSO     CMET  1  0.0096819617  2.1173034e-05
-   SDMSO     OMET  1  0.0048877412  5.216175e-06
-   SDMSO      NA+  1  0.00087241453  6.72307e-07
-   SDMSO      CL-  1  0.012075475  4.7942444e-05
-   SDMSO     CCHL  1  0.0052712788  9.3473856e-06
-   SDMSO    CLCHL  1  0.0093665606  1.720225e-05
-   SDMSO     HCHL  1  0.0006310078  3.0404041e-07
-   SDMSO    SDMSO  1  0.010561673  2.149806e-05
-   CDMSO        O  1  0.0045248108  4.016601e-06
-   CDMSO       OM  1  0.0045248108  4.016601e-06
-   CDMSO       OA  1  0.0045248108  5.2475625e-06
-   CDMSO       OW  1  0.0048673112  7.201988e-06
-   CDMSO        N  1  0.004696061  6.0685145e-06
-   CDMSO       NT  1  0.004696061  6.0685145e-06
-   CDMSO       NL  1  0.004696061  6.0685145e-06
-   CDMSO       NR  1  0.004696061  6.0685145e-06
-   CDMSO       NZ  1  0.004696061  6.0685145e-06
-   CDMSO       NE  1  0.004696061  6.0685145e-06
-   CDMSO        C  1  0.0046028248  8.5686865e-06
-   CDMSO      CH1  1  0.0051337004  9.0164785e-06
-   CDMSO      CH2  1  0.0065389035  1.2440222e-05
-   CDMSO      CH3  1  0.0078756064  1.6199809e-05
-   CDMSO      CH4  1  0.010921957  2.7343299e-05
-   CDMSO      CR1  1  0.0070735846  1.3461747e-05
-   CDMSO       HC  1  0.0008752788  5.737335e-07
-   CDMSO        H  1           0           0
-   CDMSO      DUM  1           0           0
-   CDMSO        S  1  0.0095062889  1.6866832e-05
-   CDMSO     CU1+  1  0.0019455925  3.3393156e-07
-   CDMSO     CU2+  1  0.0019455925  3.3393156e-07
-   CDMSO       FE  1           0           0
-   CDMSO     ZN2+  1  0.0019455925  4.5320282e-07
-   CDMSO     MG2+  1  0.00076872312  2.7231351e-07
-   CDMSO     CA2+  1  0.0030159063  3.2917377e-06
-   CDMSO        P  1  0.011549875  2.197446e-05
-   CDMSO       AR  1  0.0075302519  1.4637201e-05
-   CDMSO        F  1  0.0032651705  4.0683769e-06
-   CDMSO       CL  1  0.0089069132  1.824286e-05
-   CDMSO       BR  1  0.0032670733  3.7745134e-05
-   CDMSO     CMET  1  0.0089630452  2.1300439e-05
-   CDMSO     OMET  1  0.0045248108  5.2475625e-06
-   CDMSO      NA+  1  0.00080763497  6.763525e-07
-   CDMSO      CL-  1  0.011178832  4.823093e-05
-   CDMSO     CCHL  1  0.0048798696  9.403632e-06
-   CDMSO    CLCHL  1  0.0086710636  1.7305761e-05
-   CDMSO     HCHL  1  0.00058415346  3.0586992e-07
-   CDMSO    SDMSO  1  0.0097827      21.6523E-6
-   CDMSO    CDMSO  1  0.0090514293  2.175756e-05
-   ODMSO        O  1  0.0022663291  7.4645315e-07
-   ODMSO       OM  1  0.0022663291  7.4645315e-07
-   ODMSO       OA  1  0.0022663291  9.752175e-07
-   ODMSO       OW  1  0.0024378763  1.3384318e-06
-   ODMSO        N  1  0.0023521027  1.1277849e-06
-   ODMSO       NT  1  0.0023521027  1.1277849e-06
-   ODMSO       NL  1  0.0023521027  1.1277849e-06
-   ODMSO       NR  1  0.0023521027  1.1277849e-06
-   ODMSO       NZ  1  0.0023521027  1.1277849e-06
-   ODMSO       NE  1  0.0023521027  1.1277849e-06
-   ODMSO        C  1  0.0023054038  1.5924218e-06
-   ODMSO      CH1  1  0.0025713019  1.6756404e-06
-   ODMSO      CH2  1  0.003275122  2.3119156e-06
-   ODMSO      CH3  1  0.0039446326  3.0106048e-06
-   ODMSO      CH4  1  0.0054704496  5.0815333e-06
-   ODMSO      CR1  1  0.0035429262  2.501758e-06
-   ODMSO       HC  1  0.0004383984  1.0662378e-07
-   ODMSO        H  1           0           0
-   ODMSO      DUM  1           0           0
-   ODMSO        S  1  0.0047613878  3.1345658e-06
-   ODMSO     CU1+  1  0.0009744834  6.2058507e-08
-   ODMSO     CU2+  1  0.0009744834  6.2058507e-08
-   ODMSO       FE  1           0           0
-   ODMSO     ZN2+  1  0.0009744834  8.4224118e-08
-   ODMSO     MG2+  1  0.00038502816  5.0607287e-08
-   ODMSO     CA2+  1  0.0015105684  6.117431e-07
-   ODMSO        P  1  0.0057849528  4.0837775e-06
-   ODMSO       AR  1  0.0037716558  2.7202067e-06
-   ODMSO        F  1  0.0016354166  7.5607529e-07
-   ODMSO       CL  1  0.0044611802  3.3902895e-06
-   ODMSO       BR  1  0.0016363697  7.0146311e-06
-   ODMSO     CMET  1  0.0044892949  3.9585162e-06
-   ODMSO     OMET  1  0.0022663291  9.752175e-07
-   ODMSO      NA+  1  0.00040451783  1.256947e-07
-   ODMSO      CL-  1  0.00559911  8.9633324e-06
-   ODMSO     CCHL  1  0.0024441664  1.7475898e-06
-   ODMSO    CLCHL  1  0.0043430509  3.2161373e-06
-   ODMSO     HCHL  1  0.00029258328  5.6843478e-08
-   ODMSO    SDMSO  1  0.0052442       4.6094E-6
-   ODMSO    CDMSO  1  0.0049187       4.7597E-6
-   ODMSO    ODMSO  1  0.0022707131  7.5144626e-07
-    CCL4        O  1  0.0024394475  2.3738805e-06
-    CCL4       OM  1  0.0024394475  2.3738805e-06
-    CCL4       OA  1  0.0024394475  3.1014e-06
-    CCL4       OW  1  0.0026240987  4.2564992e-06
-    CCL4        N  1  0.0025317731  3.5865968e-06
-    CCL4       NT  1  0.0025317731  3.5865968e-06
-    CCL4       NL  1  0.0025317731  3.5865968e-06
-    CCL4       NR  1  0.0025317731  3.5865968e-06
-    CCL4       NZ  1  0.0025317731  3.5865968e-06
-    CCL4       NE  1  0.0025317731  3.5865968e-06
-    CCL4        C  1  0.002481507  5.0642416e-06
-    CCL4      CH1  1  0.0027677163  5.3288944e-06
-    CCL4      CH2  1  0.0035252992  7.3523856e-06
-    CCL4      CH3  1  0.0042459518  9.5743664e-06
-    CCL4      CH4  1  0.0058883216  1.6160362e-05
-    CCL4      CR1  1  0.0038135602  7.9561248e-06
-    CCL4       HC  1  0.0004718864  3.390864e-07
-    CCL4        H  1           0           0
-    CCL4      DUM  1           0           0
-    CCL4        S  1  0.0051250966  9.9685888e-06
-    CCL4     CU1+  1  0.0010489214  1.9735931e-07
-    CCL4     CU2+  1  0.0010489214  1.9735931e-07
-    CCL4       FE  1           0           0
-    CCL4     ZN2+  1  0.0010489214  2.6785069e-07
-    CCL4     MG2+  1  0.00041443936  1.6094198e-07
-    CCL4     CA2+  1  0.0016259564  1.9454738e-06
-    CCL4        P  1  0.0062268488  1.2987285e-05
-    CCL4       AR  1  0.0040597618  8.6508384e-06
-    CCL4        F  1  0.0017603414  2.404481e-06
-    CCL4       CL  1  0.004801957  1.0781845e-05
-    CCL4       BR  1  0.0017613673  2.2308026e-05
-    CCL4     CMET  1  0.0048322193  1.2588927e-05
-    CCL4     OMET  1  0.0024394475  3.1014e-06
-    CCL4      NA+  1  0.00043541779  3.99736e-07
-    CCL4      CL-  1  0.00602681  2.8505312e-05
-    CCL4     CCHL  1  0.0026308693  5.5577088e-06
-    CCL4    CLCHL  1  0.0046748042  1.0228004e-05
-    CCL4     HCHL  1  0.00031493288  1.807744e-07
-    CCL4    SDMSO  1  0.0052712788  1.2782179e-05
-    CCL4    CDMSO  1  0.0048798696  1.2859094e-05
-    CCL4    ODMSO  1  0.0024441664  2.3897596e-06
-    CCL4     CCL4  1  0.0026308693  7.5999462e-06
-   CLCL4        O  1  0.0041472796  3.0768825e-06
-   CLCL4       OM  1  0.0041472796  3.0768825e-06
-   CLCL4       OA  1  0.0041472796  4.01985e-06
-   CLCL4       OW  1  0.0044612032  5.5170208e-06
-   CLCL4        N  1  0.0043042414  4.6487332e-06
-   CLCL4       NT  1  0.0043042414  4.6487332e-06
-   CLCL4       NL  1  0.0043042414  4.6487332e-06
-   CLCL4       NR  1  0.0043042414  4.6487332e-06
-   CLCL4       NZ  1  0.0043042414  4.6487332e-06
-   CLCL4       NE  1  0.0043042414  4.6487332e-06
-   CLCL4        C  1  0.0042187844  6.5639684e-06
-   CLCL4      CH1  1  0.004705366  6.9069956e-06
-   CLCL4      CH2  1  0.0059933247  9.5297244e-06
-   CLCL4      CH3  1  0.0072184988  1.2409724e-05
-   CLCL4      CH4  1  0.010010675  2.0946098e-05
-   CLCL4      CR1  1  0.0064833944  1.0312255e-05
-   CLCL4       HC  1  0.0008022492  4.395036e-07
-   CLCL4        H  1           0           0
-   CLCL4      DUM  1           0           0
-   CLCL4        S  1  0.0087131239  1.2920691e-05
-   CLCL4     CU1+  1  0.0017832604  2.5580539e-07
-   CLCL4     CU2+  1  0.0017832604  2.5580539e-07
-   CLCL4       FE  1           0           0
-   CLCL4     ZN2+  1  0.0017832604  3.4717211e-07
-   CLCL4     MG2+  1  0.00070458408  2.0860342e-07
-   CLCL4     CA2+  1  0.0027642717  2.5216072e-06
-   CLCL4        P  1  0.010586201  1.6833345e-05
-   CLCL4       AR  1  0.0069019592  1.1212702e-05
-   CLCL4        F  1  0.0029927383  3.116545e-06
-   CLCL4       CL  1  0.0081637576  1.3974785e-05
-   CLCL4       BR  1  0.0029944823  2.8914334e-05
-   CLCL4     CMET  1  0.0082152062  1.6317018e-05
-   CLCL4     OMET  1  0.0041472796  4.01985e-06
-   CLCL4      NA+  1  0.00074024929  5.18114e-07
-   CLCL4      CL-  1  0.010246117  3.6946888e-05
-   CLCL4     CCHL  1  0.0044727137  7.2035712e-06
-   CLCL4    CLCHL  1  0.0079475863  1.3256929e-05
-   CLCL4     HCHL  1  0.00053541414  2.3430902e-07
-   CLCL4    SDMSO  1  0.0089616468  1.6567499e-05
-   CLCL4    CDMSO  1  0.0082962159  1.6667191e-05
-   CLCL4    ODMSO  1  0.0041553021  3.0974642e-06
-   CLCL4     CCL4  1  0.0044727137  9.8505978e-06
-   CLCL4    CLCL4  1  0.0076040144  1.2767758e-05
+    CChl        O  1  0.0024394475  1.7359776e-06
+    CChl       OM  1  0.0024394475  1.7359776e-06
+    CChl       OA  1  0.0024394475   2.268e-06
+    CChl       OW  1  0.0026240987  3.112704e-06
+    CChl        N  1  0.0025317731  2.622816e-06
+    CChl       NT  1  0.0025317731  2.622816e-06
+    CChl       NL  1  0.0025317731  2.622816e-06
+    CChl       NR  1  0.0025317731  2.622816e-06
+    CChl       NZ  1  0.0025317731  2.622816e-06
+    CChl       NE  1  0.0025317731  2.622816e-06
+    CChl        C  1  0.002481507  3.703392e-06
+    CChl      CH1  1  0.0027677163  3.896928e-06
+    CChl      CH2  1  0.0035252992  5.376672e-06
+    CChl      CH3  1  0.0042459518  7.001568e-06
+    CChl      CH4  1  0.0058883216  1.1817792e-05
+    CChl      CR1  1  0.0038135602  5.818176e-06
+    CChl       HC  1  0.0004718864  2.47968e-07
+    CChl        H  1           0           0
+    CChl      DUM  1           0           0
+    CChl        S  1  0.0051250966  7.289856e-06
+    CChl     CU1+  1  0.0010489214  1.4432544e-07
+    CChl     CU2+  1  0.0010489214  1.4432544e-07
+    CChl       FE  1           0           0
+    CChl     ZN2+  1  0.0010489214  1.9587456e-07
+    CChl     MG2+  1  0.00041443936  1.1769408e-07
+    CChl     CA2+  1  0.0016259564  1.4226912e-06
+    CChl        P  1  0.0062268488  9.497376e-06
+    CChl       AR  1  0.0040597618  6.326208e-06
+    CChl        F  1  0.0017603414  1.7583552e-06
+    CChl       CL  1  0.004801957  7.884576e-06
+    CChl       BR  1  0.0017613673  1.6313472e-05
+    CChl     CMet  1  0.0048322193  9.206064e-06
+    CChl     OMet  1  0.0024394475   2.268e-06
+    CChl      NA+  1  0.00043541779  2.9232e-07
+    CChl      CL-  1  0.00602681  2.084544e-05
+    CChl     CChl  1  0.0026308693  4.064256e-06
+   CLChl        O  1  0.004334666  3.1947671e-06
+   CLChl       OM  1  0.004334666  3.1947671e-06
+   CLChl       OA  1  0.004334666  4.1738625e-06
+   CLChl       OW  1  0.0046627736  5.7283944e-06
+   CLChl        N  1  0.0044987198  4.8268401e-06
+   CLChl       NT  1  0.0044987198  4.8268401e-06
+   CLChl       NL  1  0.0044987198  4.8268401e-06
+   CLChl       NR  1  0.0044987198  4.8268401e-06
+   CLChl       NZ  1  0.0044987198  4.8268401e-06
+   CLChl       NE  1  0.0044987198  4.8268401e-06
+   CLChl        C  1  0.0044094016  6.8154537e-06
+   CLChl      CH1  1  0.0049179684  7.1716233e-06
+   CLChl      CH2  1  0.0062641209  9.8948367e-06
+   CLChl      CH3  1  0.007544652  1.2885177e-05
+   CLChl      CH4  1  0.010462987  2.1748606e-05
+   CLChl      CR1  1  0.0067763334  1.0707349e-05
+   CLChl       HC  1  0.0008384972  4.563423e-07
+   CLChl        H  1           0           0
+   CLChl      DUM  1           0           0
+   CLChl        S  1  0.0091068087  1.3415722e-05
+   CLChl     CU1+  1  0.0018638335  2.6560606e-07
+   CLChl     CU2+  1  0.0018638335  2.6560606e-07
+   CLChl       FE  1           0           0
+   CLChl     ZN2+  1  0.0018638335  3.6047332e-07
+   CLChl     MG2+  1  0.00073641928  2.1659564e-07
+   CLChl     CA2+  1  0.0028891697  2.6182176e-06
+   CLChl        P  1  0.011064517  1.7478281e-05
+   CLChl       AR  1  0.0072138101  1.1642294e-05
+   CLChl        F  1  0.0031279591  3.2359492e-06
+   CLChl       CL  1  0.0085326204  1.4510201e-05
+   CLChl       BR  1  0.0031297819  3.0022129e-05
+   CLChl     CMet  1  0.0085863936  1.6942172e-05
+   CLChl     OMet  1  0.004334666  4.1738625e-06
+   CLChl      NA+  1  0.00077369595  5.379645e-07
+   CLChl      CL-  1  0.010709067  3.8362434e-05
+   CLChl     CChl  1  0.0046754       7.4813E-6
+   CLChl    CLChl  1  0.0083066819  1.3764842e-05
+    HChl        O  1  0.0002920184  5.6465771e-08
+    HChl       OM  1  0.0002920184  5.6465771e-08
+    HChl       OA  1  0.0002920184  7.377075e-08
+    HChl       OW  1  0.0003141224  1.0124626e-07
+    HChl        N  1  0.0003030704  8.5311774e-08
+    HChl       NT  1  0.0003030704  8.5311774e-08
+    HChl       NL  1  0.0003030704  8.5311774e-08
+    HChl       NR  1  0.0003030704  8.5311774e-08
+    HChl       NZ  1  0.0003030704  8.5311774e-08
+    HChl       NE  1  0.0003030704  8.5311774e-08
+    HChl        C  1  0.0002970532  1.2045944e-07
+    HChl      CH1  1  0.0003313144  1.2675454e-07
+    HChl      CH2  1  0.0004220022  1.7488586e-07
+    HChl      CH3  1  0.0005082692  2.277385e-07
+    HChl      CH4  1  0.000704872  3.8439479e-07
+    HChl      CR1  1  0.000456509  1.8924656e-07
+    HChl       HC  1  5.6488e-05  8.065602e-09
+    HChl        H  1           0           0
+    HChl      DUM  1           0           0
+    HChl        S  1  0.0006135088  2.3711558e-07
+    HChl     CU1+  1  0.000125563  4.6944427e-09
+    HChl     CU2+  1  0.000125563  4.6944427e-09
+    HChl       FE  1           0           0
+    HChl     ZN2+  1  0.000125563  6.3711698e-09
+    HChl     MG2+  1  4.96112e-05  3.8282101e-09
+    HChl     CA2+  1  0.000194638  4.6275572e-08
+    HChl        P  1  0.000745396  3.0891911e-07
+    HChl       AR  1  0.000485981  2.0577121e-07
+    HChl        F  1  0.0002107248  5.7193643e-08
+    HChl       CL  1  0.0005748268  2.5645991e-07
+    HChl       BR  1  0.0002108476  5.3062481e-07
+    HChl     CMet  1  0.0005784494  2.9944367e-07
+    HChl     OMet  1  0.0002920184  7.377075e-08
+    HChl      NA+  1  5.212246e-05  9.50823e-09
+    HChl      CL-  1  0.00072145  6.7803516e-07
+    HChl     CChl  1  0.0003622       0.1745E-6
+    HChl    CLChl  1  0.0006493       0.3266E-6
+    HChl     HChl  1  3.76996e-05  4.2999495e-09
+   SDmso        O  1  0.0048877412  3.9925763e-06
+   SDmso       OM  1  0.0048877412  3.9925763e-06
+   SDmso       OA  1  0.0048877412  5.216175e-06
+   SDmso       OW  1  0.0052577132  7.1589104e-06
+   SDmso        N  1  0.0050727272  6.0322166e-06
+   SDmso       NT  1  0.0050727272  6.0322166e-06
+   SDmso       NL  1  0.0050727272  6.0322166e-06
+   SDmso       NR  1  0.0050727272  6.0322166e-06
+   SDmso       NZ  1  0.0050727272  6.0322166e-06
+   SDmso       NE  1  0.0050727272  6.0322166e-06
+   SDmso        C  1  0.0049720126  8.5174342e-06
+   SDmso      CH1  1  0.0055454692  8.9625478e-06
+   SDmso      CH2  1  0.0070633821  1.2365812e-05
+   SDmso      CH3  1  0.0085073006  1.6102912e-05
+   SDmso      CH4  1  0.011797996  2.7179749e-05
+   SDmso      CR1  1  0.0076409495  1.3381228e-05
+   SDmso       HC  1  0.000945484  5.703018e-07
+   SDmso        H  1           0           0
+   SDmso      DUM  1           0           0
+   SDmso        S  1  0.010268778  1.6765946e-05
+   SDmso     CU1+  1  0.0021016465  3.3193419e-07
+   SDmso     CU2+  1  0.0021016465  3.3193419e-07
+   SDmso       FE  1           0           0
+   SDmso     ZN2+  1  0.0021016465  4.5049206e-07
+   SDmso     MG2+  1  0.0008303816  2.7068471e-07
+   SDmso     CA2+  1  0.003257809  3.2720486e-06
+   SDmso        P  1  0.012476278  2.1843023e-05
+   SDmso       AR  1  0.0081342455  1.4549651e-05
+   SDmso        F  1  0.0035270664  4.0440425e-06
+   SDmso       CL  1  0.0096213274  1.8133743e-05
+   SDmso       BR  1  0.0035291218  3.7519367e-05
+   SDmso     CMet  1  0.0096819617  2.1173034e-05
+   SDmso     OMet  1  0.0048877412  5.216175e-06
+   SDmso      NA+  1  0.00087241453  6.72307e-07
+   SDmso      CL-  1  0.012075475  4.7942444e-05
+   SDmso     CChl  1  0.0052712788  9.3473856e-06
+   SDmso    CLChl  1  0.0093665606  1.720225e-05
+   SDmso     HChl  1  0.0006310078  3.0404041e-07
+   SDmso    SDmso  1  0.010561673  2.149806e-05
+   CDmso        O  1  0.0045248108  4.016601e-06
+   CDmso       OM  1  0.0045248108  4.016601e-06
+   CDmso       OA  1  0.0045248108  5.2475625e-06
+   CDmso       OW  1  0.0048673112  7.201988e-06
+   CDmso        N  1  0.004696061  6.0685145e-06
+   CDmso       NT  1  0.004696061  6.0685145e-06
+   CDmso       NL  1  0.004696061  6.0685145e-06
+   CDmso       NR  1  0.004696061  6.0685145e-06
+   CDmso       NZ  1  0.004696061  6.0685145e-06
+   CDmso       NE  1  0.004696061  6.0685145e-06
+   CDmso        C  1  0.0046028248  8.5686865e-06
+   CDmso      CH1  1  0.0051337004  9.0164785e-06
+   CDmso      CH2  1  0.0065389035  1.2440222e-05
+   CDmso      CH3  1  0.0078756064  1.6199809e-05
+   CDmso      CH4  1  0.010921957  2.7343299e-05
+   CDmso      CR1  1  0.0070735846  1.3461747e-05
+   CDmso       HC  1  0.0008752788  5.737335e-07
+   CDmso        H  1           0           0
+   CDmso      DUM  1           0           0
+   CDmso        S  1  0.0095062889  1.6866832e-05
+   CDmso     CU1+  1  0.0019455925  3.3393156e-07
+   CDmso     CU2+  1  0.0019455925  3.3393156e-07
+   CDmso       FE  1           0           0
+   CDmso     ZN2+  1  0.0019455925  4.5320282e-07
+   CDmso     MG2+  1  0.00076872312  2.7231351e-07
+   CDmso     CA2+  1  0.0030159063  3.2917377e-06
+   CDmso        P  1  0.011549875  2.197446e-05
+   CDmso       AR  1  0.0075302519  1.4637201e-05
+   CDmso        F  1  0.0032651705  4.0683769e-06
+   CDmso       CL  1  0.0089069132  1.824286e-05
+   CDmso       BR  1  0.0032670733  3.7745134e-05
+   CDmso     CMet  1  0.0089630452  2.1300439e-05
+   CDmso     OMet  1  0.0045248108  5.2475625e-06
+   CDmso      NA+  1  0.00080763497  6.763525e-07
+   CDmso      CL-  1  0.011178832  4.823093e-05
+   CDmso     CChl  1  0.0048798696  9.403632e-06
+   CDmso    CLChl  1  0.0086710636  1.7305761e-05
+   CDmso     HChl  1  0.00058415346  3.0586992e-07
+   CDmso    SDmso  1  0.0097827      21.6523E-6
+   CDmso    CDmso  1  0.0090514293  2.175756e-05
+   ODmso        O  1  0.0022663291  7.4645315e-07
+   ODmso       OM  1  0.0022663291  7.4645315e-07
+   ODmso       OA  1  0.0022663291  9.752175e-07
+   ODmso       OW  1  0.0024378763  1.3384318e-06
+   ODmso        N  1  0.0023521027  1.1277849e-06
+   ODmso       NT  1  0.0023521027  1.1277849e-06
+   ODmso       NL  1  0.0023521027  1.1277849e-06
+   ODmso       NR  1  0.0023521027  1.1277849e-06
+   ODmso       NZ  1  0.0023521027  1.1277849e-06
+   ODmso       NE  1  0.0023521027  1.1277849e-06
+   ODmso        C  1  0.0023054038  1.5924218e-06
+   ODmso      CH1  1  0.0025713019  1.6756404e-06
+   ODmso      CH2  1  0.003275122  2.3119156e-06
+   ODmso      CH3  1  0.0039446326  3.0106048e-06
+   ODmso      CH4  1  0.0054704496  5.0815333e-06
+   ODmso      CR1  1  0.0035429262  2.501758e-06
+   ODmso       HC  1  0.0004383984  1.0662378e-07
+   ODmso        H  1           0           0
+   ODmso      DUM  1           0           0
+   ODmso        S  1  0.0047613878  3.1345658e-06
+   ODmso     CU1+  1  0.0009744834  6.2058507e-08
+   ODmso     CU2+  1  0.0009744834  6.2058507e-08
+   ODmso       FE  1           0           0
+   ODmso     ZN2+  1  0.0009744834  8.4224118e-08
+   ODmso     MG2+  1  0.00038502816  5.0607287e-08
+   ODmso     CA2+  1  0.0015105684  6.117431e-07
+   ODmso        P  1  0.0057849528  4.0837775e-06
+   ODmso       AR  1  0.0037716558  2.7202067e-06
+   ODmso        F  1  0.0016354166  7.5607529e-07
+   ODmso       CL  1  0.0044611802  3.3902895e-06
+   ODmso       BR  1  0.0016363697  7.0146311e-06
+   ODmso     CMet  1  0.0044892949  3.9585162e-06
+   ODmso     OMet  1  0.0022663291  9.752175e-07
+   ODmso      NA+  1  0.00040451783  1.256947e-07
+   ODmso      CL-  1  0.00559911  8.9633324e-06
+   ODmso     CChl  1  0.0024441664  1.7475898e-06
+   ODmso    CLChl  1  0.0043430509  3.2161373e-06
+   ODmso     HChl  1  0.00029258328  5.6843478e-08
+   ODmso    SDmso  1  0.0052442       4.6094E-6
+   ODmso    CDmso  1  0.0049187       4.7597E-6
+   ODmso    ODmso  1  0.0022707131  7.5144626e-07
+    CCl4        O  1  0.0024394475  2.3738805e-06
+    CCl4       OM  1  0.0024394475  2.3738805e-06
+    CCl4       OA  1  0.0024394475  3.1014e-06
+    CCl4       OW  1  0.0026240987  4.2564992e-06
+    CCl4        N  1  0.0025317731  3.5865968e-06
+    CCl4       NT  1  0.0025317731  3.5865968e-06
+    CCl4       NL  1  0.0025317731  3.5865968e-06
+    CCl4       NR  1  0.0025317731  3.5865968e-06
+    CCl4       NZ  1  0.0025317731  3.5865968e-06
+    CCl4       NE  1  0.0025317731  3.5865968e-06
+    CCl4        C  1  0.002481507  5.0642416e-06
+    CCl4      CH1  1  0.0027677163  5.3288944e-06
+    CCl4      CH2  1  0.0035252992  7.3523856e-06
+    CCl4      CH3  1  0.0042459518  9.5743664e-06
+    CCl4      CH4  1  0.0058883216  1.6160362e-05
+    CCl4      CR1  1  0.0038135602  7.9561248e-06
+    CCl4       HC  1  0.0004718864  3.390864e-07
+    CCl4        H  1           0           0
+    CCl4      DUM  1           0           0
+    CCl4        S  1  0.0051250966  9.9685888e-06
+    CCl4     CU1+  1  0.0010489214  1.9735931e-07
+    CCl4     CU2+  1  0.0010489214  1.9735931e-07
+    CCl4       FE  1           0           0
+    CCl4     ZN2+  1  0.0010489214  2.6785069e-07
+    CCl4     MG2+  1  0.00041443936  1.6094198e-07
+    CCl4     CA2+  1  0.0016259564  1.9454738e-06
+    CCl4        P  1  0.0062268488  1.2987285e-05
+    CCl4       AR  1  0.0040597618  8.6508384e-06
+    CCl4        F  1  0.0017603414  2.404481e-06
+    CCl4       CL  1  0.004801957  1.0781845e-05
+    CCl4       BR  1  0.0017613673  2.2308026e-05
+    CCl4     CMet  1  0.0048322193  1.2588927e-05
+    CCl4     OMet  1  0.0024394475  3.1014e-06
+    CCl4      NA+  1  0.00043541779  3.99736e-07
+    CCl4      CL-  1  0.00602681  2.8505312e-05
+    CCl4     CChl  1  0.0026308693  5.5577088e-06
+    CCl4    CLChl  1  0.0046748042  1.0228004e-05
+    CCl4     HChl  1  0.00031493288  1.807744e-07
+    CCl4    SDmso  1  0.0052712788  1.2782179e-05
+    CCl4    CDmso  1  0.0048798696  1.2859094e-05
+    CCl4    ODmso  1  0.0024441664  2.3897596e-06
+    CCl4     CCl4  1  0.0026308693  7.5999462e-06
+   CLCl4        O  1  0.0041472796  3.0768825e-06
+   CLCl4       OM  1  0.0041472796  3.0768825e-06
+   CLCl4       OA  1  0.0041472796  4.01985e-06
+   CLCl4       OW  1  0.0044612032  5.5170208e-06
+   CLCl4        N  1  0.0043042414  4.6487332e-06
+   CLCl4       NT  1  0.0043042414  4.6487332e-06
+   CLCl4       NL  1  0.0043042414  4.6487332e-06
+   CLCl4       NR  1  0.0043042414  4.6487332e-06
+   CLCl4       NZ  1  0.0043042414  4.6487332e-06
+   CLCl4       NE  1  0.0043042414  4.6487332e-06
+   CLCl4        C  1  0.0042187844  6.5639684e-06
+   CLCl4      CH1  1  0.004705366  6.9069956e-06
+   CLCl4      CH2  1  0.0059933247  9.5297244e-06
+   CLCl4      CH3  1  0.0072184988  1.2409724e-05
+   CLCl4      CH4  1  0.010010675  2.0946098e-05
+   CLCl4      CR1  1  0.0064833944  1.0312255e-05
+   CLCl4       HC  1  0.0008022492  4.395036e-07
+   CLCl4        H  1           0           0
+   CLCl4      DUM  1           0           0
+   CLCl4        S  1  0.0087131239  1.2920691e-05
+   CLCl4     CU1+  1  0.0017832604  2.5580539e-07
+   CLCl4     CU2+  1  0.0017832604  2.5580539e-07
+   CLCl4       FE  1           0           0
+   CLCl4     ZN2+  1  0.0017832604  3.4717211e-07
+   CLCl4     MG2+  1  0.00070458408  2.0860342e-07
+   CLCl4     CA2+  1  0.0027642717  2.5216072e-06
+   CLCl4        P  1  0.010586201  1.6833345e-05
+   CLCl4       AR  1  0.0069019592  1.1212702e-05
+   CLCl4        F  1  0.0029927383  3.116545e-06
+   CLCl4       CL  1  0.0081637576  1.3974785e-05
+   CLCl4       BR  1  0.0029944823  2.8914334e-05
+   CLCl4     CMet  1  0.0082152062  1.6317018e-05
+   CLCl4     OMet  1  0.0041472796  4.01985e-06
+   CLCl4      NA+  1  0.00074024929  5.18114e-07
+   CLCl4      CL-  1  0.010246117  3.6946888e-05
+   CLCl4     CChl  1  0.0044727137  7.2035712e-06
+   CLCl4    CLChl  1  0.0079475863  1.3256929e-05
+   CLCl4     HChl  1  0.00053541414  2.3430902e-07
+   CLCl4    SDmso  1  0.0089616468  1.6567499e-05
+   CLCl4    CDmso  1  0.0082962159  1.6667191e-05
+   CLCl4    ODmso  1  0.0041553021  3.0974642e-06
+   CLCl4     CCl4  1  0.0044727137  9.8505978e-06
+   CLCl4    CLCl4  1  0.0076040144  1.2767758e-05
       SI        O  1           0           0
       SI       OM  1           0           0
       SI       OA  1           0           0
@@ -1978,16 +1978,16 @@ CLCL4   17      0.000      0.000     A  0.0076040144  1.2767758e-05
       SI        F  1           0           0
       SI       CL  1           0           0
       SI       BR  1           0           0
-      SI     CMET  1           0           0
-      SI     OMET  1           0           0
+      SI     CMet  1           0           0
+      SI     OMet  1           0           0
       SI      NA+  1           0           0
       SI      CL-  1           0           0
-      SI     CCHL  1           0           0
-      SI    CLCHL  1           0           0
-      SI     HCHL  1           0           0
-      SI    SDMSO  1           0           0
-      SI    CDMSO  1           0           0
-      SI    ODMSO  1           0           0
-      SI     CCL4  1           0           0
-      SI    CLCL4  1           0           0
+      SI     CChl  1           0           0
+      SI    CLChl  1           0           0
+      SI     HChl  1           0           0
+      SI    SDmso  1           0           0
+      SI    CDmso  1           0           0
+      SI    ODmso  1           0           0
+      SI     CCl4  1           0           0
+      SI    CLCl4  1           0           0
       SI       SI  1           0           0
diff --git a/share/top/gromos43a1.ff/watermodels.dat b/share/top/gromos43a1.ff/watermodels.dat
new file mode 100644 (file)
index 0000000..a68dbed
--- /dev/null
@@ -0,0 +1,2 @@
+spc    SPC    simple point charge, recommended
+spce   SPC/E  extended simple point charge
index 28f33e561316a698778799810282fc588291f3c9..c310a45f5d44a1e2fe2a9d772e279612bfcd5d53 100644 (file)
@@ -9,7 +9,8 @@ aminoacids.c.tdb        atomtypes.atp           ions.itp        \
 aminoacids.hdb         ffbonded.itp            spc.itp         \
 aminoacids.n.tdb       ffnonbonded.itp         spce.itp        \
 aminoacids.rtp         forcefield.doc          tip3p.itp       \
-aminoacids.vsd         forcefield.itp          tip4p.itp
+aminoacids.vsd         forcefield.itp          tip4p.itp       \
+aminoacids.r2b         watermodels.dat
 
 EXTRA_DIST = ${topol_DATA}
 
diff --git a/share/top/gromos43a2.ff/aminoacids.r2b b/share/top/gromos43a2.ff/aminoacids.r2b
new file mode 100644 (file)
index 0000000..823db90
--- /dev/null
@@ -0,0 +1,7 @@
+; rtp residue to rtp building block table
+;GMX   Force-field
+CYS    CYSH
+HISD   HISA
+HISE   HISB
+LYS    LYSH
+LYSN   LYS
index 0a16e92db94684260e9cb290bd38c35289ee6f8f..fe2c5d6006ed5cfb883687b405115ffa6d55e402 100644 (file)
@@ -20,6 +20,7 @@
      C     O   gb_4
      C    +N   gb_9
  [ angles ]
+   CA     C     O    ga_30
    CA     C    +N    ga_18
     O     C    +N    ga_32
  [ impropers ]
@@ -9216,11 +9217,10 @@ AO3PB   APG AO3PG AH3PG     gd_9
    OW  OWT4    0.0     0
   HW1     H    0.52     0
   HW2     H    0.52     0
-  HW3    IW   -1.04     0
+   MW    IW   -1.04     0
  [ bonds ]
    OW   HW1    gb_35
    OW   HW2    gb_35
-   OW   HW3    gb_35
  [ angles ]
 ;   ai    aj    ak  gromos type
  [ impropers ]
@@ -9246,11 +9246,11 @@ AO3PB   APG AO3PG AH3PG     gd_9
 
 [ CHCL3 ]
  [ atoms ]
- CChl  CCHL     0.17900     0
- HChl  HCHL     0.08200     0
-CLCh1 CLCHL    -0.08700     0
-CLCh2 CLCHL    -0.08700     0
-CLCh3 CLCHL    -0.08700     0
+ CChl  CChl     0.17900     0
+ HChl  HChl     0.08200     0
+CLCh1 CLChl    -0.08700     0
+CLCh2 CLChl    -0.08700     0
+CLCh3 CLChl    -0.08700     0
  [ bonds ]
  CChl CLCh1    gb_37   
  CChl CLCh2    gb_37   
@@ -9270,10 +9270,10 @@ CLCh2 CLCh3    gb_43
 
 [ DMSO ]
  [ atoms ]
-SDmso SDMSO     0.13900     0
-ODmso ODMSO    -0.45900     0
-CDms1 CDMSO     0.16000     0
-CDms2 CDMSO     0.16000     0
+SDmso SDmso     0.13900     0
+ODmso ODmso    -0.45900     0
+CDms1 CDmso     0.16000     0
+CDms2 CDmso     0.16000     0
  [ bonds ]
 SDmso ODmso    gb_38   
 SDmso CDms1    gb_39   
@@ -9290,9 +9290,9 @@ CDms1 CDms2    gb_45
 
 [ CH3OH ]
  [ atoms ]
- Omet  OMET    -0.57400     0
+ Omet  OMet    -0.57400     0
  HMet     H     0.39800     0
- CMet  CMET     0.17600     0
+ CMet  CMet     0.17600     0
  [ bonds ]
  Omet  HMet    gb_1    
  Omet  CMet    gb_17   
@@ -9306,11 +9306,11 @@ CDms1 CDms2    gb_45
 
 [ CCL4 ]
  [ atoms ]
- CCl4  CCL4     0.00000     0
-CLCl1 CLCL4     0.00000     0
-CLCl2 CLCL4     0.00000     0
-CLCl3 CLCL4     0.00000     0
-CLCl4 CLCL4     0.00000     0
+ CCl4  CCl4     0.00000     0
+CLCl1 CLCl4     0.00000     0
+CLCl2 CLCl4     0.00000     0
+CLCl3 CLCl4     0.00000     0
+CLCl4 CLCl4     0.00000     0
  [ bonds ]
  CCl4 CLCl1    gb_40   
  CCl4 CLCl2    gb_40   
index 3fa34e288501fda3bf79434a9e8872b5456cbc01..127d88473edf4d88c3e7d8a9a55bbaaabd088989 100644 (file)
     F  18.99840 ;     fluor (non-ionic)
    CL  35.45300 ;     chlorine (non-ionic)
    BR  79.90400 ;     bromine (non-ionic)
- CMET  15.035   ;     CH3-group in methanol (solvent)
- OMET  15.9994  ;     oxygen in methanol (solvent)
+ CMet  15.035   ;     CH3-group in methanol (solvent)
+ OMet  15.9994  ;     oxygen in methanol (solvent)
   NA+  22.9898  ;     sodium (charge 1+)
   CL-  35.45300 ;     chlorine (charge 1-)
- CCHL  12.011   ;     carbon in chloroform (solvent)
-CLCHL  35.453   ;     chloride in chloroform (solvent)
- HCHL  1.008    ;     hydrogen in chloroform (solvent)
-SDMSO  32.06000 ;     DMSO Sulphur (solvent)
-CDMSO  15.03500 ;     DMSO Carbon (solvent)
-ODMSO  15.99940 ;     DMSO Oxygen (solvent)
- CCL4  12.011   ;     carbon in carbontetrachloride (solvent)
-CLCL4  35.453   ;     chloride in carbontetrachloride (solvent)
+ CChl  12.011   ;     carbon in chloroform (solvent)
+CLChl  35.453   ;     chloride in chloroform (solvent)
+ HChl  1.008    ;     hydrogen in chloroform (solvent)
+SDmso  32.06000 ;     DMSO Sulphur (solvent)
+CDmso  15.03500 ;     DMSO Carbon (solvent)
+ODmso  15.99940 ;     DMSO Oxygen (solvent)
+ CCl4  12.011   ;     carbon in carbontetrachloride (solvent)
+CLCl4  35.453   ;     chloride in carbontetrachloride (solvent)
    SI  28.08   ;     silicon
  MNH3   0       ;     Dummy mass in rigid tetraedrical NH3 group
    MW   0       ;     Dummy mass in rigid tyrosine rings
index 02ce60a5130d4a9659dea349c74803bccfef2416..1eaed13fe8e44aef8ca953d17813b80944e99aef 100644 (file)
     F      9  0.000      0.000     A  0.0011778624  7.6073284e-07
    CL     17  0.000      0.000     A  0.0087647044  1.5295921e-05
    BR     35  0.000      0.000     A  0.0011792356  6.5480464e-05
- CMET      6  0.000      0.000     A  0.0088755241  2.0852922e-05
- OMET      8  0.000      0.000     A  0.0022619536  1.505529e-06
+ CMet      6  0.000      0.000     A  0.0088755241  2.0852922e-05
+ OMet      8  0.000      0.000     A  0.0022619536  1.505529e-06
   NA+     11  0.000      0.000     A  7.2063121e-05  2.1025e-08
   CL-     17  0.000      0.000     A  0.01380625  0.0001069156
- CCHL      6  0.000      0.000     A  0.0026308693  4.064256e-06
-CLCHL     17  0.000      0.000     A  0.0083066819  1.3764842e-05
- HCHL      1  0.000      0.000     A  3.76996e-05  4.2999495e-09
-SDMSO     16  0.000      0.000     A  0.010561673  2.149806e-05
-CDMSO      6  0.000      0.000     A  0.0090514293  2.175756e-05
-ODMSO      8  0.000      0.000     A  0.0022707131  7.5144626e-07
- CCL4      6  0.000      0.000     A  0.0026308693  7.5999462e-06
-CLCL4     17  0.000      0.000     A  0.0076040144  1.2767758e-05
+ CChl      6  0.000      0.000     A  0.0026308693  4.064256e-06
+CLChl     17  0.000      0.000     A  0.0083066819  1.3764842e-05
+ HChl      1  0.000      0.000     A  3.76996e-05  4.2999495e-09
+SDmso     16  0.000      0.000     A  0.010561673  2.149806e-05
+CDmso      6  0.000      0.000     A  0.0090514293  2.175756e-05
+ODmso      8  0.000      0.000     A  0.0022707131  7.5144626e-07
+ CCl4      6  0.000      0.000     A  0.0026308693  7.5999462e-06
+CLCl4     17  0.000      0.000     A  0.0076040144  1.2767758e-05
    SI     14  0.000      0.000     A  0.01473796  2.2193521e-05
  MNH3      0  0.000      0.000     A   0.0           0.0
  OWT3      8 15.9994     0.000     A   0.24889E-02   0.24352E-05
@@ -519,69 +519,69 @@ CLCL4     17  0.000      0.000     A  0.0076040144  1.2767758e-05
       BR       AR  1  0.002718011  2.5392696e-05
       BR        F  1  0.0011785488  7.0578424e-06
       BR       CL  1  0.0032149108  3.1647812e-05
-    CMET        O  1  0.0044806276  3.9322131e-06
-    CMET       OM  1  0.0044806276  3.9322131e-06
-    CMET       OA  1  0.0044806276  5.1373125e-06
-    CMET       OW  1  0.0048197836  7.050676e-06
-    CMET        N  1  0.0046502056  5.9410165e-06
-    CMET       NT  1  0.0046502056  5.9410165e-06
-    CMET       NL  1  0.0046502056  5.9410165e-06
-    CMET       NR  1  0.0046502056  5.9410165e-06
-    CMET       NZ  1  0.0046502056  5.9410165e-06
-    CMET       NE  1  0.0046502056  5.9410165e-06
-    CMET        C  1  0.0045578798  8.3886605e-06
-    CMET      CH1  1  0.0057920308  1.5402804e-05
-    CMET      CH2  1  0.0079409609  2.318412e-05
-    CMET      CH3  1  0.0093814318  2.6458301e-05
-    CMET      CH4  1  0.010815308  2.6768823e-05
-    CMET      CR1  1  0.0069950925  1.7754552e-05
-    CMET       HC  1  0.000866732  5.616795e-07
-    CMET        H  1           0           0
-    CMET      DUM  1           0           0
-    CMET        S  1  0.0094134632  1.6512464e-05
-    CMET     CU1+  1  0.0019265945  3.2691574e-07
-    CMET     CU2+  1  0.0019265945  3.2691574e-07
-    CMET       FE  1           0           0
-    CMET     ZN2+  1  0.0019265945  4.4368114e-07
-    CMET     MG2+  1  0.0007612168  2.6659227e-07
-    CMET     CA2+  1  0.002986457  3.222579e-06
-    CMET        P  1  0.011437094  2.1512782e-05
-    CMET       AR  1  0.0074567215  1.4329677e-05
-    CMET        F  1  0.0032332872  3.9829013e-06
-    CMET       CL  1  0.0088199402  1.7859582e-05
-    CMET       BR  1  0.0032351714  3.6952118e-05
-    OMET        O  1  0.0022619536  1.380375e-06
-    OMET       OM  1  0.0022619536  2.258907e-06
-    OMET       OA  1  0.0022619536  1.505529e-06
-    OMET       OW  1  0.0024331696  1.991421e-06
-    OMET        N  1  0.0023475616  2.384061e-06
-    OMET       NT  1  0.0023475616  2.76075e-06
-    OMET       NL  1  0.0023475616  3.764436e-06
-    OMET       NR  1  0.0023475616  2.258907e-06
-    OMET       NZ  1  0.0023475616  2.635596e-06
-    OMET       NE  1  0.0023475616  2.434368e-06
-    OMET        C  1  0.0023009528  2.066625e-06
-    OMET      CH1  1  0.0029239888  3.794625e-06
-    OMET      CH2  1  0.0040088324  5.711625e-06
-    OMET      CH3  1  0.0047360248  6.51825e-06
-    OMET      CH4  1  0.005459888  6.59475e-06
-    OMET      CR1  1  0.00353133   4.374e-06
-    OMET       HC  1  0.000437552  1.38375e-07
-    OMET        H  1           0           0
-    OMET      DUM  1           0           0
-    OMET        S  1  0.0047521952   4.068e-06
-    OMET     CU1+  1  0.000972602  2.76075e-07
-    OMET     CU2+  1  0.000972602  5.019657e-07
-    OMET       FE  1           0           0
-    OMET     ZN2+  1  0.000972602  1.1921532e-07
-    OMET     MG2+  1  0.0003842848  7.163226e-08
-    OMET     CA2+  1  0.001507652  8.658939e-07
-    OMET        P  1  0.005773784  5.780397e-06
-    OMET       AR  1  0.003764374  3.53025e-06
-    OMET        F  1  0.0016322592  1.505529e-06
-    OMET       CL  1  0.0044525672  4.798797e-06
-    OMET       BR  1  0.0016332104  9.928884e-06
-    OMET     CMET  1  0.0044806276  5.1373125e-06
+    CMet        O  1  0.0044806276  3.9322131e-06
+    CMet       OM  1  0.0044806276  3.9322131e-06
+    CMet       OA  1  0.0044806276  5.1373125e-06
+    CMet       OW  1  0.0048197836  7.050676e-06
+    CMet        N  1  0.0046502056  5.9410165e-06
+    CMet       NT  1  0.0046502056  5.9410165e-06
+    CMet       NL  1  0.0046502056  5.9410165e-06
+    CMet       NR  1  0.0046502056  5.9410165e-06
+    CMet       NZ  1  0.0046502056  5.9410165e-06
+    CMet       NE  1  0.0046502056  5.9410165e-06
+    CMet        C  1  0.0045578798  8.3886605e-06
+    CMet      CH1  1  0.0057920308  1.5402804e-05
+    CMet      CH2  1  0.0079409609  2.318412e-05
+    CMet      CH3  1  0.0093814318  2.6458301e-05
+    CMet      CH4  1  0.010815308  2.6768823e-05
+    CMet      CR1  1  0.0069950925  1.7754552e-05
+    CMet       HC  1  0.000866732  5.616795e-07
+    CMet        H  1           0           0
+    CMet      DUM  1           0           0
+    CMet        S  1  0.0094134632  1.6512464e-05
+    CMet     CU1+  1  0.0019265945  3.2691574e-07
+    CMet     CU2+  1  0.0019265945  3.2691574e-07
+    CMet       FE  1           0           0
+    CMet     ZN2+  1  0.0019265945  4.4368114e-07
+    CMet     MG2+  1  0.0007612168  2.6659227e-07
+    CMet     CA2+  1  0.002986457  3.222579e-06
+    CMet        P  1  0.011437094  2.1512782e-05
+    CMet       AR  1  0.0074567215  1.4329677e-05
+    CMet        F  1  0.0032332872  3.9829013e-06
+    CMet       CL  1  0.0088199402  1.7859582e-05
+    CMet       BR  1  0.0032351714  3.6952118e-05
+    OMet        O  1  0.0022619536  1.380375e-06
+    OMet       OM  1  0.0022619536  2.258907e-06
+    OMet       OA  1  0.0022619536  1.505529e-06
+    OMet       OW  1  0.0024331696  1.991421e-06
+    OMet        N  1  0.0023475616  2.384061e-06
+    OMet       NT  1  0.0023475616  2.76075e-06
+    OMet       NL  1  0.0023475616  3.764436e-06
+    OMet       NR  1  0.0023475616  2.258907e-06
+    OMet       NZ  1  0.0023475616  2.635596e-06
+    OMet       NE  1  0.0023475616  2.434368e-06
+    OMet        C  1  0.0023009528  2.066625e-06
+    OMet      CH1  1  0.0029239888  3.794625e-06
+    OMet      CH2  1  0.0040088324  5.711625e-06
+    OMet      CH3  1  0.0047360248  6.51825e-06
+    OMet      CH4  1  0.005459888  6.59475e-06
+    OMet      CR1  1  0.00353133   4.374e-06
+    OMet       HC  1  0.000437552  1.38375e-07
+    OMet        H  1           0           0
+    OMet      DUM  1           0           0
+    OMet        S  1  0.0047521952   4.068e-06
+    OMet     CU1+  1  0.000972602  2.76075e-07
+    OMet     CU2+  1  0.000972602  5.019657e-07
+    OMet       FE  1           0           0
+    OMet     ZN2+  1  0.000972602  1.1921532e-07
+    OMet     MG2+  1  0.0003842848  7.163226e-08
+    OMet     CA2+  1  0.001507652  8.658939e-07
+    OMet        P  1  0.005773784  5.780397e-06
+    OMet       AR  1  0.003764374  3.53025e-06
+    OMet        F  1  0.0016322592  1.505529e-06
+    OMet       CL  1  0.0044525672  4.798797e-06
+    OMet       BR  1  0.0016332104  9.928884e-06
+    OMet     CMet  1  0.0044806276  5.1373125e-06
      NA+        O  1  0.00040373684  1.63125e-07
      NA+       OM  1  0.00040373684  4.4486e-07
      NA+       OA  1  0.00040373684  1.77915e-07
@@ -613,8 +613,8 @@ CLCL4     17  0.000      0.000     A  0.0076040144  1.2767758e-05
      NA+        F  1  0.00029134248  1.77915e-07
      NA+       CL  1  0.00079474018  5.67095e-07
      NA+       BR  1  0.00029151226  1.17334e-06
-     NA+     CMET  1  0.00079974869  6.621425e-07
-     NA+     OMET  1  0.00040373684  1.77915e-07
+     NA+     CMet  1  0.00079974869  6.621425e-07
+     NA+     OMet  1  0.00040373684  1.77915e-07
      CL-        O  1   0.0055883  8.903774e-06
      CL-       OM  1   0.0055883  8.903774e-06
      CL-       OA  1   0.0055883  1.268718e-05
@@ -646,317 +646,317 @@ CLCL4     17  0.000      0.000     A  0.0076040144  1.2767758e-05
      CL-        F  1   0.0040326  9.018548e-06
      CL-       CL  1  0.01100035  4.043974e-05
      CL-       BR  1  0.00403495  8.367128e-05
-     CL-     CMET  1  0.011069675  4.721761e-05
-     CL-     OMET  1   0.0055883  1.268718e-05
+     CL-     CMet  1  0.011069675  4.721761e-05
+     CL-     OMet  1   0.0055883  1.268718e-05
      CL-      NA+  1  0.0009974575  1.4993e-06
-    CCHL        O  1  0.0024394475  1.7359776e-06
-    CCHL       OM  1  0.0024394475  1.7359776e-06
-    CCHL       OA  1  0.0024394475   2.268e-06
-    CCHL       OW  1  0.0026240987  3.112704e-06
-    CCHL        N  1  0.0025317731  2.622816e-06
-    CCHL       NT  1  0.0025317731  2.622816e-06
-    CCHL       NL  1  0.0025317731  2.622816e-06
-    CCHL       NR  1  0.0025317731  2.622816e-06
-    CCHL       NZ  1  0.0025317731  2.622816e-06
-    CCHL       NE  1  0.0025317731  2.622816e-06
-    CCHL        C  1  0.002481507  3.703392e-06
-    CCHL      CH1  1  0.0031534322  6.799968e-06
-    CCHL      CH2  1  0.0043234027  1.0235232e-05
-    CCHL      CH3  1  0.0051076574  1.1680704e-05
-    CCHL      CH4  1  0.0058883216  1.1817792e-05
-    CCHL      CR1  1  0.003808431  7.838208e-06
-    CCHL       HC  1  0.0004718864  2.47968e-07
-    CCHL        H  1           0           0
-    CCHL      DUM  1           0           0
-    CCHL        S  1  0.0051250966  7.289856e-06
-    CCHL     CU1+  1  0.0010489214  1.4432544e-07
-    CCHL     CU2+  1  0.0010489214  1.4432544e-07
-    CCHL       FE  1           0           0
-    CCHL     ZN2+  1  0.0010489214  1.9587456e-07
-    CCHL     MG2+  1  0.00041443936  1.1769408e-07
-    CCHL     CA2+  1  0.0016259564  1.4226912e-06
-    CCHL        P  1  0.0062268488  9.497376e-06
-    CCHL       AR  1  0.0040597618  6.326208e-06
-    CCHL        F  1  0.0017603414  1.7583552e-06
-    CCHL       CL  1  0.004801957  7.884576e-06
-    CCHL       BR  1  0.0017613673  1.6313472e-05
-    CCHL     CMET  1  0.0048322193  9.206064e-06
-    CCHL     OMET  1  0.0024394475   2.268e-06
-    CCHL      NA+  1  0.00043541779  2.9232e-07
-    CCHL      CL-  1  0.00602681  2.084544e-05
-   CLCHL        O  1  0.004334666  3.1947671e-06
-   CLCHL       OM  1  0.004334666  3.1947671e-06
-   CLCHL       OA  1  0.004334666  4.1738625e-06
-   CLCHL       OW  1  0.0046627736  5.7283944e-06
-   CLCHL        N  1  0.0044987198  4.8268401e-06
-   CLCHL       NT  1  0.0044987198  4.8268401e-06
-   CLCHL       NL  1  0.0044987198  4.8268401e-06
-   CLCHL       NR  1  0.0044987198  4.8268401e-06
-   CLCHL       NZ  1  0.0044987198  4.8268401e-06
-   CLCHL       NE  1  0.0044987198  4.8268401e-06
-   CLCHL        C  1  0.0044094016  6.8154537e-06
-   CLCHL      CH1  1  0.0056033487  1.2514167e-05
-   CLCHL      CH2  1  0.0076822749  1.8836178e-05
-   CLCHL      CH3  1  0.0090758208  2.1496319e-05
-   CLCHL      CH4  1  0.010462987  2.1748606e-05
-   CLCHL      CR1  1  0.0067672192  1.4424869e-05
-   CLCHL       HC  1  0.0008384972  4.563423e-07
-   CLCHL        H  1           0           0
-   CLCHL      DUM  1           0           0
-   CLCHL        S  1  0.0091068087  1.3415722e-05
-   CLCHL     CU1+  1  0.0018638335  2.6560606e-07
-   CLCHL     CU2+  1  0.0018638335  2.6560606e-07
-   CLCHL       FE  1           0           0
-   CLCHL     ZN2+  1  0.0018638335  3.6047332e-07
-   CLCHL     MG2+  1  0.00073641928  2.1659564e-07
-   CLCHL     CA2+  1  0.0028891697  2.6182176e-06
-   CLCHL        P  1  0.011064517  1.7478281e-05
-   CLCHL       AR  1  0.0072138101  1.1642294e-05
-   CLCHL        F  1  0.0031279591  3.2359492e-06
-   CLCHL       CL  1  0.0085326204  1.4510201e-05
-   CLCHL       BR  1  0.0031297819  3.0022129e-05
-   CLCHL     CMET  1  0.0085863936  1.6942172e-05
-   CLCHL     OMET  1  0.004334666  4.1738625e-06
-   CLCHL      NA+  1  0.00077369595  5.379645e-07
-   CLCHL      CL-  1  0.010709067  3.8362434e-05
-   CLCHL     CCHL  1  0.0046754       7.4813E-6
-    HCHL        O  1  0.0002920184  5.6465771e-08
-    HCHL       OM  1  0.0002920184  5.6465771e-08
-    HCHL       OA  1  0.0002920184  7.377075e-08
-    HCHL       OW  1  0.0003141224  1.0124626e-07
-    HCHL        N  1  0.0003030704  8.5311774e-08
-    HCHL       NT  1  0.0003030704  8.5311774e-08
-    HCHL       NL  1  0.0003030704  8.5311774e-08
-    HCHL       NR  1  0.0003030704  8.5311774e-08
-    HCHL       NZ  1  0.0003030704  8.5311774e-08
-    HCHL       NE  1  0.0003030704  8.5311774e-08
-    HCHL        C  1  0.0002970532  1.2045944e-07
-    HCHL      CH1  1  0.0003774872  2.211811e-07
-    HCHL      CH2  1  0.0005175406  3.329192e-07
-    HCHL      CH3  1  0.0006114212  3.7993576e-07
-    HCHL      CH4  1  0.000704872  3.8439479e-07
-    HCHL      CR1  1  0.000455895  2.5495171e-07
-    HCHL       HC  1  5.6488e-05  8.065602e-09
-    HCHL        H  1           0           0
-    HCHL      DUM  1           0           0
-    HCHL        S  1  0.0006135088  2.3711558e-07
-    HCHL     CU1+  1  0.000125563  4.6944427e-09
-    HCHL     CU2+  1  0.000125563  4.6944427e-09
-    HCHL       FE  1           0           0
-    HCHL     ZN2+  1  0.000125563  6.3711698e-09
-    HCHL     MG2+  1  4.96112e-05  3.8282101e-09
-    HCHL     CA2+  1  0.000194638  4.6275572e-08
-    HCHL        P  1  0.000745396  3.0891911e-07
-    HCHL       AR  1  0.000485981  2.0577121e-07
-    HCHL        F  1  0.0002107248  5.7193643e-08
-    HCHL       CL  1  0.0005748268  2.5645991e-07
-    HCHL       BR  1  0.0002108476  5.3062481e-07
-    HCHL     CMET  1  0.0005784494  2.9944367e-07
-    HCHL     OMET  1  0.0002920184  7.377075e-08
-    HCHL      NA+  1  5.212246e-05  9.50823e-09
-    HCHL      CL-  1  0.00072145  6.7803516e-07
-    HCHL     CCHL  1  0.0003622       0.1745E-6
-    HCHL    CLCHL  1  0.0006493       0.3266E-6
-   SDMSO        O  1  0.0048877412  3.9925763e-06
-   SDMSO       OM  1  0.0048877412  3.9925763e-06
-   SDMSO       OA  1  0.0048877412  5.216175e-06
-   SDMSO       OW  1  0.0052577132  7.1589104e-06
-   SDMSO        N  1  0.0050727272  6.0322166e-06
-   SDMSO       NT  1  0.0050727272  6.0322166e-06
-   SDMSO       NL  1  0.0050727272  6.0322166e-06
-   SDMSO       NR  1  0.0050727272  6.0322166e-06
-   SDMSO       NZ  1  0.0050727272  6.0322166e-06
-   SDMSO       NE  1  0.0050727272  6.0322166e-06
-   SDMSO        C  1  0.0049720126  8.5174342e-06
-   SDMSO      CH1  1  0.0063182996  1.5639252e-05
-   SDMSO      CH2  1  0.0086624833  2.3540018e-05
-   SDMSO      CH3  1  0.010233837  2.686446e-05
-   SDMSO      CH4  1  0.011797996  2.7179749e-05
-   SDMSO      CR1  1  0.0076306725  1.8027101e-05
-   SDMSO       HC  1  0.000945484  5.703018e-07
-   SDMSO        H  1           0           0
-   SDMSO      DUM  1           0           0
-   SDMSO        S  1  0.010268778  1.6765946e-05
-   SDMSO     CU1+  1  0.0021016465  3.3193419e-07
-   SDMSO     CU2+  1  0.0021016465  3.3193419e-07
-   SDMSO       FE  1           0           0
-   SDMSO     ZN2+  1  0.0021016465  4.5049206e-07
-   SDMSO     MG2+  1  0.0008303816  2.7068471e-07
-   SDMSO     CA2+  1  0.003257809  3.2720486e-06
-   SDMSO        P  1  0.012476278  2.1843023e-05
-   SDMSO       AR  1  0.0081342455  1.4549651e-05
-   SDMSO        F  1  0.0035270664  4.0440425e-06
-   SDMSO       CL  1  0.0096213274  1.8133743e-05
-   SDMSO       BR  1  0.0035291218  3.7519367e-05
-   SDMSO     CMET  1  0.0096819617  2.1173034e-05
-   SDMSO     OMET  1  0.0048877412  5.216175e-06
-   SDMSO      NA+  1  0.00087241453  6.72307e-07
-   SDMSO      CL-  1  0.012075475  4.7942444e-05
-   SDMSO     CCHL  1  0.0052712788  9.3473856e-06
-   SDMSO    CLCHL  1  0.0093665606  1.720225e-05
-   SDMSO     HCHL  1  0.0006310078  3.0404041e-07
-   CDMSO        O  1  0.0045248108  4.016601e-06
-   CDMSO       OM  1  0.0045248108  4.016601e-06
-   CDMSO       OA  1  0.0045248108  5.2475625e-06
-   CDMSO       OW  1  0.0048673112  7.201988e-06
-   CDMSO        N  1  0.004696061  6.0685145e-06
-   CDMSO       NT  1  0.004696061  6.0685145e-06
-   CDMSO       NL  1  0.004696061  6.0685145e-06
-   CDMSO       NR  1  0.004696061  6.0685145e-06
-   CDMSO       NZ  1  0.004696061  6.0685145e-06
-   CDMSO       NE  1  0.004696061  6.0685145e-06
-   CDMSO        C  1  0.0046028248  8.5686865e-06
-   CDMSO      CH1  1  0.0058491457  1.5733359e-05
-   CDMSO      CH2  1  0.0080192663  2.3681667e-05
-   CDMSO      CH3  1  0.0094739416  2.7026113e-05
-   CDMSO      CH4  1  0.010921957  2.7343299e-05
-   CDMSO      CR1  1  0.0070640708  1.8135576e-05
-   CDMSO       HC  1  0.0008752788  5.737335e-07
-   CDMSO        H  1           0           0
-   CDMSO      DUM  1           0           0
-   CDMSO        S  1  0.0095062889  1.6866832e-05
-   CDMSO     CU1+  1  0.0019455925  3.3393156e-07
-   CDMSO     CU2+  1  0.0019455925  3.3393156e-07
-   CDMSO       FE  1           0           0
-   CDMSO     ZN2+  1  0.0019455925  4.5320282e-07
-   CDMSO     MG2+  1  0.00076872312  2.7231351e-07
-   CDMSO     CA2+  1  0.0030159063  3.2917377e-06
-   CDMSO        P  1  0.011549875  2.197446e-05
-   CDMSO       AR  1  0.0075302519  1.4637201e-05
-   CDMSO        F  1  0.0032651705  4.0683769e-06
-   CDMSO       CL  1  0.0089069132  1.824286e-05
-   CDMSO       BR  1  0.0032670733  3.7745134e-05
-   CDMSO     CMET  1  0.0089630452  2.1300439e-05
-   CDMSO     OMET  1  0.0045248108  5.2475625e-06
-   CDMSO      NA+  1  0.00080763497  6.763525e-07
-   CDMSO      CL-  1  0.011178832  4.823093e-05
-   CDMSO     CCHL  1  0.0048798696  9.403632e-06
-   CDMSO    CLCHL  1  0.0086710636  1.7305761e-05
-   CDMSO     HCHL  1  0.00058415346  3.0586992e-07
-   CDMSO    SDMSO  1  0.0097827      21.6523E-6
-   ODMSO        O  1  0.0022663291  7.4645315e-07
-   ODMSO       OM  1  0.0022663291  7.4645315e-07
-   ODMSO       OA  1  0.0022663291  1.380375e-06
-   ODMSO       OW  1  0.0024378763  1.825875e-06
-   ODMSO        N  1  0.0023521027  2.185875e-06
-   ODMSO       NT  1  0.0023521027  2.53125e-06
-   ODMSO       NL  1  0.0023521027  3.4515e-06
-   ODMSO       NR  1  0.0023521027  2.071125e-06
-   ODMSO       NZ  1  0.0023521027  2.4165e-06
-   ODMSO       NE  1  0.0023521027   2.232e-06
-   ODMSO        C  1  0.0023054038  1.5924218e-06
-   ODMSO      CH1  1  0.002929645  2.9239188e-06
-   ODMSO      CH2  1  0.0040165871  4.4010482e-06
-   ODMSO      CH3  1  0.0047451862  5.0225868e-06
-   ODMSO      CH4  1  0.0054704496  5.0815333e-06
-   ODMSO      CR1  1  0.003538161  3.3703517e-06
-   ODMSO       HC  1  0.0004383984  1.0662378e-07
-   ODMSO        H  1           0           0
-   ODMSO      DUM  1           0           0
-   ODMSO        S  1  0.0047613878  3.1345658e-06
-   ODMSO     CU1+  1  0.0009744834  2.53125e-07
-   ODMSO     CU2+  1  0.0009744834  4.602375e-07
-   ODMSO       FE  1           0           0
-   ODMSO     ZN2+  1  0.0009744834  1.09305e-07
-   ODMSO     MG2+  1  0.00038502816  6.56775e-08
-   ODMSO     CA2+  1  0.0015105684  7.939125e-07
-   ODMSO        P  1  0.0057849528  5.299875e-06
-   ODMSO       AR  1  0.0037716558  2.7202067e-06
-   ODMSO        F  1  0.0016354166  7.5607529e-07
-   ODMSO       CL  1  0.0044611802  3.3902895e-06
-   ODMSO       BR  1  0.0016363697  7.0146311e-06
-   ODMSO     CMET  1  0.0044892949  3.9585162e-06
-   ODMSO     OMET  1  0.0022663291  1.380375e-06
-   ODMSO      NA+  1  0.00040451783  1.63125e-07
-   ODMSO      CL-  1  0.00559911  8.9633324e-06
-   ODMSO     CCHL  1  0.0024441664  1.7475898e-06
-   ODMSO    CLCHL  1  0.0043430509  3.2161373e-06
-   ODMSO     HCHL  1  0.00029258328  5.6843478e-08
-   ODMSO    SDMSO  1  0.0052442       4.6094E-6
-   ODMSO    CDMSO  1  0.0049187       4.7597E-6
-    CCL4        O  1  0.0024394475  2.3738805e-06
-    CCL4       OM  1  0.0024394475  2.3738805e-06
-    CCL4       OA  1  0.0024394475  3.1014e-06
-    CCL4       OW  1  0.0026240987  4.2564992e-06
-    CCL4        N  1  0.0025317731  3.5865968e-06
-    CCL4       NT  1  0.0025317731  3.5865968e-06
-    CCL4       NL  1  0.0025317731  3.5865968e-06
-    CCL4       NR  1  0.0025317731  3.5865968e-06
-    CCL4       NZ  1  0.0025317731  3.5865968e-06
-    CCL4       NE  1  0.0025317731  3.5865968e-06
-    CCL4        C  1  0.002481507  5.0642416e-06
-    CCL4      CH1  1  0.0031534322  9.2986864e-06
-    CCL4      CH2  1  0.0043234027  1.3996274e-05
-    CCL4      CH3  1  0.0051076574  1.5972899e-05
-    CCL4      CH4  1  0.0058883216  1.6160362e-05
-    CCL4      CR1  1  0.003808431  1.0718438e-05
-    CCL4       HC  1  0.0004718864  3.390864e-07
-    CCL4        H  1           0           0
-    CCL4      DUM  1           0           0
-    CCL4        S  1  0.0051250966  9.9685888e-06
-    CCL4     CU1+  1  0.0010489214  1.9735931e-07
-    CCL4     CU2+  1  0.0010489214  1.9735931e-07
-    CCL4       FE  1           0           0
-    CCL4     ZN2+  1  0.0010489214  2.6785069e-07
-    CCL4     MG2+  1  0.00041443936  1.6094198e-07
-    CCL4     CA2+  1  0.0016259564  1.9454738e-06
-    CCL4        P  1  0.0062268488  1.2987285e-05
-    CCL4       AR  1  0.0040597618  8.6508384e-06
-    CCL4        F  1  0.0017603414  2.404481e-06
-    CCL4       CL  1  0.004801957  1.0781845e-05
-    CCL4       BR  1  0.0017613673  2.2308026e-05
-    CCL4     CMET  1  0.0048322193  1.2588927e-05
-    CCL4     OMET  1  0.0024394475  3.1014e-06
-    CCL4      NA+  1  0.00043541779  3.99736e-07
-    CCL4      CL-  1  0.00602681  2.8505312e-05
-    CCL4     CCHL  1  0.0026308693  5.5577088e-06
-    CCL4    CLCHL  1  0.0046748042  1.0228004e-05
-    CCL4     HCHL  1  0.00031493288  1.807744e-07
-    CCL4    SDMSO  1  0.0052712788  1.2782179e-05
-    CCL4    CDMSO  1  0.0048798696  1.2859094e-05
-    CCL4    ODMSO  1  0.0024441664  2.3897596e-06
-   CLCL4        O  1  0.0041472796  3.0768825e-06
-   CLCL4       OM  1  0.0041472796  3.0768825e-06
-   CLCL4       OA  1  0.0041472796  4.01985e-06
-   CLCL4       OW  1  0.0044612032  5.5170208e-06
-   CLCL4        N  1  0.0043042414  4.6487332e-06
-   CLCL4       NT  1  0.0043042414  4.6487332e-06
-   CLCL4       NL  1  0.0043042414  4.6487332e-06
-   CLCL4       NR  1  0.0043042414  4.6487332e-06
-   CLCL4       NZ  1  0.0043042414  4.6487332e-06
-   CLCL4       NE  1  0.0043042414  4.6487332e-06
-   CLCL4        C  1  0.0042187844  6.5639684e-06
-   CLCL4      CH1  1  0.0053611175  1.2052404e-05
-   CLCL4      CH2  1  0.0073501723  1.8141136e-05
-   CLCL4      CH3  1  0.0086834756  2.0703121e-05
-   CLCL4      CH4  1  0.010010675  2.0946098e-05
-   CLCL4      CR1  1  0.0064746742  1.3892602e-05
-   CLCL4       HC  1  0.0008022492  4.395036e-07
-   CLCL4        H  1           0           0
-   CLCL4      DUM  1           0           0
-   CLCL4        S  1  0.0087131239  1.2920691e-05
-   CLCL4     CU1+  1  0.0017832604  2.5580539e-07
-   CLCL4     CU2+  1  0.0017832604  2.5580539e-07
-   CLCL4       FE  1           0           0
-   CLCL4     ZN2+  1  0.0017832604  3.4717211e-07
-   CLCL4     MG2+  1  0.00070458408  2.0860342e-07
-   CLCL4     CA2+  1  0.0027642717  2.5216072e-06
-   CLCL4        P  1  0.010586201  1.6833345e-05
-   CLCL4       AR  1  0.0069019592  1.1212702e-05
-   CLCL4        F  1  0.0029927383  3.116545e-06
-   CLCL4       CL  1  0.0081637576  1.3974785e-05
-   CLCL4       BR  1  0.0029944823  2.8914334e-05
-   CLCL4     CMET  1  0.0082152062  1.6317018e-05
-   CLCL4     OMET  1  0.0041472796  4.01985e-06
-   CLCL4      NA+  1  0.00074024929  5.18114e-07
-   CLCL4      CL-  1  0.010246117  3.6946888e-05
-   CLCL4     CCHL  1  0.0044727137  7.2035712e-06
-   CLCL4    CLCHL  1  0.0079475863  1.3256929e-05
-   CLCL4     HCHL  1  0.00053541414  2.3430902e-07
-   CLCL4    SDMSO  1  0.0089616468  1.6567499e-05
-   CLCL4    CDMSO  1  0.0082962159  1.6667191e-05
-   CLCL4    ODMSO  1  0.0041553021  3.0974642e-06
-   CLCL4     CCL4  1  0.0044727137  9.8505978e-06
+    CChl        O  1  0.0024394475  1.7359776e-06
+    CChl       OM  1  0.0024394475  1.7359776e-06
+    CChl       OA  1  0.0024394475   2.268e-06
+    CChl       OW  1  0.0026240987  3.112704e-06
+    CChl        N  1  0.0025317731  2.622816e-06
+    CChl       NT  1  0.0025317731  2.622816e-06
+    CChl       NL  1  0.0025317731  2.622816e-06
+    CChl       NR  1  0.0025317731  2.622816e-06
+    CChl       NZ  1  0.0025317731  2.622816e-06
+    CChl       NE  1  0.0025317731  2.622816e-06
+    CChl        C  1  0.002481507  3.703392e-06
+    CChl      CH1  1  0.0031534322  6.799968e-06
+    CChl      CH2  1  0.0043234027  1.0235232e-05
+    CChl      CH3  1  0.0051076574  1.1680704e-05
+    CChl      CH4  1  0.0058883216  1.1817792e-05
+    CChl      CR1  1  0.003808431  7.838208e-06
+    CChl       HC  1  0.0004718864  2.47968e-07
+    CChl        H  1           0           0
+    CChl      DUM  1           0           0
+    CChl        S  1  0.0051250966  7.289856e-06
+    CChl     CU1+  1  0.0010489214  1.4432544e-07
+    CChl     CU2+  1  0.0010489214  1.4432544e-07
+    CChl       FE  1           0           0
+    CChl     ZN2+  1  0.0010489214  1.9587456e-07
+    CChl     MG2+  1  0.00041443936  1.1769408e-07
+    CChl     CA2+  1  0.0016259564  1.4226912e-06
+    CChl        P  1  0.0062268488  9.497376e-06
+    CChl       AR  1  0.0040597618  6.326208e-06
+    CChl        F  1  0.0017603414  1.7583552e-06
+    CChl       CL  1  0.004801957  7.884576e-06
+    CChl       BR  1  0.0017613673  1.6313472e-05
+    CChl     CMet  1  0.0048322193  9.206064e-06
+    CChl     OMet  1  0.0024394475   2.268e-06
+    CChl      NA+  1  0.00043541779  2.9232e-07
+    CChl      CL-  1  0.00602681  2.084544e-05
+   CLChl        O  1  0.004334666  3.1947671e-06
+   CLChl       OM  1  0.004334666  3.1947671e-06
+   CLChl       OA  1  0.004334666  4.1738625e-06
+   CLChl       OW  1  0.0046627736  5.7283944e-06
+   CLChl        N  1  0.0044987198  4.8268401e-06
+   CLChl       NT  1  0.0044987198  4.8268401e-06
+   CLChl       NL  1  0.0044987198  4.8268401e-06
+   CLChl       NR  1  0.0044987198  4.8268401e-06
+   CLChl       NZ  1  0.0044987198  4.8268401e-06
+   CLChl       NE  1  0.0044987198  4.8268401e-06
+   CLChl        C  1  0.0044094016  6.8154537e-06
+   CLChl      CH1  1  0.0056033487  1.2514167e-05
+   CLChl      CH2  1  0.0076822749  1.8836178e-05
+   CLChl      CH3  1  0.0090758208  2.1496319e-05
+   CLChl      CH4  1  0.010462987  2.1748606e-05
+   CLChl      CR1  1  0.0067672192  1.4424869e-05
+   CLChl       HC  1  0.0008384972  4.563423e-07
+   CLChl        H  1           0           0
+   CLChl      DUM  1           0           0
+   CLChl        S  1  0.0091068087  1.3415722e-05
+   CLChl     CU1+  1  0.0018638335  2.6560606e-07
+   CLChl     CU2+  1  0.0018638335  2.6560606e-07
+   CLChl       FE  1           0           0
+   CLChl     ZN2+  1  0.0018638335  3.6047332e-07
+   CLChl     MG2+  1  0.00073641928  2.1659564e-07
+   CLChl     CA2+  1  0.0028891697  2.6182176e-06
+   CLChl        P  1  0.011064517  1.7478281e-05
+   CLChl       AR  1  0.0072138101  1.1642294e-05
+   CLChl        F  1  0.0031279591  3.2359492e-06
+   CLChl       CL  1  0.0085326204  1.4510201e-05
+   CLChl       BR  1  0.0031297819  3.0022129e-05
+   CLChl     CMet  1  0.0085863936  1.6942172e-05
+   CLChl     OMet  1  0.004334666  4.1738625e-06
+   CLChl      NA+  1  0.00077369595  5.379645e-07
+   CLChl      CL-  1  0.010709067  3.8362434e-05
+   CLChl     CChl  1  0.0046754       7.4813E-6
+    HChl        O  1  0.0002920184  5.6465771e-08
+    HChl       OM  1  0.0002920184  5.6465771e-08
+    HChl       OA  1  0.0002920184  7.377075e-08
+    HChl       OW  1  0.0003141224  1.0124626e-07
+    HChl        N  1  0.0003030704  8.5311774e-08
+    HChl       NT  1  0.0003030704  8.5311774e-08
+    HChl       NL  1  0.0003030704  8.5311774e-08
+    HChl       NR  1  0.0003030704  8.5311774e-08
+    HChl       NZ  1  0.0003030704  8.5311774e-08
+    HChl       NE  1  0.0003030704  8.5311774e-08
+    HChl        C  1  0.0002970532  1.2045944e-07
+    HChl      CH1  1  0.0003774872  2.211811e-07
+    HChl      CH2  1  0.0005175406  3.329192e-07
+    HChl      CH3  1  0.0006114212  3.7993576e-07
+    HChl      CH4  1  0.000704872  3.8439479e-07
+    HChl      CR1  1  0.000455895  2.5495171e-07
+    HChl       HC  1  5.6488e-05  8.065602e-09
+    HChl        H  1           0           0
+    HChl      DUM  1           0           0
+    HChl        S  1  0.0006135088  2.3711558e-07
+    HChl     CU1+  1  0.000125563  4.6944427e-09
+    HChl     CU2+  1  0.000125563  4.6944427e-09
+    HChl       FE  1           0           0
+    HChl     ZN2+  1  0.000125563  6.3711698e-09
+    HChl     MG2+  1  4.96112e-05  3.8282101e-09
+    HChl     CA2+  1  0.000194638  4.6275572e-08
+    HChl        P  1  0.000745396  3.0891911e-07
+    HChl       AR  1  0.000485981  2.0577121e-07
+    HChl        F  1  0.0002107248  5.7193643e-08
+    HChl       CL  1  0.0005748268  2.5645991e-07
+    HChl       BR  1  0.0002108476  5.3062481e-07
+    HChl     CMet  1  0.0005784494  2.9944367e-07
+    HChl     OMet  1  0.0002920184  7.377075e-08
+    HChl      NA+  1  5.212246e-05  9.50823e-09
+    HChl      CL-  1  0.00072145  6.7803516e-07
+    HChl     CChl  1  0.0003622       0.1745E-6
+    HChl    CLChl  1  0.0006493       0.3266E-6
+   SDmso        O  1  0.0048877412  3.9925763e-06
+   SDmso       OM  1  0.0048877412  3.9925763e-06
+   SDmso       OA  1  0.0048877412  5.216175e-06
+   SDmso       OW  1  0.0052577132  7.1589104e-06
+   SDmso        N  1  0.0050727272  6.0322166e-06
+   SDmso       NT  1  0.0050727272  6.0322166e-06
+   SDmso       NL  1  0.0050727272  6.0322166e-06
+   SDmso       NR  1  0.0050727272  6.0322166e-06
+   SDmso       NZ  1  0.0050727272  6.0322166e-06
+   SDmso       NE  1  0.0050727272  6.0322166e-06
+   SDmso        C  1  0.0049720126  8.5174342e-06
+   SDmso      CH1  1  0.0063182996  1.5639252e-05
+   SDmso      CH2  1  0.0086624833  2.3540018e-05
+   SDmso      CH3  1  0.010233837  2.686446e-05
+   SDmso      CH4  1  0.011797996  2.7179749e-05
+   SDmso      CR1  1  0.0076306725  1.8027101e-05
+   SDmso       HC  1  0.000945484  5.703018e-07
+   SDmso        H  1           0           0
+   SDmso      DUM  1           0           0
+   SDmso        S  1  0.010268778  1.6765946e-05
+   SDmso     CU1+  1  0.0021016465  3.3193419e-07
+   SDmso     CU2+  1  0.0021016465  3.3193419e-07
+   SDmso       FE  1           0           0
+   SDmso     ZN2+  1  0.0021016465  4.5049206e-07
+   SDmso     MG2+  1  0.0008303816  2.7068471e-07
+   SDmso     CA2+  1  0.003257809  3.2720486e-06
+   SDmso        P  1  0.012476278  2.1843023e-05
+   SDmso       AR  1  0.0081342455  1.4549651e-05
+   SDmso        F  1  0.0035270664  4.0440425e-06
+   SDmso       CL  1  0.0096213274  1.8133743e-05
+   SDmso       BR  1  0.0035291218  3.7519367e-05
+   SDmso     CMet  1  0.0096819617  2.1173034e-05
+   SDmso     OMet  1  0.0048877412  5.216175e-06
+   SDmso      NA+  1  0.00087241453  6.72307e-07
+   SDmso      CL-  1  0.012075475  4.7942444e-05
+   SDmso     CChl  1  0.0052712788  9.3473856e-06
+   SDmso    CLChl  1  0.0093665606  1.720225e-05
+   SDmso     HChl  1  0.0006310078  3.0404041e-07
+   CDmso        O  1  0.0045248108  4.016601e-06
+   CDmso       OM  1  0.0045248108  4.016601e-06
+   CDmso       OA  1  0.0045248108  5.2475625e-06
+   CDmso       OW  1  0.0048673112  7.201988e-06
+   CDmso        N  1  0.004696061  6.0685145e-06
+   CDmso       NT  1  0.004696061  6.0685145e-06
+   CDmso       NL  1  0.004696061  6.0685145e-06
+   CDmso       NR  1  0.004696061  6.0685145e-06
+   CDmso       NZ  1  0.004696061  6.0685145e-06
+   CDmso       NE  1  0.004696061  6.0685145e-06
+   CDmso        C  1  0.0046028248  8.5686865e-06
+   CDmso      CH1  1  0.0058491457  1.5733359e-05
+   CDmso      CH2  1  0.0080192663  2.3681667e-05
+   CDmso      CH3  1  0.0094739416  2.7026113e-05
+   CDmso      CH4  1  0.010921957  2.7343299e-05
+   CDmso      CR1  1  0.0070640708  1.8135576e-05
+   CDmso       HC  1  0.0008752788  5.737335e-07
+   CDmso        H  1           0           0
+   CDmso      DUM  1           0           0
+   CDmso        S  1  0.0095062889  1.6866832e-05
+   CDmso     CU1+  1  0.0019455925  3.3393156e-07
+   CDmso     CU2+  1  0.0019455925  3.3393156e-07
+   CDmso       FE  1           0           0
+   CDmso     ZN2+  1  0.0019455925  4.5320282e-07
+   CDmso     MG2+  1  0.00076872312  2.7231351e-07
+   CDmso     CA2+  1  0.0030159063  3.2917377e-06
+   CDmso        P  1  0.011549875  2.197446e-05
+   CDmso       AR  1  0.0075302519  1.4637201e-05
+   CDmso        F  1  0.0032651705  4.0683769e-06
+   CDmso       CL  1  0.0089069132  1.824286e-05
+   CDmso       BR  1  0.0032670733  3.7745134e-05
+   CDmso     CMet  1  0.0089630452  2.1300439e-05
+   CDmso     OMet  1  0.0045248108  5.2475625e-06
+   CDmso      NA+  1  0.00080763497  6.763525e-07
+   CDmso      CL-  1  0.011178832  4.823093e-05
+   CDmso     CChl  1  0.0048798696  9.403632e-06
+   CDmso    CLChl  1  0.0086710636  1.7305761e-05
+   CDmso     HChl  1  0.00058415346  3.0586992e-07
+   CDmso    SDmso  1  0.0097827      21.6523E-6
+   ODmso        O  1  0.0022663291  7.4645315e-07
+   ODmso       OM  1  0.0022663291  7.4645315e-07
+   ODmso       OA  1  0.0022663291  1.380375e-06
+   ODmso       OW  1  0.0024378763  1.825875e-06
+   ODmso        N  1  0.0023521027  2.185875e-06
+   ODmso       NT  1  0.0023521027  2.53125e-06
+   ODmso       NL  1  0.0023521027  3.4515e-06
+   ODmso       NR  1  0.0023521027  2.071125e-06
+   ODmso       NZ  1  0.0023521027  2.4165e-06
+   ODmso       NE  1  0.0023521027   2.232e-06
+   ODmso        C  1  0.0023054038  1.5924218e-06
+   ODmso      CH1  1  0.002929645  2.9239188e-06
+   ODmso      CH2  1  0.0040165871  4.4010482e-06
+   ODmso      CH3  1  0.0047451862  5.0225868e-06
+   ODmso      CH4  1  0.0054704496  5.0815333e-06
+   ODmso      CR1  1  0.003538161  3.3703517e-06
+   ODmso       HC  1  0.0004383984  1.0662378e-07
+   ODmso        H  1           0           0
+   ODmso      DUM  1           0           0
+   ODmso        S  1  0.0047613878  3.1345658e-06
+   ODmso     CU1+  1  0.0009744834  2.53125e-07
+   ODmso     CU2+  1  0.0009744834  4.602375e-07
+   ODmso       FE  1           0           0
+   ODmso     ZN2+  1  0.0009744834  1.09305e-07
+   ODmso     MG2+  1  0.00038502816  6.56775e-08
+   ODmso     CA2+  1  0.0015105684  7.939125e-07
+   ODmso        P  1  0.0057849528  5.299875e-06
+   ODmso       AR  1  0.0037716558  2.7202067e-06
+   ODmso        F  1  0.0016354166  7.5607529e-07
+   ODmso       CL  1  0.0044611802  3.3902895e-06
+   ODmso       BR  1  0.0016363697  7.0146311e-06
+   ODmso     CMet  1  0.0044892949  3.9585162e-06
+   ODmso     OMet  1  0.0022663291  1.380375e-06
+   ODmso      NA+  1  0.00040451783  1.63125e-07
+   ODmso      CL-  1  0.00559911  8.9633324e-06
+   ODmso     CChl  1  0.0024441664  1.7475898e-06
+   ODmso    CLChl  1  0.0043430509  3.2161373e-06
+   ODmso     HChl  1  0.00029258328  5.6843478e-08
+   ODmso    SDmso  1  0.0052442       4.6094E-6
+   ODmso    CDmso  1  0.0049187       4.7597E-6
+    CCl4        O  1  0.0024394475  2.3738805e-06
+    CCl4       OM  1  0.0024394475  2.3738805e-06
+    CCl4       OA  1  0.0024394475  3.1014e-06
+    CCl4       OW  1  0.0026240987  4.2564992e-06
+    CCl4        N  1  0.0025317731  3.5865968e-06
+    CCl4       NT  1  0.0025317731  3.5865968e-06
+    CCl4       NL  1  0.0025317731  3.5865968e-06
+    CCl4       NR  1  0.0025317731  3.5865968e-06
+    CCl4       NZ  1  0.0025317731  3.5865968e-06
+    CCl4       NE  1  0.0025317731  3.5865968e-06
+    CCl4        C  1  0.002481507  5.0642416e-06
+    CCl4      CH1  1  0.0031534322  9.2986864e-06
+    CCl4      CH2  1  0.0043234027  1.3996274e-05
+    CCl4      CH3  1  0.0051076574  1.5972899e-05
+    CCl4      CH4  1  0.0058883216  1.6160362e-05
+    CCl4      CR1  1  0.003808431  1.0718438e-05
+    CCl4       HC  1  0.0004718864  3.390864e-07
+    CCl4        H  1           0           0
+    CCl4      DUM  1           0           0
+    CCl4        S  1  0.0051250966  9.9685888e-06
+    CCl4     CU1+  1  0.0010489214  1.9735931e-07
+    CCl4     CU2+  1  0.0010489214  1.9735931e-07
+    CCl4       FE  1           0           0
+    CCl4     ZN2+  1  0.0010489214  2.6785069e-07
+    CCl4     MG2+  1  0.00041443936  1.6094198e-07
+    CCl4     CA2+  1  0.0016259564  1.9454738e-06
+    CCl4        P  1  0.0062268488  1.2987285e-05
+    CCl4       AR  1  0.0040597618  8.6508384e-06
+    CCl4        F  1  0.0017603414  2.404481e-06
+    CCl4       CL  1  0.004801957  1.0781845e-05
+    CCl4       BR  1  0.0017613673  2.2308026e-05
+    CCl4     CMet  1  0.0048322193  1.2588927e-05
+    CCl4     OMet  1  0.0024394475  3.1014e-06
+    CCl4      NA+  1  0.00043541779  3.99736e-07
+    CCl4      CL-  1  0.00602681  2.8505312e-05
+    CCl4     CChl  1  0.0026308693  5.5577088e-06
+    CCl4    CLChl  1  0.0046748042  1.0228004e-05
+    CCl4     HChl  1  0.00031493288  1.807744e-07
+    CCl4    SDmso  1  0.0052712788  1.2782179e-05
+    CCl4    CDmso  1  0.0048798696  1.2859094e-05
+    CCl4    ODmso  1  0.0024441664  2.3897596e-06
+   CLCl4        O  1  0.0041472796  3.0768825e-06
+   CLCl4       OM  1  0.0041472796  3.0768825e-06
+   CLCl4       OA  1  0.0041472796  4.01985e-06
+   CLCl4       OW  1  0.0044612032  5.5170208e-06
+   CLCl4        N  1  0.0043042414  4.6487332e-06
+   CLCl4       NT  1  0.0043042414  4.6487332e-06
+   CLCl4       NL  1  0.0043042414  4.6487332e-06
+   CLCl4       NR  1  0.0043042414  4.6487332e-06
+   CLCl4       NZ  1  0.0043042414  4.6487332e-06
+   CLCl4       NE  1  0.0043042414  4.6487332e-06
+   CLCl4        C  1  0.0042187844  6.5639684e-06
+   CLCl4      CH1  1  0.0053611175  1.2052404e-05
+   CLCl4      CH2  1  0.0073501723  1.8141136e-05
+   CLCl4      CH3  1  0.0086834756  2.0703121e-05
+   CLCl4      CH4  1  0.010010675  2.0946098e-05
+   CLCl4      CR1  1  0.0064746742  1.3892602e-05
+   CLCl4       HC  1  0.0008022492  4.395036e-07
+   CLCl4        H  1           0           0
+   CLCl4      DUM  1           0           0
+   CLCl4        S  1  0.0087131239  1.2920691e-05
+   CLCl4     CU1+  1  0.0017832604  2.5580539e-07
+   CLCl4     CU2+  1  0.0017832604  2.5580539e-07
+   CLCl4       FE  1           0           0
+   CLCl4     ZN2+  1  0.0017832604  3.4717211e-07
+   CLCl4     MG2+  1  0.00070458408  2.0860342e-07
+   CLCl4     CA2+  1  0.0027642717  2.5216072e-06
+   CLCl4        P  1  0.010586201  1.6833345e-05
+   CLCl4       AR  1  0.0069019592  1.1212702e-05
+   CLCl4        F  1  0.0029927383  3.116545e-06
+   CLCl4       CL  1  0.0081637576  1.3974785e-05
+   CLCl4       BR  1  0.0029944823  2.8914334e-05
+   CLCl4     CMet  1  0.0082152062  1.6317018e-05
+   CLCl4     OMet  1  0.0041472796  4.01985e-06
+   CLCl4      NA+  1  0.00074024929  5.18114e-07
+   CLCl4      CL-  1  0.010246117  3.6946888e-05
+   CLCl4     CChl  1  0.0044727137  7.2035712e-06
+   CLCl4    CLChl  1  0.0079475863  1.3256929e-05
+   CLCl4     HChl  1  0.00053541414  2.3430902e-07
+   CLCl4    SDmso  1  0.0089616468  1.6567499e-05
+   CLCl4    CDmso  1  0.0082962159  1.6667191e-05
+   CLCl4    ODmso  1  0.0041553021  3.0974642e-06
+   CLCl4     CCl4  1  0.0044727137  9.8505978e-06
       SI        O  1  0.005773784  5.299875e-06
       SI       OM  1  0.005773784  1.4453348e-05
       SI       OA  1  0.005773784  5.780397e-06
@@ -988,18 +988,18 @@ CLCL4     17  0.000      0.000     A  0.0076040144  1.2767758e-05
       SI        F  1  0.004166448  5.780397e-06
       SI       CL  1  0.011365468  1.8424721e-05
       SI       BR  1  0.004168876  3.8121412e-05
-      SI     CMET  1  0.011437094  2.1512782e-05
-      SI     OMET  1  0.005773784  5.780397e-06
+      SI     CMet  1  0.011437094  2.1512782e-05
+      SI     OMet  1  0.005773784  5.780397e-06
       SI      NA+  1  0.0010305646  6.83095e-07
       SI      CL-  1   0.0142645  4.871174e-05
-      SI     CCHL  1  0.0062268488  9.497376e-06
-      SI    CLCHL  1  0.011064517  1.7478281e-05
-      SI     HCHL  1  0.000745396  3.0891911e-07
-      SI    SDMSO  1  0.012476278  2.1843023e-05
-      SI    CDMSO  1  0.011549875  2.197446e-05
-      SI    ODMSO  1  0.0057849528  5.299875e-06
-      SI     CCL4  1  0.0062268488  1.2987285e-05
-      SI    CLCL4  1  0.010586201  1.6833345e-05
+      SI     CChl  1  0.0062268488  9.497376e-06
+      SI    CLChl  1  0.011064517  1.7478281e-05
+      SI     HChl  1  0.000745396  3.0891911e-07
+      SI    SDmso  1  0.012476278  2.1843023e-05
+      SI    CDmso  1  0.011549875  2.197446e-05
+      SI    ODmso  1  0.0057849528  5.299875e-06
+      SI     CCl4  1  0.0062268488  1.2987285e-05
+      SI    CLCl4  1  0.010586201  1.6833345e-05
 
 [ pairtypes ]
 ; i    j func          c6           c12
@@ -1499,71 +1499,71 @@ CLCL4     17  0.000      0.000     A  0.0076040144  1.2767758e-05
       BR        F  1  0.0011785488  7.0578424e-06
       BR       CL  1  0.0032149108  3.1647812e-05
       BR       BR  1  0.0011792356  6.5480464e-05
-    CMET        O  1  0.0044806276  3.9322131e-06
-    CMET       OM  1  0.0044806276  3.9322131e-06
-    CMET       OA  1  0.0044806276  5.1373125e-06
-    CMET       OW  1  0.0048197836  7.050676e-06
-    CMET        N  1  0.0046502056  5.9410165e-06
-    CMET       NT  1  0.0046502056  5.9410165e-06
-    CMET       NL  1  0.0046502056  5.9410165e-06
-    CMET       NR  1  0.0046502056  5.9410165e-06
-    CMET       NZ  1  0.0046502056  5.9410165e-06
-    CMET       NE  1  0.0046502056  5.9410165e-06
-    CMET        C  1  0.0045578798  8.3886605e-06
-    CMET      CH1  1  0.0050835716  8.8270445e-06
-    CMET      CH2  1  0.0064750533  9.943994e-06
-    CMET      CH3  1  0.0077987038  1.1214329e-05
-    CMET      CH4  1  0.010815308  2.6768823e-05
-    CMET      CR1  1  0.0070045135  1.3178919e-05
-    CMET       HC  1  0.000866732  5.616795e-07
-    CMET        H  1           0           0
-    CMET      DUM  1           0           0
-    CMET        S  1  0.0094134632  1.6512464e-05
-    CMET     CU1+  1  0.0019265945  3.2691574e-07
-    CMET     CU2+  1  0.0019265945  3.2691574e-07
-    CMET       FE  1           0           0
-    CMET     ZN2+  1  0.0019265945  4.4368114e-07
-    CMET     MG2+  1  0.0007612168  2.6659227e-07
-    CMET     CA2+  1  0.002986457  3.222579e-06
-    CMET        P  1  0.011437094  2.1512782e-05
-    CMET       AR  1  0.0074567215  1.4329677e-05
-    CMET        F  1  0.0032332872  3.9829013e-06
-    CMET       CL  1  0.0088199402  1.7859582e-05
-    CMET       BR  1  0.0032351714  3.6952118e-05
-    CMET     CMET  1  0.0088755241  2.0852922e-05
-    OMET        O  1  0.0022619536  9.687375e-07
-    OMET       OM  1  0.0022619536  9.687375e-07
-    OMET       OA  1  0.0022619536  1.265625e-06
-    OMET       OW  1  0.0024331696   1.737e-06
-    OMET        N  1  0.0023475616  1.463625e-06
-    OMET       NT  1  0.0023475616  1.463625e-06
-    OMET       NL  1  0.0023475616  1.463625e-06
-    OMET       NR  1  0.0023475616  1.463625e-06
-    OMET       NZ  1  0.0023475616  1.463625e-06
-    OMET       NE  1  0.0023475616  1.463625e-06
-    OMET        C  1  0.0023009528  2.066625e-06
-    OMET      CH1  1  0.0025663376  2.174625e-06
-    OMET      CH2  1  0.0032687988  2.4497959e-06
-    OMET      CH3  1  0.0039370168  2.7627548e-06
-    OMET      CH4  1  0.005459888  6.59475e-06
-    OMET      CR1  1  0.003536086  3.24675e-06
-    OMET       HC  1  0.000437552  1.38375e-07
-    OMET        H  1           0           0
-    OMET      DUM  1           0           0
-    OMET        S  1  0.0047521952   4.068e-06
-    OMET     CU1+  1  0.000972602  8.053875e-08
-    OMET     CU2+  1  0.000972602  8.053875e-08
-    OMET       FE  1           0           0
-    OMET     ZN2+  1  0.000972602  1.09305e-07
-    OMET     MG2+  1  0.0003842848  6.56775e-08
-    OMET     CA2+  1  0.001507652  7.939125e-07
-    OMET        P  1  0.005773784  5.299875e-06
-    OMET       AR  1  0.003764374  3.53025e-06
-    OMET        F  1  0.0016322592  9.81225e-07
-    OMET       CL  1  0.0044525672  4.399875e-06
-    OMET       BR  1  0.0016332104  9.1035e-06
-    OMET     CMET  1  0.0044806276  5.1373125e-06
-    OMET     OMET  1  0.0022619536  1.265625e-06
+    CMet        O  1  0.0044806276  3.9322131e-06
+    CMet       OM  1  0.0044806276  3.9322131e-06
+    CMet       OA  1  0.0044806276  5.1373125e-06
+    CMet       OW  1  0.0048197836  7.050676e-06
+    CMet        N  1  0.0046502056  5.9410165e-06
+    CMet       NT  1  0.0046502056  5.9410165e-06
+    CMet       NL  1  0.0046502056  5.9410165e-06
+    CMet       NR  1  0.0046502056  5.9410165e-06
+    CMet       NZ  1  0.0046502056  5.9410165e-06
+    CMet       NE  1  0.0046502056  5.9410165e-06
+    CMet        C  1  0.0045578798  8.3886605e-06
+    CMet      CH1  1  0.0050835716  8.8270445e-06
+    CMet      CH2  1  0.0064750533  9.943994e-06
+    CMet      CH3  1  0.0077987038  1.1214329e-05
+    CMet      CH4  1  0.010815308  2.6768823e-05
+    CMet      CR1  1  0.0070045135  1.3178919e-05
+    CMet       HC  1  0.000866732  5.616795e-07
+    CMet        H  1           0           0
+    CMet      DUM  1           0           0
+    CMet        S  1  0.0094134632  1.6512464e-05
+    CMet     CU1+  1  0.0019265945  3.2691574e-07
+    CMet     CU2+  1  0.0019265945  3.2691574e-07
+    CMet       FE  1           0           0
+    CMet     ZN2+  1  0.0019265945  4.4368114e-07
+    CMet     MG2+  1  0.0007612168  2.6659227e-07
+    CMet     CA2+  1  0.002986457  3.222579e-06
+    CMet        P  1  0.011437094  2.1512782e-05
+    CMet       AR  1  0.0074567215  1.4329677e-05
+    CMet        F  1  0.0032332872  3.9829013e-06
+    CMet       CL  1  0.0088199402  1.7859582e-05
+    CMet       BR  1  0.0032351714  3.6952118e-05
+    CMet     CMet  1  0.0088755241  2.0852922e-05
+    OMet        O  1  0.0022619536  9.687375e-07
+    OMet       OM  1  0.0022619536  9.687375e-07
+    OMet       OA  1  0.0022619536  1.265625e-06
+    OMet       OW  1  0.0024331696   1.737e-06
+    OMet        N  1  0.0023475616  1.463625e-06
+    OMet       NT  1  0.0023475616  1.463625e-06
+    OMet       NL  1  0.0023475616  1.463625e-06
+    OMet       NR  1  0.0023475616  1.463625e-06
+    OMet       NZ  1  0.0023475616  1.463625e-06
+    OMet       NE  1  0.0023475616  1.463625e-06
+    OMet        C  1  0.0023009528  2.066625e-06
+    OMet      CH1  1  0.0025663376  2.174625e-06
+    OMet      CH2  1  0.0032687988  2.4497959e-06
+    OMet      CH3  1  0.0039370168  2.7627548e-06
+    OMet      CH4  1  0.005459888  6.59475e-06
+    OMet      CR1  1  0.003536086  3.24675e-06
+    OMet       HC  1  0.000437552  1.38375e-07
+    OMet        H  1           0           0
+    OMet      DUM  1           0           0
+    OMet        S  1  0.0047521952   4.068e-06
+    OMet     CU1+  1  0.000972602  8.053875e-08
+    OMet     CU2+  1  0.000972602  8.053875e-08
+    OMet       FE  1           0           0
+    OMet     ZN2+  1  0.000972602  1.09305e-07
+    OMet     MG2+  1  0.0003842848  6.56775e-08
+    OMet     CA2+  1  0.001507652  7.939125e-07
+    OMet        P  1  0.005773784  5.299875e-06
+    OMet       AR  1  0.003764374  3.53025e-06
+    OMet        F  1  0.0016322592  9.81225e-07
+    OMet       CL  1  0.0044525672  4.399875e-06
+    OMet       BR  1  0.0016332104  9.1035e-06
+    OMet     CMet  1  0.0044806276  5.1373125e-06
+    OMet     OMet  1  0.0022619536  1.265625e-06
      NA+        O  1  0.00040373684  1.248595e-07
      NA+       OM  1  0.00040373684  1.248595e-07
      NA+       OA  1  0.00040373684  1.63125e-07
@@ -1595,8 +1595,8 @@ CLCL4     17  0.000      0.000     A  0.0076040144  1.2767758e-05
      NA+        F  1  0.00029134248  1.26469e-07
      NA+       CL  1  0.00079474018  5.67095e-07
      NA+       BR  1  0.00029151226  1.17334e-06
-     NA+     CMET  1  0.00079974869  6.621425e-07
-     NA+     OMET  1  0.00040373684  1.63125e-07
+     NA+     CMet  1  0.00079974869  6.621425e-07
+     NA+     OMet  1  0.00040373684  1.63125e-07
      NA+      NA+  1  7.2063121e-05  2.1025e-08
      CL-        O  1   0.0055883  8.903774e-06
      CL-       OM  1   0.0055883  8.903774e-06
@@ -1629,326 +1629,326 @@ CLCL4     17  0.000      0.000     A  0.0076040144  1.2767758e-05
      CL-        F  1   0.0040326  9.018548e-06
      CL-       CL  1  0.01100035  4.043974e-05
      CL-       BR  1  0.00403495  8.367128e-05
-     CL-     CMET  1  0.011069675  4.721761e-05
-     CL-     OMET  1   0.0055883  1.16325e-05
+     CL-     CMet  1  0.011069675  4.721761e-05
+     CL-     OMet  1   0.0055883  1.16325e-05
      CL-      NA+  1  0.0009974575  1.4993e-06
      CL-      CL-  1  0.01380625  0.0001069156
-    CCHL        O  1  0.0024394475  1.7359776e-06
-    CCHL       OM  1  0.0024394475  1.7359776e-06
-    CCHL       OA  1  0.0024394475   2.268e-06
-    CCHL       OW  1  0.0026240987  3.112704e-06
-    CCHL        N  1  0.0025317731  2.622816e-06
-    CCHL       NT  1  0.0025317731  2.622816e-06
-    CCHL       NL  1  0.0025317731  2.622816e-06
-    CCHL       NR  1  0.0025317731  2.622816e-06
-    CCHL       NZ  1  0.0025317731  2.622816e-06
-    CCHL       NE  1  0.0025317731  2.622816e-06
-    CCHL        C  1  0.002481507  3.703392e-06
-    CCHL      CH1  1  0.0027677163  3.896928e-06
-    CCHL      CH2  1  0.0035252992  4.3900343e-06
-    CCHL      CH3  1  0.0042459518  4.9508565e-06
-    CCHL      CH4  1  0.0058883216  1.1817792e-05
-    CCHL      CR1  1  0.0038135602  5.818176e-06
-    CCHL       HC  1  0.0004718864  2.47968e-07
-    CCHL        H  1           0           0
-    CCHL      DUM  1           0           0
-    CCHL        S  1  0.0051250966  7.289856e-06
-    CCHL     CU1+  1  0.0010489214  1.4432544e-07
-    CCHL     CU2+  1  0.0010489214  1.4432544e-07
-    CCHL       FE  1           0           0
-    CCHL     ZN2+  1  0.0010489214  1.9587456e-07
-    CCHL     MG2+  1  0.00041443936  1.1769408e-07
-    CCHL     CA2+  1  0.0016259564  1.4226912e-06
-    CCHL        P  1  0.0062268488  9.497376e-06
-    CCHL       AR  1  0.0040597618  6.326208e-06
-    CCHL        F  1  0.0017603414  1.7583552e-06
-    CCHL       CL  1  0.004801957  7.884576e-06
-    CCHL       BR  1  0.0017613673  1.6313472e-05
-    CCHL     CMET  1  0.0048322193  9.206064e-06
-    CCHL     OMET  1  0.0024394475   2.268e-06
-    CCHL      NA+  1  0.00043541779  2.9232e-07
-    CCHL      CL-  1  0.00602681  2.084544e-05
-    CCHL     CCHL  1  0.0026308693  4.064256e-06
-   CLCHL        O  1  0.004334666  3.1947671e-06
-   CLCHL       OM  1  0.004334666  3.1947671e-06
-   CLCHL       OA  1  0.004334666  4.1738625e-06
-   CLCHL       OW  1  0.0046627736  5.7283944e-06
-   CLCHL        N  1  0.0044987198  4.8268401e-06
-   CLCHL       NT  1  0.0044987198  4.8268401e-06
-   CLCHL       NL  1  0.0044987198  4.8268401e-06
-   CLCHL       NR  1  0.0044987198  4.8268401e-06
-   CLCHL       NZ  1  0.0044987198  4.8268401e-06
-   CLCHL       NE  1  0.0044987198  4.8268401e-06
-   CLCHL        C  1  0.0044094016  6.8154537e-06
-   CLCHL      CH1  1  0.0049179684  7.1716233e-06
-   CLCHL      CH2  1  0.0062641209  8.0791004e-06
-   CLCHL      CH3  1  0.007544652  9.1111968e-06
-   CLCHL      CH4  1  0.010462987  2.1748606e-05
-   CLCHL      CR1  1  0.0067763334  1.0707349e-05
-   CLCHL       HC  1  0.0008384972  4.563423e-07
-   CLCHL        H  1           0           0
-   CLCHL      DUM  1           0           0
-   CLCHL        S  1  0.0091068087  1.3415722e-05
-   CLCHL     CU1+  1  0.0018638335  2.6560606e-07
-   CLCHL     CU2+  1  0.0018638335  2.6560606e-07
-   CLCHL       FE  1           0           0
-   CLCHL     ZN2+  1  0.0018638335  3.6047332e-07
-   CLCHL     MG2+  1  0.00073641928  2.1659564e-07
-   CLCHL     CA2+  1  0.0028891697  2.6182176e-06
-   CLCHL        P  1  0.011064517  1.7478281e-05
-   CLCHL       AR  1  0.0072138101  1.1642294e-05
-   CLCHL        F  1  0.0031279591  3.2359492e-06
-   CLCHL       CL  1  0.0085326204  1.4510201e-05
-   CLCHL       BR  1  0.0031297819  3.0022129e-05
-   CLCHL     CMET  1  0.0085863936  1.6942172e-05
-   CLCHL     OMET  1  0.004334666  4.1738625e-06
-   CLCHL      NA+  1  0.00077369595  5.379645e-07
-   CLCHL      CL-  1  0.010709067  3.8362434e-05
-   CLCHL     CCHL  1  0.0046754       7.4813E-6
-   CLCHL    CLCHL  1  0.0083066819  1.3764842e-05
-    HCHL        O  1  0.0002920184  5.6465771e-08
-    HCHL       OM  1  0.0002920184  5.6465771e-08
-    HCHL       OA  1  0.0002920184  7.377075e-08
-    HCHL       OW  1  0.0003141224  1.0124626e-07
-    HCHL        N  1  0.0003030704  8.5311774e-08
-    HCHL       NT  1  0.0003030704  8.5311774e-08
-    HCHL       NL  1  0.0003030704  8.5311774e-08
-    HCHL       NR  1  0.0003030704  8.5311774e-08
-    HCHL       NZ  1  0.0003030704  8.5311774e-08
-    HCHL       NE  1  0.0003030704  8.5311774e-08
-    HCHL        C  1  0.0002970532  1.2045944e-07
-    HCHL      CH1  1  0.0003313144  1.2675454e-07
-    HCHL      CH2  1  0.0004220022  1.4279371e-07
-    HCHL      CH3  1  0.0005082692  1.6103545e-07
-    HCHL      CH4  1  0.000704872  3.8439479e-07
-    HCHL      CR1  1  0.000456509  1.8924656e-07
-    HCHL       HC  1  5.6488e-05  8.065602e-09
-    HCHL        H  1           0           0
-    HCHL      DUM  1           0           0
-    HCHL        S  1  0.0006135088  2.3711558e-07
-    HCHL     CU1+  1  0.000125563  4.6944427e-09
-    HCHL     CU2+  1  0.000125563  4.6944427e-09
-    HCHL       FE  1           0           0
-    HCHL     ZN2+  1  0.000125563  6.3711698e-09
-    HCHL     MG2+  1  4.96112e-05  3.8282101e-09
-    HCHL     CA2+  1  0.000194638  4.6275572e-08
-    HCHL        P  1  0.000745396  3.0891911e-07
-    HCHL       AR  1  0.000485981  2.0577121e-07
-    HCHL        F  1  0.0002107248  5.7193643e-08
-    HCHL       CL  1  0.0005748268  2.5645991e-07
-    HCHL       BR  1  0.0002108476  5.3062481e-07
-    HCHL     CMET  1  0.0005784494  2.9944367e-07
-    HCHL     OMET  1  0.0002920184  7.377075e-08
-    HCHL      NA+  1  5.212246e-05  9.50823e-09
-    HCHL      CL-  1  0.00072145  6.7803516e-07
-    HCHL     CCHL  1  0.0003622       0.1745E-6
-    HCHL    CLCHL  1  0.0006493       0.3266E-6
-    HCHL     HCHL  1  3.76996e-05  4.2999495e-09
-   SDMSO        O  1  0.0048877412  3.9925763e-06
-   SDMSO       OM  1  0.0048877412  3.9925763e-06
-   SDMSO       OA  1  0.0048877412  5.216175e-06
-   SDMSO       OW  1  0.0052577132  7.1589104e-06
-   SDMSO        N  1  0.0050727272  6.0322166e-06
-   SDMSO       NT  1  0.0050727272  6.0322166e-06
-   SDMSO       NL  1  0.0050727272  6.0322166e-06
-   SDMSO       NR  1  0.0050727272  6.0322166e-06
-   SDMSO       NZ  1  0.0050727272  6.0322166e-06
-   SDMSO       NE  1  0.0050727272  6.0322166e-06
-   SDMSO        C  1  0.0049720126  8.5174342e-06
-   SDMSO      CH1  1  0.0055454692  8.9625478e-06
-   SDMSO      CH2  1  0.0070633821  1.0096643e-05
-   SDMSO      CH3  1  0.0085073006  1.1386479e-05
-   SDMSO      CH4  1  0.011797996  2.7179749e-05
-   SDMSO      CR1  1  0.0076409495  1.3381228e-05
-   SDMSO       HC  1  0.000945484  5.703018e-07
-   SDMSO        H  1           0           0
-   SDMSO      DUM  1           0           0
-   SDMSO        S  1  0.010268778  1.6765946e-05
-   SDMSO     CU1+  1  0.0021016465  3.3193419e-07
-   SDMSO     CU2+  1  0.0021016465  3.3193419e-07
-   SDMSO       FE  1           0           0
-   SDMSO     ZN2+  1  0.0021016465  4.5049206e-07
-   SDMSO     MG2+  1  0.0008303816  2.7068471e-07
-   SDMSO     CA2+  1  0.003257809  3.2720486e-06
-   SDMSO        P  1  0.012476278  2.1843023e-05
-   SDMSO       AR  1  0.0081342455  1.4549651e-05
-   SDMSO        F  1  0.0035270664  4.0440425e-06
-   SDMSO       CL  1  0.0096213274  1.8133743e-05
-   SDMSO       BR  1  0.0035291218  3.7519367e-05
-   SDMSO     CMET  1  0.0096819617  2.1173034e-05
-   SDMSO     OMET  1  0.0048877412  5.216175e-06
-   SDMSO      NA+  1  0.00087241453  6.72307e-07
-   SDMSO      CL-  1  0.012075475  4.7942444e-05
-   SDMSO     CCHL  1  0.0052712788  9.3473856e-06
-   SDMSO    CLCHL  1  0.0093665606  1.720225e-05
-   SDMSO     HCHL  1  0.0006310078  3.0404041e-07
-   SDMSO    SDMSO  1  0.010561673  2.149806e-05
-   CDMSO        O  1  0.0045248108  4.016601e-06
-   CDMSO       OM  1  0.0045248108  4.016601e-06
-   CDMSO       OA  1  0.0045248108  5.2475625e-06
-   CDMSO       OW  1  0.0048673112  7.201988e-06
-   CDMSO        N  1  0.004696061  6.0685145e-06
-   CDMSO       NT  1  0.004696061  6.0685145e-06
-   CDMSO       NL  1  0.004696061  6.0685145e-06
-   CDMSO       NR  1  0.004696061  6.0685145e-06
-   CDMSO       NZ  1  0.004696061  6.0685145e-06
-   CDMSO       NE  1  0.004696061  6.0685145e-06
-   CDMSO        C  1  0.0046028248  8.5686865e-06
-   CDMSO      CH1  1  0.0051337004  9.0164785e-06
-   CDMSO      CH2  1  0.0065389035  1.0157398e-05
-   CDMSO      CH3  1  0.0078756064  1.1454995e-05
-   CDMSO      CH4  1  0.010921957  2.7343299e-05
-   CDMSO      CR1  1  0.0070735846  1.3461747e-05
-   CDMSO       HC  1  0.0008752788  5.737335e-07
-   CDMSO        H  1           0           0
-   CDMSO      DUM  1           0           0
-   CDMSO        S  1  0.0095062889  1.6866832e-05
-   CDMSO     CU1+  1  0.0019455925  3.3393156e-07
-   CDMSO     CU2+  1  0.0019455925  3.3393156e-07
-   CDMSO       FE  1           0           0
-   CDMSO     ZN2+  1  0.0019455925  4.5320282e-07
-   CDMSO     MG2+  1  0.00076872312  2.7231351e-07
-   CDMSO     CA2+  1  0.0030159063  3.2917377e-06
-   CDMSO        P  1  0.011549875  2.197446e-05
-   CDMSO       AR  1  0.0075302519  1.4637201e-05
-   CDMSO        F  1  0.0032651705  4.0683769e-06
-   CDMSO       CL  1  0.0089069132  1.824286e-05
-   CDMSO       BR  1  0.0032670733  3.7745134e-05
-   CDMSO     CMET  1  0.0089630452  2.1300439e-05
-   CDMSO     OMET  1  0.0045248108  5.2475625e-06
-   CDMSO      NA+  1  0.00080763497  6.763525e-07
-   CDMSO      CL-  1  0.011178832  4.823093e-05
-   CDMSO     CCHL  1  0.0048798696  9.403632e-06
-   CDMSO    CLCHL  1  0.0086710636  1.7305761e-05
-   CDMSO     HCHL  1  0.00058415346  3.0586992e-07
-   CDMSO    SDMSO  1  0.0097827      21.6523E-6
-   CDMSO    CDMSO  1  0.0090514293  2.175756e-05
-   ODMSO        O  1  0.0022663291  7.4645315e-07
-   ODMSO       OM  1  0.0022663291  7.4645315e-07
-   ODMSO       OA  1  0.0022663291  9.752175e-07
-   ODMSO       OW  1  0.0024378763  1.3384318e-06
-   ODMSO        N  1  0.0023521027  1.1277849e-06
-   ODMSO       NT  1  0.0023521027  1.1277849e-06
-   ODMSO       NL  1  0.0023521027  1.1277849e-06
-   ODMSO       NR  1  0.0023521027  1.1277849e-06
-   ODMSO       NZ  1  0.0023521027  1.1277849e-06
-   ODMSO       NE  1  0.0023521027  1.1277849e-06
-   ODMSO        C  1  0.0023054038  1.5924218e-06
-   ODMSO      CH1  1  0.0025713019  1.6756404e-06
-   ODMSO      CH2  1  0.003275122  1.8876712e-06
-   ODMSO      CH3  1  0.0039446326  2.1288192e-06
-   ODMSO      CH4  1  0.0054704496  5.0815333e-06
-   ODMSO      CR1  1  0.0035429262  2.501758e-06
-   ODMSO       HC  1  0.0004383984  1.0662378e-07
-   ODMSO        H  1           0           0
-   ODMSO      DUM  1           0           0
-   ODMSO        S  1  0.0047613878  3.1345658e-06
-   ODMSO     CU1+  1  0.0009744834  6.2058507e-08
-   ODMSO     CU2+  1  0.0009744834  6.2058507e-08
-   ODMSO       FE  1           0           0
-   ODMSO     ZN2+  1  0.0009744834  8.4224118e-08
-   ODMSO     MG2+  1  0.00038502816  5.0607287e-08
-   ODMSO     CA2+  1  0.0015105684  6.117431e-07
-   ODMSO        P  1  0.0057849528  4.0837775e-06
-   ODMSO       AR  1  0.0037716558  2.7202067e-06
-   ODMSO        F  1  0.0016354166  7.5607529e-07
-   ODMSO       CL  1  0.0044611802  3.3902895e-06
-   ODMSO       BR  1  0.0016363697  7.0146311e-06
-   ODMSO     CMET  1  0.0044892949  3.9585162e-06
-   ODMSO     OMET  1  0.0022663291  9.752175e-07
-   ODMSO      NA+  1  0.00040451783  1.256947e-07
-   ODMSO      CL-  1  0.00559911  8.9633324e-06
-   ODMSO     CCHL  1  0.0024441664  1.7475898e-06
-   ODMSO    CLCHL  1  0.0043430509  3.2161373e-06
-   ODMSO     HCHL  1  0.00029258328  5.6843478e-08
-   ODMSO    SDMSO  1  0.0052442       4.6094E-6
-   ODMSO    CDMSO  1  0.0049187       4.7597E-6
-   ODMSO    ODMSO  1  0.0022707131  7.5144626e-07
-    CCL4        O  1  0.0024394475  2.3738805e-06
-    CCL4       OM  1  0.0024394475  2.3738805e-06
-    CCL4       OA  1  0.0024394475  3.1014e-06
-    CCL4       OW  1  0.0026240987  4.2564992e-06
-    CCL4        N  1  0.0025317731  3.5865968e-06
-    CCL4       NT  1  0.0025317731  3.5865968e-06
-    CCL4       NL  1  0.0025317731  3.5865968e-06
-    CCL4       NR  1  0.0025317731  3.5865968e-06
-    CCL4       NZ  1  0.0025317731  3.5865968e-06
-    CCL4       NE  1  0.0025317731  3.5865968e-06
-    CCL4        C  1  0.002481507  5.0642416e-06
-    CCL4      CH1  1  0.0027677163  5.3288944e-06
-    CCL4      CH2  1  0.0035252992  6.0031978e-06
-    CCL4      CH3  1  0.0042459518  6.7700998e-06
-    CCL4      CH4  1  0.0058883216  1.6160362e-05
-    CCL4      CR1  1  0.0038135602  7.9561248e-06
-    CCL4       HC  1  0.0004718864  3.390864e-07
-    CCL4        H  1           0           0
-    CCL4      DUM  1           0           0
-    CCL4        S  1  0.0051250966  9.9685888e-06
-    CCL4     CU1+  1  0.0010489214  1.9735931e-07
-    CCL4     CU2+  1  0.0010489214  1.9735931e-07
-    CCL4       FE  1           0           0
-    CCL4     ZN2+  1  0.0010489214  2.6785069e-07
-    CCL4     MG2+  1  0.00041443936  1.6094198e-07
-    CCL4     CA2+  1  0.0016259564  1.9454738e-06
-    CCL4        P  1  0.0062268488  1.2987285e-05
-    CCL4       AR  1  0.0040597618  8.6508384e-06
-    CCL4        F  1  0.0017603414  2.404481e-06
-    CCL4       CL  1  0.004801957  1.0781845e-05
-    CCL4       BR  1  0.0017613673  2.2308026e-05
-    CCL4     CMET  1  0.0048322193  1.2588927e-05
-    CCL4     OMET  1  0.0024394475  3.1014e-06
-    CCL4      NA+  1  0.00043541779  3.99736e-07
-    CCL4      CL-  1  0.00602681  2.8505312e-05
-    CCL4     CCHL  1  0.0026308693  5.5577088e-06
-    CCL4    CLCHL  1  0.0046748042  1.0228004e-05
-    CCL4     HCHL  1  0.00031493288  1.807744e-07
-    CCL4    SDMSO  1  0.0052712788  1.2782179e-05
-    CCL4    CDMSO  1  0.0048798696  1.2859094e-05
-    CCL4    ODMSO  1  0.0024441664  2.3897596e-06
-    CCL4     CCL4  1  0.0026308693  7.5999462e-06
-   CLCL4        O  1  0.0041472796  3.0768825e-06
-   CLCL4       OM  1  0.0041472796  3.0768825e-06
-   CLCL4       OA  1  0.0041472796  4.01985e-06
-   CLCL4       OW  1  0.0044612032  5.5170208e-06
-   CLCL4        N  1  0.0043042414  4.6487332e-06
-   CLCL4       NT  1  0.0043042414  4.6487332e-06
-   CLCL4       NL  1  0.0043042414  4.6487332e-06
-   CLCL4       NR  1  0.0043042414  4.6487332e-06
-   CLCL4       NZ  1  0.0043042414  4.6487332e-06
-   CLCL4       NE  1  0.0043042414  4.6487332e-06
-   CLCL4        C  1  0.0042187844  6.5639684e-06
-   CLCL4      CH1  1  0.004705366  6.9069956e-06
-   CLCL4      CH2  1  0.0059933247  7.7809875e-06
-   CLCL4      CH3  1  0.0072184988  8.7750002e-06
-   CLCL4      CH4  1  0.010010675  2.0946098e-05
-   CLCL4      CR1  1  0.0064833944  1.0312255e-05
-   CLCL4       HC  1  0.0008022492  4.395036e-07
-   CLCL4        H  1           0           0
-   CLCL4      DUM  1           0           0
-   CLCL4        S  1  0.0087131239  1.2920691e-05
-   CLCL4     CU1+  1  0.0017832604  2.5580539e-07
-   CLCL4     CU2+  1  0.0017832604  2.5580539e-07
-   CLCL4       FE  1           0           0
-   CLCL4     ZN2+  1  0.0017832604  3.4717211e-07
-   CLCL4     MG2+  1  0.00070458408  2.0860342e-07
-   CLCL4     CA2+  1  0.0027642717  2.5216072e-06
-   CLCL4        P  1  0.010586201  1.6833345e-05
-   CLCL4       AR  1  0.0069019592  1.1212702e-05
-   CLCL4        F  1  0.0029927383  3.116545e-06
-   CLCL4       CL  1  0.0081637576  1.3974785e-05
-   CLCL4       BR  1  0.0029944823  2.8914334e-05
-   CLCL4     CMET  1  0.0082152062  1.6317018e-05
-   CLCL4     OMET  1  0.0041472796  4.01985e-06
-   CLCL4      NA+  1  0.00074024929  5.18114e-07
-   CLCL4      CL-  1  0.010246117  3.6946888e-05
-   CLCL4     CCHL  1  0.0044727137  7.2035712e-06
-   CLCL4    CLCHL  1  0.0079475863  1.3256929e-05
-   CLCL4     HCHL  1  0.00053541414  2.3430902e-07
-   CLCL4    SDMSO  1  0.0089616468  1.6567499e-05
-   CLCL4    CDMSO  1  0.0082962159  1.6667191e-05
-   CLCL4    ODMSO  1  0.0041553021  3.0974642e-06
-   CLCL4     CCL4  1  0.0044727137  9.8505978e-06
-   CLCL4    CLCL4  1  0.0076040144  1.2767758e-05
+    CChl        O  1  0.0024394475  1.7359776e-06
+    CChl       OM  1  0.0024394475  1.7359776e-06
+    CChl       OA  1  0.0024394475   2.268e-06
+    CChl       OW  1  0.0026240987  3.112704e-06
+    CChl        N  1  0.0025317731  2.622816e-06
+    CChl       NT  1  0.0025317731  2.622816e-06
+    CChl       NL  1  0.0025317731  2.622816e-06
+    CChl       NR  1  0.0025317731  2.622816e-06
+    CChl       NZ  1  0.0025317731  2.622816e-06
+    CChl       NE  1  0.0025317731  2.622816e-06
+    CChl        C  1  0.002481507  3.703392e-06
+    CChl      CH1  1  0.0027677163  3.896928e-06
+    CChl      CH2  1  0.0035252992  4.3900343e-06
+    CChl      CH3  1  0.0042459518  4.9508565e-06
+    CChl      CH4  1  0.0058883216  1.1817792e-05
+    CChl      CR1  1  0.0038135602  5.818176e-06
+    CChl       HC  1  0.0004718864  2.47968e-07
+    CChl        H  1           0           0
+    CChl      DUM  1           0           0
+    CChl        S  1  0.0051250966  7.289856e-06
+    CChl     CU1+  1  0.0010489214  1.4432544e-07
+    CChl     CU2+  1  0.0010489214  1.4432544e-07
+    CChl       FE  1           0           0
+    CChl     ZN2+  1  0.0010489214  1.9587456e-07
+    CChl     MG2+  1  0.00041443936  1.1769408e-07
+    CChl     CA2+  1  0.0016259564  1.4226912e-06
+    CChl        P  1  0.0062268488  9.497376e-06
+    CChl       AR  1  0.0040597618  6.326208e-06
+    CChl        F  1  0.0017603414  1.7583552e-06
+    CChl       CL  1  0.004801957  7.884576e-06
+    CChl       BR  1  0.0017613673  1.6313472e-05
+    CChl     CMet  1  0.0048322193  9.206064e-06
+    CChl     OMet  1  0.0024394475   2.268e-06
+    CChl      NA+  1  0.00043541779  2.9232e-07
+    CChl      CL-  1  0.00602681  2.084544e-05
+    CChl     CChl  1  0.0026308693  4.064256e-06
+   CLChl        O  1  0.004334666  3.1947671e-06
+   CLChl       OM  1  0.004334666  3.1947671e-06
+   CLChl       OA  1  0.004334666  4.1738625e-06
+   CLChl       OW  1  0.0046627736  5.7283944e-06
+   CLChl        N  1  0.0044987198  4.8268401e-06
+   CLChl       NT  1  0.0044987198  4.8268401e-06
+   CLChl       NL  1  0.0044987198  4.8268401e-06
+   CLChl       NR  1  0.0044987198  4.8268401e-06
+   CLChl       NZ  1  0.0044987198  4.8268401e-06
+   CLChl       NE  1  0.0044987198  4.8268401e-06
+   CLChl        C  1  0.0044094016  6.8154537e-06
+   CLChl      CH1  1  0.0049179684  7.1716233e-06
+   CLChl      CH2  1  0.0062641209  8.0791004e-06
+   CLChl      CH3  1  0.007544652  9.1111968e-06
+   CLChl      CH4  1  0.010462987  2.1748606e-05
+   CLChl      CR1  1  0.0067763334  1.0707349e-05
+   CLChl       HC  1  0.0008384972  4.563423e-07
+   CLChl        H  1           0           0
+   CLChl      DUM  1           0           0
+   CLChl        S  1  0.0091068087  1.3415722e-05
+   CLChl     CU1+  1  0.0018638335  2.6560606e-07
+   CLChl     CU2+  1  0.0018638335  2.6560606e-07
+   CLChl       FE  1           0           0
+   CLChl     ZN2+  1  0.0018638335  3.6047332e-07
+   CLChl     MG2+  1  0.00073641928  2.1659564e-07
+   CLChl     CA2+  1  0.0028891697  2.6182176e-06
+   CLChl        P  1  0.011064517  1.7478281e-05
+   CLChl       AR  1  0.0072138101  1.1642294e-05
+   CLChl        F  1  0.0031279591  3.2359492e-06
+   CLChl       CL  1  0.0085326204  1.4510201e-05
+   CLChl       BR  1  0.0031297819  3.0022129e-05
+   CLChl     CMet  1  0.0085863936  1.6942172e-05
+   CLChl     OMet  1  0.004334666  4.1738625e-06
+   CLChl      NA+  1  0.00077369595  5.379645e-07
+   CLChl      CL-  1  0.010709067  3.8362434e-05
+   CLChl     CChl  1  0.0046754       7.4813E-6
+   CLChl    CLChl  1  0.0083066819  1.3764842e-05
+    HChl        O  1  0.0002920184  5.6465771e-08
+    HChl       OM  1  0.0002920184  5.6465771e-08
+    HChl       OA  1  0.0002920184  7.377075e-08
+    HChl       OW  1  0.0003141224  1.0124626e-07
+    HChl        N  1  0.0003030704  8.5311774e-08
+    HChl       NT  1  0.0003030704  8.5311774e-08
+    HChl       NL  1  0.0003030704  8.5311774e-08
+    HChl       NR  1  0.0003030704  8.5311774e-08
+    HChl       NZ  1  0.0003030704  8.5311774e-08
+    HChl       NE  1  0.0003030704  8.5311774e-08
+    HChl        C  1  0.0002970532  1.2045944e-07
+    HChl      CH1  1  0.0003313144  1.2675454e-07
+    HChl      CH2  1  0.0004220022  1.4279371e-07
+    HChl      CH3  1  0.0005082692  1.6103545e-07
+    HChl      CH4  1  0.000704872  3.8439479e-07
+    HChl      CR1  1  0.000456509  1.8924656e-07
+    HChl       HC  1  5.6488e-05  8.065602e-09
+    HChl        H  1           0           0
+    HChl      DUM  1           0           0
+    HChl        S  1  0.0006135088  2.3711558e-07
+    HChl     CU1+  1  0.000125563  4.6944427e-09
+    HChl     CU2+  1  0.000125563  4.6944427e-09
+    HChl       FE  1           0           0
+    HChl     ZN2+  1  0.000125563  6.3711698e-09
+    HChl     MG2+  1  4.96112e-05  3.8282101e-09
+    HChl     CA2+  1  0.000194638  4.6275572e-08
+    HChl        P  1  0.000745396  3.0891911e-07
+    HChl       AR  1  0.000485981  2.0577121e-07
+    HChl        F  1  0.0002107248  5.7193643e-08
+    HChl       CL  1  0.0005748268  2.5645991e-07
+    HChl       BR  1  0.0002108476  5.3062481e-07
+    HChl     CMet  1  0.0005784494  2.9944367e-07
+    HChl     OMet  1  0.0002920184  7.377075e-08
+    HChl      NA+  1  5.212246e-05  9.50823e-09
+    HChl      CL-  1  0.00072145  6.7803516e-07
+    HChl     CChl  1  0.0003622       0.1745E-6
+    HChl    CLChl  1  0.0006493       0.3266E-6
+    HChl     HChl  1  3.76996e-05  4.2999495e-09
+   SDmso        O  1  0.0048877412  3.9925763e-06
+   SDmso       OM  1  0.0048877412  3.9925763e-06
+   SDmso       OA  1  0.0048877412  5.216175e-06
+   SDmso       OW  1  0.0052577132  7.1589104e-06
+   SDmso        N  1  0.0050727272  6.0322166e-06
+   SDmso       NT  1  0.0050727272  6.0322166e-06
+   SDmso       NL  1  0.0050727272  6.0322166e-06
+   SDmso       NR  1  0.0050727272  6.0322166e-06
+   SDmso       NZ  1  0.0050727272  6.0322166e-06
+   SDmso       NE  1  0.0050727272  6.0322166e-06
+   SDmso        C  1  0.0049720126  8.5174342e-06
+   SDmso      CH1  1  0.0055454692  8.9625478e-06
+   SDmso      CH2  1  0.0070633821  1.0096643e-05
+   SDmso      CH3  1  0.0085073006  1.1386479e-05
+   SDmso      CH4  1  0.011797996  2.7179749e-05
+   SDmso      CR1  1  0.0076409495  1.3381228e-05
+   SDmso       HC  1  0.000945484  5.703018e-07
+   SDmso        H  1           0           0
+   SDmso      DUM  1           0           0
+   SDmso        S  1  0.010268778  1.6765946e-05
+   SDmso     CU1+  1  0.0021016465  3.3193419e-07
+   SDmso     CU2+  1  0.0021016465  3.3193419e-07
+   SDmso       FE  1           0           0
+   SDmso     ZN2+  1  0.0021016465  4.5049206e-07
+   SDmso     MG2+  1  0.0008303816  2.7068471e-07
+   SDmso     CA2+  1  0.003257809  3.2720486e-06
+   SDmso        P  1  0.012476278  2.1843023e-05
+   SDmso       AR  1  0.0081342455  1.4549651e-05
+   SDmso        F  1  0.0035270664  4.0440425e-06
+   SDmso       CL  1  0.0096213274  1.8133743e-05
+   SDmso       BR  1  0.0035291218  3.7519367e-05
+   SDmso     CMet  1  0.0096819617  2.1173034e-05
+   SDmso     OMet  1  0.0048877412  5.216175e-06
+   SDmso      NA+  1  0.00087241453  6.72307e-07
+   SDmso      CL-  1  0.012075475  4.7942444e-05
+   SDmso     CChl  1  0.0052712788  9.3473856e-06
+   SDmso    CLChl  1  0.0093665606  1.720225e-05
+   SDmso     HChl  1  0.0006310078  3.0404041e-07
+   SDmso    SDmso  1  0.010561673  2.149806e-05
+   CDmso        O  1  0.0045248108  4.016601e-06
+   CDmso       OM  1  0.0045248108  4.016601e-06
+   CDmso       OA  1  0.0045248108  5.2475625e-06
+   CDmso       OW  1  0.0048673112  7.201988e-06
+   CDmso        N  1  0.004696061  6.0685145e-06
+   CDmso       NT  1  0.004696061  6.0685145e-06
+   CDmso       NL  1  0.004696061  6.0685145e-06
+   CDmso       NR  1  0.004696061  6.0685145e-06
+   CDmso       NZ  1  0.004696061  6.0685145e-06
+   CDmso       NE  1  0.004696061  6.0685145e-06
+   CDmso        C  1  0.0046028248  8.5686865e-06
+   CDmso      CH1  1  0.0051337004  9.0164785e-06
+   CDmso      CH2  1  0.0065389035  1.0157398e-05
+   CDmso      CH3  1  0.0078756064  1.1454995e-05
+   CDmso      CH4  1  0.010921957  2.7343299e-05
+   CDmso      CR1  1  0.0070735846  1.3461747e-05
+   CDmso       HC  1  0.0008752788  5.737335e-07
+   CDmso        H  1           0           0
+   CDmso      DUM  1           0           0
+   CDmso        S  1  0.0095062889  1.6866832e-05
+   CDmso     CU1+  1  0.0019455925  3.3393156e-07
+   CDmso     CU2+  1  0.0019455925  3.3393156e-07
+   CDmso       FE  1           0           0
+   CDmso     ZN2+  1  0.0019455925  4.5320282e-07
+   CDmso     MG2+  1  0.00076872312  2.7231351e-07
+   CDmso     CA2+  1  0.0030159063  3.2917377e-06
+   CDmso        P  1  0.011549875  2.197446e-05
+   CDmso       AR  1  0.0075302519  1.4637201e-05
+   CDmso        F  1  0.0032651705  4.0683769e-06
+   CDmso       CL  1  0.0089069132  1.824286e-05
+   CDmso       BR  1  0.0032670733  3.7745134e-05
+   CDmso     CMet  1  0.0089630452  2.1300439e-05
+   CDmso     OMet  1  0.0045248108  5.2475625e-06
+   CDmso      NA+  1  0.00080763497  6.763525e-07
+   CDmso      CL-  1  0.011178832  4.823093e-05
+   CDmso     CChl  1  0.0048798696  9.403632e-06
+   CDmso    CLChl  1  0.0086710636  1.7305761e-05
+   CDmso     HChl  1  0.00058415346  3.0586992e-07
+   CDmso    SDmso  1  0.0097827      21.6523E-6
+   CDmso    CDmso  1  0.0090514293  2.175756e-05
+   ODmso        O  1  0.0022663291  7.4645315e-07
+   ODmso       OM  1  0.0022663291  7.4645315e-07
+   ODmso       OA  1  0.0022663291  9.752175e-07
+   ODmso       OW  1  0.0024378763  1.3384318e-06
+   ODmso        N  1  0.0023521027  1.1277849e-06
+   ODmso       NT  1  0.0023521027  1.1277849e-06
+   ODmso       NL  1  0.0023521027  1.1277849e-06
+   ODmso       NR  1  0.0023521027  1.1277849e-06
+   ODmso       NZ  1  0.0023521027  1.1277849e-06
+   ODmso       NE  1  0.0023521027  1.1277849e-06
+   ODmso        C  1  0.0023054038  1.5924218e-06
+   ODmso      CH1  1  0.0025713019  1.6756404e-06
+   ODmso      CH2  1  0.003275122  1.8876712e-06
+   ODmso      CH3  1  0.0039446326  2.1288192e-06
+   ODmso      CH4  1  0.0054704496  5.0815333e-06
+   ODmso      CR1  1  0.0035429262  2.501758e-06
+   ODmso       HC  1  0.0004383984  1.0662378e-07
+   ODmso        H  1           0           0
+   ODmso      DUM  1           0           0
+   ODmso        S  1  0.0047613878  3.1345658e-06
+   ODmso     CU1+  1  0.0009744834  6.2058507e-08
+   ODmso     CU2+  1  0.0009744834  6.2058507e-08
+   ODmso       FE  1           0           0
+   ODmso     ZN2+  1  0.0009744834  8.4224118e-08
+   ODmso     MG2+  1  0.00038502816  5.0607287e-08
+   ODmso     CA2+  1  0.0015105684  6.117431e-07
+   ODmso        P  1  0.0057849528  4.0837775e-06
+   ODmso       AR  1  0.0037716558  2.7202067e-06
+   ODmso        F  1  0.0016354166  7.5607529e-07
+   ODmso       CL  1  0.0044611802  3.3902895e-06
+   ODmso       BR  1  0.0016363697  7.0146311e-06
+   ODmso     CMet  1  0.0044892949  3.9585162e-06
+   ODmso     OMet  1  0.0022663291  9.752175e-07
+   ODmso      NA+  1  0.00040451783  1.256947e-07
+   ODmso      CL-  1  0.00559911  8.9633324e-06
+   ODmso     CChl  1  0.0024441664  1.7475898e-06
+   ODmso    CLChl  1  0.0043430509  3.2161373e-06
+   ODmso     HChl  1  0.00029258328  5.6843478e-08
+   ODmso    SDmso  1  0.0052442       4.6094E-6
+   ODmso    CDmso  1  0.0049187       4.7597E-6
+   ODmso    ODmso  1  0.0022707131  7.5144626e-07
+    CCl4        O  1  0.0024394475  2.3738805e-06
+    CCl4       OM  1  0.0024394475  2.3738805e-06
+    CCl4       OA  1  0.0024394475  3.1014e-06
+    CCl4       OW  1  0.0026240987  4.2564992e-06
+    CCl4        N  1  0.0025317731  3.5865968e-06
+    CCl4       NT  1  0.0025317731  3.5865968e-06
+    CCl4       NL  1  0.0025317731  3.5865968e-06
+    CCl4       NR  1  0.0025317731  3.5865968e-06
+    CCl4       NZ  1  0.0025317731  3.5865968e-06
+    CCl4       NE  1  0.0025317731  3.5865968e-06
+    CCl4        C  1  0.002481507  5.0642416e-06
+    CCl4      CH1  1  0.0027677163  5.3288944e-06
+    CCl4      CH2  1  0.0035252992  6.0031978e-06
+    CCl4      CH3  1  0.0042459518  6.7700998e-06
+    CCl4      CH4  1  0.0058883216  1.6160362e-05
+    CCl4      CR1  1  0.0038135602  7.9561248e-06
+    CCl4       HC  1  0.0004718864  3.390864e-07
+    CCl4        H  1           0           0
+    CCl4      DUM  1           0           0
+    CCl4        S  1  0.0051250966  9.9685888e-06
+    CCl4     CU1+  1  0.0010489214  1.9735931e-07
+    CCl4     CU2+  1  0.0010489214  1.9735931e-07
+    CCl4       FE  1           0           0
+    CCl4     ZN2+  1  0.0010489214  2.6785069e-07
+    CCl4     MG2+  1  0.00041443936  1.6094198e-07
+    CCl4     CA2+  1  0.0016259564  1.9454738e-06
+    CCl4        P  1  0.0062268488  1.2987285e-05
+    CCl4       AR  1  0.0040597618  8.6508384e-06
+    CCl4        F  1  0.0017603414  2.404481e-06
+    CCl4       CL  1  0.004801957  1.0781845e-05
+    CCl4       BR  1  0.0017613673  2.2308026e-05
+    CCl4     CMet  1  0.0048322193  1.2588927e-05
+    CCl4     OMet  1  0.0024394475  3.1014e-06
+    CCl4      NA+  1  0.00043541779  3.99736e-07
+    CCl4      CL-  1  0.00602681  2.8505312e-05
+    CCl4     CChl  1  0.0026308693  5.5577088e-06
+    CCl4    CLChl  1  0.0046748042  1.0228004e-05
+    CCl4     HChl  1  0.00031493288  1.807744e-07
+    CCl4    SDmso  1  0.0052712788  1.2782179e-05
+    CCl4    CDmso  1  0.0048798696  1.2859094e-05
+    CCl4    ODmso  1  0.0024441664  2.3897596e-06
+    CCl4     CCl4  1  0.0026308693  7.5999462e-06
+   CLCl4        O  1  0.0041472796  3.0768825e-06
+   CLCl4       OM  1  0.0041472796  3.0768825e-06
+   CLCl4       OA  1  0.0041472796  4.01985e-06
+   CLCl4       OW  1  0.0044612032  5.5170208e-06
+   CLCl4        N  1  0.0043042414  4.6487332e-06
+   CLCl4       NT  1  0.0043042414  4.6487332e-06
+   CLCl4       NL  1  0.0043042414  4.6487332e-06
+   CLCl4       NR  1  0.0043042414  4.6487332e-06
+   CLCl4       NZ  1  0.0043042414  4.6487332e-06
+   CLCl4       NE  1  0.0043042414  4.6487332e-06
+   CLCl4        C  1  0.0042187844  6.5639684e-06
+   CLCl4      CH1  1  0.004705366  6.9069956e-06
+   CLCl4      CH2  1  0.0059933247  7.7809875e-06
+   CLCl4      CH3  1  0.0072184988  8.7750002e-06
+   CLCl4      CH4  1  0.010010675  2.0946098e-05
+   CLCl4      CR1  1  0.0064833944  1.0312255e-05
+   CLCl4       HC  1  0.0008022492  4.395036e-07
+   CLCl4        H  1           0           0
+   CLCl4      DUM  1           0           0
+   CLCl4        S  1  0.0087131239  1.2920691e-05
+   CLCl4     CU1+  1  0.0017832604  2.5580539e-07
+   CLCl4     CU2+  1  0.0017832604  2.5580539e-07
+   CLCl4       FE  1           0           0
+   CLCl4     ZN2+  1  0.0017832604  3.4717211e-07
+   CLCl4     MG2+  1  0.00070458408  2.0860342e-07
+   CLCl4     CA2+  1  0.0027642717  2.5216072e-06
+   CLCl4        P  1  0.010586201  1.6833345e-05
+   CLCl4       AR  1  0.0069019592  1.1212702e-05
+   CLCl4        F  1  0.0029927383  3.116545e-06
+   CLCl4       CL  1  0.0081637576  1.3974785e-05
+   CLCl4       BR  1  0.0029944823  2.8914334e-05
+   CLCl4     CMet  1  0.0082152062  1.6317018e-05
+   CLCl4     OMet  1  0.0041472796  4.01985e-06
+   CLCl4      NA+  1  0.00074024929  5.18114e-07
+   CLCl4      CL-  1  0.010246117  3.6946888e-05
+   CLCl4     CChl  1  0.0044727137  7.2035712e-06
+   CLCl4    CLChl  1  0.0079475863  1.3256929e-05
+   CLCl4     HChl  1  0.00053541414  2.3430902e-07
+   CLCl4    SDmso  1  0.0089616468  1.6567499e-05
+   CLCl4    CDmso  1  0.0082962159  1.6667191e-05
+   CLCl4    ODmso  1  0.0041553021  3.0974642e-06
+   CLCl4     CCl4  1  0.0044727137  9.8505978e-06
+   CLCl4    CLCl4  1  0.0076040144  1.2767758e-05
       SI        O  1           0           0
       SI       OM  1           0           0
       SI       OA  1           0           0
@@ -1980,16 +1980,16 @@ CLCL4     17  0.000      0.000     A  0.0076040144  1.2767758e-05
       SI        F  1           0           0
       SI       CL  1           0           0
       SI       BR  1           0           0
-      SI     CMET  1           0           0
-      SI     OMET  1           0           0
+      SI     CMet  1           0           0
+      SI     OMet  1           0           0
       SI      NA+  1           0           0
       SI      CL-  1           0           0
-      SI     CCHL  1           0           0
-      SI    CLCHL  1           0           0
-      SI     HCHL  1           0           0
-      SI    SDMSO  1           0           0
-      SI    CDMSO  1           0           0
-      SI    ODMSO  1           0           0
-      SI     CCL4  1           0           0
-      SI    CLCL4  1           0           0
+      SI     CChl  1           0           0
+      SI    CLChl  1           0           0
+      SI     HChl  1           0           0
+      SI    SDmso  1           0           0
+      SI    CDmso  1           0           0
+      SI    ODmso  1           0           0
+      SI     CCl4  1           0           0
+      SI    CLCl4  1           0           0
       SI       SI  1           0           0
diff --git a/share/top/gromos43a2.ff/watermodels.dat b/share/top/gromos43a2.ff/watermodels.dat
new file mode 100644 (file)
index 0000000..a68dbed
--- /dev/null
@@ -0,0 +1,2 @@
+spc    SPC    simple point charge, recommended
+spce   SPC/E  extended simple point charge
index b0b3e89e8035a9c0a01199758a1a83ad58051bba..98fbefcff1e1a3501e3d92e6bacdc437bdd2efa8 100644 (file)
@@ -9,7 +9,8 @@ aminoacids.c.tdb        atomtypes.atp           ions.itp        \
 aminoacids.hdb         ffbonded.itp            spc.itp         \
 aminoacids.n.tdb       ffnonbonded.itp         spce.itp        \
 aminoacids.rtp         forcefield.doc          tip3p.itp       \
-aminoacids.vsd         forcefield.itp          tip4p.itp
+aminoacids.vsd         forcefield.itp          tip4p.itp       \
+aminoacids.r2b         watermodels.dat
 
 EXTRA_DIST = ${topol_DATA}
 
diff --git a/share/top/gromos45a3.ff/aminoacids.r2b b/share/top/gromos45a3.ff/aminoacids.r2b
new file mode 100644 (file)
index 0000000..823db90
--- /dev/null
@@ -0,0 +1,7 @@
+; rtp residue to rtp building block table
+;GMX   Force-field
+CYS    CYSH
+HISD   HISA
+HISE   HISB
+LYS    LYSH
+LYSN   LYS
index f6837e85c1bba1eaf6fab1aa93f32fa8cceacd1b..5b19b7950130e008d4cbbe52e5f8c634cad5c929 100644 (file)
@@ -12,6 +12,7 @@
      C     O   gb_4
      C    +N   gb_9
  [ angles ]
+   CA     C     O    ga_30
    CA     C    +N    ga_18
     O     C    +N    ga_32
  [ impropers ]
@@ -9221,11 +9222,11 @@ AO3PB   APG AO3PG AH3PG     gd_9
 
 [ CHCL3 ]
  [ atoms ]
- CChl  CCHL     0.17900     0
- HChl  HCHL     0.08200     0
-CLCh1 CLCHL    -0.08700     0
-CLCh2 CLCHL    -0.08700     0
-CLCh3 CLCHL    -0.08700     0
+ CChl  CChl     0.17900     0
+ HChl  HChl     0.08200     0
+CLCh1 CLChl    -0.08700     0
+CLCh2 CLChl    -0.08700     0
+CLCh3 CLChl    -0.08700     0
  [ bonds ]
  CChl CLCh1    gb_37   
  CChl CLCh2    gb_37   
@@ -9245,10 +9246,10 @@ CLCh2 CLCh3    gb_43
 
 [ DMSO ]
  [ atoms ]
-SDmso SDMSO     0.13900     0
-ODmso ODMSO    -0.45900     0
-CDms1 CDMSO     0.16000     0
-CDms2 CDMSO     0.16000     0
+SDmso SDmso     0.13900     0
+ODmso ODmso    -0.45900     0
+CDms1 CDmso     0.16000     0
+CDms2 CDmso     0.16000     0
  [ bonds ]
 SDmso ODmso    gb_38   
 SDmso CDms1    gb_39   
@@ -9265,9 +9266,9 @@ CDms1 CDms2    gb_45
 
 [ CH3OH ]
  [ atoms ]
- Omet  OMET    -0.57400     0
+ Omet  OMet    -0.57400     0
  HMet     H     0.39800     0
- CMet  CMET     0.17600     0
+ CMet  CMet     0.17600     0
  [ bonds ]
  Omet  HMet    gb_1    
  Omet  CMet    gb_17   
@@ -9281,11 +9282,11 @@ CDms1 CDms2    gb_45
 
 [ CCL4 ]
  [ atoms ]
- CCl4  CCL4     0.00000     0
-CLCl1 CLCL4     0.00000     0
-CLCl2 CLCL4     0.00000     0
-CLCl3 CLCL4     0.00000     0
-CLCl4 CLCL4     0.00000     0
+ CCl4  CCl4     0.00000     0
+CLCl1 CLCl4     0.00000     0
+CLCl2 CLCl4     0.00000     0
+CLCl3 CLCl4     0.00000     0
+CLCl4 CLCl4     0.00000     0
  [ bonds ]
  CCl4 CLCl1    gb_40   
  CCl4 CLCl2    gb_40   
index 64c43e724adbe79fe713328488a5610b5f2c6d07..3b11ae95e360cc85be324ef0001681418a68052c 100644 (file)
     F  18.99840 ;     fluor (non-ionic)
    CL  35.45300 ;     chlorine (non-ionic)
    BR  79.90400 ;     bromine (non-ionic)
- CMET  15.035   ;     CH3-group in methanol (solvent)
- OMET  15.9994  ;     oxygen in methanol (solvent)
+ CMet  15.035   ;     CH3-group in methanol (solvent)
+ OMet  15.9994  ;     oxygen in methanol (solvent)
   NA+  22.9898  ;     sodium (charge 1+)
   CL-  35.45300 ;     chlorine (charge 1-)
- CCHL  12.011   ;     carbon in chloroform (solvent)
-CLCHL  35.453   ;     chloride in chloroform (solvent)
- HCHL  1.008    ;     hydrogen in chloroform (solvent)
-SDMSO  32.06000 ;     DMSO Sulphur (solvent)
-CDMSO  15.03500 ;     DMSO Carbon (solvent)
-ODMSO  15.99940 ;     DMSO Oxygen (solvent)
- CCL4  12.011   ;     carbon in carbontetrachloride (solvent)
-CLCL4  35.453   ;     chloride in carbontetrachloride (solvent)
+ CChl  12.011   ;     carbon in chloroform (solvent)
+CLChl  35.453   ;     chloride in chloroform (solvent)
+ HChl  1.008    ;     hydrogen in chloroform (solvent)
+SDmso  32.06000 ;     DMSO Sulphur (solvent)
+CDmso  15.03500 ;     DMSO Carbon (solvent)
+ODmso  15.99940 ;     DMSO Oxygen (solvent)
+ CCl4  12.011   ;     carbon in carbontetrachloride (solvent)
+CLCl4  35.453   ;     chloride in carbontetrachloride (solvent)
    SI  28.08   ;     silicon
  MNH3   0       ;     Dummy mass in rigid tetraedrical NH3 group
    MW   0       ;     Dummy mass in rigid tyrosine rings
index 443bfb7650e0f1efadec3292008f8d03ccc3ee2c..9ba98bb4bb7cd02176ad34117128d8f178f85864 100644 (file)
     F    9     0.000      0.000     A  0.0011778624  7.6073284e-07
    CL   17     0.000      0.000     A  0.0087647044  1.5295921e-05
    BR   35     0.000      0.000     A  0.0011792356  6.5480464e-05
- CMET    5     0.000      0.000     A  0.0088755241  2.0852922e-05
- OMET    8     0.000      0.000     A  0.0022619536  1.505529e-06
+ CMet    5     0.000      0.000     A  0.0088755241  2.0852922e-05
+ OMet    8     0.000      0.000     A  0.0022619536  1.505529e-06
   NA+   11     0.000      0.000     A  7.2063121e-05  2.1025e-08
   CL-   17     0.000      0.000     A  0.01380625  0.0001069156
- CCHL    6     0.000      0.000     A  0.0026308693  4.064256e-06
-CLCHL   17     0.000      0.000     A  0.0083066819  1.3764842e-05
- HCHL    1     0.000      0.000     A  3.76996e-05  4.2999495e-09
-SDMSO   16     0.000      0.000     A  0.010561673  2.149806e-05
-CDMSO    6     0.000      0.000     A  0.0090514293  2.175756e-05
-ODMSO    8     0.000      0.000     A  0.0022707131  7.5144626e-07
- CCL4    6     0.000      0.000     A  0.0026308693  7.5999462e-06
-CLCL4   17     0.000      0.000     A  0.0076040144  1.2767758e-05
+ CChl    6     0.000      0.000     A  0.0026308693  4.064256e-06
+CLChl   17     0.000      0.000     A  0.0083066819  1.3764842e-05
+ HChl    1     0.000      0.000     A  3.76996e-05  4.2999495e-09
+SDmso   16     0.000      0.000     A  0.010561673  2.149806e-05
+CDmso    6     0.000      0.000     A  0.0090514293  2.175756e-05
+ODmso    8     0.000      0.000     A  0.0022707131  7.5144626e-07
+ CCl4    6     0.000      0.000     A  0.0026308693  7.5999462e-06
+CLCl4   17     0.000      0.000     A  0.0076040144  1.2767758e-05
  CH2r    6     0.000      0.000     A  0.0073342096  2.8058209e-05
   CH0    6     0.000      0.000     A  0.0023970816  0.0002053489
    SI   14     0.000      0.000     A  0.01473796  2.2193521e-05
@@ -516,69 +516,69 @@ CLCL4   17        0.000      0.000     A  0.0076040144  1.2767758e-05
       BR       AR  1  0.002718011  2.5392696e-05
       BR        F  1  0.0011785488  7.0578424e-06
       BR       CL  1  0.0032149108  3.1647812e-05
-    CMET        O  1  0.0044806276  3.9322131e-06
-    CMET       OM  1  0.0044806276  3.9322131e-06
-    CMET       OA  1  0.0044806276  5.1373125e-06
-    CMET       OW  1  0.0048197836  7.4114295e-06
-    CMET        N  1  0.0046502056  5.9410165e-06
-    CMET       NT  1  0.0046502056  5.9410165e-06
-    CMET       NL  1  0.0046502056  5.9410165e-06
-    CMET       NR  1  0.0046502056  5.9410165e-06
-    CMET       NZ  1  0.0046502056  5.9410165e-06
-    CMET       NE  1  0.0046502056  5.9410165e-06
-    CMET        C  1  0.0045578798  8.3886605e-06
-    CMET      CH1  1  0.007338959  4.4980025e-05
-    CMET      CH2  1  0.0081416282  2.6613562e-05
-    CMET      CH3  1  0.0092372905  2.3572273e-05
-    CMET      CH4  1  0.010815308  2.6768823e-05
-    CMET      CR1  1  0.0069950925  1.7754552e-05
-    CMET       HC  1  0.000866732  5.616795e-07
-    CMET        H  1           0           0
-    CMET      DUM  1           0           0
-    CMET        S  1  0.0094134632  1.6512464e-05
-    CMET     CU1+  1  0.0019265945  3.2691574e-07
-    CMET     CU2+  1  0.0019265945  3.2691574e-07
-    CMET       FE  1           0           0
-    CMET     ZN2+  1  0.0019265945  4.4368114e-07
-    CMET     MG2+  1  0.0007612168  2.6659227e-07
-    CMET     CA2+  1  0.002986457  3.222579e-06
-    CMET        P  1  0.011437094  2.1512782e-05
-    CMET       AR  1  0.0074567215  1.4329677e-05
-    CMET        F  1  0.0032332872  3.9829013e-06
-    CMET       CL  1  0.0088199402  1.7859582e-05
-    CMET       BR  1  0.0032351714  3.6952118e-05
-    OMET        O  1  0.0022619536  1.380375e-06
-    OMET       OM  1  0.0022619536  2.258907e-06
-    OMET       OA  1  0.0022619536  1.505529e-06
-    OMET       OW  1  0.0024331696  1.991421e-06
-    OMET        N  1  0.0023475616  2.384061e-06
-    OMET       NT  1  0.0023475616  2.76075e-06
-    OMET       NL  1  0.0023475616  3.764436e-06
-    OMET       NR  1  0.0023475616  2.258907e-06
-    OMET       NZ  1  0.0023475616  2.635596e-06
-    OMET       NE  1  0.0023475616  2.434368e-06
-    OMET        C  1  0.0023009528  2.066625e-06
-    OMET      CH1  1  0.003704924  1.108125e-05
-    OMET      CH2  1  0.0041101352  6.5565e-06
-    OMET      CH3  1  0.004663258  5.80725e-06
-    OMET      CH4  1  0.005459888  6.59475e-06
-    OMET      CR1  1  0.00353133   4.374e-06
-    OMET       HC  1  0.000437552  1.38375e-07
-    OMET        H  1           0           0
-    OMET      DUM  1           0           0
-    OMET        S  1  0.0047521952   4.068e-06
-    OMET     CU1+  1  0.000972602  2.76075e-07
-    OMET     CU2+  1  0.000972602  5.019657e-07
-    OMET       FE  1           0           0
-    OMET     ZN2+  1  0.000972602  1.1921532e-07
-    OMET     MG2+  1  0.0003842848  7.163226e-08
-    OMET     CA2+  1  0.001507652  8.658939e-07
-    OMET        P  1  0.005773784  5.780397e-06
-    OMET       AR  1  0.003764374  3.53025e-06
-    OMET        F  1  0.0016322592  1.505529e-06
-    OMET       CL  1  0.0044525672  4.798797e-06
-    OMET       BR  1  0.0016332104  9.928884e-06
-    OMET     CMET  1  0.0044806276  5.1373125e-06
+    CMet        O  1  0.0044806276  3.9322131e-06
+    CMet       OM  1  0.0044806276  3.9322131e-06
+    CMet       OA  1  0.0044806276  5.1373125e-06
+    CMet       OW  1  0.0048197836  7.4114295e-06
+    CMet        N  1  0.0046502056  5.9410165e-06
+    CMet       NT  1  0.0046502056  5.9410165e-06
+    CMet       NL  1  0.0046502056  5.9410165e-06
+    CMet       NR  1  0.0046502056  5.9410165e-06
+    CMet       NZ  1  0.0046502056  5.9410165e-06
+    CMet       NE  1  0.0046502056  5.9410165e-06
+    CMet        C  1  0.0045578798  8.3886605e-06
+    CMet      CH1  1  0.007338959  4.4980025e-05
+    CMet      CH2  1  0.0081416282  2.6613562e-05
+    CMet      CH3  1  0.0092372905  2.3572273e-05
+    CMet      CH4  1  0.010815308  2.6768823e-05
+    CMet      CR1  1  0.0069950925  1.7754552e-05
+    CMet       HC  1  0.000866732  5.616795e-07
+    CMet        H  1           0           0
+    CMet      DUM  1           0           0
+    CMet        S  1  0.0094134632  1.6512464e-05
+    CMet     CU1+  1  0.0019265945  3.2691574e-07
+    CMet     CU2+  1  0.0019265945  3.2691574e-07
+    CMet       FE  1           0           0
+    CMet     ZN2+  1  0.0019265945  4.4368114e-07
+    CMet     MG2+  1  0.0007612168  2.6659227e-07
+    CMet     CA2+  1  0.002986457  3.222579e-06
+    CMet        P  1  0.011437094  2.1512782e-05
+    CMet       AR  1  0.0074567215  1.4329677e-05
+    CMet        F  1  0.0032332872  3.9829013e-06
+    CMet       CL  1  0.0088199402  1.7859582e-05
+    CMet       BR  1  0.0032351714  3.6952118e-05
+    OMet        O  1  0.0022619536  1.380375e-06
+    OMet       OM  1  0.0022619536  2.258907e-06
+    OMet       OA  1  0.0022619536  1.505529e-06
+    OMet       OW  1  0.0024331696  1.991421e-06
+    OMet        N  1  0.0023475616  2.384061e-06
+    OMet       NT  1  0.0023475616  2.76075e-06
+    OMet       NL  1  0.0023475616  3.764436e-06
+    OMet       NR  1  0.0023475616  2.258907e-06
+    OMet       NZ  1  0.0023475616  2.635596e-06
+    OMet       NE  1  0.0023475616  2.434368e-06
+    OMet        C  1  0.0023009528  2.066625e-06
+    OMet      CH1  1  0.003704924  1.108125e-05
+    OMet      CH2  1  0.0041101352  6.5565e-06
+    OMet      CH3  1  0.004663258  5.80725e-06
+    OMet      CH4  1  0.005459888  6.59475e-06
+    OMet      CR1  1  0.00353133   4.374e-06
+    OMet       HC  1  0.000437552  1.38375e-07
+    OMet        H  1           0           0
+    OMet      DUM  1           0           0
+    OMet        S  1  0.0047521952   4.068e-06
+    OMet     CU1+  1  0.000972602  2.76075e-07
+    OMet     CU2+  1  0.000972602  5.019657e-07
+    OMet       FE  1           0           0
+    OMet     ZN2+  1  0.000972602  1.1921532e-07
+    OMet     MG2+  1  0.0003842848  7.163226e-08
+    OMet     CA2+  1  0.001507652  8.658939e-07
+    OMet        P  1  0.005773784  5.780397e-06
+    OMet       AR  1  0.003764374  3.53025e-06
+    OMet        F  1  0.0016322592  1.505529e-06
+    OMet       CL  1  0.0044525672  4.798797e-06
+    OMet       BR  1  0.0016332104  9.928884e-06
+    OMet     CMet  1  0.0044806276  5.1373125e-06
      NA+        O  1  0.00040373684  1.63125e-07
      NA+       OM  1  0.00040373684  4.4486e-07
      NA+       OA  1  0.00040373684  1.77915e-07
@@ -610,8 +610,8 @@ CLCL4   17          0.000      0.000     A  0.0076040144  1.2767758e-05
      NA+        F  1  0.00029134248  1.77915e-07
      NA+       CL  1  0.00079474018  5.67095e-07
      NA+       BR  1  0.00029151226  1.17334e-06
-     NA+     CMET  1  0.00079974869  6.621425e-07
-     NA+     OMET  1  0.00040373684  1.77915e-07
+     NA+     CMet  1  0.00079974869  6.621425e-07
+     NA+     OMet  1  0.00040373684  1.77915e-07
      CL-        O  1   0.0055883  8.903774e-06
      CL-       OM  1   0.0055883  8.903774e-06
      CL-       OA  1   0.0055883  1.268718e-05
@@ -643,317 +643,317 @@ CLCL4   17      0.000      0.000     A  0.0076040144  1.2767758e-05
      CL-        F  1   0.0040326  9.018548e-06
      CL-       CL  1  0.01100035  4.043974e-05
      CL-       BR  1  0.00403495  8.367128e-05
-     CL-     CMET  1  0.011069675  4.721761e-05
-     CL-     OMET  1   0.0055883  1.268718e-05
+     CL-     CMet  1  0.011069675  4.721761e-05
+     CL-     OMet  1   0.0055883  1.268718e-05
      CL-      NA+  1  0.0009974575  1.4993e-06
-    CCHL        O  1  0.0024394475  1.7359776e-06
-    CCHL       OM  1  0.0024394475  1.7359776e-06
-    CCHL       OA  1  0.0024394475   2.268e-06
-    CCHL       OW  1  0.0026240987  3.271968e-06
-    CCHL        N  1  0.0025317731  2.622816e-06
-    CCHL       NT  1  0.0025317731  2.622816e-06
-    CCHL       NL  1  0.0025317731  2.622816e-06
-    CCHL       NR  1  0.0025317731  2.622816e-06
-    CCHL       NZ  1  0.0025317731  2.622816e-06
-    CCHL       NE  1  0.0025317731  2.622816e-06
-    CCHL        C  1  0.002481507  3.703392e-06
-    CCHL      CH1  1  0.0039956468  1.98576e-05
-    CCHL      CH2  1  0.0044326546  1.1749248e-05
-    CCHL      CH3  1  0.0050291806  1.0406592e-05
-    CCHL      CH4  1  0.0058883216  1.1817792e-05
-    CCHL      CR1  1  0.003808431  7.838208e-06
-    CCHL       HC  1  0.0004718864  2.47968e-07
-    CCHL        H  1           0           0
-    CCHL      DUM  1           0           0
-    CCHL        S  1  0.0051250966  7.289856e-06
-    CCHL     CU1+  1  0.0010489214  1.4432544e-07
-    CCHL     CU2+  1  0.0010489214  1.4432544e-07
-    CCHL       FE  1           0           0
-    CCHL     ZN2+  1  0.0010489214  1.9587456e-07
-    CCHL     MG2+  1  0.00041443936  1.1769408e-07
-    CCHL     CA2+  1  0.0016259564  1.4226912e-06
-    CCHL        P  1  0.0062268488  9.497376e-06
-    CCHL       AR  1  0.0040597618  6.326208e-06
-    CCHL        F  1  0.0017603414  1.7583552e-06
-    CCHL       CL  1  0.004801957  7.884576e-06
-    CCHL       BR  1  0.0017613673  1.6313472e-05
-    CCHL     CMET  1  0.0048322193  9.206064e-06
-    CCHL     OMET  1  0.0024394475   2.268e-06
-    CCHL      NA+  1  0.00043541779  2.9232e-07
-    CCHL      CL-  1  0.00602681  2.084544e-05
-   CLCHL        O  1  0.004334666  3.1947671e-06
-   CLCHL       OM  1  0.004334666  3.1947671e-06
-   CLCHL       OA  1  0.004334666  4.1738625e-06
-   CLCHL       OW  1  0.0046627736  6.0214923e-06
-   CLCHL        N  1  0.0044987198  4.8268401e-06
-   CLCHL       NT  1  0.0044987198  4.8268401e-06
-   CLCHL       NL  1  0.0044987198  4.8268401e-06
-   CLCHL       NR  1  0.0044987198  4.8268401e-06
-   CLCHL       NZ  1  0.0044987198  4.8268401e-06
-   CLCHL       NE  1  0.0044987198  4.8268401e-06
-   CLCHL        C  1  0.0044094016  6.8154537e-06
-   CLCHL      CH1  1  0.0070998839  3.6544485e-05
-   CLCHL      CH2  1  0.0078764052  2.1622463e-05
-   CLCHL      CH3  1  0.0089363751  1.9151536e-05
-   CLCHL      CH4  1  0.010462987  2.1748606e-05
-   CLCHL      CR1  1  0.0067672192  1.4424869e-05
-   CLCHL       HC  1  0.0008384972  4.563423e-07
-   CLCHL        H  1           0           0
-   CLCHL      DUM  1           0           0
-   CLCHL        S  1  0.0091068087  1.3415722e-05
-   CLCHL     CU1+  1  0.0018638335  2.6560606e-07
-   CLCHL     CU2+  1  0.0018638335  2.6560606e-07
-   CLCHL       FE  1           0           0
-   CLCHL     ZN2+  1  0.0018638335  3.6047332e-07
-   CLCHL     MG2+  1  0.00073641928  2.1659564e-07
-   CLCHL     CA2+  1  0.0028891697  2.6182176e-06
-   CLCHL        P  1  0.011064517  1.7478281e-05
-   CLCHL       AR  1  0.0072138101  1.1642294e-05
-   CLCHL        F  1  0.0031279591  3.2359492e-06
-   CLCHL       CL  1  0.0085326204  1.4510201e-05
-   CLCHL       BR  1  0.0031297819  3.0022129e-05
-   CLCHL     CMET  1  0.0085863936  1.6942172e-05
-   CLCHL     OMET  1  0.004334666  4.1738625e-06
-   CLCHL      NA+  1  0.00077369595  5.379645e-07
-   CLCHL      CL-  1  0.010709067  3.8362434e-05
-   CLCHL     CCHL  1  0.0046748042  7.4795616e-06
-    HCHL        O  1  0.0002920184  5.6465771e-08
-    HCHL       OM  1  0.0002920184  5.6465771e-08
-    HCHL       OA  1  0.0002920184  7.377075e-08
-    HCHL       OW  1  0.0003141224  1.064266e-07
-    HCHL        N  1  0.0003030704  8.5311774e-08
-    HCHL       NT  1  0.0003030704  8.5311774e-08
-    HCHL       NL  1  0.0003030704  8.5311774e-08
-    HCHL       NR  1  0.0003030704  8.5311774e-08
-    HCHL       NZ  1  0.0003030704  8.5311774e-08
-    HCHL       NE  1  0.0003030704  8.5311774e-08
-    HCHL        C  1  0.0002970532  1.2045944e-07
-    HCHL      CH1  1  0.000478306  6.459039e-07
-    HCHL      CH2  1  0.0005306188  3.8216527e-07
-    HCHL      CH3  1  0.000602027  3.3849299e-07
-    HCHL      CH4  1  0.000704872  3.8439479e-07
-    HCHL      CR1  1  0.000455895  2.5495171e-07
-    HCHL       HC  1  5.6488e-05  8.065602e-09
-    HCHL        H  1           0           0
-    HCHL      DUM  1           0           0
-    HCHL        S  1  0.0006135088  2.3711558e-07
-    HCHL     CU1+  1  0.000125563  4.6944427e-09
-    HCHL     CU2+  1  0.000125563  4.6944427e-09
-    HCHL       FE  1           0           0
-    HCHL     ZN2+  1  0.000125563  6.3711698e-09
-    HCHL     MG2+  1  4.96112e-05  3.8282101e-09
-    HCHL     CA2+  1  0.000194638  4.6275572e-08
-    HCHL        P  1  0.000745396  3.0891911e-07
-    HCHL       AR  1  0.000485981  2.0577121e-07
-    HCHL        F  1  0.0002107248  5.7193643e-08
-    HCHL       CL  1  0.0005748268  2.5645991e-07
-    HCHL       BR  1  0.0002108476  5.3062481e-07
-    HCHL     CMET  1  0.0005784494  2.9944367e-07
-    HCHL     OMET  1  0.0002920184  7.377075e-08
-    HCHL      NA+  1  5.212246e-05  9.50823e-09
-    HCHL      CL-  1  0.00072145  6.7803516e-07
-    HCHL     CCHL  1  0.00031493288  1.3219718e-07
-    HCHL    CLCHL  1  0.00055960574  2.432861e-07
-   SDMSO        O  1  0.0048877412  3.9925763e-06
-   SDMSO       OM  1  0.0048877412  3.9925763e-06
-   SDMSO       OA  1  0.0048877412  5.216175e-06
-   SDMSO       OW  1  0.0052577132  7.5252018e-06
-   SDMSO        N  1  0.0050727272  6.0322166e-06
-   SDMSO       NT  1  0.0050727272  6.0322166e-06
-   SDMSO       NL  1  0.0050727272  6.0322166e-06
-   SDMSO       NR  1  0.0050727272  6.0322166e-06
-   SDMSO       NZ  1  0.0050727272  6.0322166e-06
-   SDMSO       NE  1  0.0050727272  6.0322166e-06
-   SDMSO        C  1  0.0049720126  8.5174342e-06
-   SDMSO      CH1  1  0.008005783  4.567051e-05
-   SDMSO      CH2  1  0.0088813834  2.7022105e-05
-   SDMSO      CH3  1  0.010076599  2.3934129e-05
-   SDMSO      CH4  1  0.011797996  2.7179749e-05
-   SDMSO      CR1  1  0.0076306725  1.8027101e-05
-   SDMSO       HC  1  0.000945484  5.703018e-07
-   SDMSO        H  1           0           0
-   SDMSO      DUM  1           0           0
-   SDMSO        S  1  0.010268778  1.6765946e-05
-   SDMSO     CU1+  1  0.0021016465  3.3193419e-07
-   SDMSO     CU2+  1  0.0021016465  3.3193419e-07
-   SDMSO       FE  1           0           0
-   SDMSO     ZN2+  1  0.0021016465  4.5049206e-07
-   SDMSO     MG2+  1  0.0008303816  2.7068471e-07
-   SDMSO     CA2+  1  0.003257809  3.2720486e-06
-   SDMSO        P  1  0.012476278  2.1843023e-05
-   SDMSO       AR  1  0.0081342455  1.4549651e-05
-   SDMSO        F  1  0.0035270664  4.0440425e-06
-   SDMSO       CL  1  0.0096213274  1.8133743e-05
-   SDMSO       BR  1  0.0035291218  3.7519367e-05
-   SDMSO     CMET  1  0.0096819617  2.1173034e-05
-   SDMSO     OMET  1  0.0048877412  5.216175e-06
-   SDMSO      NA+  1  0.00087241453  6.72307e-07
-   SDMSO      CL-  1  0.012075475  4.7942444e-05
-   SDMSO     CCHL  1  0.0052712788  9.3473856e-06
-   SDMSO    CLCHL  1  0.0093665606  1.720225e-05
-   SDMSO     HCHL  1  0.0006310078  3.0404041e-07
-   CDMSO        O  1  0.0045248108  4.016601e-06
-   CDMSO       OM  1  0.0045248108  4.016601e-06
-   CDMSO       OA  1  0.0045248108  5.2475625e-06
-   CDMSO       OW  1  0.0048673112  7.5704835e-06
-   CDMSO        N  1  0.004696061  6.0685145e-06
-   CDMSO       NT  1  0.004696061  6.0685145e-06
-   CDMSO       NL  1  0.004696061  6.0685145e-06
-   CDMSO       NR  1  0.004696061  6.0685145e-06
-   CDMSO       NZ  1  0.004696061  6.0685145e-06
-   CDMSO       NE  1  0.004696061  6.0685145e-06
-   CDMSO        C  1  0.0046028248  8.5686865e-06
-   CDMSO      CH1  1  0.0074113281  4.5945325e-05
-   CDMSO      CH2  1  0.0082219124  2.7184706e-05
-   CDMSO      CH3  1  0.009328379  2.4078149e-05
-   CDMSO      CH4  1  0.010921957  2.7343299e-05
-   CDMSO      CR1  1  0.0070640708  1.8135576e-05
-   CDMSO       HC  1  0.0008752788  5.737335e-07
-   CDMSO        H  1           0           0
-   CDMSO      DUM  1           0           0
-   CDMSO        S  1  0.0095062889  1.6866832e-05
-   CDMSO     CU1+  1  0.0019455925  3.3393156e-07
-   CDMSO     CU2+  1  0.0019455925  3.3393156e-07
-   CDMSO       FE  1           0           0
-   CDMSO     ZN2+  1  0.0019455925  4.5320282e-07
-   CDMSO     MG2+  1  0.00076872312  2.7231351e-07
-   CDMSO     CA2+  1  0.0030159063  3.2917377e-06
-   CDMSO        P  1  0.011549875  2.197446e-05
-   CDMSO       AR  1  0.0075302519  1.4637201e-05
-   CDMSO        F  1  0.0032651705  4.0683769e-06
-   CDMSO       CL  1  0.0089069132  1.824286e-05
-   CDMSO       BR  1  0.0032670733  3.7745134e-05
-   CDMSO     CMET  1  0.0089630452  2.1300439e-05
-   CDMSO     OMET  1  0.0045248108  5.2475625e-06
-   CDMSO      NA+  1  0.00080763497  6.763525e-07
-   CDMSO      CL-  1  0.011178832  4.823093e-05
-   CDMSO     CCHL  1  0.0048798696  9.403632e-06
-   CDMSO    CLCHL  1  0.0086710636  1.7305761e-05
-   CDMSO     HCHL  1  0.00058415346  3.0586992e-07
-   CDMSO    SDMSO  1  0.009777435  2.1627421e-05
-   ODMSO        O  1  0.0022663291  7.4645315e-07
-   ODMSO       OM  1  0.0022663291  7.4645315e-07
-   ODMSO       OA  1  0.0022663291  1.380375e-06
-   ODMSO       OW  1  0.0024378763  1.825875e-06
-   ODMSO        N  1  0.0023521027  2.185875e-06
-   ODMSO       NT  1  0.0023521027  2.53125e-06
-   ODMSO       NL  1  0.0023521027  3.4515e-06
-   ODMSO       NR  1  0.0023521027  2.071125e-06
-   ODMSO       NZ  1  0.0023521027  2.4165e-06
-   ODMSO       NE  1  0.0023521027   2.232e-06
-   ODMSO        C  1  0.0023054038  1.5924218e-06
-   ODMSO      CH1  1  0.0037120908  8.538571e-06
-   ODMSO      CH2  1  0.0041180858  5.0520601e-06
-   ODMSO      CH3  1  0.0046722786  4.4747313e-06
-   ODMSO      CH4  1  0.0054704496  5.0815333e-06
-   ODMSO      CR1  1  0.003538161  3.3703517e-06
-   ODMSO       HC  1  0.0004383984  1.0662378e-07
-   ODMSO        H  1           0           0
-   ODMSO      DUM  1           0           0
-   ODMSO        S  1  0.0047613878  3.1345658e-06
-   ODMSO     CU1+  1  0.0009744834  2.53125e-07
-   ODMSO     CU2+  1  0.0009744834  4.602375e-07
-   ODMSO       FE  1           0           0
-   ODMSO     ZN2+  1  0.0009744834  1.09305e-07
-   ODMSO     MG2+  1  0.00038502816  6.56775e-08
-   ODMSO     CA2+  1  0.0015105684  7.939125e-07
-   ODMSO        P  1  0.0057849528  5.299875e-06
-   ODMSO       AR  1  0.0037716558  2.7202067e-06
-   ODMSO        F  1  0.0016354166  7.5607529e-07
-   ODMSO       CL  1  0.0044611802  3.3902895e-06
-   ODMSO       BR  1  0.0016363697  7.0146311e-06
-   ODMSO     CMET  1  0.0044892949  3.9585162e-06
-   ODMSO     OMET  1  0.0022663291  1.380375e-06
-   ODMSO      NA+  1  0.00040451783  1.63125e-07
-   ODMSO      CL-  1  0.00559911  8.9633324e-06
-   ODMSO     CCHL  1  0.0024441664  1.7475898e-06
-   ODMSO    CLCHL  1  0.0043430509  3.2161373e-06
-   ODMSO     HCHL  1  0.00029258328  5.6843478e-08
-   ODMSO    SDMSO  1  0.004897196  4.0192831e-06
-   ODMSO    CDMSO  1  0.0045335636  4.0434685e-06
-    CCL4        O  1  0.0024394475  2.3738805e-06
-    CCL4       OM  1  0.0024394475  2.3738805e-06
-    CCL4       OA  1  0.0024394475  3.1014e-06
-    CCL4       OW  1  0.0026240987  4.4742864e-06
-    CCL4        N  1  0.0025317731  3.5865968e-06
-    CCL4       NT  1  0.0025317731  3.5865968e-06
-    CCL4       NL  1  0.0025317731  3.5865968e-06
-    CCL4       NR  1  0.0025317731  3.5865968e-06
-    CCL4       NZ  1  0.0025317731  3.5865968e-06
-    CCL4       NE  1  0.0025317731  3.5865968e-06
-    CCL4        C  1  0.002481507  5.0642416e-06
-    CCL4      CH1  1  0.0039956468  2.715448e-05
-    CCL4      CH2  1  0.0044326546  1.606663e-05
-    CCL4      CH3  1  0.0050291806  1.4230602e-05
-    CCL4      CH4  1  0.0058883216  1.6160362e-05
-    CCL4      CR1  1  0.003808431  1.0718438e-05
-    CCL4       HC  1  0.0004718864  3.390864e-07
-    CCL4        H  1           0           0
-    CCL4      DUM  1           0           0
-    CCL4        S  1  0.0051250966  9.9685888e-06
-    CCL4     CU1+  1  0.0010489214  1.9735931e-07
-    CCL4     CU2+  1  0.0010489214  1.9735931e-07
-    CCL4       FE  1           0           0
-    CCL4     ZN2+  1  0.0010489214  2.6785069e-07
-    CCL4     MG2+  1  0.00041443936  1.6094198e-07
-    CCL4     CA2+  1  0.0016259564  1.9454738e-06
-    CCL4        P  1  0.0062268488  1.2987285e-05
-    CCL4       AR  1  0.0040597618  8.6508384e-06
-    CCL4        F  1  0.0017603414  2.404481e-06
-    CCL4       CL  1  0.004801957  1.0781845e-05
-    CCL4       BR  1  0.0017613673  2.2308026e-05
-    CCL4     CMET  1  0.0048322193  1.2588927e-05
-    CCL4     OMET  1  0.0024394475  3.1014e-06
-    CCL4      NA+  1  0.00043541779  3.99736e-07
-    CCL4      CL-  1  0.00602681  2.8505312e-05
-    CCL4     CCHL  1  0.0026308693  5.5577088e-06
-    CCL4    CLCHL  1  0.0046748042  1.0228004e-05
-    CCL4     HCHL  1  0.00031493288  1.807744e-07
-    CCL4    SDMSO  1  0.0052712788  1.2782179e-05
-    CCL4    CDMSO  1  0.0048798696  1.2859094e-05
-    CCL4    ODMSO  1  0.0024441664  2.3897596e-06
-   CLCL4        O  1  0.0041472796  3.0768825e-06
-   CLCL4       OM  1  0.0041472796  3.0768825e-06
-   CLCL4       OA  1  0.0041472796  4.01985e-06
-   CLCL4       OW  1  0.0044612032  5.7993036e-06
-   CLCL4        N  1  0.0043042414  4.6487332e-06
-   CLCL4       NT  1  0.0043042414  4.6487332e-06
-   CLCL4       NL  1  0.0043042414  4.6487332e-06
-   CLCL4       NR  1  0.0043042414  4.6487332e-06
-   CLCL4       NZ  1  0.0043042414  4.6487332e-06
-   CLCL4       NE  1  0.0043042414  4.6487332e-06
-   CLCL4        C  1  0.0042187844  6.5639684e-06
-   CLCL4      CH1  1  0.0067929579  3.519602e-05
-   CLCL4      CH2  1  0.0075359104  2.082461e-05
-   CLCL4      CH3  1  0.008550058  1.8444858e-05
-   CLCL4      CH4  1  0.010010675  2.0946098e-05
-   CLCL4      CR1  1  0.0064746742  1.3892602e-05
-   CLCL4       HC  1  0.0008022492  4.395036e-07
-   CLCL4        H  1           0           0
-   CLCL4      DUM  1           0           0
-   CLCL4        S  1  0.0087131239  1.2920691e-05
-   CLCL4     CU1+  1  0.0017832604  2.5580539e-07
-   CLCL4     CU2+  1  0.0017832604  2.5580539e-07
-   CLCL4       FE  1           0           0
-   CLCL4     ZN2+  1  0.0017832604  3.4717211e-07
-   CLCL4     MG2+  1  0.00070458408  2.0860342e-07
-   CLCL4     CA2+  1  0.0027642717  2.5216072e-06
-   CLCL4        P  1  0.010586201  1.6833345e-05
-   CLCL4       AR  1  0.0069019592  1.1212702e-05
-   CLCL4        F  1  0.0029927383  3.116545e-06
-   CLCL4       CL  1  0.0081637576  1.3974785e-05
-   CLCL4       BR  1  0.0029944823  2.8914334e-05
-   CLCL4     CMET  1  0.0082152062  1.6317018e-05
-   CLCL4     OMET  1  0.0041472796  4.01985e-06
-   CLCL4      NA+  1  0.00074024929  5.18114e-07
-   CLCL4      CL-  1  0.010246117  3.6946888e-05
-   CLCL4     CCHL  1  0.0044727137  7.2035712e-06
-   CLCL4    CLCHL  1  0.0079475863  1.3256929e-05
-   CLCL4     HCHL  1  0.00053541414  2.3430902e-07
-   CLCL4    SDMSO  1  0.0089616468  1.6567499e-05
-   CLCL4    CDMSO  1  0.0082962159  1.6667191e-05
-   CLCL4    ODMSO  1  0.0041553021  3.0974642e-06
-   CLCL4     CCL4  1  0.0044727137  9.8505978e-06
+    CChl        O  1  0.0024394475  1.7359776e-06
+    CChl       OM  1  0.0024394475  1.7359776e-06
+    CChl       OA  1  0.0024394475   2.268e-06
+    CChl       OW  1  0.0026240987  3.271968e-06
+    CChl        N  1  0.0025317731  2.622816e-06
+    CChl       NT  1  0.0025317731  2.622816e-06
+    CChl       NL  1  0.0025317731  2.622816e-06
+    CChl       NR  1  0.0025317731  2.622816e-06
+    CChl       NZ  1  0.0025317731  2.622816e-06
+    CChl       NE  1  0.0025317731  2.622816e-06
+    CChl        C  1  0.002481507  3.703392e-06
+    CChl      CH1  1  0.0039956468  1.98576e-05
+    CChl      CH2  1  0.0044326546  1.1749248e-05
+    CChl      CH3  1  0.0050291806  1.0406592e-05
+    CChl      CH4  1  0.0058883216  1.1817792e-05
+    CChl      CR1  1  0.003808431  7.838208e-06
+    CChl       HC  1  0.0004718864  2.47968e-07
+    CChl        H  1           0           0
+    CChl      DUM  1           0           0
+    CChl        S  1  0.0051250966  7.289856e-06
+    CChl     CU1+  1  0.0010489214  1.4432544e-07
+    CChl     CU2+  1  0.0010489214  1.4432544e-07
+    CChl       FE  1           0           0
+    CChl     ZN2+  1  0.0010489214  1.9587456e-07
+    CChl     MG2+  1  0.00041443936  1.1769408e-07
+    CChl     CA2+  1  0.0016259564  1.4226912e-06
+    CChl        P  1  0.0062268488  9.497376e-06
+    CChl       AR  1  0.0040597618  6.326208e-06
+    CChl        F  1  0.0017603414  1.7583552e-06
+    CChl       CL  1  0.004801957  7.884576e-06
+    CChl       BR  1  0.0017613673  1.6313472e-05
+    CChl     CMet  1  0.0048322193  9.206064e-06
+    CChl     OMet  1  0.0024394475   2.268e-06
+    CChl      NA+  1  0.00043541779  2.9232e-07
+    CChl      CL-  1  0.00602681  2.084544e-05
+   CLChl        O  1  0.004334666  3.1947671e-06
+   CLChl       OM  1  0.004334666  3.1947671e-06
+   CLChl       OA  1  0.004334666  4.1738625e-06
+   CLChl       OW  1  0.0046627736  6.0214923e-06
+   CLChl        N  1  0.0044987198  4.8268401e-06
+   CLChl       NT  1  0.0044987198  4.8268401e-06
+   CLChl       NL  1  0.0044987198  4.8268401e-06
+   CLChl       NR  1  0.0044987198  4.8268401e-06
+   CLChl       NZ  1  0.0044987198  4.8268401e-06
+   CLChl       NE  1  0.0044987198  4.8268401e-06
+   CLChl        C  1  0.0044094016  6.8154537e-06
+   CLChl      CH1  1  0.0070998839  3.6544485e-05
+   CLChl      CH2  1  0.0078764052  2.1622463e-05
+   CLChl      CH3  1  0.0089363751  1.9151536e-05
+   CLChl      CH4  1  0.010462987  2.1748606e-05
+   CLChl      CR1  1  0.0067672192  1.4424869e-05
+   CLChl       HC  1  0.0008384972  4.563423e-07
+   CLChl        H  1           0           0
+   CLChl      DUM  1           0           0
+   CLChl        S  1  0.0091068087  1.3415722e-05
+   CLChl     CU1+  1  0.0018638335  2.6560606e-07
+   CLChl     CU2+  1  0.0018638335  2.6560606e-07
+   CLChl       FE  1           0           0
+   CLChl     ZN2+  1  0.0018638335  3.6047332e-07
+   CLChl     MG2+  1  0.00073641928  2.1659564e-07
+   CLChl     CA2+  1  0.0028891697  2.6182176e-06
+   CLChl        P  1  0.011064517  1.7478281e-05
+   CLChl       AR  1  0.0072138101  1.1642294e-05
+   CLChl        F  1  0.0031279591  3.2359492e-06
+   CLChl       CL  1  0.0085326204  1.4510201e-05
+   CLChl       BR  1  0.0031297819  3.0022129e-05
+   CLChl     CMet  1  0.0085863936  1.6942172e-05
+   CLChl     OMet  1  0.004334666  4.1738625e-06
+   CLChl      NA+  1  0.00077369595  5.379645e-07
+   CLChl      CL-  1  0.010709067  3.8362434e-05
+   CLChl     CChl  1  0.0046748042  7.4795616e-06
+    HChl        O  1  0.0002920184  5.6465771e-08
+    HChl       OM  1  0.0002920184  5.6465771e-08
+    HChl       OA  1  0.0002920184  7.377075e-08
+    HChl       OW  1  0.0003141224  1.064266e-07
+    HChl        N  1  0.0003030704  8.5311774e-08
+    HChl       NT  1  0.0003030704  8.5311774e-08
+    HChl       NL  1  0.0003030704  8.5311774e-08
+    HChl       NR  1  0.0003030704  8.5311774e-08
+    HChl       NZ  1  0.0003030704  8.5311774e-08
+    HChl       NE  1  0.0003030704  8.5311774e-08
+    HChl        C  1  0.0002970532  1.2045944e-07
+    HChl      CH1  1  0.000478306  6.459039e-07
+    HChl      CH2  1  0.0005306188  3.8216527e-07
+    HChl      CH3  1  0.000602027  3.3849299e-07
+    HChl      CH4  1  0.000704872  3.8439479e-07
+    HChl      CR1  1  0.000455895  2.5495171e-07
+    HChl       HC  1  5.6488e-05  8.065602e-09
+    HChl        H  1           0           0
+    HChl      DUM  1           0           0
+    HChl        S  1  0.0006135088  2.3711558e-07
+    HChl     CU1+  1  0.000125563  4.6944427e-09
+    HChl     CU2+  1  0.000125563  4.6944427e-09
+    HChl       FE  1           0           0
+    HChl     ZN2+  1  0.000125563  6.3711698e-09
+    HChl     MG2+  1  4.96112e-05  3.8282101e-09
+    HChl     CA2+  1  0.000194638  4.6275572e-08
+    HChl        P  1  0.000745396  3.0891911e-07
+    HChl       AR  1  0.000485981  2.0577121e-07
+    HChl        F  1  0.0002107248  5.7193643e-08
+    HChl       CL  1  0.0005748268  2.5645991e-07
+    HChl       BR  1  0.0002108476  5.3062481e-07
+    HChl     CMet  1  0.0005784494  2.9944367e-07
+    HChl     OMet  1  0.0002920184  7.377075e-08
+    HChl      NA+  1  5.212246e-05  9.50823e-09
+    HChl      CL-  1  0.00072145  6.7803516e-07
+    HChl     CChl  1  0.00031493288  1.3219718e-07
+    HChl    CLChl  1  0.00055960574  2.432861e-07
+   SDmso        O  1  0.0048877412  3.9925763e-06
+   SDmso       OM  1  0.0048877412  3.9925763e-06
+   SDmso       OA  1  0.0048877412  5.216175e-06
+   SDmso       OW  1  0.0052577132  7.5252018e-06
+   SDmso        N  1  0.0050727272  6.0322166e-06
+   SDmso       NT  1  0.0050727272  6.0322166e-06
+   SDmso       NL  1  0.0050727272  6.0322166e-06
+   SDmso       NR  1  0.0050727272  6.0322166e-06
+   SDmso       NZ  1  0.0050727272  6.0322166e-06
+   SDmso       NE  1  0.0050727272  6.0322166e-06
+   SDmso        C  1  0.0049720126  8.5174342e-06
+   SDmso      CH1  1  0.008005783  4.567051e-05
+   SDmso      CH2  1  0.0088813834  2.7022105e-05
+   SDmso      CH3  1  0.010076599  2.3934129e-05
+   SDmso      CH4  1  0.011797996  2.7179749e-05
+   SDmso      CR1  1  0.0076306725  1.8027101e-05
+   SDmso       HC  1  0.000945484  5.703018e-07
+   SDmso        H  1           0           0
+   SDmso      DUM  1           0           0
+   SDmso        S  1  0.010268778  1.6765946e-05
+   SDmso     CU1+  1  0.0021016465  3.3193419e-07
+   SDmso     CU2+  1  0.0021016465  3.3193419e-07
+   SDmso       FE  1           0           0
+   SDmso     ZN2+  1  0.0021016465  4.5049206e-07
+   SDmso     MG2+  1  0.0008303816  2.7068471e-07
+   SDmso     CA2+  1  0.003257809  3.2720486e-06
+   SDmso        P  1  0.012476278  2.1843023e-05
+   SDmso       AR  1  0.0081342455  1.4549651e-05
+   SDmso        F  1  0.0035270664  4.0440425e-06
+   SDmso       CL  1  0.0096213274  1.8133743e-05
+   SDmso       BR  1  0.0035291218  3.7519367e-05
+   SDmso     CMet  1  0.0096819617  2.1173034e-05
+   SDmso     OMet  1  0.0048877412  5.216175e-06
+   SDmso      NA+  1  0.00087241453  6.72307e-07
+   SDmso      CL-  1  0.012075475  4.7942444e-05
+   SDmso     CChl  1  0.0052712788  9.3473856e-06
+   SDmso    CLChl  1  0.0093665606  1.720225e-05
+   SDmso     HChl  1  0.0006310078  3.0404041e-07
+   CDmso        O  1  0.0045248108  4.016601e-06
+   CDmso       OM  1  0.0045248108  4.016601e-06
+   CDmso       OA  1  0.0045248108  5.2475625e-06
+   CDmso       OW  1  0.0048673112  7.5704835e-06
+   CDmso        N  1  0.004696061  6.0685145e-06
+   CDmso       NT  1  0.004696061  6.0685145e-06
+   CDmso       NL  1  0.004696061  6.0685145e-06
+   CDmso       NR  1  0.004696061  6.0685145e-06
+   CDmso       NZ  1  0.004696061  6.0685145e-06
+   CDmso       NE  1  0.004696061  6.0685145e-06
+   CDmso        C  1  0.0046028248  8.5686865e-06
+   CDmso      CH1  1  0.0074113281  4.5945325e-05
+   CDmso      CH2  1  0.0082219124  2.7184706e-05
+   CDmso      CH3  1  0.009328379  2.4078149e-05
+   CDmso      CH4  1  0.010921957  2.7343299e-05
+   CDmso      CR1  1  0.0070640708  1.8135576e-05
+   CDmso       HC  1  0.0008752788  5.737335e-07
+   CDmso        H  1           0           0
+   CDmso      DUM  1           0           0
+   CDmso        S  1  0.0095062889  1.6866832e-05
+   CDmso     CU1+  1  0.0019455925  3.3393156e-07
+   CDmso     CU2+  1  0.0019455925  3.3393156e-07
+   CDmso       FE  1           0           0
+   CDmso     ZN2+  1  0.0019455925  4.5320282e-07
+   CDmso     MG2+  1  0.00076872312  2.7231351e-07
+   CDmso     CA2+  1  0.0030159063  3.2917377e-06
+   CDmso        P  1  0.011549875  2.197446e-05
+   CDmso       AR  1  0.0075302519  1.4637201e-05
+   CDmso        F  1  0.0032651705  4.0683769e-06
+   CDmso       CL  1  0.0089069132  1.824286e-05
+   CDmso       BR  1  0.0032670733  3.7745134e-05
+   CDmso     CMet  1  0.0089630452  2.1300439e-05
+   CDmso     OMet  1  0.0045248108  5.2475625e-06
+   CDmso      NA+  1  0.00080763497  6.763525e-07
+   CDmso      CL-  1  0.011178832  4.823093e-05
+   CDmso     CChl  1  0.0048798696  9.403632e-06
+   CDmso    CLChl  1  0.0086710636  1.7305761e-05
+   CDmso     HChl  1  0.00058415346  3.0586992e-07
+   CDmso    SDmso  1  0.009777435  2.1627421e-05
+   ODmso        O  1  0.0022663291  7.4645315e-07
+   ODmso       OM  1  0.0022663291  7.4645315e-07
+   ODmso       OA  1  0.0022663291  1.380375e-06
+   ODmso       OW  1  0.0024378763  1.825875e-06
+   ODmso        N  1  0.0023521027  2.185875e-06
+   ODmso       NT  1  0.0023521027  2.53125e-06
+   ODmso       NL  1  0.0023521027  3.4515e-06
+   ODmso       NR  1  0.0023521027  2.071125e-06
+   ODmso       NZ  1  0.0023521027  2.4165e-06
+   ODmso       NE  1  0.0023521027   2.232e-06
+   ODmso        C  1  0.0023054038  1.5924218e-06
+   ODmso      CH1  1  0.0037120908  8.538571e-06
+   ODmso      CH2  1  0.0041180858  5.0520601e-06
+   ODmso      CH3  1  0.0046722786  4.4747313e-06
+   ODmso      CH4  1  0.0054704496  5.0815333e-06
+   ODmso      CR1  1  0.003538161  3.3703517e-06
+   ODmso       HC  1  0.0004383984  1.0662378e-07
+   ODmso        H  1           0           0
+   ODmso      DUM  1           0           0
+   ODmso        S  1  0.0047613878  3.1345658e-06
+   ODmso     CU1+  1  0.0009744834  2.53125e-07
+   ODmso     CU2+  1  0.0009744834  4.602375e-07
+   ODmso       FE  1           0           0
+   ODmso     ZN2+  1  0.0009744834  1.09305e-07
+   ODmso     MG2+  1  0.00038502816  6.56775e-08
+   ODmso     CA2+  1  0.0015105684  7.939125e-07
+   ODmso        P  1  0.0057849528  5.299875e-06
+   ODmso       AR  1  0.0037716558  2.7202067e-06
+   ODmso        F  1  0.0016354166  7.5607529e-07
+   ODmso       CL  1  0.0044611802  3.3902895e-06
+   ODmso       BR  1  0.0016363697  7.0146311e-06
+   ODmso     CMet  1  0.0044892949  3.9585162e-06
+   ODmso     OMet  1  0.0022663291  1.380375e-06
+   ODmso      NA+  1  0.00040451783  1.63125e-07
+   ODmso      CL-  1  0.00559911  8.9633324e-06
+   ODmso     CChl  1  0.0024441664  1.7475898e-06
+   ODmso    CLChl  1  0.0043430509  3.2161373e-06
+   ODmso     HChl  1  0.00029258328  5.6843478e-08
+   ODmso    SDmso  1  0.004897196  4.0192831e-06
+   ODmso    CDmso  1  0.0045335636  4.0434685e-06
+    CCl4        O  1  0.0024394475  2.3738805e-06
+    CCl4       OM  1  0.0024394475  2.3738805e-06
+    CCl4       OA  1  0.0024394475  3.1014e-06
+    CCl4       OW  1  0.0026240987  4.4742864e-06
+    CCl4        N  1  0.0025317731  3.5865968e-06
+    CCl4       NT  1  0.0025317731  3.5865968e-06
+    CCl4       NL  1  0.0025317731  3.5865968e-06
+    CCl4       NR  1  0.0025317731  3.5865968e-06
+    CCl4       NZ  1  0.0025317731  3.5865968e-06
+    CCl4       NE  1  0.0025317731  3.5865968e-06
+    CCl4        C  1  0.002481507  5.0642416e-06
+    CCl4      CH1  1  0.0039956468  2.715448e-05
+    CCl4      CH2  1  0.0044326546  1.606663e-05
+    CCl4      CH3  1  0.0050291806  1.4230602e-05
+    CCl4      CH4  1  0.0058883216  1.6160362e-05
+    CCl4      CR1  1  0.003808431  1.0718438e-05
+    CCl4       HC  1  0.0004718864  3.390864e-07
+    CCl4        H  1           0           0
+    CCl4      DUM  1           0           0
+    CCl4        S  1  0.0051250966  9.9685888e-06
+    CCl4     CU1+  1  0.0010489214  1.9735931e-07
+    CCl4     CU2+  1  0.0010489214  1.9735931e-07
+    CCl4       FE  1           0           0
+    CCl4     ZN2+  1  0.0010489214  2.6785069e-07
+    CCl4     MG2+  1  0.00041443936  1.6094198e-07
+    CCl4     CA2+  1  0.0016259564  1.9454738e-06
+    CCl4        P  1  0.0062268488  1.2987285e-05
+    CCl4       AR  1  0.0040597618  8.6508384e-06
+    CCl4        F  1  0.0017603414  2.404481e-06
+    CCl4       CL  1  0.004801957  1.0781845e-05
+    CCl4       BR  1  0.0017613673  2.2308026e-05
+    CCl4     CMet  1  0.0048322193  1.2588927e-05
+    CCl4     OMet  1  0.0024394475  3.1014e-06
+    CCl4      NA+  1  0.00043541779  3.99736e-07
+    CCl4      CL-  1  0.00602681  2.8505312e-05
+    CCl4     CChl  1  0.0026308693  5.5577088e-06
+    CCl4    CLChl  1  0.0046748042  1.0228004e-05
+    CCl4     HChl  1  0.00031493288  1.807744e-07
+    CCl4    SDmso  1  0.0052712788  1.2782179e-05
+    CCl4    CDmso  1  0.0048798696  1.2859094e-05
+    CCl4    ODmso  1  0.0024441664  2.3897596e-06
+   CLCl4        O  1  0.0041472796  3.0768825e-06
+   CLCl4       OM  1  0.0041472796  3.0768825e-06
+   CLCl4       OA  1  0.0041472796  4.01985e-06
+   CLCl4       OW  1  0.0044612032  5.7993036e-06
+   CLCl4        N  1  0.0043042414  4.6487332e-06
+   CLCl4       NT  1  0.0043042414  4.6487332e-06
+   CLCl4       NL  1  0.0043042414  4.6487332e-06
+   CLCl4       NR  1  0.0043042414  4.6487332e-06
+   CLCl4       NZ  1  0.0043042414  4.6487332e-06
+   CLCl4       NE  1  0.0043042414  4.6487332e-06
+   CLCl4        C  1  0.0042187844  6.5639684e-06
+   CLCl4      CH1  1  0.0067929579  3.519602e-05
+   CLCl4      CH2  1  0.0075359104  2.082461e-05
+   CLCl4      CH3  1  0.008550058  1.8444858e-05
+   CLCl4      CH4  1  0.010010675  2.0946098e-05
+   CLCl4      CR1  1  0.0064746742  1.3892602e-05
+   CLCl4       HC  1  0.0008022492  4.395036e-07
+   CLCl4        H  1           0           0
+   CLCl4      DUM  1           0           0
+   CLCl4        S  1  0.0087131239  1.2920691e-05
+   CLCl4     CU1+  1  0.0017832604  2.5580539e-07
+   CLCl4     CU2+  1  0.0017832604  2.5580539e-07
+   CLCl4       FE  1           0           0
+   CLCl4     ZN2+  1  0.0017832604  3.4717211e-07
+   CLCl4     MG2+  1  0.00070458408  2.0860342e-07
+   CLCl4     CA2+  1  0.0027642717  2.5216072e-06
+   CLCl4        P  1  0.010586201  1.6833345e-05
+   CLCl4       AR  1  0.0069019592  1.1212702e-05
+   CLCl4        F  1  0.0029927383  3.116545e-06
+   CLCl4       CL  1  0.0081637576  1.3974785e-05
+   CLCl4       BR  1  0.0029944823  2.8914334e-05
+   CLCl4     CMet  1  0.0082152062  1.6317018e-05
+   CLCl4     OMet  1  0.0041472796  4.01985e-06
+   CLCl4      NA+  1  0.00074024929  5.18114e-07
+   CLCl4      CL-  1  0.010246117  3.6946888e-05
+   CLCl4     CChl  1  0.0044727137  7.2035712e-06
+   CLCl4    CLChl  1  0.0079475863  1.3256929e-05
+   CLCl4     HChl  1  0.00053541414  2.3430902e-07
+   CLCl4    SDmso  1  0.0089616468  1.6567499e-05
+   CLCl4    CDmso  1  0.0082962159  1.6667191e-05
+   CLCl4    ODmso  1  0.0041553021  3.0974642e-06
+   CLCl4     CCl4  1  0.0044727137  9.8505978e-06
     CH2r        O  1  0.0040730384  4.5612467e-06
     CH2r       OM  1  0.0040730384  4.5612467e-06
     CH2r       OA  1  0.0040730384  5.959125e-06
@@ -985,18 +985,18 @@ CLCL4   17        0.000      0.000     A  0.0076040144  1.2767758e-05
     CH2r        F  1  0.0029391648  4.6200434e-06
     CH2r       CL  1  0.0080176168  2.0716567e-05
     CH2r       BR  1  0.0029408776  4.2863324e-05
-    CH2r     CMET  1  0.0080681444  2.418875e-05
-    CH2r     OMET  1  0.0040730384  5.959125e-06
+    CH2r     CMet  1  0.0080681444  2.418875e-05
+    CH2r     OMet  1  0.0040730384  5.959125e-06
     CH2r      NA+  1  0.00072699796  7.68065e-07
     CH2r      CL-  1   0.0100627  5.477098e-05
-    CH2r     CCHL  1  0.0043926469  1.0678752e-05
-    CH2r    CLCHL  1  0.0078053152  1.96524e-05
-    CH2r     HCHL  1  0.0005258296  3.4734548e-07
-    CH2r    SDMSO  1  0.0088012228  2.456007e-05
-    CH2r    CDMSO  1  0.008147704  2.4707856e-05
-    CH2r    ODMSO  1  0.0040809173  4.5917574e-06
-    CH2r     CCL4  1  0.0043926469  1.460277e-05
-    CH2r    CLCL4  1  0.0074678936  1.892724e-05
+    CH2r     CChl  1  0.0043926469  1.0678752e-05
+    CH2r    CLChl  1  0.0078053152  1.96524e-05
+    CH2r     HChl  1  0.0005258296  3.4734548e-07
+    CH2r    SDmso  1  0.0088012228  2.456007e-05
+    CH2r    CDmso  1  0.008147704  2.4707856e-05
+    CH2r    ODmso  1  0.0040809173  4.5917574e-06
+    CH2r     CCl4  1  0.0043926469  1.460277e-05
+    CH2r    CLCl4  1  0.0074678936  1.892724e-05
      CH0        O  1  0.0023285376  1.2339563e-05
      CH0       OM  1  0.0023285376  1.2339563e-05
      CH0       OA  1  0.0023285376  1.612125e-05
@@ -1028,18 +1028,18 @@ CLCL4   17      0.000      0.000     A  0.0076040144  1.2767758e-05
      CH0        F  1  0.0016803072  1.2498626e-05
      CH0       CL  1  0.0045836352  5.604463e-05
      CH0       BR  1  0.0016812864  0.00011595836
-     CH0     CMET  1  0.0046125216  6.5437945e-05
-     CH0     OMET  1  0.0023285376  1.612125e-05
+     CH0     CMet  1  0.0046125216  6.5437945e-05
+     CH0     OMet  1  0.0023285376  1.612125e-05
      CH0      NA+  1  0.00041562144  2.07785e-06
      CH0      CL-  1   0.0057528  0.0001481722
-     CH0     CCHL  1  0.0025112563  2.888928e-05
-     CH0    CLCHL  1  0.0044622634  5.3165733e-05
-     CH0     HCHL  1  0.0003006144  9.3967542e-07
-     CH0    SDMSO  1  0.0050316192  6.6442478e-05
-     CH0    CDMSO  1  0.0046580054  6.6842285e-05
-     CH0    ODMSO  1  0.0023330419  1.2422104e-05
-     CH0     CCL4  1  0.0025112563  3.9504944e-05
-     CH0    CLCL4  1  0.004269361  5.1203956e-05
+     CH0     CChl  1  0.0025112563  2.888928e-05
+     CH0    CLChl  1  0.0044622634  5.3165733e-05
+     CH0     HChl  1  0.0003006144  9.3967542e-07
+     CH0    SDmso  1  0.0050316192  6.6442478e-05
+     CH0    CDmso  1  0.0046580054  6.6842285e-05
+     CH0    ODmso  1  0.0023330419  1.2422104e-05
+     CH0     CCl4  1  0.0025112563  3.9504944e-05
+     CH0    CLCl4  1  0.004269361  5.1203956e-05
      CH0     CH2r  1  0.0041929344  7.590601e-05
       SI        O  1  0.005773784  5.299875e-06
       SI       OM  1  0.005773784  1.4453348e-05
@@ -1072,18 +1072,18 @@ CLCL4   17      0.000      0.000     A  0.0076040144  1.2767758e-05
       SI        F  1  0.004166448  5.780397e-06
       SI       CL  1  0.011365468  1.8424721e-05
       SI       BR  1  0.004168876  3.8121412e-05
-      SI     CMET  1  0.011437094  2.1512782e-05
-      SI     OMET  1  0.005773784  5.780397e-06
+      SI     CMet  1  0.011437094  2.1512782e-05
+      SI     OMet  1  0.005773784  5.780397e-06
       SI      NA+  1  0.0010305646  6.83095e-07
       SI      CL-  1   0.0142645  4.871174e-05
-      SI     CCHL  1  0.0062268488  9.497376e-06
-      SI    CLCHL  1  0.011064517  1.7478281e-05
-      SI     HCHL  1  0.000745396  3.0891911e-07
-      SI    SDMSO  1  0.012476278  2.1843023e-05
-      SI    CDMSO  1  0.011549875  2.197446e-05
-      SI    ODMSO  1  0.0057849528  5.299875e-06
-      SI     CCL4  1  0.0062268488  1.2987285e-05
-      SI    CLCL4  1  0.010586201  1.6833345e-05
+      SI     CChl  1  0.0062268488  9.497376e-06
+      SI    CLChl  1  0.011064517  1.7478281e-05
+      SI     HChl  1  0.000745396  3.0891911e-07
+      SI    SDmso  1  0.012476278  2.1843023e-05
+      SI    CDmso  1  0.011549875  2.197446e-05
+      SI    ODmso  1  0.0057849528  5.299875e-06
+      SI     CCl4  1  0.0062268488  1.2987285e-05
+      SI    CLCl4  1  0.010586201  1.6833345e-05
       SI     CH2r  1  0.010396696  2.4954167e-05
       SI      CH0  1  0.005943744  6.750863e-05
 
@@ -1585,71 +1585,71 @@ CLCL4   17      0.000      0.000     A  0.0076040144  1.2767758e-05
       BR        F  1  0.0011785488  7.0578424e-06
       BR       CL  1  0.0032149108  3.1647812e-05
       BR       BR  1  0.0011792356  6.5480464e-05
-    CMET        O  1  0.0044806276  3.9322131e-06
-    CMET       OM  1  0.0044806276  3.9322131e-06
-    CMET       OA  1  0.0044806276  5.1373125e-06
-    CMET       OW  1  0.0048197836  7.4114295e-06
-    CMET        N  1  0.0046502056  5.9410165e-06
-    CMET       NT  1  0.0046502056  5.9410165e-06
-    CMET       NL  1  0.0046502056  5.9410165e-06
-    CMET       NR  1  0.0046502056  5.9410165e-06
-    CMET       NZ  1  0.0046502056  5.9410165e-06
-    CMET       NE  1  0.0046502056  5.9410165e-06
-    CMET        C  1  0.0045578798  8.3886605e-06
-    CMET      CH1  1  0.0050835716  8.8270445e-06
-    CMET      CH2  1  0.0064750533  9.943994e-06
-    CMET      CH3  1  0.0077987038  1.1214329e-05
-    CMET      CH4  1  0.010815308  2.6768823e-05
-    CMET      CR1  1  0.0070045135  1.3178919e-05
-    CMET       HC  1  0.000866732  5.616795e-07
-    CMET        H  1           0           0
-    CMET      DUM  1           0           0
-    CMET        S  1  0.0094134632  1.6512464e-05
-    CMET     CU1+  1  0.0019265945  3.2691574e-07
-    CMET     CU2+  1  0.0019265945  3.2691574e-07
-    CMET       FE  1           0           0
-    CMET     ZN2+  1  0.0019265945  4.4368114e-07
-    CMET     MG2+  1  0.0007612168  2.6659227e-07
-    CMET     CA2+  1  0.002986457  3.222579e-06
-    CMET        P  1  0.011437094  2.1512782e-05
-    CMET       AR  1  0.0074567215  1.4329677e-05
-    CMET        F  1  0.0032332872  3.9829013e-06
-    CMET       CL  1  0.0088199402  1.7859582e-05
-    CMET       BR  1  0.0032351714  3.6952118e-05
-    CMET     CMET  1  0.0088755241  2.0852922e-05
-    OMET        O  1  0.0022619536  9.687375e-07
-    OMET       OM  1  0.0022619536  9.687375e-07
-    OMET       OA  1  0.0022619536  1.265625e-06
-    OMET       OW  1  0.0024331696  1.825875e-06
-    OMET        N  1  0.0023475616  1.463625e-06
-    OMET       NT  1  0.0023475616  1.463625e-06
-    OMET       NL  1  0.0023475616  1.463625e-06
-    OMET       NR  1  0.0023475616  1.463625e-06
-    OMET       NZ  1  0.0023475616  1.463625e-06
-    OMET       NE  1  0.0023475616  1.463625e-06
-    OMET        C  1  0.0023009528  2.066625e-06
-    OMET      CH1  1  0.0025663376  2.174625e-06
-    OMET      CH2  1  0.0032687988  2.4497959e-06
-    OMET      CH3  1  0.0039370168  2.7627548e-06
-    OMET      CH4  1  0.005459888  6.59475e-06
-    OMET      CR1  1  0.003536086  3.24675e-06
-    OMET       HC  1  0.000437552  1.38375e-07
-    OMET        H  1           0           0
-    OMET      DUM  1           0           0
-    OMET        S  1  0.0047521952   4.068e-06
-    OMET     CU1+  1  0.000972602  8.053875e-08
-    OMET     CU2+  1  0.000972602  8.053875e-08
-    OMET       FE  1           0           0
-    OMET     ZN2+  1  0.000972602  1.09305e-07
-    OMET     MG2+  1  0.0003842848  6.56775e-08
-    OMET     CA2+  1  0.001507652  7.939125e-07
-    OMET        P  1  0.005773784  5.299875e-06
-    OMET       AR  1  0.003764374  3.53025e-06
-    OMET        F  1  0.0016322592  9.81225e-07
-    OMET       CL  1  0.0044525672  4.399875e-06
-    OMET       BR  1  0.0016332104  9.1035e-06
-    OMET     CMET  1  0.0044806276  5.1373125e-06
-    OMET     OMET  1  0.0022619536  1.265625e-06
+    CMet        O  1  0.0044806276  3.9322131e-06
+    CMet       OM  1  0.0044806276  3.9322131e-06
+    CMet       OA  1  0.0044806276  5.1373125e-06
+    CMet       OW  1  0.0048197836  7.4114295e-06
+    CMet        N  1  0.0046502056  5.9410165e-06
+    CMet       NT  1  0.0046502056  5.9410165e-06
+    CMet       NL  1  0.0046502056  5.9410165e-06
+    CMet       NR  1  0.0046502056  5.9410165e-06
+    CMet       NZ  1  0.0046502056  5.9410165e-06
+    CMet       NE  1  0.0046502056  5.9410165e-06
+    CMet        C  1  0.0045578798  8.3886605e-06
+    CMet      CH1  1  0.0050835716  8.8270445e-06
+    CMet      CH2  1  0.0064750533  9.943994e-06
+    CMet      CH3  1  0.0077987038  1.1214329e-05
+    CMet      CH4  1  0.010815308  2.6768823e-05
+    CMet      CR1  1  0.0070045135  1.3178919e-05
+    CMet       HC  1  0.000866732  5.616795e-07
+    CMet        H  1           0           0
+    CMet      DUM  1           0           0
+    CMet        S  1  0.0094134632  1.6512464e-05
+    CMet     CU1+  1  0.0019265945  3.2691574e-07
+    CMet     CU2+  1  0.0019265945  3.2691574e-07
+    CMet       FE  1           0           0
+    CMet     ZN2+  1  0.0019265945  4.4368114e-07
+    CMet     MG2+  1  0.0007612168  2.6659227e-07
+    CMet     CA2+  1  0.002986457  3.222579e-06
+    CMet        P  1  0.011437094  2.1512782e-05
+    CMet       AR  1  0.0074567215  1.4329677e-05
+    CMet        F  1  0.0032332872  3.9829013e-06
+    CMet       CL  1  0.0088199402  1.7859582e-05
+    CMet       BR  1  0.0032351714  3.6952118e-05
+    CMet     CMet  1  0.0088755241  2.0852922e-05
+    OMet        O  1  0.0022619536  9.687375e-07
+    OMet       OM  1  0.0022619536  9.687375e-07
+    OMet       OA  1  0.0022619536  1.265625e-06
+    OMet       OW  1  0.0024331696  1.825875e-06
+    OMet        N  1  0.0023475616  1.463625e-06
+    OMet       NT  1  0.0023475616  1.463625e-06
+    OMet       NL  1  0.0023475616  1.463625e-06
+    OMet       NR  1  0.0023475616  1.463625e-06
+    OMet       NZ  1  0.0023475616  1.463625e-06
+    OMet       NE  1  0.0023475616  1.463625e-06
+    OMet        C  1  0.0023009528  2.066625e-06
+    OMet      CH1  1  0.0025663376  2.174625e-06
+    OMet      CH2  1  0.0032687988  2.4497959e-06
+    OMet      CH3  1  0.0039370168  2.7627548e-06
+    OMet      CH4  1  0.005459888  6.59475e-06
+    OMet      CR1  1  0.003536086  3.24675e-06
+    OMet       HC  1  0.000437552  1.38375e-07
+    OMet        H  1           0           0
+    OMet      DUM  1           0           0
+    OMet        S  1  0.0047521952   4.068e-06
+    OMet     CU1+  1  0.000972602  8.053875e-08
+    OMet     CU2+  1  0.000972602  8.053875e-08
+    OMet       FE  1           0           0
+    OMet     ZN2+  1  0.000972602  1.09305e-07
+    OMet     MG2+  1  0.0003842848  6.56775e-08
+    OMet     CA2+  1  0.001507652  7.939125e-07
+    OMet        P  1  0.005773784  5.299875e-06
+    OMet       AR  1  0.003764374  3.53025e-06
+    OMet        F  1  0.0016322592  9.81225e-07
+    OMet       CL  1  0.0044525672  4.399875e-06
+    OMet       BR  1  0.0016332104  9.1035e-06
+    OMet     CMet  1  0.0044806276  5.1373125e-06
+    OMet     OMet  1  0.0022619536  1.265625e-06
      NA+        O  1  0.00040373684  1.248595e-07
      NA+       OM  1  0.00040373684  1.248595e-07
      NA+       OA  1  0.00040373684  1.63125e-07
@@ -1681,8 +1681,8 @@ CLCL4   17        0.000      0.000     A  0.0076040144  1.2767758e-05
      NA+        F  1  0.00029134248  1.26469e-07
      NA+       CL  1  0.00079474018  5.67095e-07
      NA+       BR  1  0.00029151226  1.17334e-06
-     NA+     CMET  1  0.00079974869  6.621425e-07
-     NA+     OMET  1  0.00040373684  1.63125e-07
+     NA+     CMet  1  0.00079974869  6.621425e-07
+     NA+     OMet  1  0.00040373684  1.63125e-07
      NA+      NA+  1  7.2063121e-05  2.1025e-08
      CL-        O  1   0.0055883  8.903774e-06
      CL-       OM  1   0.0055883  8.903774e-06
@@ -1715,326 +1715,326 @@ CLCL4   17    0.000      0.000     A  0.0076040144  1.2767758e-05
      CL-        F  1   0.0040326  9.018548e-06
      CL-       CL  1  0.01100035  4.043974e-05
      CL-       BR  1  0.00403495  8.367128e-05
-     CL-     CMET  1  0.011069675  4.721761e-05
-     CL-     OMET  1   0.0055883  1.16325e-05
+     CL-     CMet  1  0.011069675  4.721761e-05
+     CL-     OMet  1   0.0055883  1.16325e-05
      CL-      NA+  1  0.0009974575  1.4993e-06
      CL-      CL-  1  0.01380625  0.0001069156
-    CCHL        O  1  0.0024394475  1.7359776e-06
-    CCHL       OM  1  0.0024394475  1.7359776e-06
-    CCHL       OA  1  0.0024394475   2.268e-06
-    CCHL       OW  1  0.0026240987  3.271968e-06
-    CCHL        N  1  0.0025317731  2.622816e-06
-    CCHL       NT  1  0.0025317731  2.622816e-06
-    CCHL       NL  1  0.0025317731  2.622816e-06
-    CCHL       NR  1  0.0025317731  2.622816e-06
-    CCHL       NZ  1  0.0025317731  2.622816e-06
-    CCHL       NE  1  0.0025317731  2.622816e-06
-    CCHL        C  1  0.002481507  3.703392e-06
-    CCHL      CH1  1  0.0027677163  3.896928e-06
-    CCHL      CH2  1  0.0035252992  4.3900343e-06
-    CCHL      CH3  1  0.0042459518  4.9508565e-06
-    CCHL      CH4  1  0.0058883216  1.1817792e-05
-    CCHL      CR1  1  0.0038135602  5.818176e-06
-    CCHL       HC  1  0.0004718864  2.47968e-07
-    CCHL        H  1           0           0
-    CCHL      DUM  1           0           0
-    CCHL        S  1  0.0051250966  7.289856e-06
-    CCHL     CU1+  1  0.0010489214  1.4432544e-07
-    CCHL     CU2+  1  0.0010489214  1.4432544e-07
-    CCHL       FE  1           0           0
-    CCHL     ZN2+  1  0.0010489214  1.9587456e-07
-    CCHL     MG2+  1  0.00041443936  1.1769408e-07
-    CCHL     CA2+  1  0.0016259564  1.4226912e-06
-    CCHL        P  1  0.0062268488  9.497376e-06
-    CCHL       AR  1  0.0040597618  6.326208e-06
-    CCHL        F  1  0.0017603414  1.7583552e-06
-    CCHL       CL  1  0.004801957  7.884576e-06
-    CCHL       BR  1  0.0017613673  1.6313472e-05
-    CCHL     CMET  1  0.0048322193  9.206064e-06
-    CCHL     OMET  1  0.0024394475   2.268e-06
-    CCHL      NA+  1  0.00043541779  2.9232e-07
-    CCHL      CL-  1  0.00602681  2.084544e-05
-    CCHL     CCHL  1  0.0026308693  4.064256e-06
-   CLCHL        O  1  0.004334666  3.1947671e-06
-   CLCHL       OM  1  0.004334666  3.1947671e-06
-   CLCHL       OA  1  0.004334666  4.1738625e-06
-   CLCHL       OW  1  0.0046627736  6.0214923e-06
-   CLCHL        N  1  0.0044987198  4.8268401e-06
-   CLCHL       NT  1  0.0044987198  4.8268401e-06
-   CLCHL       NL  1  0.0044987198  4.8268401e-06
-   CLCHL       NR  1  0.0044987198  4.8268401e-06
-   CLCHL       NZ  1  0.0044987198  4.8268401e-06
-   CLCHL       NE  1  0.0044987198  4.8268401e-06
-   CLCHL        C  1  0.0044094016  6.8154537e-06
-   CLCHL      CH1  1  0.0049179684  7.1716233e-06
-   CLCHL      CH2  1  0.0062641209  8.0791004e-06
-   CLCHL      CH3  1  0.007544652  9.1111968e-06
-   CLCHL      CH4  1  0.010462987  2.1748606e-05
-   CLCHL      CR1  1  0.0067763334  1.0707349e-05
-   CLCHL       HC  1  0.0008384972  4.563423e-07
-   CLCHL        H  1           0           0
-   CLCHL      DUM  1           0           0
-   CLCHL        S  1  0.0091068087  1.3415722e-05
-   CLCHL     CU1+  1  0.0018638335  2.6560606e-07
-   CLCHL     CU2+  1  0.0018638335  2.6560606e-07
-   CLCHL       FE  1           0           0
-   CLCHL     ZN2+  1  0.0018638335  3.6047332e-07
-   CLCHL     MG2+  1  0.00073641928  2.1659564e-07
-   CLCHL     CA2+  1  0.0028891697  2.6182176e-06
-   CLCHL        P  1  0.011064517  1.7478281e-05
-   CLCHL       AR  1  0.0072138101  1.1642294e-05
-   CLCHL        F  1  0.0031279591  3.2359492e-06
-   CLCHL       CL  1  0.0085326204  1.4510201e-05
-   CLCHL       BR  1  0.0031297819  3.0022129e-05
-   CLCHL     CMET  1  0.0085863936  1.6942172e-05
-   CLCHL     OMET  1  0.004334666  4.1738625e-06
-   CLCHL      NA+  1  0.00077369595  5.379645e-07
-   CLCHL      CL-  1  0.010709067  3.8362434e-05
-   CLCHL     CCHL  1  0.0046748042  7.4795616e-06
-   CLCHL    CLCHL  1  0.0083066819  1.3764842e-05
-    HCHL        O  1  0.0002920184  5.6465771e-08
-    HCHL       OM  1  0.0002920184  5.6465771e-08
-    HCHL       OA  1  0.0002920184  7.377075e-08
-    HCHL       OW  1  0.0003141224  1.064266e-07
-    HCHL        N  1  0.0003030704  8.5311774e-08
-    HCHL       NT  1  0.0003030704  8.5311774e-08
-    HCHL       NL  1  0.0003030704  8.5311774e-08
-    HCHL       NR  1  0.0003030704  8.5311774e-08
-    HCHL       NZ  1  0.0003030704  8.5311774e-08
-    HCHL       NE  1  0.0003030704  8.5311774e-08
-    HCHL        C  1  0.0002970532  1.2045944e-07
-    HCHL      CH1  1  0.0003313144  1.2675454e-07
-    HCHL      CH2  1  0.0004220022  1.4279371e-07
-    HCHL      CH3  1  0.0005082692  1.6103545e-07
-    HCHL      CH4  1  0.000704872  3.8439479e-07
-    HCHL      CR1  1  0.000456509  1.8924656e-07
-    HCHL       HC  1  5.6488e-05  8.065602e-09
-    HCHL        H  1           0           0
-    HCHL      DUM  1           0           0
-    HCHL        S  1  0.0006135088  2.3711558e-07
-    HCHL     CU1+  1  0.000125563  4.6944427e-09
-    HCHL     CU2+  1  0.000125563  4.6944427e-09
-    HCHL       FE  1           0           0
-    HCHL     ZN2+  1  0.000125563  6.3711698e-09
-    HCHL     MG2+  1  4.96112e-05  3.8282101e-09
-    HCHL     CA2+  1  0.000194638  4.6275572e-08
-    HCHL        P  1  0.000745396  3.0891911e-07
-    HCHL       AR  1  0.000485981  2.0577121e-07
-    HCHL        F  1  0.0002107248  5.7193643e-08
-    HCHL       CL  1  0.0005748268  2.5645991e-07
-    HCHL       BR  1  0.0002108476  5.3062481e-07
-    HCHL     CMET  1  0.0005784494  2.9944367e-07
-    HCHL     OMET  1  0.0002920184  7.377075e-08
-    HCHL      NA+  1  5.212246e-05  9.50823e-09
-    HCHL      CL-  1  0.00072145  6.7803516e-07
-    HCHL     CCHL  1  0.00031493288  1.3219718e-07
-    HCHL    CLCHL  1  0.00055960574  2.432861e-07
-    HCHL     HCHL  1  3.76996e-05  4.2999495e-09
-   SDMSO        O  1  0.0048877412  3.9925763e-06
-   SDMSO       OM  1  0.0048877412  3.9925763e-06
-   SDMSO       OA  1  0.0048877412  5.216175e-06
-   SDMSO       OW  1  0.0052577132  7.5252018e-06
-   SDMSO        N  1  0.0050727272  6.0322166e-06
-   SDMSO       NT  1  0.0050727272  6.0322166e-06
-   SDMSO       NL  1  0.0050727272  6.0322166e-06
-   SDMSO       NR  1  0.0050727272  6.0322166e-06
-   SDMSO       NZ  1  0.0050727272  6.0322166e-06
-   SDMSO       NE  1  0.0050727272  6.0322166e-06
-   SDMSO        C  1  0.0049720126  8.5174342e-06
-   SDMSO      CH1  1  0.0055454692  8.9625478e-06
-   SDMSO      CH2  1  0.0070633821  1.0096643e-05
-   SDMSO      CH3  1  0.0085073006  1.1386479e-05
-   SDMSO      CH4  1  0.011797996  2.7179749e-05
-   SDMSO      CR1  1  0.0076409495  1.3381228e-05
-   SDMSO       HC  1  0.000945484  5.703018e-07
-   SDMSO        H  1           0           0
-   SDMSO      DUM  1           0           0
-   SDMSO        S  1  0.010268778  1.6765946e-05
-   SDMSO     CU1+  1  0.0021016465  3.3193419e-07
-   SDMSO     CU2+  1  0.0021016465  3.3193419e-07
-   SDMSO       FE  1           0           0
-   SDMSO     ZN2+  1  0.0021016465  4.5049206e-07
-   SDMSO     MG2+  1  0.0008303816  2.7068471e-07
-   SDMSO     CA2+  1  0.003257809  3.2720486e-06
-   SDMSO        P  1  0.012476278  2.1843023e-05
-   SDMSO       AR  1  0.0081342455  1.4549651e-05
-   SDMSO        F  1  0.0035270664  4.0440425e-06
-   SDMSO       CL  1  0.0096213274  1.8133743e-05
-   SDMSO       BR  1  0.0035291218  3.7519367e-05
-   SDMSO     CMET  1  0.0096819617  2.1173034e-05
-   SDMSO     OMET  1  0.0048877412  5.216175e-06
-   SDMSO      NA+  1  0.00087241453  6.72307e-07
-   SDMSO      CL-  1  0.012075475  4.7942444e-05
-   SDMSO     CCHL  1  0.0052712788  9.3473856e-06
-   SDMSO    CLCHL  1  0.0093665606  1.720225e-05
-   SDMSO     HCHL  1  0.0006310078  3.0404041e-07
-   SDMSO    SDMSO  1  0.010561673  2.149806e-05
-   CDMSO        O  1  0.0045248108  4.016601e-06
-   CDMSO       OM  1  0.0045248108  4.016601e-06
-   CDMSO       OA  1  0.0045248108  5.2475625e-06
-   CDMSO       OW  1  0.0048673112  7.5704835e-06
-   CDMSO        N  1  0.004696061  6.0685145e-06
-   CDMSO       NT  1  0.004696061  6.0685145e-06
-   CDMSO       NL  1  0.004696061  6.0685145e-06
-   CDMSO       NR  1  0.004696061  6.0685145e-06
-   CDMSO       NZ  1  0.004696061  6.0685145e-06
-   CDMSO       NE  1  0.004696061  6.0685145e-06
-   CDMSO        C  1  0.0046028248  8.5686865e-06
-   CDMSO      CH1  1  0.0051337004  9.0164785e-06
-   CDMSO      CH2  1  0.0065389035  1.0157398e-05
-   CDMSO      CH3  1  0.0078756064  1.1454995e-05
-   CDMSO      CH4  1  0.010921957  2.7343299e-05
-   CDMSO      CR1  1  0.0070735846  1.3461747e-05
-   CDMSO       HC  1  0.0008752788  5.737335e-07
-   CDMSO        H  1           0           0
-   CDMSO      DUM  1           0           0
-   CDMSO        S  1  0.0095062889  1.6866832e-05
-   CDMSO     CU1+  1  0.0019455925  3.3393156e-07
-   CDMSO     CU2+  1  0.0019455925  3.3393156e-07
-   CDMSO       FE  1           0           0
-   CDMSO     ZN2+  1  0.0019455925  4.5320282e-07
-   CDMSO     MG2+  1  0.00076872312  2.7231351e-07
-   CDMSO     CA2+  1  0.0030159063  3.2917377e-06
-   CDMSO        P  1  0.011549875  2.197446e-05
-   CDMSO       AR  1  0.0075302519  1.4637201e-05
-   CDMSO        F  1  0.0032651705  4.0683769e-06
-   CDMSO       CL  1  0.0089069132  1.824286e-05
-   CDMSO       BR  1  0.0032670733  3.7745134e-05
-   CDMSO     CMET  1  0.0089630452  2.1300439e-05
-   CDMSO     OMET  1  0.0045248108  5.2475625e-06
-   CDMSO      NA+  1  0.00080763497  6.763525e-07
-   CDMSO      CL-  1  0.011178832  4.823093e-05
-   CDMSO     CCHL  1  0.0048798696  9.403632e-06
-   CDMSO    CLCHL  1  0.0086710636  1.7305761e-05
-   CDMSO     HCHL  1  0.00058415346  3.0586992e-07
-   CDMSO    SDMSO  1  0.009777435  2.1627421e-05
-   CDMSO    CDMSO  1  0.0090514293  2.175756e-05
-   ODMSO        O  1  0.0022663291  7.4645315e-07
-   ODMSO       OM  1  0.0022663291  7.4645315e-07
-   ODMSO       OA  1  0.0022663291  9.752175e-07
-   ODMSO       OW  1  0.0024378763  1.4069138e-06
-   ODMSO        N  1  0.0023521027  1.1277849e-06
-   ODMSO       NT  1  0.0023521027  1.1277849e-06
-   ODMSO       NL  1  0.0023521027  1.1277849e-06
-   ODMSO       NR  1  0.0023521027  1.1277849e-06
-   ODMSO       NZ  1  0.0023521027  1.1277849e-06
-   ODMSO       NE  1  0.0023521027  1.1277849e-06
-   ODMSO        C  1  0.0023054038  1.5924218e-06
-   ODMSO      CH1  1  0.0025713019  1.6756404e-06
-   ODMSO      CH2  1  0.003275122  1.8876712e-06
-   ODMSO      CH3  1  0.0039446326  2.1288192e-06
-   ODMSO      CH4  1  0.0054704496  5.0815333e-06
-   ODMSO      CR1  1  0.0035429262  2.501758e-06
-   ODMSO       HC  1  0.0004383984  1.0662378e-07
-   ODMSO        H  1           0           0
-   ODMSO      DUM  1           0           0
-   ODMSO        S  1  0.0047613878  3.1345658e-06
-   ODMSO     CU1+  1  0.0009744834  6.2058507e-08
-   ODMSO     CU2+  1  0.0009744834  6.2058507e-08
-   ODMSO       FE  1           0           0
-   ODMSO     ZN2+  1  0.0009744834  8.4224118e-08
-   ODMSO     MG2+  1  0.00038502816  5.0607287e-08
-   ODMSO     CA2+  1  0.0015105684  6.117431e-07
-   ODMSO        P  1  0.0057849528  4.0837775e-06
-   ODMSO       AR  1  0.0037716558  2.7202067e-06
-   ODMSO        F  1  0.0016354166  7.5607529e-07
-   ODMSO       CL  1  0.0044611802  3.3902895e-06
-   ODMSO       BR  1  0.0016363697  7.0146311e-06
-   ODMSO     CMET  1  0.0044892949  3.9585162e-06
-   ODMSO     OMET  1  0.0022663291  9.752175e-07
-   ODMSO      NA+  1  0.00040451783  1.256947e-07
-   ODMSO      CL-  1  0.00559911  8.9633324e-06
-   ODMSO     CCHL  1  0.0024441664  1.7475898e-06
-   ODMSO    CLCHL  1  0.0043430509  3.2161373e-06
-   ODMSO     HCHL  1  0.00029258328  5.6843478e-08
-   ODMSO    SDMSO  1  0.004897196  4.0192831e-06
-   ODMSO    CDMSO  1  0.0045335636  4.0434685e-06
-   ODMSO    ODMSO  1  0.0022707131  7.5144626e-07
-    CCL4        O  1  0.0024394475  2.3738805e-06
-    CCL4       OM  1  0.0024394475  2.3738805e-06
-    CCL4       OA  1  0.0024394475  3.1014e-06
-    CCL4       OW  1  0.0026240987  4.4742864e-06
-    CCL4        N  1  0.0025317731  3.5865968e-06
-    CCL4       NT  1  0.0025317731  3.5865968e-06
-    CCL4       NL  1  0.0025317731  3.5865968e-06
-    CCL4       NR  1  0.0025317731  3.5865968e-06
-    CCL4       NZ  1  0.0025317731  3.5865968e-06
-    CCL4       NE  1  0.0025317731  3.5865968e-06
-    CCL4        C  1  0.002481507  5.0642416e-06
-    CCL4      CH1  1  0.0027677163  5.3288944e-06
-    CCL4      CH2  1  0.0035252992  6.0031978e-06
-    CCL4      CH3  1  0.0042459518  6.7700998e-06
-    CCL4      CH4  1  0.0058883216  1.6160362e-05
-    CCL4      CR1  1  0.0038135602  7.9561248e-06
-    CCL4       HC  1  0.0004718864  3.390864e-07
-    CCL4        H  1           0           0
-    CCL4      DUM  1           0           0
-    CCL4        S  1  0.0051250966  9.9685888e-06
-    CCL4     CU1+  1  0.0010489214  1.9735931e-07
-    CCL4     CU2+  1  0.0010489214  1.9735931e-07
-    CCL4       FE  1           0           0
-    CCL4     ZN2+  1  0.0010489214  2.6785069e-07
-    CCL4     MG2+  1  0.00041443936  1.6094198e-07
-    CCL4     CA2+  1  0.0016259564  1.9454738e-06
-    CCL4        P  1  0.0062268488  1.2987285e-05
-    CCL4       AR  1  0.0040597618  8.6508384e-06
-    CCL4        F  1  0.0017603414  2.404481e-06
-    CCL4       CL  1  0.004801957  1.0781845e-05
-    CCL4       BR  1  0.0017613673  2.2308026e-05
-    CCL4     CMET  1  0.0048322193  1.2588927e-05
-    CCL4     OMET  1  0.0024394475  3.1014e-06
-    CCL4      NA+  1  0.00043541779  3.99736e-07
-    CCL4      CL-  1  0.00602681  2.8505312e-05
-    CCL4     CCHL  1  0.0026308693  5.5577088e-06
-    CCL4    CLCHL  1  0.0046748042  1.0228004e-05
-    CCL4     HCHL  1  0.00031493288  1.807744e-07
-    CCL4    SDMSO  1  0.0052712788  1.2782179e-05
-    CCL4    CDMSO  1  0.0048798696  1.2859094e-05
-    CCL4    ODMSO  1  0.0024441664  2.3897596e-06
-    CCL4     CCL4  1  0.0026308693  7.5999462e-06
-   CLCL4        O  1  0.0041472796  3.0768825e-06
-   CLCL4       OM  1  0.0041472796  3.0768825e-06
-   CLCL4       OA  1  0.0041472796  4.01985e-06
-   CLCL4       OW  1  0.0044612032  5.7993036e-06
-   CLCL4        N  1  0.0043042414  4.6487332e-06
-   CLCL4       NT  1  0.0043042414  4.6487332e-06
-   CLCL4       NL  1  0.0043042414  4.6487332e-06
-   CLCL4       NR  1  0.0043042414  4.6487332e-06
-   CLCL4       NZ  1  0.0043042414  4.6487332e-06
-   CLCL4       NE  1  0.0043042414  4.6487332e-06
-   CLCL4        C  1  0.0042187844  6.5639684e-06
-   CLCL4      CH1  1  0.004705366  6.9069956e-06
-   CLCL4      CH2  1  0.0059933247  7.7809875e-06
-   CLCL4      CH3  1  0.0072184988  8.7750002e-06
-   CLCL4      CH4  1  0.010010675  2.0946098e-05
-   CLCL4      CR1  1  0.0064833944  1.0312255e-05
-   CLCL4       HC  1  0.0008022492  4.395036e-07
-   CLCL4        H  1           0           0
-   CLCL4      DUM  1           0           0
-   CLCL4        S  1  0.0087131239  1.2920691e-05
-   CLCL4     CU1+  1  0.0017832604  2.5580539e-07
-   CLCL4     CU2+  1  0.0017832604  2.5580539e-07
-   CLCL4       FE  1           0           0
-   CLCL4     ZN2+  1  0.0017832604  3.4717211e-07
-   CLCL4     MG2+  1  0.00070458408  2.0860342e-07
-   CLCL4     CA2+  1  0.0027642717  2.5216072e-06
-   CLCL4        P  1  0.010586201  1.6833345e-05
-   CLCL4       AR  1  0.0069019592  1.1212702e-05
-   CLCL4        F  1  0.0029927383  3.116545e-06
-   CLCL4       CL  1  0.0081637576  1.3974785e-05
-   CLCL4       BR  1  0.0029944823  2.8914334e-05
-   CLCL4     CMET  1  0.0082152062  1.6317018e-05
-   CLCL4     OMET  1  0.0041472796  4.01985e-06
-   CLCL4      NA+  1  0.00074024929  5.18114e-07
-   CLCL4      CL-  1  0.010246117  3.6946888e-05
-   CLCL4     CCHL  1  0.0044727137  7.2035712e-06
-   CLCL4    CLCHL  1  0.0079475863  1.3256929e-05
-   CLCL4     HCHL  1  0.00053541414  2.3430902e-07
-   CLCL4    SDMSO  1  0.0089616468  1.6567499e-05
-   CLCL4    CDMSO  1  0.0082962159  1.6667191e-05
-   CLCL4    ODMSO  1  0.0041553021  3.0974642e-06
-   CLCL4     CCL4  1  0.0044727137  9.8505978e-06
-   CLCL4    CLCL4  1  0.0076040144  1.2767758e-05
+    CChl        O  1  0.0024394475  1.7359776e-06
+    CChl       OM  1  0.0024394475  1.7359776e-06
+    CChl       OA  1  0.0024394475   2.268e-06
+    CChl       OW  1  0.0026240987  3.271968e-06
+    CChl        N  1  0.0025317731  2.622816e-06
+    CChl       NT  1  0.0025317731  2.622816e-06
+    CChl       NL  1  0.0025317731  2.622816e-06
+    CChl       NR  1  0.0025317731  2.622816e-06
+    CChl       NZ  1  0.0025317731  2.622816e-06
+    CChl       NE  1  0.0025317731  2.622816e-06
+    CChl        C  1  0.002481507  3.703392e-06
+    CChl      CH1  1  0.0027677163  3.896928e-06
+    CChl      CH2  1  0.0035252992  4.3900343e-06
+    CChl      CH3  1  0.0042459518  4.9508565e-06
+    CChl      CH4  1  0.0058883216  1.1817792e-05
+    CChl      CR1  1  0.0038135602  5.818176e-06
+    CChl       HC  1  0.0004718864  2.47968e-07
+    CChl        H  1           0           0
+    CChl      DUM  1           0           0
+    CChl        S  1  0.0051250966  7.289856e-06
+    CChl     CU1+  1  0.0010489214  1.4432544e-07
+    CChl     CU2+  1  0.0010489214  1.4432544e-07
+    CChl       FE  1           0           0
+    CChl     ZN2+  1  0.0010489214  1.9587456e-07
+    CChl     MG2+  1  0.00041443936  1.1769408e-07
+    CChl     CA2+  1  0.0016259564  1.4226912e-06
+    CChl        P  1  0.0062268488  9.497376e-06
+    CChl       AR  1  0.0040597618  6.326208e-06
+    CChl        F  1  0.0017603414  1.7583552e-06
+    CChl       CL  1  0.004801957  7.884576e-06
+    CChl       BR  1  0.0017613673  1.6313472e-05
+    CChl     CMet  1  0.0048322193  9.206064e-06
+    CChl     OMet  1  0.0024394475   2.268e-06
+    CChl      NA+  1  0.00043541779  2.9232e-07
+    CChl      CL-  1  0.00602681  2.084544e-05
+    CChl     CChl  1  0.0026308693  4.064256e-06
+   CLChl        O  1  0.004334666  3.1947671e-06
+   CLChl       OM  1  0.004334666  3.1947671e-06
+   CLChl       OA  1  0.004334666  4.1738625e-06
+   CLChl       OW  1  0.0046627736  6.0214923e-06
+   CLChl        N  1  0.0044987198  4.8268401e-06
+   CLChl       NT  1  0.0044987198  4.8268401e-06
+   CLChl       NL  1  0.0044987198  4.8268401e-06
+   CLChl       NR  1  0.0044987198  4.8268401e-06
+   CLChl       NZ  1  0.0044987198  4.8268401e-06
+   CLChl       NE  1  0.0044987198  4.8268401e-06
+   CLChl        C  1  0.0044094016  6.8154537e-06
+   CLChl      CH1  1  0.0049179684  7.1716233e-06
+   CLChl      CH2  1  0.0062641209  8.0791004e-06
+   CLChl      CH3  1  0.007544652  9.1111968e-06
+   CLChl      CH4  1  0.010462987  2.1748606e-05
+   CLChl      CR1  1  0.0067763334  1.0707349e-05
+   CLChl       HC  1  0.0008384972  4.563423e-07
+   CLChl        H  1           0           0
+   CLChl      DUM  1           0           0
+   CLChl        S  1  0.0091068087  1.3415722e-05
+   CLChl     CU1+  1  0.0018638335  2.6560606e-07
+   CLChl     CU2+  1  0.0018638335  2.6560606e-07
+   CLChl       FE  1           0           0
+   CLChl     ZN2+  1  0.0018638335  3.6047332e-07
+   CLChl     MG2+  1  0.00073641928  2.1659564e-07
+   CLChl     CA2+  1  0.0028891697  2.6182176e-06
+   CLChl        P  1  0.011064517  1.7478281e-05
+   CLChl       AR  1  0.0072138101  1.1642294e-05
+   CLChl        F  1  0.0031279591  3.2359492e-06
+   CLChl       CL  1  0.0085326204  1.4510201e-05
+   CLChl       BR  1  0.0031297819  3.0022129e-05
+   CLChl     CMet  1  0.0085863936  1.6942172e-05
+   CLChl     OMet  1  0.004334666  4.1738625e-06
+   CLChl      NA+  1  0.00077369595  5.379645e-07
+   CLChl      CL-  1  0.010709067  3.8362434e-05
+   CLChl     CChl  1  0.0046748042  7.4795616e-06
+   CLChl    CLChl  1  0.0083066819  1.3764842e-05
+    HChl        O  1  0.0002920184  5.6465771e-08
+    HChl       OM  1  0.0002920184  5.6465771e-08
+    HChl       OA  1  0.0002920184  7.377075e-08
+    HChl       OW  1  0.0003141224  1.064266e-07
+    HChl        N  1  0.0003030704  8.5311774e-08
+    HChl       NT  1  0.0003030704  8.5311774e-08
+    HChl       NL  1  0.0003030704  8.5311774e-08
+    HChl       NR  1  0.0003030704  8.5311774e-08
+    HChl       NZ  1  0.0003030704  8.5311774e-08
+    HChl       NE  1  0.0003030704  8.5311774e-08
+    HChl        C  1  0.0002970532  1.2045944e-07
+    HChl      CH1  1  0.0003313144  1.2675454e-07
+    HChl      CH2  1  0.0004220022  1.4279371e-07
+    HChl      CH3  1  0.0005082692  1.6103545e-07
+    HChl      CH4  1  0.000704872  3.8439479e-07
+    HChl      CR1  1  0.000456509  1.8924656e-07
+    HChl       HC  1  5.6488e-05  8.065602e-09
+    HChl        H  1           0           0
+    HChl      DUM  1           0           0
+    HChl        S  1  0.0006135088  2.3711558e-07
+    HChl     CU1+  1  0.000125563  4.6944427e-09
+    HChl     CU2+  1  0.000125563  4.6944427e-09
+    HChl       FE  1           0           0
+    HChl     ZN2+  1  0.000125563  6.3711698e-09
+    HChl     MG2+  1  4.96112e-05  3.8282101e-09
+    HChl     CA2+  1  0.000194638  4.6275572e-08
+    HChl        P  1  0.000745396  3.0891911e-07
+    HChl       AR  1  0.000485981  2.0577121e-07
+    HChl        F  1  0.0002107248  5.7193643e-08
+    HChl       CL  1  0.0005748268  2.5645991e-07
+    HChl       BR  1  0.0002108476  5.3062481e-07
+    HChl     CMet  1  0.0005784494  2.9944367e-07
+    HChl     OMet  1  0.0002920184  7.377075e-08
+    HChl      NA+  1  5.212246e-05  9.50823e-09
+    HChl      CL-  1  0.00072145  6.7803516e-07
+    HChl     CChl  1  0.00031493288  1.3219718e-07
+    HChl    CLChl  1  0.00055960574  2.432861e-07
+    HChl     HChl  1  3.76996e-05  4.2999495e-09
+   SDmso        O  1  0.0048877412  3.9925763e-06
+   SDmso       OM  1  0.0048877412  3.9925763e-06
+   SDmso       OA  1  0.0048877412  5.216175e-06
+   SDmso       OW  1  0.0052577132  7.5252018e-06
+   SDmso        N  1  0.0050727272  6.0322166e-06
+   SDmso       NT  1  0.0050727272  6.0322166e-06
+   SDmso       NL  1  0.0050727272  6.0322166e-06
+   SDmso       NR  1  0.0050727272  6.0322166e-06
+   SDmso       NZ  1  0.0050727272  6.0322166e-06
+   SDmso       NE  1  0.0050727272  6.0322166e-06
+   SDmso        C  1  0.0049720126  8.5174342e-06
+   SDmso      CH1  1  0.0055454692  8.9625478e-06
+   SDmso      CH2  1  0.0070633821  1.0096643e-05
+   SDmso      CH3  1  0.0085073006  1.1386479e-05
+   SDmso      CH4  1  0.011797996  2.7179749e-05
+   SDmso      CR1  1  0.0076409495  1.3381228e-05
+   SDmso       HC  1  0.000945484  5.703018e-07
+   SDmso        H  1           0           0
+   SDmso      DUM  1           0           0
+   SDmso        S  1  0.010268778  1.6765946e-05
+   SDmso     CU1+  1  0.0021016465  3.3193419e-07
+   SDmso     CU2+  1  0.0021016465  3.3193419e-07
+   SDmso       FE  1           0           0
+   SDmso     ZN2+  1  0.0021016465  4.5049206e-07
+   SDmso     MG2+  1  0.0008303816  2.7068471e-07
+   SDmso     CA2+  1  0.003257809  3.2720486e-06
+   SDmso        P  1  0.012476278  2.1843023e-05
+   SDmso       AR  1  0.0081342455  1.4549651e-05
+   SDmso        F  1  0.0035270664  4.0440425e-06
+   SDmso       CL  1  0.0096213274  1.8133743e-05
+   SDmso       BR  1  0.0035291218  3.7519367e-05
+   SDmso     CMet  1  0.0096819617  2.1173034e-05
+   SDmso     OMet  1  0.0048877412  5.216175e-06
+   SDmso      NA+  1  0.00087241453  6.72307e-07
+   SDmso      CL-  1  0.012075475  4.7942444e-05
+   SDmso     CChl  1  0.0052712788  9.3473856e-06
+   SDmso    CLChl  1  0.0093665606  1.720225e-05
+   SDmso     HChl  1  0.0006310078  3.0404041e-07
+   SDmso    SDmso  1  0.010561673  2.149806e-05
+   CDmso        O  1  0.0045248108  4.016601e-06
+   CDmso       OM  1  0.0045248108  4.016601e-06
+   CDmso       OA  1  0.0045248108  5.2475625e-06
+   CDmso       OW  1  0.0048673112  7.5704835e-06
+   CDmso        N  1  0.004696061  6.0685145e-06
+   CDmso       NT  1  0.004696061  6.0685145e-06
+   CDmso       NL  1  0.004696061  6.0685145e-06
+   CDmso       NR  1  0.004696061  6.0685145e-06
+   CDmso       NZ  1  0.004696061  6.0685145e-06
+   CDmso       NE  1  0.004696061  6.0685145e-06
+   CDmso        C  1  0.0046028248  8.5686865e-06
+   CDmso      CH1  1  0.0051337004  9.0164785e-06
+   CDmso      CH2  1  0.0065389035  1.0157398e-05
+   CDmso      CH3  1  0.0078756064  1.1454995e-05
+   CDmso      CH4  1  0.010921957  2.7343299e-05
+   CDmso      CR1  1  0.0070735846  1.3461747e-05
+   CDmso       HC  1  0.0008752788  5.737335e-07
+   CDmso        H  1           0           0
+   CDmso      DUM  1           0           0
+   CDmso        S  1  0.0095062889  1.6866832e-05
+   CDmso     CU1+  1  0.0019455925  3.3393156e-07
+   CDmso     CU2+  1  0.0019455925  3.3393156e-07
+   CDmso       FE  1           0           0
+   CDmso     ZN2+  1  0.0019455925  4.5320282e-07
+   CDmso     MG2+  1  0.00076872312  2.7231351e-07
+   CDmso     CA2+  1  0.0030159063  3.2917377e-06
+   CDmso        P  1  0.011549875  2.197446e-05
+   CDmso       AR  1  0.0075302519  1.4637201e-05
+   CDmso        F  1  0.0032651705  4.0683769e-06
+   CDmso       CL  1  0.0089069132  1.824286e-05
+   CDmso       BR  1  0.0032670733  3.7745134e-05
+   CDmso     CMet  1  0.0089630452  2.1300439e-05
+   CDmso     OMet  1  0.0045248108  5.2475625e-06
+   CDmso      NA+  1  0.00080763497  6.763525e-07
+   CDmso      CL-  1  0.011178832  4.823093e-05
+   CDmso     CChl  1  0.0048798696  9.403632e-06
+   CDmso    CLChl  1  0.0086710636  1.7305761e-05
+   CDmso     HChl  1  0.00058415346  3.0586992e-07
+   CDmso    SDmso  1  0.009777435  2.1627421e-05
+   CDmso    CDmso  1  0.0090514293  2.175756e-05
+   ODmso        O  1  0.0022663291  7.4645315e-07
+   ODmso       OM  1  0.0022663291  7.4645315e-07
+   ODmso       OA  1  0.0022663291  9.752175e-07
+   ODmso       OW  1  0.0024378763  1.4069138e-06
+   ODmso        N  1  0.0023521027  1.1277849e-06
+   ODmso       NT  1  0.0023521027  1.1277849e-06
+   ODmso       NL  1  0.0023521027  1.1277849e-06
+   ODmso       NR  1  0.0023521027  1.1277849e-06
+   ODmso       NZ  1  0.0023521027  1.1277849e-06
+   ODmso       NE  1  0.0023521027  1.1277849e-06
+   ODmso        C  1  0.0023054038  1.5924218e-06
+   ODmso      CH1  1  0.0025713019  1.6756404e-06
+   ODmso      CH2  1  0.003275122  1.8876712e-06
+   ODmso      CH3  1  0.0039446326  2.1288192e-06
+   ODmso      CH4  1  0.0054704496  5.0815333e-06
+   ODmso      CR1  1  0.0035429262  2.501758e-06
+   ODmso       HC  1  0.0004383984  1.0662378e-07
+   ODmso        H  1           0           0
+   ODmso      DUM  1           0           0
+   ODmso        S  1  0.0047613878  3.1345658e-06
+   ODmso     CU1+  1  0.0009744834  6.2058507e-08
+   ODmso     CU2+  1  0.0009744834  6.2058507e-08
+   ODmso       FE  1           0           0
+   ODmso     ZN2+  1  0.0009744834  8.4224118e-08
+   ODmso     MG2+  1  0.00038502816  5.0607287e-08
+   ODmso     CA2+  1  0.0015105684  6.117431e-07
+   ODmso        P  1  0.0057849528  4.0837775e-06
+   ODmso       AR  1  0.0037716558  2.7202067e-06
+   ODmso        F  1  0.0016354166  7.5607529e-07
+   ODmso       CL  1  0.0044611802  3.3902895e-06
+   ODmso       BR  1  0.0016363697  7.0146311e-06
+   ODmso     CMet  1  0.0044892949  3.9585162e-06
+   ODmso     OMet  1  0.0022663291  9.752175e-07
+   ODmso      NA+  1  0.00040451783  1.256947e-07
+   ODmso      CL-  1  0.00559911  8.9633324e-06
+   ODmso     CChl  1  0.0024441664  1.7475898e-06
+   ODmso    CLChl  1  0.0043430509  3.2161373e-06
+   ODmso     HChl  1  0.00029258328  5.6843478e-08
+   ODmso    SDmso  1  0.004897196  4.0192831e-06
+   ODmso    CDmso  1  0.0045335636  4.0434685e-06
+   ODmso    ODmso  1  0.0022707131  7.5144626e-07
+    CCl4        O  1  0.0024394475  2.3738805e-06
+    CCl4       OM  1  0.0024394475  2.3738805e-06
+    CCl4       OA  1  0.0024394475  3.1014e-06
+    CCl4       OW  1  0.0026240987  4.4742864e-06
+    CCl4        N  1  0.0025317731  3.5865968e-06
+    CCl4       NT  1  0.0025317731  3.5865968e-06
+    CCl4       NL  1  0.0025317731  3.5865968e-06
+    CCl4       NR  1  0.0025317731  3.5865968e-06
+    CCl4       NZ  1  0.0025317731  3.5865968e-06
+    CCl4       NE  1  0.0025317731  3.5865968e-06
+    CCl4        C  1  0.002481507  5.0642416e-06
+    CCl4      CH1  1  0.0027677163  5.3288944e-06
+    CCl4      CH2  1  0.0035252992  6.0031978e-06
+    CCl4      CH3  1  0.0042459518  6.7700998e-06
+    CCl4      CH4  1  0.0058883216  1.6160362e-05
+    CCl4      CR1  1  0.0038135602  7.9561248e-06
+    CCl4       HC  1  0.0004718864  3.390864e-07
+    CCl4        H  1           0           0
+    CCl4      DUM  1           0           0
+    CCl4        S  1  0.0051250966  9.9685888e-06
+    CCl4     CU1+  1  0.0010489214  1.9735931e-07
+    CCl4     CU2+  1  0.0010489214  1.9735931e-07
+    CCl4       FE  1           0           0
+    CCl4     ZN2+  1  0.0010489214  2.6785069e-07
+    CCl4     MG2+  1  0.00041443936  1.6094198e-07
+    CCl4     CA2+  1  0.0016259564  1.9454738e-06
+    CCl4        P  1  0.0062268488  1.2987285e-05
+    CCl4       AR  1  0.0040597618  8.6508384e-06
+    CCl4        F  1  0.0017603414  2.404481e-06
+    CCl4       CL  1  0.004801957  1.0781845e-05
+    CCl4       BR  1  0.0017613673  2.2308026e-05
+    CCl4     CMet  1  0.0048322193  1.2588927e-05
+    CCl4     OMet  1  0.0024394475  3.1014e-06
+    CCl4      NA+  1  0.00043541779  3.99736e-07
+    CCl4      CL-  1  0.00602681  2.8505312e-05
+    CCl4     CChl  1  0.0026308693  5.5577088e-06
+    CCl4    CLChl  1  0.0046748042  1.0228004e-05
+    CCl4     HChl  1  0.00031493288  1.807744e-07
+    CCl4    SDmso  1  0.0052712788  1.2782179e-05
+    CCl4    CDmso  1  0.0048798696  1.2859094e-05
+    CCl4    ODmso  1  0.0024441664  2.3897596e-06
+    CCl4     CCl4  1  0.0026308693  7.5999462e-06
+   CLCl4        O  1  0.0041472796  3.0768825e-06
+   CLCl4       OM  1  0.0041472796  3.0768825e-06
+   CLCl4       OA  1  0.0041472796  4.01985e-06
+   CLCl4       OW  1  0.0044612032  5.7993036e-06
+   CLCl4        N  1  0.0043042414  4.6487332e-06
+   CLCl4       NT  1  0.0043042414  4.6487332e-06
+   CLCl4       NL  1  0.0043042414  4.6487332e-06
+   CLCl4       NR  1  0.0043042414  4.6487332e-06
+   CLCl4       NZ  1  0.0043042414  4.6487332e-06
+   CLCl4       NE  1  0.0043042414  4.6487332e-06
+   CLCl4        C  1  0.0042187844  6.5639684e-06
+   CLCl4      CH1  1  0.004705366  6.9069956e-06
+   CLCl4      CH2  1  0.0059933247  7.7809875e-06
+   CLCl4      CH3  1  0.0072184988  8.7750002e-06
+   CLCl4      CH4  1  0.010010675  2.0946098e-05
+   CLCl4      CR1  1  0.0064833944  1.0312255e-05
+   CLCl4       HC  1  0.0008022492  4.395036e-07
+   CLCl4        H  1           0           0
+   CLCl4      DUM  1           0           0
+   CLCl4        S  1  0.0087131239  1.2920691e-05
+   CLCl4     CU1+  1  0.0017832604  2.5580539e-07
+   CLCl4     CU2+  1  0.0017832604  2.5580539e-07
+   CLCl4       FE  1           0           0
+   CLCl4     ZN2+  1  0.0017832604  3.4717211e-07
+   CLCl4     MG2+  1  0.00070458408  2.0860342e-07
+   CLCl4     CA2+  1  0.0027642717  2.5216072e-06
+   CLCl4        P  1  0.010586201  1.6833345e-05
+   CLCl4       AR  1  0.0069019592  1.1212702e-05
+   CLCl4        F  1  0.0029927383  3.116545e-06
+   CLCl4       CL  1  0.0081637576  1.3974785e-05
+   CLCl4       BR  1  0.0029944823  2.8914334e-05
+   CLCl4     CMet  1  0.0082152062  1.6317018e-05
+   CLCl4     OMet  1  0.0041472796  4.01985e-06
+   CLCl4      NA+  1  0.00074024929  5.18114e-07
+   CLCl4      CL-  1  0.010246117  3.6946888e-05
+   CLCl4     CChl  1  0.0044727137  7.2035712e-06
+   CLCl4    CLChl  1  0.0079475863  1.3256929e-05
+   CLCl4     HChl  1  0.00053541414  2.3430902e-07
+   CLCl4    SDmso  1  0.0089616468  1.6567499e-05
+   CLCl4    CDmso  1  0.0082962159  1.6667191e-05
+   CLCl4    ODmso  1  0.0041553021  3.0974642e-06
+   CLCl4     CCl4  1  0.0044727137  9.8505978e-06
+   CLCl4    CLCl4  1  0.0076040144  1.2767758e-05
     CH2r        O  1  0.0032687988  1.8751283e-06
     CH2r       OM  1  0.0032687988  1.8751283e-06
     CH2r       OA  1  0.0032687988  2.4497959e-06
@@ -2066,18 +2066,18 @@ CLCL4   17      0.000      0.000     A  0.0076040144  1.2767758e-05
     CH2r        F  1  0.0023588136  1.8992996e-06
     CH2r       CL  1  0.0064345026  8.5165795e-06
     CH2r       BR  1  0.0023601882  1.762111e-05
-    CH2r     CMET  1  0.0064750533  9.943994e-06
-    CH2r     OMET  1  0.0032687988  2.4497959e-06
+    CH2r     CMet  1  0.0064750533  9.943994e-06
+    CH2r     OMet  1  0.0032687988  2.4497959e-06
     CH2r      NA+  1  0.00058344897  3.1575148e-07
     CH2r      CL-  1  0.008075775  2.2516347e-05
-    CH2r     CCHL  1  0.0035252992  4.3900343e-06
-    CH2r    CLCHL  1  0.0062641209  8.0791004e-06
-    CH2r     HCHL  1  0.0004220022  1.4279371e-07
-    CH2r    SDMSO  1  0.0070633821  1.0096643e-05
-    CH2r    CDMSO  1  0.0065389035  1.0157398e-05
-    CH2r    ODMSO  1  0.003275122  1.8876712e-06
-    CH2r     CCL4  1  0.0035252992  6.0031978e-06
-    CH2r    CLCL4  1  0.0059933247  7.7809875e-06
+    CH2r     CChl  1  0.0035252992  4.3900343e-06
+    CH2r    CLChl  1  0.0062641209  8.0791004e-06
+    CH2r     HChl  1  0.0004220022  1.4279371e-07
+    CH2r    SDmso  1  0.0070633821  1.0096643e-05
+    CH2r    CDmso  1  0.0065389035  1.0157398e-05
+    CH2r    ODmso  1  0.003275122  1.8876712e-06
+    CH2r     CCl4  1  0.0035252992  6.0031978e-06
+    CH2r    CLCl4  1  0.0059933247  7.7809875e-06
     CH2r     CH2r  1  0.0047238129  4.7419261e-06
      CH0        O  1  0.0023009528  1.5818407e-06
      CH0       OM  1  0.0023009528  1.5818407e-06
@@ -2110,18 +2110,18 @@ CLCL4   17      0.000      0.000     A  0.0076040144  1.2767758e-05
      CH0        F  1  0.0016604016  1.6022314e-06
      CH0       CL  1  0.0045293356  7.184507e-06
      CH0       BR  1  0.0016613692  1.4865004e-05
-     CH0     CMET  1  0.0045578798  8.3886605e-06
-     CH0     OMET  1  0.0023009528  2.066625e-06
+     CH0     CMet  1  0.0045578798  8.3886605e-06
+     CH0     OMet  1  0.0023009528  2.066625e-06
      CH0      NA+  1  0.00041069782  2.66365e-07
      CH0      CL-  1  0.00568465  1.899458e-05
-     CH0     CCHL  1  0.002481507  3.703392e-06
-     CH0    CLCHL  1  0.0044094016  6.8154537e-06
-     CH0     HCHL  1  0.0002970532  1.2045944e-07
-     CH0    SDMSO  1  0.0049720126  8.5174342e-06
-     CH0    CDMSO  1  0.0046028248  8.5686865e-06
-     CH0    ODMSO  1  0.0023054038  1.5924218e-06
-     CH0     CCL4  1  0.002481507  5.0642416e-06
-     CH0    CLCL4  1  0.0042187844  6.5639684e-06
+     CH0     CChl  1  0.002481507  3.703392e-06
+     CH0    CLChl  1  0.0044094016  6.8154537e-06
+     CH0     HChl  1  0.0002970532  1.2045944e-07
+     CH0    SDmso  1  0.0049720126  8.5174342e-06
+     CH0    CDmso  1  0.0046028248  8.5686865e-06
+     CH0    ODmso  1  0.0023054038  1.5924218e-06
+     CH0     CCl4  1  0.002481507  5.0642416e-06
+     CH0    CLCl4  1  0.0042187844  6.5639684e-06
      CH0     CH2r  1  0.0033251574  4.0002446e-06
      CH0      CH0  1  0.0023406244  3.374569e-06
       SI        O  1  0.005773784  4.0566421e-06
@@ -2155,18 +2155,18 @@ CLCL4   17      0.000      0.000     A  0.0076040144  1.2767758e-05
       SI        F  1  0.004166448  4.1089342e-06
       SI       CL  1  0.011365468  1.8424721e-05
       SI       BR  1  0.004168876  3.8121412e-05
-      SI     CMET  1  0.011437094  2.1512782e-05
-      SI     OMET  1  0.005773784  5.299875e-06
+      SI     CMet  1  0.011437094  2.1512782e-05
+      SI     OMet  1  0.005773784  5.299875e-06
       SI      NA+  1  0.0010305646  6.83095e-07
       SI      CL-  1   0.0142645  4.871174e-05
-      SI     CCHL  1  0.0062268488  9.497376e-06
-      SI    CLCHL  1  0.011064517  1.7478281e-05
-      SI     HCHL  1  0.000745396  3.0891911e-07
-      SI    SDMSO  1  0.012476278  2.1843023e-05
-      SI    CDMSO  1  0.011549875  2.197446e-05
-      SI    ODMSO  1  0.0057849528  4.0837775e-06
-      SI     CCL4  1  0.0062268488  1.2987285e-05
-      SI    CLCL4  1  0.010586201  1.6833345e-05
+      SI     CChl  1  0.0062268488  9.497376e-06
+      SI    CLChl  1  0.011064517  1.7478281e-05
+      SI     HChl  1  0.000745396  3.0891911e-07
+      SI    SDmso  1  0.012476278  2.1843023e-05
+      SI    CDmso  1  0.011549875  2.197446e-05
+      SI    ODmso  1  0.0057849528  4.0837775e-06
+      SI     CCl4  1  0.0062268488  1.2987285e-05
+      SI    CLCl4  1  0.010586201  1.6833345e-05
       SI     CH2r  1  0.008343822  1.0258657e-05
       SI      CH0  1  0.005873332  8.654107e-06
       SI       SI  1  0.01473796  2.2193521e-05
diff --git a/share/top/gromos45a3.ff/watermodels.dat b/share/top/gromos45a3.ff/watermodels.dat
new file mode 100644 (file)
index 0000000..a68dbed
--- /dev/null
@@ -0,0 +1,2 @@
+spc    SPC    simple point charge, recommended
+spce   SPC/E  extended simple point charge
index 0cf7b44b3df1c656d24c0492dd5473ebc0e213fc..5804cf57755eb1a7eace68105ebfd0cdd287ac3b 100644 (file)
@@ -9,7 +9,8 @@ aminoacids.c.tdb        atomtypes.atp           ions.itp        \
 aminoacids.hdb         ffbonded.itp            spc.itp         \
 aminoacids.n.tdb       ffnonbonded.itp         spce.itp        \
 aminoacids.rtp         forcefield.doc          tip3p.itp       \
-aminoacids.vsd         forcefield.itp          tip4p.itp
+aminoacids.vsd         forcefield.itp          tip4p.itp       \
+aminoacids.r2b         atomname2type.n2t       watermodels.dat
 
 EXTRA_DIST = ${topol_DATA}
 
index ee2246f7c089d320253f3ba49cb42e5be3ad2967..c4d5386d2b5679aa510725888793612a5f22913f 100644 (file)
@@ -27,6 +27,11 @@ ASP1    2
 ASPH    2       
 1      1       H       N       -C      CA
 1      2       HD2     OD2     CG      CB
+ATP    4
+2      3       AH6     AN6     AC6     AC5
+1      2       AH2*    AO2*    AC2*    AC3*
+1      2       AH3*    AO3*    AC3*    AC2*
+1      2       AH3G    AO3G    APG     AO2G
 BEN     7       
 1      1       H2      C2      C1      C3
 1      1       H3      C3      C2      C4
@@ -40,6 +45,13 @@ CYS2    1
 CYSH    2       
 1      1       H       N       -C      CA
 1      2       HG      SG      CB      CA
+DADE   3
+1      1       H2      C2      N1      N3
+1      1       H8      C8      N7      N9
+2      3       H6      N6      C6      C5
+DTHY   2
+1      1       H3      N3      C2      C4
+1      1       H6      C6      C5      N1
 FAD     7       
 2      3       HN6     AN6     AC6     AC5
 1      2       HO2*    AO2*    AC2*    AC1*
index 7c7611264b745652d4e83105f50701a0e5495d02..08f0beb2315e9e8892bc80d22a32557b519b71bf 100644 (file)
@@ -45,7 +45,7 @@ H1    N       CA      C       gd_29
 [ replace ]
 N              NT      14.0067 0.128
 CA             CH1     13.019  0.188
-CD             CH2R    14.027  0.188
+CD             CH2r    14.027  0.188
 [ add ]
 2      4       H       N       CA      C
        H       1.008   0.248
diff --git a/share/top/gromos53a5.ff/aminoacids.r2b b/share/top/gromos53a5.ff/aminoacids.r2b
new file mode 100644 (file)
index 0000000..823db90
--- /dev/null
@@ -0,0 +1,7 @@
+; rtp residue to rtp building block table
+;GMX   Force-field
+CYS    CYSH
+HISD   HISA
+HISE   HISB
+LYS    LYSH
+LYSN   LYS
index e7febdef274e179df3d878571070d2fe14494c37..d5351295420074b7eabb59492aa6b4652698f552 100644 (file)
  [ atoms ]
     N     N     0.00000     0
    CA   CH1     0.00000     1
-   CB  CH2R     0.00000     1
+   CB  CH2r     0.00000     1
    CG   CH1     0.20800     2
   OD1    OA    -0.61100     2
   HD1     H     0.40300     2
-  CD2  CH2R     0.00000     3
+  CD2  CH2r     0.00000     3
     C     C       0.450     4
     O     O      -0.450     4
  [ bonds ]
  [ atoms ]
     N     N     0.00000     0
    CA   CH1     0.00000     1
-   CB  CH2R     0.00000     1
-   CG  CH2R     0.00000     2
-   CD  CH2R     0.00000     2
+   CB  CH2r     0.00000     1
+   CG  CH2r     0.00000     2
+   CD  CH2r     0.00000     2
     C     C       0.450     3
     O     O      -0.450     3
  [ bonds ]
    N7    NR    -0.54000     7
    C8     C     0.44000     7
    H8    HC     0.10000     7
-  C2*  CH2R     0.00000     8
+  C2*  CH2r     0.00000     8
   C3*   CH1       0.000     8
   O3*    OA      -0.360     9
  [ bonds ]
    N7    NR    -0.54000     8
    C8     C     0.44000     8
    H8    HC     0.10000     8
-  C2*  CH2R     0.00000     9
+  C2*  CH2r     0.00000     9
   C3*   CH1       0.000     9
   O3*    OA      -0.360    10
  [ bonds ]
   H42     H     0.41500     6
    C5     C    -0.10000     7
    H5    HC     0.10000     7
-  C2*  CH2R     0.00000     8
+  C2*  CH2r     0.00000     8
   C3*   CH1       0.000     8
   O3*    OA      -0.360     9
  [ bonds ]
    O4     O    -0.45000     6
    C5     C     0.00000     7
   C5M   CH3     0.00000     7
-  C2*  CH2R     0.00000     8
+  C2*  CH2r     0.00000     8
   C3*   CH1       0.000     8
   O3*    OA      -0.360     9
  [ bonds ]
@@ -8460,7 +8460,7 @@ FC10A  FC4A   FN5  FC5A     gi_1
   OSI    OA    -0.36000     8
   SI2     P     0.54000     8
   O5*    OA    -0.36000     8
-  C5*  CH2R     0.00000     9
+  C5*  CH2r     0.00000     9
   C11   CH1     0.00000    10
  C111   CH3     0.00000    10
  C112   CH3     0.00000    10
@@ -10089,18 +10089,18 @@ FC10A  FC4A   FN5  FC5A     gi_1
  AC5*   CH2     0.00000     8
  AO5*    OA    -0.36000     9
   APA     P     0.70500     9
-AO1PA    OM    -0.63500     9
-AO2PA    OM    -0.63500     9
-AO3PA    OA    -0.36000    10
+AO1A    OM    -0.63500     9
+AO2A    OM    -0.63500     9
+AO3A    OA    -0.36000    10
   APB     P     0.70500    10
-AO1PB    OM    -0.63500    10
-AO2PB    OM    -0.63500    10
-AO3PB    OA    -0.36000    11
+AO1B    OM    -0.63500    10
+AO2B    OM    -0.63500    10
+AO3B    OA    -0.36000    11
   APG     P     0.63000    11
-AO1PG    OM    -0.63500    11
-AO2PG    OM    -0.63500    11
-AO3PG    OA    -0.54800    11
-AH3PG     H     0.39800    11
+AO1G    OM    -0.63500    11
+AO2G    OM    -0.63500    11
+AO3G    OA    -0.54800    11
+AH3G     H     0.39800    11
  [ bonds ]
   AN9   AC4    gb_10   
   AN9   AC8    gb_10   
@@ -10128,18 +10128,18 @@ AH3PG     H     0.39800    11
  AO3*  AH3*    gb_1    
  AC5*  AO5*    gb_20   
  AO5*   APA    gb_28   
-  APA AO1PA    gb_24   
-  APA AO2PA    gb_24   
-  APA AO3PA    gb_28   
-AO3PA   APB    gb_28   
-  APB AO1PB    gb_24   
-  APB AO2PB    gb_24   
-  APB AO3PB    gb_28   
-AO3PB   APG    gb_28   
-  APG AO1PG    gb_24   
-  APG AO2PG    gb_24   
-  APG AO3PG    gb_28   
-AO3PG AH3PG    gb_1    
+  APA AO1A    gb_24   
+  APA AO2A    gb_24   
+  APA AO3A    gb_28   
+AO3A   APB    gb_28   
+  APB AO1B    gb_24   
+  APB AO2B    gb_24   
+  APB AO3B    gb_28   
+AO3B   APG    gb_28   
+  APG AO1G    gb_24   
+  APG AO2G    gb_24   
+  APG AO3G    gb_28   
+AO3G AH3G    gb_1    
  [ exclusions ]
 ;  ai    aj
   AN9   AC2
@@ -10156,9 +10156,9 @@ AO3PG AH3PG    gb_1
   AC6   AC8
   AC5  AC1*
   AN7  AC1*
-AO3PB AH3PG
-AO1PG AH3PG
-AO2PG AH3PG
+AO3B AH3G
+AO1G AH3G
+AO2G AH3G
  [ angles ]
 ;  ai    aj    ak   gromos type
   AC4   AN9   AC8     ga_7    
@@ -10198,27 +10198,27 @@ AO2PG AH3PG
  AC3*  AO3*  AH3*     ga_12   
  AC4*  AC5*  AO5*     ga_9    
  AC5*  AO5*   APA     ga_26   
- AO5*   APA AO1PA     ga_14   
- AO5*   APA AO2PA     ga_14   
- AO5*   APA AO3PA     ga_5    
-AO1PA   APA AO2PA     ga_29   
-AO1PA   APA AO3PA     ga_14   
-AO2PA   APA AO3PA     ga_14   
-  APA AO3PA   APB     ga_26   
-AO3PA   APB AO1PB     ga_14   
-AO3PA   APB AO2PB     ga_14   
-AO3PA   APB AO3PB     ga_5    
-AO1PB   APB AO2PB     ga_29   
-AO1PB   APB AO3PB     ga_14   
-AO2PB   APB AO3PB     ga_14   
-  APB AO3PB   APG     ga_26   
-AO3PB   APG AO1PG     ga_14   
-AO3PB   APG AO2PG     ga_14   
-AO3PB   APG AO3PG     ga_5    
-AO1PG   APG AO2PG     ga_29   
-AO1PG   APG AO3PG     ga_14   
-AO2PG   APG AO3PG     ga_14   
-  APG AO3PG AH3PG     ga_12   
+ AO5*   APA AO1A     ga_14   
+ AO5*   APA AO2A     ga_14   
+ AO5*   APA AO3A     ga_5    
+AO1A   APA AO2A     ga_29   
+AO1A   APA AO3A     ga_14   
+AO2A   APA AO3A     ga_14   
+  APA AO3A   APB     ga_26   
+AO3A   APB AO1B     ga_14   
+AO3A   APB AO2B     ga_14   
+AO3A   APB AO3B     ga_5    
+AO1B   APB AO2B     ga_29   
+AO1B   APB AO3B     ga_14   
+AO2B   APB AO3B     ga_14   
+  APB AO3B   APG     ga_26   
+AO3B   APG AO1G     ga_14   
+AO3B   APG AO2G     ga_14   
+AO3B   APG AO3G     ga_5    
+AO1G   APG AO2G     ga_29   
+AO1G   APG AO3G     ga_14   
+AO2G   APG AO3G     ga_14   
+  APG AO3G AH3G     ga_12   
  [ impropers ]
 ;  ai    aj    ak    al   gromos type
   AN9   AC4   AC5   AN7     gi_1    
@@ -10265,18 +10265,18 @@ AO2PG   APG AO3PG     ga_14
  AO2*  AC2*  AC3*  AO3*     gd_18   
  AC4*  AC3*  AO3*  AH3*     gd_23   
  AC4*  AC5*  AO5*   APA     gd_29   
- AC5*  AO5*   APA AO3PA     gd_19   
- AC5*  AO5*   APA AO3PA     gd_22   
- AO5*   APA AO3PA   APB     gd_19   
- AO5*   APA AO3PA   APB     gd_22   
-  APA AO3PA   APB AO3PB     gd_19   
-  APA AO3PA   APB AO3PB     gd_22   
-AO3PA   APB AO3PB   APG     gd_19   
-AO3PA   APB AO3PB   APG     gd_22   
-  APB AO3PB   APG AO3PG     gd_19   
-  APB AO3PB   APG AO3PG     gd_22   
-AO3PB   APG AO3PG AH3PG     gd_19   
-AO3PB   APG AO3PG AH3PG     gd_22   
+ AC5*  AO5*   APA AO3A     gd_19   
+ AC5*  AO5*   APA AO3A     gd_22   
+ AO5*   APA AO3A   APB     gd_19   
+ AO5*   APA AO3A   APB     gd_22   
+  APA AO3A   APB AO3B     gd_19   
+  APA AO3A   APB AO3B     gd_22   
+AO3A   APB AO3B   APG     gd_19   
+AO3A   APB AO3B   APG     gd_22   
+  APB AO3B   APG AO3G     gd_19   
+  APB AO3B   APG AO3G     gd_22   
+AO3B   APG AO3G AH3G     gd_19   
+AO3B   APG AO3G AH3G     gd_22   
 
 [ PMB ]
  [ atoms ]
@@ -10519,9 +10519,9 @@ AO3PB   APG AO3PG AH3PG     gd_22
   C18   CH3     0.00000     0
   C17   CH3     0.00000     0
    C1   CH0     0.00000     0
-   C2  CH2R     0.00000     1
-   C3  CH2R     0.00000     1
-   C4  CH2R     0.00000     1
+   C2  CH2r     0.00000     1
+   C3  CH2r     0.00000     1
+   C4  CH2r     0.00000     1
    C5     C     0.00000     2
   C16   CH3     0.00000     2
    C6     C     0.00000     2
@@ -10913,11 +10913,11 @@ AO3PB   APG AO3PG AH3PG     gd_22
 
 [ CHCL3 ]
  [ atoms ]
- CChl  CCHL     0.17900     0
- HChl  HCHL     0.08200     0
-CLCh1 CLCHL    -0.08700     0
-CLCh2 CLCHL    -0.08700     0
-CLCh3 CLCHL    -0.08700     0
+ CChl  CChl     0.17900     0
+ HChl  HChl     0.08200     0
+CLCh1 CLChl    -0.08700     0
+CLCh2 CLChl    -0.08700     0
+CLCh3 CLChl    -0.08700     0
  [ bonds ]
  CChl CLCh1    gb_40   
  CChl CLCh2    gb_40   
@@ -10937,10 +10937,10 @@ CLCh2 CLCh3    gb_48
 
 [ DMSO ]
  [ atoms ]
-SDmso SDMSO     0.12753     0
-ODmso ODMSO    -0.44753     0
-CDms1 CDMSO     0.16000     0
-CDms2 CDMSO     0.16000     0
+SDmso SDmso     0.12753     0
+ODmso ODmso    -0.44753     0
+CDms1 CDmso     0.16000     0
+CDms2 CDmso     0.16000     0
  [ bonds ]
 SDmso ODmso    gb_41   
 SDmso CDms1    gb_42   
@@ -10957,9 +10957,9 @@ CDms1 CDms2    gb_50
 
 [ CH3OH ]
  [ atoms ]
- Omet  OMET    -0.67400     0
+ Omet  OMet    -0.67400     0
  HMet     H     0.40800     0
- CMet  CMET     0.26600     0
+ CMet  CMet     0.26600     0
  [ bonds ]
  Omet  HMet    gb_1    
  Omet  CMet    gb_27   
@@ -10973,11 +10973,11 @@ CDms1 CDms2    gb_50
 
 [ CCL4 ]
  [ atoms ]
- CCl4  CCL4     0.00000     0
-CLCl1 CLCL4     0.00000     0
-CLCl2 CLCL4     0.00000     0
-CLCl3 CLCL4     0.00000     0
-CLCl4 CLCL4     0.00000     0
+ CCl4  CCl4     0.00000     0
+CLCl1 CLCl4     0.00000     0
+CLCl2 CLCl4     0.00000     0
+CLCl3 CLCl4     0.00000     0
+CLCl4 CLCl4     0.00000     0
  [ bonds ]
  CCl4 CLCl1    gb_43   
  CCl4 CLCl2    gb_43   
@@ -11029,12 +11029,12 @@ CLCl2 CLCl4    gb_52
 
 [ UREA ]
  [ atoms ]
-   OU OUREA    -0.39000     0
-   CU CUREA     0.14200     0
-  N1U NUREA    -0.54200     0
+   OU OUrea    -0.39000     0
+   CU CUrea     0.14200     0
+  N1U NUrea    -0.54200     0
  H11U     H     0.33300     0
  H12U     H     0.33300     0
-  N2U NUREA    -0.54200     0
+  N2U NUrea    -0.54200     0
  H21U     H     0.33300     0
  H22U     H     0.33300     0
  [ bonds ]
@@ -11079,7 +11079,3 @@ CLCl2 CLCl4    gb_52
 ;  ai    aj    ak    al   gromos type
    OU    CU   N1U  H11U     gd_15   
    OU    CU   N2U  H21U     gd_15   
-
-
-
-
index ef502b0ad4955bb2ce4f8c723712fd19203901cb..fa25c3ab7ac5c2a77c9c652aab44c5fdc571322c 100644 (file)
@@ -15,7 +15,7 @@
   CH2  14.02700 ;     aliphatic or sugar CH2-group
   CH3  15.03500 ;     aliphatic CH3-group
   CH4  16.04300 ;     methane
- CH2R  14.02700 ;     CH2-group in a ring
+ CH2r  14.02700 ;     CH2-group in a ring
   CR1  13.01900 ;     aromatic CH-group 
    HC   1.00800 ;     hydrogen bound to carbon
     H   1.00800 ;     hydrogen not bound to carbon
     F  18.99840 ;     fluor (non-ionic)
    CL  35.45300 ;     chlorine (non-ionic)
    BR  79.90400 ;     bromine (non-ionic)
- CMET  15.035   ;     CH3-group in methanol (solvent)
- OMET  15.9994  ;     oxygen in methanol (solvent)
+ CMet  15.035   ;     CH3-group in methanol (solvent)
+ OMet  15.9994  ;     oxygen in methanol (solvent)
   NA+  22.9898  ;     sodium (charge 1+)
   CL-  35.45300 ;     chlorine (charge 1-)
- CCHL  12.011   ;     carbon in chloroform (solvent)
-CLCHL  35.453   ;     chloride in chloroform (solvent)
- HCHL  1.008    ;     hydrogen in chloroform (solvent)
-SDMSO  32.06000 ;     DMSO Sulphur (solvent)
-CDMSO  15.03500 ;     DMSO Carbon (solvent)
-ODMSO  15.99940 ;     DMSO Oxygen (solvent)
- CCL4  12.011   ;     carbon in carbontetrachloride (solvent)
-CLCL4  35.453   ;     chloride in carbontetrachloride (solvent)
+ CChl  12.011   ;     carbon in chloroform (solvent)
+CLChl  35.453   ;     chloride in chloroform (solvent)
+ HChl  1.008    ;     hydrogen in chloroform (solvent)
+SDmso  32.06000 ;     DMSO Sulphur (solvent)
+CDmso  15.03500 ;     DMSO Carbon (solvent)
+ODmso  15.99940 ;     DMSO Oxygen (solvent)
+ CCl4  12.011   ;     carbon in carbontetrachloride (solvent)
+CLCl4  35.453   ;     chloride in carbontetrachloride (solvent)
  FTFE  18.99840 ;     fluor in trifluoroethanol
  CTFE  12.01100 ;     carbon in trifluoroethanol
 CHTFE  14.0270  ;     CH2-group in trifluoroethanol
  OTFE  15.99940 ;     oxygen in trifluoroethanol
-CUREA  12.01100 ;     carbon in urea
-OUREA  15.99940 ;     oxygen in urea
-NUREA  14.00670 ;     nitrogen in urea
+CUrea  12.01100 ;     carbon in urea
+OUrea  15.99940 ;     oxygen in urea
+NUrea  14.00670 ;     nitrogen in urea
    SI  28.08   ;     silicon
  MNH3   0       ;     Dummy mass in rigid tetraedrical NH3 group
    MW   0       ;     Dummy mass in rigid tyrosine rings
diff --git a/share/top/gromos53a5.ff/watermodels.dat b/share/top/gromos53a5.ff/watermodels.dat
new file mode 100644 (file)
index 0000000..a68dbed
--- /dev/null
@@ -0,0 +1,2 @@
+spc    SPC    simple point charge, recommended
+spce   SPC/E  extended simple point charge
index dcc2c9f1a0ada8ca7f2599474f1f7cbc97ae781b..fe64868f353e9d66f1f90f9bbeda8fdf0c55b884 100644 (file)
@@ -9,7 +9,8 @@ aminoacids.c.tdb        atomtypes.atp           ions.itp        \
 aminoacids.hdb         ffbonded.itp            spc.itp         \
 aminoacids.n.tdb       ffnonbonded.itp         spce.itp        \
 aminoacids.rtp         forcefield.doc          tip3p.itp       \
-aminoacids.vsd         forcefield.itp          tip4p.itp
+aminoacids.vsd         forcefield.itp          tip4p.itp       \
+aminoacids.r2b         watermodels.dat
 
 EXTRA_DIST = ${topol_DATA}
 
index ee2246f7c089d320253f3ba49cb42e5be3ad2967..c4d5386d2b5679aa510725888793612a5f22913f 100644 (file)
@@ -27,6 +27,11 @@ ASP1    2
 ASPH    2       
 1      1       H       N       -C      CA
 1      2       HD2     OD2     CG      CB
+ATP    4
+2      3       AH6     AN6     AC6     AC5
+1      2       AH2*    AO2*    AC2*    AC3*
+1      2       AH3*    AO3*    AC3*    AC2*
+1      2       AH3G    AO3G    APG     AO2G
 BEN     7       
 1      1       H2      C2      C1      C3
 1      1       H3      C3      C2      C4
@@ -40,6 +45,13 @@ CYS2    1
 CYSH    2       
 1      1       H       N       -C      CA
 1      2       HG      SG      CB      CA
+DADE   3
+1      1       H2      C2      N1      N3
+1      1       H8      C8      N7      N9
+2      3       H6      N6      C6      C5
+DTHY   2
+1      1       H3      N3      C2      C4
+1      1       H6      C6      C5      N1
 FAD     7       
 2      3       HN6     AN6     AC6     AC5
 1      2       HO2*    AO2*    AC2*    AC1*
index ae700b0dc3419072c4029b0a01ec429c16ca705d..3d58ae40b3bada8cf0f539e303cbe82d062506ac 100644 (file)
@@ -46,7 +46,7 @@ H1    N       CA      C       gd_29
 [ replace ]
 N              NT      14.0067 0.128
 CA             CH1     13.019  0.188
-CD             CH2R    14.027  0.188
+CD             CH2r    14.027  0.188
 [ add ]
 2      4       H       N       CA      C
        H       1.008   0.248
diff --git a/share/top/gromos53a6.ff/aminoacids.r2b b/share/top/gromos53a6.ff/aminoacids.r2b
new file mode 100644 (file)
index 0000000..823db90
--- /dev/null
@@ -0,0 +1,7 @@
+; rtp residue to rtp building block table
+;GMX   Force-field
+CYS    CYSH
+HISD   HISA
+HISE   HISB
+LYS    LYSH
+LYSN   LYS
index ef46d0134aac9204f9fc829b05db55c4468fe56a..07ec151d3dc6b14ca09829b1f31ae7f74389c643 100644 (file)
  [ atoms ]
     N     N     0.00000     0
    CA   CH1     0.00000     1
-   CB  CH2R     0.00000     1
+   CB  CH2r     0.00000     1
    CG   CH1     0.26600     2
   OD1    OA    -0.67400     2
   HD1     H     0.40800     2
-  CD2  CH2R     0.00000     3
+  CD2  CH2r     0.00000     3
     C     C       0.450     4
     O     O      -0.450     4
  [ bonds ]
  [ atoms ]
     N     N     0.00000     0
    CA   CH1     0.00000     1
-   CB  CH2R     0.00000     1
-   CG  CH2R     0.00000     2
-   CD  CH2R     0.00000     2
+   CB  CH2r     0.00000     1
+   CG  CH2r     0.00000     2
+   CD  CH2r     0.00000     2
     C     C       0.450     3
     O     O      -0.450     3
  [ bonds ]
    N7    NR    -0.54000     7
    C8     C     0.44000     7
    H8    HC     0.10000     7
-  C2*  CH2R     0.00000     8
+  C2*  CH2r     0.00000     8
   C3*   CH1       0.000     8
   O3*    OA      -0.360     9
  [ bonds ]
    N7    NR    -0.54000     8
    C8     C     0.44000     8
    H8    HC     0.10000     8
-  C2*  CH2R     0.00000     9
+  C2*  CH2r     0.00000     9
   C3*   CH1       0.000     9
   O3*    OA      -0.360    10
  [ bonds ]
   H42     H     0.41500     6
    C5     C    -0.10000     7
    H5    HC     0.10000     7
-  C2*  CH2R     0.00000     8
+  C2*  CH2r     0.00000     8
   C3*   CH1       0.000     8
   O3*    OA      -0.360     9
  [ bonds ]
    O4     O    -0.45000     6
    C5     C     0.00000     7
   C5M   CH3     0.00000     7
-  C2*  CH2R     0.00000     8
+  C2*  CH2r     0.00000     8
   C3*   CH1       0.000     8
   O3*    OA      -0.360     9
  [ bonds ]
@@ -8460,7 +8460,7 @@ FC10A  FC4A   FN5  FC5A     gi_1
   OSI    OA    -0.36000     8
   SI2     P     0.54000     8
   O5*    OA    -0.36000     8
-  C5*  CH2R     0.00000     9
+  C5*  CH2r     0.00000     9
   C11   CH1     0.00000    10
  C111   CH3     0.00000    10
  C112   CH3     0.00000    10
@@ -10089,18 +10089,18 @@ FC10A  FC4A   FN5  FC5A     gi_1
  AC5*   CH2     0.00000     8
  AO5*    OA    -0.36000     9
   APA     P     0.70500     9
-AO1PA    OM    -0.63500     9
-AO2PA    OM    -0.63500     9
-AO3PA    OA    -0.36000    10
+AO1A    OM    -0.63500     9
+AO2A    OM    -0.63500     9
+AO3A    OA    -0.36000    10
   APB     P     0.70500    10
-AO1PB    OM    -0.63500    10
-AO2PB    OM    -0.63500    10
-AO3PB    OA    -0.36000    11
+AO1B    OM    -0.63500    10
+AO2B    OM    -0.63500    10
+AO3B    OA    -0.36000    11
   APG     P     0.63000    11
-AO1PG    OM    -0.63500    11
-AO2PG    OM    -0.63500    11
-AO3PG    OA    -0.54800    11
-AH3PG     H     0.39800    11
+AO1G    OM    -0.63500    11
+AO2G    OM    -0.63500    11
+AO3G    OA    -0.54800    11
+AH3G     H     0.39800    11
  [ bonds ]
   AN9   AC4    gb_10   
   AN9   AC8    gb_10   
@@ -10128,18 +10128,18 @@ AH3PG     H     0.39800    11
  AO3*  AH3*    gb_1    
  AC5*  AO5*    gb_20   
  AO5*   APA    gb_28   
-  APA AO1PA    gb_24   
-  APA AO2PA    gb_24   
-  APA AO3PA    gb_28   
-AO3PA   APB    gb_28   
-  APB AO1PB    gb_24   
-  APB AO2PB    gb_24   
-  APB AO3PB    gb_28   
-AO3PB   APG    gb_28   
-  APG AO1PG    gb_24   
-  APG AO2PG    gb_24   
-  APG AO3PG    gb_28   
-AO3PG AH3PG    gb_1    
+  APA AO1A    gb_24   
+  APA AO2A    gb_24   
+  APA AO3A    gb_28   
+AO3A   APB    gb_28   
+  APB AO1B    gb_24   
+  APB AO2B    gb_24   
+  APB AO3B    gb_28   
+AO3B   APG    gb_28   
+  APG AO1G    gb_24   
+  APG AO2G    gb_24   
+  APG AO3G    gb_28   
+AO3G AH3G    gb_1    
  [ exclusions ]
 ;  ai    aj
   AN9   AC2
@@ -10156,9 +10156,9 @@ AO3PG AH3PG    gb_1
   AC6   AC8
   AC5  AC1*
   AN7  AC1*
-AO3PB AH3PG
-AO1PG AH3PG
-AO2PG AH3PG
+AO3B AH3G
+AO1G AH3G
+AO2G AH3G
  [ angles ]
 ;  ai    aj    ak   gromos type
   AC4   AN9   AC8     ga_7    
@@ -10198,27 +10198,27 @@ AO2PG AH3PG
  AC3*  AO3*  AH3*     ga_12   
  AC4*  AC5*  AO5*     ga_9    
  AC5*  AO5*   APA     ga_26   
- AO5*   APA AO1PA     ga_14   
- AO5*   APA AO2PA     ga_14   
- AO5*   APA AO3PA     ga_5    
-AO1PA   APA AO2PA     ga_29   
-AO1PA   APA AO3PA     ga_14   
-AO2PA   APA AO3PA     ga_14   
-  APA AO3PA   APB     ga_26   
-AO3PA   APB AO1PB     ga_14   
-AO3PA   APB AO2PB     ga_14   
-AO3PA   APB AO3PB     ga_5    
-AO1PB   APB AO2PB     ga_29   
-AO1PB   APB AO3PB     ga_14   
-AO2PB   APB AO3PB     ga_14   
-  APB AO3PB   APG     ga_26   
-AO3PB   APG AO1PG     ga_14   
-AO3PB   APG AO2PG     ga_14   
-AO3PB   APG AO3PG     ga_5    
-AO1PG   APG AO2PG     ga_29   
-AO1PG   APG AO3PG     ga_14   
-AO2PG   APG AO3PG     ga_14   
-  APG AO3PG AH3PG     ga_12   
+ AO5*   APA AO1A     ga_14   
+ AO5*   APA AO2A     ga_14   
+ AO5*   APA AO3A     ga_5    
+AO1A   APA AO2A     ga_29   
+AO1A   APA AO3A     ga_14   
+AO2A   APA AO3A     ga_14   
+  APA AO3A   APB     ga_26   
+AO3A   APB AO1B     ga_14   
+AO3A   APB AO2B     ga_14   
+AO3A   APB AO3B     ga_5    
+AO1B   APB AO2B     ga_29   
+AO1B   APB AO3B     ga_14   
+AO2B   APB AO3B     ga_14   
+  APB AO3B   APG     ga_26   
+AO3B   APG AO1G     ga_14   
+AO3B   APG AO2G     ga_14   
+AO3B   APG AO3G     ga_5    
+AO1G   APG AO2G     ga_29   
+AO1G   APG AO3G     ga_14   
+AO2G   APG AO3G     ga_14   
+  APG AO3G AH3G     ga_12   
  [ impropers ]
 ;  ai    aj    ak    al   gromos type
   AN9   AC4   AC5   AN7     gi_1    
@@ -10265,18 +10265,18 @@ AO2PG   APG AO3PG     ga_14
  AO2*  AC2*  AC3*  AO3*     gd_18   
  AC4*  AC3*  AO3*  AH3*     gd_23   
  AC4*  AC5*  AO5*   APA     gd_29   
- AC5*  AO5*   APA AO3PA     gd_19   
- AC5*  AO5*   APA AO3PA     gd_22   
- AO5*   APA AO3PA   APB     gd_19   
- AO5*   APA AO3PA   APB     gd_22   
-  APA AO3PA   APB AO3PB     gd_19   
-  APA AO3PA   APB AO3PB     gd_22   
-AO3PA   APB AO3PB   APG     gd_19   
-AO3PA   APB AO3PB   APG     gd_22   
-  APB AO3PB   APG AO3PG     gd_19   
-  APB AO3PB   APG AO3PG     gd_22   
-AO3PB   APG AO3PG AH3PG     gd_19   
-AO3PB   APG AO3PG AH3PG     gd_22   
+ AC5*  AO5*   APA AO3A     gd_19   
+ AC5*  AO5*   APA AO3A     gd_22   
+ AO5*   APA AO3A   APB     gd_19   
+ AO5*   APA AO3A   APB     gd_22   
+  APA AO3A   APB AO3B     gd_19   
+  APA AO3A   APB AO3B     gd_22   
+AO3A   APB AO3B   APG     gd_19   
+AO3A   APB AO3B   APG     gd_22   
+  APB AO3B   APG AO3G     gd_19   
+  APB AO3B   APG AO3G     gd_22   
+AO3B   APG AO3G AH3G     gd_19   
+AO3B   APG AO3G AH3G     gd_22   
 
 [ PMB ]
  [ atoms ]
@@ -10519,9 +10519,9 @@ AO3PB   APG AO3PG AH3PG     gd_22
   C18   CH3     0.00000     0
   C17   CH3     0.00000     0
    C1   CH0     0.00000     0
-   C2  CH2R     0.00000     1
-   C3  CH2R     0.00000     1
-   C4  CH2R     0.00000     1
+   C2  CH2r     0.00000     1
+   C3  CH2r     0.00000     1
+   C4  CH2r     0.00000     1
    C5     C     0.00000     2
   C16   CH3     0.00000     2
    C6     C     0.00000     2
@@ -10913,11 +10913,11 @@ AO3PB   APG AO3PG AH3PG     gd_22
 
 [ CHCL3 ]
  [ atoms ]
- CChl  CCHL     0.17900     0
- HChl  HCHL     0.08200     0
-CLCh1 CLCHL    -0.08700     0
-CLCh2 CLCHL    -0.08700     0
-CLCh3 CLCHL    -0.08700     0
+ CChl  CChl     0.17900     0
+ HChl  HChl     0.08200     0
+CLCh1 CLChl    -0.08700     0
+CLCh2 CLChl    -0.08700     0
+CLCh3 CLChl    -0.08700     0
  [ bonds ]
  CChl CLCh1    gb_40   
  CChl CLCh2    gb_40   
@@ -10937,10 +10937,10 @@ CLCh2 CLCh3    gb_48
 
 [ DMSO ]
  [ atoms ]
-SDmso SDMSO     0.12753     0
-ODmso ODMSO    -0.44753     0
-CDms1 CDMSO     0.16000     0
-CDms2 CDMSO     0.16000     0
+SDmso SDmso     0.12753     0
+ODmso ODmso    -0.44753     0
+CDms1 CDmso     0.16000     0
+CDms2 CDmso     0.16000     0
  [ bonds ]
 SDmso ODmso    gb_41   
 SDmso CDms1    gb_42   
@@ -10957,9 +10957,9 @@ CDms1 CDms2    gb_50
 
 [ CH3OH ]
  [ atoms ]
- Omet  OMET    -0.67400     0
+ Omet  OMet    -0.67400     0
  HMet     H     0.40800     0
- CMet  CMET     0.26600     0
+ CMet  CMet     0.26600     0
  [ bonds ]
  Omet  HMet    gb_1    
  Omet  CMet    gb_27   
@@ -10973,11 +10973,11 @@ CDms1 CDms2    gb_50
 
 [ CCL4 ]
  [ atoms ]
- CCl4  CCL4     0.00000     0
-CLCl1 CLCL4     0.00000     0
-CLCl2 CLCL4     0.00000     0
-CLCl3 CLCL4     0.00000     0
-CLCl4 CLCL4     0.00000     0
+ CCl4  CCl4     0.00000     0
+CLCl1 CLCl4     0.00000     0
+CLCl2 CLCl4     0.00000     0
+CLCl3 CLCl4     0.00000     0
+CLCl4 CLCl4     0.00000     0
  [ bonds ]
  CCl4 CLCl1    gb_43   
  CCl4 CLCl2    gb_43   
@@ -11029,12 +11029,12 @@ CLCl2 CLCl4    gb_52
 
 [ UREA ]
  [ atoms ]
-   OU OUREA    -0.39000     0
-   CU CUREA     0.14200     0
-  N1U NUREA    -0.54200     0
+   OU OUrea    -0.39000     0
+   CU CUrea     0.14200     0
+  N1U NUrea    -0.54200     0
  H11U     H     0.33300     0
  H12U     H     0.33300     0
-  N2U NUREA    -0.54200     0
+  N2U NUrea    -0.54200     0
  H21U     H     0.33300     0
  H22U     H     0.33300     0
  [ bonds ]
@@ -11079,4 +11079,3 @@ CLCl2 CLCl4    gb_52
 ;  ai    aj    ak    al   gromos type
    OU    CU   N1U  H11U     gd_15   
    OU    CU   N2U  H21U     gd_15   
-
index ef502b0ad4955bb2ce4f8c723712fd19203901cb..fa25c3ab7ac5c2a77c9c652aab44c5fdc571322c 100644 (file)
@@ -15,7 +15,7 @@
   CH2  14.02700 ;     aliphatic or sugar CH2-group
   CH3  15.03500 ;     aliphatic CH3-group
   CH4  16.04300 ;     methane
- CH2R  14.02700 ;     CH2-group in a ring
+ CH2r  14.02700 ;     CH2-group in a ring
   CR1  13.01900 ;     aromatic CH-group 
    HC   1.00800 ;     hydrogen bound to carbon
     H   1.00800 ;     hydrogen not bound to carbon
     F  18.99840 ;     fluor (non-ionic)
    CL  35.45300 ;     chlorine (non-ionic)
    BR  79.90400 ;     bromine (non-ionic)
- CMET  15.035   ;     CH3-group in methanol (solvent)
- OMET  15.9994  ;     oxygen in methanol (solvent)
+ CMet  15.035   ;     CH3-group in methanol (solvent)
+ OMet  15.9994  ;     oxygen in methanol (solvent)
   NA+  22.9898  ;     sodium (charge 1+)
   CL-  35.45300 ;     chlorine (charge 1-)
- CCHL  12.011   ;     carbon in chloroform (solvent)
-CLCHL  35.453   ;     chloride in chloroform (solvent)
- HCHL  1.008    ;     hydrogen in chloroform (solvent)
-SDMSO  32.06000 ;     DMSO Sulphur (solvent)
-CDMSO  15.03500 ;     DMSO Carbon (solvent)
-ODMSO  15.99940 ;     DMSO Oxygen (solvent)
- CCL4  12.011   ;     carbon in carbontetrachloride (solvent)
-CLCL4  35.453   ;     chloride in carbontetrachloride (solvent)
+ CChl  12.011   ;     carbon in chloroform (solvent)
+CLChl  35.453   ;     chloride in chloroform (solvent)
+ HChl  1.008    ;     hydrogen in chloroform (solvent)
+SDmso  32.06000 ;     DMSO Sulphur (solvent)
+CDmso  15.03500 ;     DMSO Carbon (solvent)
+ODmso  15.99940 ;     DMSO Oxygen (solvent)
+ CCl4  12.011   ;     carbon in carbontetrachloride (solvent)
+CLCl4  35.453   ;     chloride in carbontetrachloride (solvent)
  FTFE  18.99840 ;     fluor in trifluoroethanol
  CTFE  12.01100 ;     carbon in trifluoroethanol
 CHTFE  14.0270  ;     CH2-group in trifluoroethanol
  OTFE  15.99940 ;     oxygen in trifluoroethanol
-CUREA  12.01100 ;     carbon in urea
-OUREA  15.99940 ;     oxygen in urea
-NUREA  14.00670 ;     nitrogen in urea
+CUrea  12.01100 ;     carbon in urea
+OUrea  15.99940 ;     oxygen in urea
+NUrea  14.00670 ;     nitrogen in urea
    SI  28.08   ;     silicon
  MNH3   0       ;     Dummy mass in rigid tetraedrical NH3 group
    MW   0       ;     Dummy mass in rigid tyrosine rings
diff --git a/share/top/gromos53a6.ff/watermodels.dat b/share/top/gromos53a6.ff/watermodels.dat
new file mode 100644 (file)
index 0000000..a68dbed
--- /dev/null
@@ -0,0 +1,2 @@
+spc    SPC    simple point charge, recommended
+spce   SPC/E  extended simple point charge
index 5972a12596e7165ad668f43fe9724bb720bf3148..fa17ed1c9d01dcef432363017da6cff43740f4c0 100644 (file)
@@ -1,4 +1,4 @@
-357
+363
 ��ߦ��ߨ���߬��������߻���ߦ��߷���ߋ�߻�߶�ߦ��������׷���������߶��
 �߳���ߋ��߳���߫���ߨ���߫���߻���׫������
 �����߽����߲�߷������ײ��������
 �������������ߖ�ߞ��ߋ���ߘ������׹����ߥ�����
 �߳���ߦ���߶ߨ���ߴ���ߦ��߳����׫����ߖ�߹��������
 ������߶ߌ���ߑ�����ߜ������߈���ߚ����������ײ�����߽�����
+����ߖ�ߞߗ����������ߗ��ߒ�����ߖ�ߞߘ����׫��߭�������
+���ߖ�،ߙ�����߈���ߗ�������ߞ��ߗ�������ߐ�ߜ���������ײ�������
+��ߖ�߈����؋ߙ��ߝ��ߓ����߈�؛ߗ���ߑ�ߓ���ߞ�ߞ���׫��ߪ��������
+�����،ߑ�߈��߆��ߜ��ߍ���ߐ�ߞ�ߚ����������׸�����߸��������
+�ߓ���ߋ�߈����ߋ���߶ߙ���ߓ���߶ߛ�ߌ���������׼���߼�������
+���߶ߗ���ߚ���������ߓ�����ߋ���ߚ���������ߚ����׻���߯������
index 96887bcd45b874f75198399daec2037b7ba85157..fb2715965ac26809d10af80d97d6df96fe078211 100644 (file)
@@ -10,7 +10,9 @@ aminoacids.hdb                ffbonded.itp            spc.itp         \
 aminoacids.n.tdb       ffnonbonded.itp         spce.itp        \
 aminoacids.rtp         forcefield.doc          tip3p.itp       \
 aminoacids.vsd         forcefield.itp          tip4p.itp       \
-tip5p.itp
+aminoacids.r2b         tip5p.itp       \
+methanol.itp           ethanol.itp             1propanol.itp   \
+atomname2type.n2t      watermodels.dat
 
 EXTRA_DIST = ${topol_DATA}
 
diff --git a/share/top/oplsaa.ff/aminoacids.r2b b/share/top/oplsaa.ff/aminoacids.r2b
new file mode 100644 (file)
index 0000000..823db90
--- /dev/null
@@ -0,0 +1,7 @@
+; rtp residue to rtp building block table
+;GMX   Force-field
+CYS    CYSH
+HISD   HISA
+HISE   HISB
+LYS    LYSH
+LYSN   LYS
index ca6f970c85510980843bac178193f5df2807bee6..78ca85736aec13524e10d53ca4b530f7890abe06 100644 (file)
     OW   HW2
 
 [ HO4 ] 
-; TIP4P For software reasons, the MW particle should be called HW as well
+; TIP4P
  [ atoms ]
     OW   opls_113    0.00      0
    HW1   opls_114    0.52      0
    HW2   opls_114    0.52      0
-   HW3   opls_115   -1.04      0
+    MW   opls_115   -1.04      0
  [ bonds ]
     OW   HW1
     OW   HW2
-; Superfluous bonds are necessary to make pdb2gmx happy    
-    OW   HW3
 
 [ HO5 ] 
-; TIP5P. For software reasons, the lone pairs should be called HW as well
+; TIP5P
  [ atoms ]
+    OW   opls_118    0.00      0
    HW1   opls_119    0.248     0
    HW2   opls_119    0.248     0
-   HW3   opls_120   -0.248     0
-   HW4   opls_120   -0.248     0
-    OW   opls_118    0.00      0
+   LP1   opls_120   -0.248     0
+   LP2   opls_120   -0.248     0
  [ bonds ]
     OW   HW1
     OW   HW2
-; Superfluous bonds are necessary to make pdb2gmx happy    
-    OW   HW3
-    OW   HW4
 
 [ ILE ]
  [ atoms ]
index d0c8bc06295ea4cca447d7b6407fa3ae6856668f..2c67c42282821663ac42fa0eed7d6de15556fe54 100644 (file)
@@ -7,7 +7,7 @@
 
 ;[ atoms ]
 ; id   at type res nr  residu name     at name  cg nr  charge   mass
-;1     CU1+    1       CU1+            CU1+     1      1        63.54600
+;1     Cu1+    1       CU1+            CU1+     1      1        63.54600
 
 [ moleculetype ]
 ; molname      nrexcl
@@ -15,7 +15,7 @@ CU2+          1
 
 [ atoms ]
 ; id   at type res nr  residu name     at name  cg nr  charge   mass
-1      CU2+    1       CU2+            CU       1      2        63.54600
+1      Cu2+    1       CU2+            CU       1      2        63.54600
 
 [ moleculetype ]
 ; molname      nrexcl
@@ -23,7 +23,7 @@ ZN2+          1
 
 [ atoms ]
 ; id   at type res nr  residu name     at name  cg nr  charge   mass
-1      ZN2+    1       ZN2+            ZN       1      2        65.37000
+1      Zn2+    1       ZN2+            ZN       1      2        65.37000
 
 [ moleculetype ]
 ; molname      nrexcl
diff --git a/share/top/oplsaa.ff/watermodels.dat b/share/top/oplsaa.ff/watermodels.dat
new file mode 100644 (file)
index 0000000..513bcae
--- /dev/null
@@ -0,0 +1,5 @@
+tip4p   TIP4P  TIP 4-point, recommended
+tip3p   TIP3P  TIP 3-point
+tip5p   TIP5P  TIP 5-point
+spc     SPC    simple point charge
+spce    SPC/E  extended simple point charge
diff --git a/share/top/sfactor.dat b/share/top/sfactor.dat
new file mode 100644 (file)
index 0000000..ca475c8
--- /dev/null
@@ -0,0 +1,7 @@
+; atom  protons mass a1 ... a4 b1 ... b4 c 
+H  1   1  0.489918  0.262003  0.196767  0.049879    20.6593  7.74039  49.5519  2.20159    0.001305   
+C  6  12  2.26069  1.56165  1.05075  0.839259    22.6907  0.656665  9.75618  55.5949    0.286977   
+N  7  14 12.2126  3.13220  2.01250  1.16630        0.005700  9.89330  28.9975  0.582600    -11.529   
+O  8  16  3.04850  2.28680  1.54630  0.867000     13.2771  5.70110  0.323900  32.9089    0.250800   
+; Na+
+Na 11 23  3.25650  3.93620  1.39980  1.00320      2.66710  6.11530  0.200100  14.0390    0.404000  
index 5f50e45d4dc35048b0a6617f6a8b5a13b7f0d05e..cfe67e61f0d1e2057d84c0ef91833684ae048210 100644 (file)
@@ -1,8 +1,9 @@
-7
+8
 CYS    SG      1       CYS     SG      1       0.2     CYS2    CYS2
-CYS    SG      1       HEME    FE      2       0.25    CYS2    HEME
-CYS    SG      1       HEME    CAB     1       0.18    CYS2    HEME
-CYS    SG      1       HEME    CAC     1       0.18    CYS2    HEME
-HIS    NE2     1       HEME    FE      1       0.2     HIS1    HEME
-MET    SD      1       HEME    FE      1       0.24    MET     HEME
+CYS    SG      1       HEM     FE      2       0.25    CYS2    HEME
+CYS    SG      1       HEM     CAB     1       0.18    CYS2    HEME
+CYS    SG      1       HEM     CAC     1       0.18    CYS2    HEME
+HIS    NE2     1       HEM     FE      1       0.2     HIS1    HEME
+MET    SD      1       HEM     FE      1       0.24    MET     HEME
+CO      C       1       HEME    FE      1       0.19    CO      HEME
 CYM     SG      1       CYM     SG      1       0.2     CYS2    CYS2
diff --git a/share/top/urea+h2o.gro b/share/top/urea+h2o.gro
deleted file mode 100644 (file)
index 4732a1d..0000000
+++ /dev/null
@@ -1,1362 +0,0 @@
-Urea in Water
- 1359
-    1UREA    C1    1   2.064   2.162   0.280 -0.4650  0.0606  0.2278
-    1UREA    O2    2   2.163   2.120   0.339 -0.2571  0.2847  0.0448
-    1UREA    N3    3   2.055   2.285   0.229 -0.4005  0.0556  0.2068
-    1UREA    H4    4   1.965   2.301   0.188 -0.8661 -2.6785 -0.2199
-    1UREA    H5    5   2.136   2.342   0.212 -0.3718 -0.2607 -0.8675
-    1UREA    N6    6   1.951   2.093   0.285 -0.3042 -0.1600  0.7702
-    1UREA    H7    7   1.866   2.125   0.244 -0.6232 -1.5225  0.2764
-    1UREA    H8    8   1.958   1.999   0.320  0.3294 -1.7268 -2.7089
-    2UREA    C1    9   0.167   0.191   0.530  0.0983 -0.1688  0.0345
-    2UREA    O2   10   0.159   0.146   0.416  0.5368 -0.4096  0.1001
-    2UREA    N3   11   0.062   0.195   0.612 -0.5603  0.4575 -0.7968
-    2UREA    H4   12   0.069   0.227   0.707  0.2921  0.7131 -0.9302
-    2UREA    H5   13  -0.016   0.143   0.580 -0.3093 -1.5769  1.3454
-    2UREA    N6   14   0.277   0.242   0.583  0.0141  0.0396  0.0062
-    2UREA    H7   15   0.277   0.268   0.680 -0.0828 -0.3800  0.1180
-    2UREA    H8   16   0.366   0.253   0.539 -0.1339  1.0311 -0.0945
-    3UREA    C1   17   0.401   0.363   1.599  0.0438 -0.4272 -0.6386
-    3UREA    O2   18   0.376   0.471   1.654  0.1157 -0.6359 -0.1975
-    3UREA    N3   19   0.495   0.274   1.629 -0.5239 -0.6346  0.6527
-    3UREA    H4   20   0.505   0.187   1.581 -0.5933 -1.2504  1.7041
-    3UREA    H5   21   0.555   0.308   1.701 -0.0123 -1.0919  0.4514
-    3UREA    N6   22   0.324   0.328   1.496  0.2039  0.1564 -0.9623
-    3UREA    H7   23   0.346   0.245   1.445  2.6996  0.2525 -0.2885
-    3UREA    H8   24   0.249   0.389   1.471  0.9474  2.6180  1.6525
-    4UREA    C1   25   0.218   1.264   0.022 -0.2106  0.0426  0.4113
-    4UREA    O2   26   0.256   1.374  -0.018  0.1956 -0.2117  0.0906
-    4UREA    N3   27   0.155   1.246   0.137 -0.2782  0.2926  0.4134
-    4UREA    H4   28   0.126   1.156   0.170 -0.6101 -0.0633 -0.7796
-    4UREA    H5   29   0.141   1.331   0.190 -3.6948 -0.5115  1.3318
-    4UREA    N6   30   0.229   1.148  -0.042  0.1029  0.2261  0.1346
-    4UREA    H7   31   0.205   1.069   0.013  0.3946  1.0280  1.5092
-    4UREA    H8   32   0.274   1.143  -0.132 -1.6874  0.2737 -0.8433
-    5UREA    C1   33   2.034   1.257   1.120 -0.1680 -0.1874 -0.0922
-    5UREA    O2   34   2.061   1.280   1.237 -0.6452 -0.3566  0.0490
-    5UREA    N3   35   2.008   1.355   1.033  0.0869  0.1603  0.2214
-    5UREA    H4   36   1.995   1.328   0.938  0.6695 -1.9052  0.6197
-    5UREA    H5   37   1.997   1.450   1.062 -0.2994  0.0623  0.3918
-    5UREA    N6   38   2.049   1.143   1.053  0.1157 -0.4936  0.4833
-    5UREA    H7   39   2.039   1.134   0.954  2.7407  2.4361 -0.3746
-    5UREA    H8   40   2.074   1.056   1.095 -0.9621 -1.4199 -0.6256
-    6UREA    C1   41   1.989   1.236   2.099  0.0429  0.3060 -0.1219
-    6UREA    O2   42   1.877   1.227   2.050 -0.0277 -0.5495  0.1701
-    6UREA    N3   43   2.098   1.239   2.022  0.2637 -0.0759  0.1747
-    6UREA    H4   44   2.187   1.231   2.066 -0.2713  0.3313  1.3962
-    6UREA    H5   45   2.090   1.233   1.922  3.3377 -1.5648 -0.1985
-    6UREA    N6   46   2.016   1.238   2.229 -0.1897 -0.4980 -0.0472
-    6UREA    H7   47   2.109   1.245   2.267 -0.4690  2.5818  0.6047
-    6UREA    H8   48   1.943   1.227   2.295  1.3030 -1.1995  1.6554
-    7UREA    C1   49   0.348   2.034   1.498  0.2413 -0.0896 -0.3558
-    7UREA    O2   50   0.247   2.099   1.471  0.1987  0.0591  0.1642
-    7UREA    N3   51   0.469   2.087   1.505  0.2687 -0.1864 -0.1161
-    7UREA    H4   52   0.545   2.025   1.524  0.3918 -0.5757 -1.6391
-    7UREA    H5   53   0.485   2.185   1.492  1.1916 -0.0741  1.4450
-    7UREA    N6   54   0.351   1.903   1.521 -0.0363 -0.0224  0.0794
-    7UREA    H7   55   0.439   1.856   1.526  0.4840  0.8435 -0.4435
-    7UREA    H8   56   0.267   1.851   1.507  0.3409 -0.2119 -2.4760
-    8UREA    C1   57   0.205   0.249   0.875  0.3450  0.1296 -0.2939
-    8UREA    O2   58   0.275   0.151   0.898  0.1974  0.0884 -0.0311
-    8UREA    N3   59   0.262   0.366   0.849 -0.1763  0.4807  0.1098
-    8UREA    H4   60   0.212   0.451   0.834 -0.8074 -0.1014 -1.6341
-    8UREA    H5   61   0.361   0.368   0.862 -0.2868  2.5315  1.4500
-    8UREA    N6   62   0.073   0.264   0.880  0.2063 -0.8997 -0.4616
-    8UREA    H7   63   0.034   0.356   0.869  1.3777 -0.1582  0.9508
-    8UREA    H8   64   0.006   0.192   0.901 -1.3853  0.9596  1.9008
-    9UREA    C1   65   0.099   0.270   1.223  0.2068 -0.5778 -0.2992
-    9UREA    O2   66   0.062   0.208   1.323 -0.5278  0.0380 -0.1778
-    9UREA    N3   67   0.016   0.341   1.147 -0.0125  0.1579  0.5901
-    9UREA    H4   68   0.053   0.379   1.063  2.6711  1.0516  1.9574
-    9UREA    H5   69  -0.077   0.357   1.179  0.7286  0.8750  2.7265
-    9UREA    N6   70   0.222   0.262   1.173  0.4045  0.7461 -0.0794
-    9UREA    H7   71   0.239   0.313   1.088  0.4322 -0.5091 -0.8692
-    9UREA    H8   72   0.289   0.202   1.217 -0.3249  1.0049  1.5188
-   10UREA    C1   73   1.118   0.017   0.342  0.5081  0.2347  0.4064
-   10UREA    O2   74   1.116  -0.103   0.371 -0.6670  0.2135  0.3519
-   10UREA    N3   75   1.153   0.111   0.429  0.9963 -0.0251  0.4908
-   10UREA    H4   76   1.139   0.206   0.401  1.3134 -0.1232 -0.0202
-   10UREA    H5   77   1.181   0.088   0.523  1.2712  1.6107  0.8608
-   10UREA    N6   78   1.078   0.072   0.228  0.3354 -0.5199  0.0906
-   10UREA    H7   79   1.080   0.172   0.224 -3.4543 -0.0769  1.4901
-   10UREA    H8   80   1.036   0.016   0.157  0.4889  0.9607 -1.3159
-   11UREA    C1   81   0.555   0.298   0.690 -0.0695 -0.2672  0.6581
-   11UREA    O2   82   0.549   0.412   0.736 -0.8313 -0.2064  0.4314
-   11UREA    N3   83   0.563   0.186   0.761  0.0289 -0.5415  0.2218
-   11UREA    H4   84   0.576   0.101   0.711 -0.2934 -0.5958  0.2299
-   11UREA    H5   85   0.562   0.186   0.861  0.1100 -0.2916  0.2226
-   11UREA    N6   86   0.555   0.257   0.564  0.7632 -0.4538  0.7114
-   11UREA    H7   87   0.562   0.158   0.546 -0.4278 -0.6991  1.3735
-   11UREA    H8   88   0.550   0.337   0.505 -2.3069  0.4940  1.8783
-   12UREA    C1   89   1.440   0.502   2.032  0.5946 -0.0894 -0.0316
-   12UREA    O2   90   1.413   0.621   2.049  0.6755 -0.1381  0.4560
-   12UREA    N3   91   1.537   0.439   2.098  0.5566  0.7615  0.8774
-   12UREA    H4   92   1.553   0.341   2.093  0.2406  0.7369  0.1021
-   12UREA    H5   93   1.601   0.494   2.153  0.4968  0.4427  1.2707
-   12UREA    N6   94   1.376   0.425   1.946  0.1510  0.0857  0.1386
-   12UREA    H7   95   1.408   0.333   1.925 -1.1785 -0.3339 -0.2617
-   12UREA    H8   96   1.301   0.458   1.888 -0.0991 -1.4242 -0.5026
-   13UREA    C1   97   0.082   1.477   0.314 -0.5786  0.1348  0.7407
-   13UREA    O2   98   0.184   1.532   0.355 -0.4595  0.1711  0.3880
-   13UREA    N3   99   0.011   1.502   0.204  0.4205  0.7252  0.2052
-   13UREA    H4  100  -0.074   1.453   0.184 -0.1520  1.9096 -0.4902
-   13UREA    H5  101   0.052   1.574   0.148  2.2960 -0.5806 -0.2978
-   13UREA    N6  102   0.023   1.375   0.375  0.1201 -0.4880  0.4035
-   13UREA    H7  103  -0.060   1.336   0.333 -0.9967  1.6940  0.2923
-   13UREA    H8  104   0.057   1.347   0.464  1.1155  1.5920  0.7861
-   14UREA    C1  105   0.273   1.146   1.109 -0.5012  1.1106  0.1718
-   14UREA    O2  106   0.391   1.117   1.095 -0.7096  0.1478  0.2466
-   14UREA    N3  107   0.208   1.210   1.013 -0.7813 -0.1478 -0.5189
-   14UREA    H4  108   0.111   1.226   1.031 -1.0566 -0.6962 -1.3970
-   14UREA    H5  109   0.252   1.231   0.926 -0.5105 -1.0271 -0.6098
-   14UREA    N6  110   0.198   1.115   1.214 -0.3501  0.4732  0.0963
-   14UREA    H7  111   0.104   1.151   1.214  0.3195  2.7519 -2.1684
-   14UREA    H8  112   0.226   1.046   1.282 -1.9315 -0.6326 -0.2415
-   15UREA    C1  113   0.176   0.952   0.165 -0.0183 -0.2643 -0.0280
-   15UREA    O2  114   0.274   0.951   0.240  0.1793 -0.0663 -0.2858
-   15UREA    N3  115   0.058   1.002   0.203 -0.0326 -0.0486 -0.3607
-   15UREA    H4  116  -0.014   0.998   0.134 -1.4965 -0.1565  1.0770
-   15UREA    H5  117   0.043   1.026   0.299  1.4645 -1.5387  0.3562
-   15UREA    N6  118   0.174   0.912   0.039 -0.1581  0.1921 -0.1712
-   15UREA    H7  119   0.085   0.915  -0.008 -0.3640  1.5833  0.2421
-   15UREA    H8  120   0.258   0.872   0.001  0.0202 -1.7285  1.8591
-   16UREA    C1  121   0.388   0.050   1.428 -0.0281 -0.4258 -0.0360
-   16UREA    O2  122   0.371   0.051   1.306  0.5764 -1.4654 -0.1524
-   16UREA    N3  123   0.505   0.020   1.482 -0.2057 -0.4693  0.3187
-   16UREA    H4  124   0.521   0.012   1.581  1.0287  2.0535  0.4795
-   16UREA    H5  125   0.580  -0.005   1.421 -0.8996 -0.1185 -0.7194
-   16UREA    N6  126   0.283   0.061   1.509 -0.1120 -0.2418 -0.1742
-   16UREA    H7  127   0.296   0.046   1.607 -0.1843 -0.0627 -0.1376
-   16UREA    H8  128   0.196   0.079   1.465 -1.4646  1.6291  2.6349
-   17UREA    C1  129   0.538   0.408   1.225  0.2909  0.2067  0.1129
-   17UREA    O2  130   0.602   0.306   1.251 -0.2862 -0.3064 -0.4372
-   17UREA    N3  131   0.428   0.444   1.290  0.2432  0.9291 -0.3434
-   17UREA    H4  132   0.365   0.515   1.259 -1.8819 -1.2772 -1.8642
-   17UREA    H5  133   0.397   0.391   1.369  0.1444  0.3373 -0.7677
-   17UREA    N6  134   0.567   0.484   1.120 -0.1428 -0.1387 -0.2668
-   17UREA    H7  135   0.513   0.564   1.094  2.2287  2.0974  0.6590
-   17UREA    H8  136   0.644   0.454   1.063 -0.2267 -0.9354  0.0222
-   18UREA    C1  137   0.583   1.835   1.334  0.1384 -0.6704 -0.2682
-   18UREA    O2  138   0.513   1.849   1.235  0.1027  0.1719 -0.1368
-   18UREA    N3  139   0.670   1.926   1.378 -0.5293 -0.1591  0.0257
-   18UREA    H4  140   0.710   1.906   1.467 -2.5556 -1.0981  0.8381
-   18UREA    H5  141   0.698   2.009   1.330  1.2855 -0.8668 -0.3127
-   18UREA    N6  142   0.582   1.739   1.426 -0.2007 -0.2148  0.2123
-   18UREA    H7  143   0.636   1.741   1.510  0.1350  1.7098  0.0378
-   18UREA    H8  144   0.510   1.670   1.414 -0.4262 -0.2113  1.3099
-   19UREA    C1  145   1.458   0.079   0.017 -0.2251 -0.1139  0.0351
-   19UREA    O2  146   1.524  -0.018  -0.021  0.4561  0.2979  0.1351
-   19UREA    N3  147   1.325   0.084   0.019 -0.2213 -0.1803  0.1315
-   19UREA    H4  148   1.279   0.167   0.052 -0.2967 -0.1262 -0.1077
-   19UREA    H5  149   1.270   0.010  -0.018  1.5078 -0.6488 -1.8657
-   19UREA    N6  150   1.513   0.189   0.066  0.4248 -0.3584 -0.1309
-   19UREA    H7  151   1.460   0.268   0.096  0.2108 -0.1797 -0.9333
-   19UREA    H8  152   1.612   0.198   0.078  0.2026  0.7291  1.4927
-   20UREA    C1  153   1.399   2.106   0.175 -0.1416 -0.3775 -0.0524
-   20UREA    O2  154   1.448   1.996   0.148  0.4884 -0.1421  0.1294
-   20UREA    N3  155   1.283   2.156   0.133 -0.2464 -0.4447  0.1591
-   20UREA    H4  156   1.256   2.246   0.168 -1.1025  0.7361 -2.9494
-   20UREA    H5  157   1.228   2.111   0.063 -0.0438 -1.8789  0.8520
-   20UREA    N6  158   1.449   2.178   0.275 -0.2684 -0.4113  0.0334
-   20UREA    H7  159   1.411   2.267   0.302  1.7028  0.4066  0.4202
-   20UREA    H8  160   1.528   2.141   0.323  0.3079 -2.4204 -2.1370
-   21UREA    C1  161   1.490   0.100   0.396  0.3276  0.3532 -0.0637
-   21UREA    O2  162   1.466   0.122   0.515 -0.6284 -0.2335 -0.1207
-   21UREA    N3  163   1.609   0.080   0.341  0.2239 -0.7119  0.0541
-   21UREA    H4  164   1.607   0.058   0.244 -0.0124 -0.1108 -0.0859
-   21UREA    H5  165   1.691   0.087   0.398 -0.6948  0.8593  1.3690
-   21UREA    N6  166   1.391   0.077   0.309  0.1306 -0.4338  0.3570
-   21UREA    H7  167   1.416   0.064   0.213  0.5914  1.7255  0.0858
-   21UREA    H8  168   1.297   0.092   0.339  0.3225  0.2939  0.6227
-   22UREA    C1  169   0.713   1.373   1.278 -0.0643  0.3239  0.3268
-   22UREA    O2  170   0.830   1.354   1.244 -0.0851  0.6551  0.0584
-   22UREA    N3  171   0.665   1.325   1.392 -0.5575  0.0089 -0.0116
-   22UREA    H4  172   0.570   1.332   1.423 -0.8158  1.4311 -0.9603
-   22UREA    H5  173   0.732   1.278   1.449 -0.7796  0.7326  0.8886
-   22UREA    N6  174   0.625   1.432   1.197  0.1775  0.3224  0.0620
-   22UREA    H7  175   0.534   1.436   1.239  0.6484  0.2133  1.1480
-   22UREA    H8  176   0.646   1.458   1.103 -3.0616 -1.3798 -1.4787
-   23UREA    C1  177   0.338   1.443   1.298  0.1045 -0.0176 -0.1666
-   23UREA    O2  178   0.361   1.546   1.361 -0.2015 -0.0400 -0.0195
-   23UREA    N3  179   0.367   1.424   1.169  0.9974 -0.4045  0.0775
-   23UREA    H4  180   0.342   1.336   1.128 -1.7944  0.1097  0.2402
-   23UREA    H5  181   0.395   1.501   1.111  0.7723 -0.7302 -0.4760
-   23UREA    N6  182   0.303   1.327   1.353 -0.7390  0.1130 -0.3981
-   23UREA    H7  183   0.298   1.243   1.300  2.1458  0.1505 -1.0642
-   23UREA    H8  184   0.286   1.326   1.452 -0.1028 -1.2467 -0.2617
-   24UREA    C1  185   1.285   0.377   0.163 -0.4787 -0.2963  0.1334
-   24UREA    O2  186   1.224   0.342   0.264  0.1287 -0.3070  0.5057
-   24UREA    N3  187   1.409   0.424   0.150 -0.5721 -0.2675 -0.7214
-   24UREA    H4  188   1.442   0.444   0.058 -0.8303  1.2360 -0.5328
-   24UREA    H5  189   1.473   0.438   0.226  0.2558 -0.2812 -1.3971
-   24UREA    N6  190   1.243   0.352   0.040 -0.0288 -0.3923 -0.0009
-   24UREA    H7  191   1.301   0.360  -0.042  1.3183 -0.7497  0.8625
-   24UREA    H8  192   1.147   0.326   0.031  0.1965 -1.3027  0.0102
-   25UREA    C1  193   1.376   1.648   2.255 -0.6907 -0.4421 -0.7514
-   25UREA    O2  194   1.403   1.535   2.297  0.0921 -0.0933 -0.2763
-   25UREA    N3  195   1.438   1.707   2.154  0.3416  0.0015  0.1005
-   25UREA    H4  196   1.394   1.795   2.134 -2.9647 -1.6544 -1.5488
-   25UREA    H5  197   1.513   1.673   2.098  0.1185  1.9069 -1.6034
-   25UREA    N6  198   1.284   1.731   2.304  0.0279 -0.0491 -0.0210
-   25UREA    H7  199   1.291   1.823   2.266 -0.9542  0.7545  1.5598
-   25UREA    H8  200   1.215   1.701   2.370 -1.7648  0.3428 -1.5492
-   26UREA    C1  201   0.859   1.550   1.635 -0.5593  0.2451 -0.2114
-   26UREA    O2  202   0.822   1.505   1.743  0.0306  0.1169 -0.0605
-   26UREA    N3  203   0.795   1.530   1.520 -1.0750 -0.4070  0.1807
-   26UREA    H4  204   0.828   1.588   1.445 -0.8907  2.4922  2.1675
-   26UREA    H5  205   0.714   1.471   1.513 -0.4582 -1.5175  1.5399
-   26UREA    N6  206   0.960   1.631   1.605 -0.3275  0.0530  0.0636
-   26UREA    H7  207   0.982   1.650   1.510  0.7139 -0.5561  0.1518
-   26UREA    H8  208   1.019   1.668   1.678 -0.8031 -0.8196  0.9389
-   27UREA    C1  209   0.692   1.868   1.656 -0.0551 -0.0375 -0.3605
-   27UREA    O2  210   0.621   1.776   1.696 -0.1985  0.2444  0.0195
-   27UREA    N3  211   0.810   1.853   1.597  0.0932 -0.1518 -0.0378
-   27UREA    H4  212   0.865   1.932   1.569 -1.2599  1.3391  1.1276
-   27UREA    H5  213   0.843   1.759   1.600  0.4398 -0.0209  1.1842
-   27UREA    N6  214   0.665   1.997   1.675  0.0013 -0.1211  0.3388
-   27UREA    H7  215   0.737   2.060   1.645  0.3102 -0.7814 -0.3964
-   27UREA    H8  216   0.588   2.029   1.730  1.4019  1.5887  1.5104
-   28UREA    C1  217   1.813   0.194   2.277 -0.8408 -0.2550 -0.1465
-   28UREA    O2  218   1.813   0.073   2.301 -0.3760 -0.0594  0.9275
-   28UREA    N3  219   1.832   0.254   2.160  0.1502 -0.4181 -0.0871
-   28UREA    H4  220   1.839   0.354   2.169  0.3852 -0.4432  0.0011
-   28UREA    H5  221   1.849   0.205   2.075  1.6456  0.9279 -0.6616
-   28UREA    N6  222   1.806   0.286   2.373 -0.1819  0.1118 -0.4358
-   28UREA    H7  223   1.812   0.384   2.357  0.5354  0.1103 -0.2060
-   28UREA    H8  224   1.793   0.245   2.464  0.1703 -0.8162 -0.7780
-   29UREA    C1  225   2.119   0.576   0.852  0.0619 -0.0750  0.3217
-   29UREA    O2  226   2.216   0.644   0.884 -0.2779  0.5126  0.1315
-   29UREA    N3  227   2.096   0.548   0.724 -0.0374 -0.1307  0.3541
-   29UREA    H4  228   2.022   0.491   0.688  0.4829 -0.2711 -0.5429
-   29UREA    H5  229   2.159   0.583   0.655 -1.7691  1.5190 -0.5997
-   29UREA    N6  230   2.027   0.527   0.935 -0.3471  0.4707  0.1945
-   29UREA    H7  231   1.951   0.475   0.896  0.5739  0.7644 -2.3635
-   29UREA    H8  232   2.020   0.553   1.031 -0.6526  0.0312  0.3004
-   30UREA    C1  233   1.871   2.422   0.497  0.0733  0.1212  0.2477
-   30UREA    O2  234   1.798   2.483   0.575  0.4038  0.1728  0.5130
-   30UREA    N3  235   1.854   2.292   0.472 -0.7050  0.2915 -0.1604
-   30UREA    H4  236   1.917   2.237   0.417 -1.1849 -0.7880  0.3225
-   30UREA    H5  237   1.782   2.246   0.524 -0.2046  0.4489  0.7074
-   30UREA    N6  238   1.963   2.470   0.414  0.0230 -0.4127 -0.1244
-   30UREA    H7  239   2.000   2.406   0.346 -0.2719  1.0844 -1.8590
-   30UREA    H8  240   2.001   2.562   0.423  1.5041 -1.0422  0.7618
-   31UREA    C1  241   1.602   1.646   1.932  0.2359 -0.8253 -0.7757
-   31UREA    O2  242   1.652   1.730   1.857  0.3008 -0.4832 -0.3511
-   31UREA    N3  243   1.492   1.575   1.908 -0.2758 -0.3384  0.0501
-   31UREA    H4  244   1.466   1.501   1.970 -1.7057 -1.2389 -1.4706
-   31UREA    H5  245   1.440   1.579   1.823 -1.1696 -1.0037  0.5388
-   31UREA    N6  246   1.646   1.598   2.048  0.0741  0.0541 -0.3368
-   31UREA    H7  247   1.602   1.523   2.097  2.4627 -1.6243 -0.4067
-   31UREA    H8  248   1.734   1.632   2.082  0.8369 -1.2316 -0.8742
-   32UREA    C1  249   2.012   1.235   0.746  0.4389 -0.0053 -0.3284
-   32UREA    O2  250   2.122   1.274   0.708  0.4715 -0.2622 -0.4864
-   32UREA    N3  251   1.989   1.115   0.799 -0.1305  0.1034 -0.3245
-   32UREA    H4  252   1.898   1.086   0.829  0.6402 -2.9182 -0.2379
-   32UREA    H5  253   2.061   1.046   0.807 -1.3798 -1.1500  1.4260
-   32UREA    N6  254   1.902   1.309   0.750  0.4299 -0.0402  0.1964
-   32UREA    H7  255   1.823   1.254   0.775  1.6014 -2.9159 -1.3724
-   32UREA    H8  256   1.891   1.403   0.718 -0.7665 -0.0687  0.4331
-   33UREA    C1  257   1.699   1.119   0.897 -0.0659  0.2408 -0.3564
-   33UREA    O2  258   1.657   1.068   0.793 -0.1955 -0.1364 -0.1179
-   33UREA    N3  259   1.779   1.063   0.988 -0.2076  0.1924 -0.2680
-   33UREA    H4  260   1.811   1.120   1.064 -3.6030  3.7815 -0.8789
-   33UREA    H5  261   1.801   0.967   0.972 -2.5911 -0.5105 -0.1194
-   33UREA    N6  262   1.680   1.248   0.925 -0.2439  0.1166  0.1183
-   33UREA    H7  263   1.727   1.288   1.003  0.2559 -0.2234 -0.0052
-   33UREA    H8  264   1.623   1.308   0.869 -0.8899  1.1235  1.7191
-   34UREA    C1  265   0.408   2.105   1.832 -0.3120 -0.3477  0.4870
-   34UREA    O2  266   0.458   2.127   1.942 -0.1389 -0.0323  0.3445
-   34UREA    N3  267   0.413   1.985   1.775  0.0798 -0.1921  0.1899
-   34UREA    H4  268   0.363   1.967   1.690 -1.2837 -1.7554  1.1984
-   34UREA    H5  269   0.458   1.907   1.817  0.0783 -1.1999 -1.4948
-   34UREA    N6  270   0.331   2.198   1.776  0.4552  0.2939  0.4669
-   34UREA    H7  271   0.288   2.183   1.687 -0.7269  2.0682  0.6273
-   34UREA    H8  272   0.323   2.284   1.827  1.3287 -0.5485  2.1844
-   35UREA    C1  273   0.932   1.699   1.302  0.1059 -0.1106  0.2001
-   35UREA    O2  274   1.032   1.627   1.301 -0.1649 -0.4919 -0.5403
-   35UREA    N3  275   0.926   1.831   1.322  0.2087 -0.0989  0.1419
-   35UREA    H4  276   0.838   1.877   1.312 -0.3922 -1.2579 -0.3006
-   35UREA    H5  277   1.005   1.888   1.345 -0.3880  0.8261 -0.0348
-   35UREA    N6  278   0.809   1.656   1.280  0.1034  0.2423 -0.4757
-   35UREA    H7  279   0.731   1.719   1.278  0.9377  1.3297 -0.3655
-   35UREA    H8  280   0.801   1.559   1.256  1.4904  0.4401 -2.0915
-   36UREA    C1  281   0.222   0.140   1.795  0.1610  0.3188  0.6518
-   36UREA    O2  282   0.179   0.071   1.888 -0.4847 -0.2438 -0.0306
-   36UREA    N3  283   0.158   0.222   1.711 -0.0812 -0.0915  0.4367
-   36UREA    H4  284   0.220   0.265   1.646 -0.0213 -0.3257  0.3413
-   36UREA    H5  285   0.060   0.236   1.725 -0.0183  0.4559  0.3246
-   36UREA    N6  286   0.352   0.138   1.772  0.1435  0.6162  0.5479
-   36UREA    H7  287   0.393   0.205   1.709  1.2107 -0.5493 -0.0808
-   36UREA    H8  288   0.407   0.081   1.833 -0.3036 -0.9673 -0.4106
-   37SOL    OW1  289   1.136   2.323   1.304  0.2852 -0.1304  0.0570
-   37SOL    HW2  290   1.060   2.294   1.246  0.1913 -1.2496  0.6873
-   37SOL    HW3  291   1.216   2.342   1.246 -0.5225  1.4410 -0.6434
-   38SOL    OW1  292   1.279   0.655   1.176  0.4893 -0.4584 -0.2208
-   38SOL    HW2  293   1.370   0.680   1.209  0.3788  1.4105 -1.0905
-   38SOL    HW3  294   1.215   0.652   1.253  1.1825 -1.5270  0.3609
-   39SOL    OW1  295   0.543   1.032   0.553  0.8937 -0.7904  0.8949
-   39SOL    HW2  296   0.614   1.101   0.544 -0.5228  0.6580 -0.4457
-   39SOL    HW3  297   0.481   1.038   0.475 -0.4963 -2.2289  1.7724
-   40SOL    OW1  298   1.217   2.050   0.538  0.0832  0.0469 -0.3454
-   40SOL    HW2  299   1.158   1.987   0.588 -0.2242  1.8167  1.8503
-   40SOL    HW3  300   1.165   2.130   0.511  1.0529  0.7934 -0.1150
-   41SOL    OW1  301   0.688   0.538   1.456  0.4113 -0.3396  0.8565
-   41SOL    HW2  302   0.629   0.498   1.386  0.3574 -0.5495  1.0247
-   41SOL    HW3  303   0.650   0.627   1.484 -0.9163 -1.2591  2.3074
-   42SOL    OW1  304   0.201   2.097   0.941  0.2877 -0.1872  0.5003
-   42SOL    HW2  305   0.152   2.012   0.924  2.8847 -1.6217 -1.0097
-   42SOL    HW3  306   0.271   2.081   1.011  0.8365  0.7174  0.1789
-   43SOL    OW1  307   0.648   1.255   0.806  0.3362  0.3229  0.0646
-   43SOL    HW2  308   0.708   1.248   0.885 -0.5740 -1.8875  0.7044
-   43SOL    HW3  309   0.631   1.352   0.785  0.6408  1.0421  2.5416
-   44SOL    OW1  310   1.693   0.340   1.825  0.3183  0.4511 -0.6230
-   44SOL    HW2  311   1.766   0.395   1.867  1.1778 -0.7657 -0.4089
-   44SOL    HW3  312   1.661   0.272   1.890  0.9468 -0.7973 -1.5403
-   45SOL    OW1  313   0.045   0.532   1.727 -0.1219  0.2634 -0.0246
-   45SOL    HW2  314   0.056   0.454   1.665  0.9923  0.0810  0.3757
-   45SOL    HW3  315   0.007   0.500   1.814 -3.3184  0.7235 -0.9784
-   46SOL    OW1  316   0.901   1.456   0.347  0.0768 -0.2592  0.1823
-   46SOL    HW2  317   0.903   1.513   0.429  2.4089 -1.5030  1.1868
-   46SOL    HW3  318   0.946   1.369   0.366  0.6032 -0.7108 -2.3848
-   47SOL    OW1  319   1.896   1.940   1.100 -0.0326  0.0491 -0.1439
-   47SOL    HW2  320   1.942   2.029   1.092  3.1787 -1.2245  0.9262
-   47SOL    HW3  321   1.834   1.942   1.179  0.0103  1.2886 -0.0943
-   48SOL    OW1  322   0.923   0.703   1.433  0.0107  0.5393  0.0515
-   48SOL    HW2  323   0.854   0.634   1.409 -1.5172  1.8332  0.4146
-   48SOL    HW3  324   0.939   0.762   1.354  1.9175 -0.5499 -0.5280
-   49SOL    OW1  325   1.205   1.647   0.408 -0.6089 -0.3297 -0.5753
-   49SOL    HW2  326   1.218   1.614   0.501  0.4658 -0.5659 -0.7919
-   49SOL    HW3  327   1.263   1.727   0.393 -0.2170 -0.7238 -1.2472
-   50SOL    OW1  328   0.467   0.782   1.801  0.4096  0.2902 -0.0173
-   50SOL    HW2  329   0.515   0.697   1.782  0.8423  0.1732  1.3581
-   50SOL    HW3  330   0.532   0.858   1.801  0.1874  0.4803 -0.3396
-   51SOL    OW1  331   1.306   2.093   1.188 -0.6197  0.5462  0.3714
-   51SOL    HW2  332   1.252   2.013   1.164  0.9211 -1.2484  2.1510
-   51SOL    HW3  333   1.341   2.137   1.105 -1.6843 -0.4767 -0.6860
-   52SOL    OW1  334   1.348   1.320   1.728  0.0665  0.8787  0.8488
-   52SOL    HW2  335   1.264   1.367   1.755 -0.2613  0.4745  0.5424
-   52SOL    HW3  336   1.339   1.287   1.634  0.1759 -0.0250  1.1409
-   53SOL    OW1  337   0.601   1.152   0.206  0.1153 -0.4701 -0.3625
-   53SOL    HW2  338   0.559   1.139   0.116  0.2079 -1.9711 -0.2417
-   53SOL    HW3  339   0.529   1.153   0.276  0.0772  0.2762 -0.4008
-   54SOL    OW1  340   0.404   1.902   0.971 -0.5022 -0.0578  0.1164
-   54SOL    HW2  341   0.458   1.881   1.053 -0.0405 -1.3755 -0.4525
-   54SOL    HW3  342   0.364   1.817   0.935 -1.6317  0.6496 -0.4065
-   55SOL    OW1  343   0.929   0.697   1.699  0.1497 -0.2624 -0.0693
-   55SOL    HW2  344   0.939   0.790   1.732 -1.7633 -0.4624  1.4718
-   55SOL    HW3  345   0.924   0.697   1.599 -0.4661  1.4132 -0.1009
-   56SOL    OW1  346   0.355   2.118   1.192 -0.3272 -0.0244 -0.5704
-   56SOL    HW2  347   0.409   2.054   1.245 -1.8039 -1.0670 -0.2191
-   56SOL    HW3  348   0.343   2.203   1.243  0.4024 -0.0293 -0.3825
-   57SOL    OW1  349   0.009   1.476   1.832 -0.1854  0.0519 -0.2116
-   57SOL    HW2  350  -0.070   1.535   1.812 -0.5299  0.6623  2.2750
-   57SOL    HW3  351   0.019   1.467   1.931  1.5958 -1.8401 -0.4377
-   58SOL    OW1  352   1.134   1.091   1.824 -0.0734 -0.0629 -0.0441
-   58SOL    HW2  353   1.165   1.035   1.901 -0.5898 -2.3558 -1.3287
-   58SOL    HW3  354   1.070   1.161   1.857  0.4756 -0.2723  1.6762
-   59SOL    OW1  355   1.699   0.638   0.430 -0.1132  0.4388 -0.7596
-   59SOL    HW2  356   1.662   0.657   0.521 -0.7402 -1.1923 -0.6195
-   59SOL    HW3  357   1.798   0.645   0.432 -0.1647  1.3611 -0.2245
-   60SOL    OW1  358   1.376   2.113   1.696 -0.5818  0.0101  0.3984
-   60SOL    HW2  359   1.459   2.164   1.674 -0.7394  0.7839  1.4313
-   60SOL    HW3  360   1.396   2.043   1.764 -0.4207 -1.2366 -0.8326
-   61SOL    OW1  361   1.208   0.760   1.814 -0.0553 -0.3885  0.3323
-   61SOL    HW2  362   1.115   0.786   1.842  0.4481  0.1673  1.6820
-   61SOL    HW3  363   1.215   0.660   1.808 -0.3840 -0.5425  1.8021
-   62SOL    OW1  364   1.192   1.196   0.439  0.9122 -0.0313 -0.3822
-   62SOL    HW2  365   1.259   1.122   0.438  0.2801 -0.6438 -1.7278
-   62SOL    HW3  366   1.221   1.267   0.374 -0.4253 -1.0871 -2.3528
-   63SOL    OW1  367   1.516   0.309   1.185 -0.3898  0.8760 -0.1257
-   63SOL    HW2  368   1.480   0.360   1.107  0.6799  1.3744 -0.3119
-   63SOL    HW3  369   1.550   0.372   1.254 -0.5582  0.4226  0.3892
-   64SOL    OW1  370   1.033   1.287   1.489 -0.0249  0.2306  0.7473
-   64SOL    HW2  371   1.060   1.200   1.529  1.0482  0.2191  0.0786
-   64SOL    HW3  372   1.114   1.340   1.467 -0.5268  0.3893 -1.0206
-   65SOL    OW1  373   1.738   1.000   1.911 -0.1312 -0.1774  0.0370
-   65SOL    HW2  374   1.651   1.050   1.908  0.5773  1.1947  0.4243
-   65SOL    HW3  375   1.809   1.055   1.866  0.9007 -0.3743  1.3003
-   66SOL    OW1  376   1.133   0.677   0.588  0.3763  0.1991 -0.2947
-   66SOL    HW2  377   1.076   0.652   0.510 -0.3388  1.5659 -0.2579
-   66SOL    HW3  378   1.099   0.632   0.670  0.2804 -0.1577 -0.5291
-   67SOL    OW1  379   1.671   1.986   0.398 -0.0629 -0.2553 -0.3510
-   67SOL    HW2  380   1.689   1.900   0.352 -0.5491 -0.3315 -0.4045
-   67SOL    HW3  381   1.735   1.998   0.474 -0.8091 -1.3140  0.5071
-   68SOL    OW1  382   1.098   1.114   0.968  0.2296  0.3056 -0.0984
-   68SOL    HW2  383   1.056   1.076   0.885  0.0947 -1.2135  0.6155
-   68SOL    HW3  384   1.076   1.056   1.046  2.0704  0.5151  0.6519
-   69SOL    OW1  385   1.388   2.229   0.930 -0.4170  0.3929 -0.1630
-   69SOL    HW2  386   1.332   2.165   0.878 -2.0355  1.5280  0.0322
-   69SOL    HW3  387   1.482   2.194   0.936 -1.2514 -2.1860  0.3904
-   70SOL    OW1  388   0.340   0.728   1.494 -0.3584  0.2725  0.0880
-   70SOL    HW2  389   0.428   0.686   1.473 -0.3132 -0.0415  0.8393
-   70SOL    HW3  390   0.266   0.675   1.453 -0.1987  0.7439 -0.8557
-   71SOL    OW1  391   0.143   2.330   1.109 -0.1806 -0.0610  0.0267
-   71SOL    HW2  392   0.150   2.428   1.127 -0.1789  0.1907 -1.1654
-   71SOL    HW3  393   0.159   2.313   1.012  0.1806 -1.2961  0.2695
-   72SOL    OW1  394   1.388   1.068   0.675  0.0979  0.9826 -0.4781
-   72SOL    HW2  395   1.437   1.016   0.605  1.9188 -0.6478  1.7117
-   72SOL    HW3  396   1.289   1.052   0.666  0.4382 -1.8462 -0.8594
-   73SOL    OW1  397   0.400   1.005   0.782  0.6828 -0.0037 -0.3761
-   73SOL    HW2  398   0.455   1.020   0.864 -0.0446  1.1738 -0.0571
-   73SOL    HW3  399   0.449   1.037   0.701  0.6024  0.8055 -0.1209
-   74SOL    OW1  400   0.655   2.126   1.122 -0.1484  0.0100  0.4334
-   74SOL    HW2  401   0.556   2.133   1.108 -0.2797 -0.1070  1.2197
-   74SOL    HW3  402   0.687   2.206   1.172  0.4386  0.8074 -1.0980
-   75SOL    OW1  403   1.261   1.685   0.686  0.9478 -0.0452 -0.2167
-   75SOL    HW2  404   1.260   1.585   0.679 -0.1131 -0.0829  0.1553
-   75SOL    HW3  405   1.317   1.712   0.764  2.0297 -0.2691 -0.8743
-   76SOL    OW1  406   0.137   1.782   1.714 -0.8370  0.4849  0.0414
-   76SOL    HW2  407   0.101   1.751   1.626 -0.4785 -0.4963  0.2221
-   76SOL    HW3  408   0.107   1.876   1.731 -1.6185  0.3980 -0.7329
-   77SOL    OW1  409   1.740   0.494   0.938 -0.0261  0.4504  0.2175
-   77SOL    HW2  410   1.756   0.484   0.840 -1.5662 -0.3010 -0.0257
-   77SOL    HW3  411   1.645   0.519   0.954 -0.2195 -0.8201  1.5289
-   78SOL    OW1  412   0.940   0.201   1.027  0.6233  0.6970 -0.3180
-   78SOL    HW2  413   0.950   0.250   1.113 -0.2948  0.9349 -0.3301
-   78SOL    HW3  414   0.997   0.119   1.028 -0.9453 -0.5645  1.4685
-   79SOL    OW1  415   1.052   1.041   0.682  0.3380 -0.4574 -0.3096
-   79SOL    HW2  416   0.977   0.975   0.690 -1.5081  1.2352 -1.6186
-   79SOL    HW3  417   1.072   1.057   0.586 -0.6621  2.0477 -0.2716
-   80SOL    OW1  418   2.027   0.675   1.196 -0.5905 -0.8219 -0.3636
-   80SOL    HW2  419   1.957   0.700   1.128 -0.9854 -0.0162  0.3035
-   80SOL    HW3  420   1.984   0.625   1.271 -0.9505  1.2143  0.9712
-   81SOL    OW1  421   0.977   0.314   0.008 -0.8585 -0.3282  0.0532
-   81SOL    HW2  422   1.001   0.275  -0.081  2.7404 -2.6490  1.5980
-   81SOL    HW3  423   0.936   0.404  -0.006 -2.0059 -1.0456 -3.8075
-   82SOL    OW1  424   1.199   0.665   0.215  0.5635  0.0376  0.0445
-   82SOL    HW2  425   1.277   0.608   0.239 -1.6912 -3.6087  0.3920
-   82SOL    HW3  426   1.127   0.653   0.283 -1.1287  1.0835 -1.3868
-   83SOL    OW1  427   0.978   1.806   2.091  0.0463  0.0392  0.0319
-   83SOL    HW2  428   0.926   1.781   2.172  0.8820 -1.3259  0.2121
-   83SOL    HW3  429   1.030   1.727   2.059 -0.8704  0.2296 -2.3565
-   84SOL    OW1  430   0.482   1.093   1.536  0.1634  0.3943 -0.1332
-   84SOL    HW2  431   0.411   1.135   1.593 -0.5340  0.8577 -1.2851
-   84SOL    HW3  432   0.554   1.056   1.595 -0.4865  0.8802  1.0329
-   85SOL    OW1  433   0.840   2.006   1.949  0.2471 -0.3957  0.1918
-   85SOL    HW2  434   0.809   1.958   2.032  0.8465 -1.6771 -0.2660
-   85SOL    HW3  435   0.902   1.946   1.898  1.3027  1.0197 -0.3047
-   86SOL    OW1  436   1.926   0.136   0.903 -0.0629  0.3100 -0.5335
-   86SOL    HW2  437   1.917   0.051   0.851  1.7082 -1.4419  1.6066
-   86SOL    HW3  438   1.842   0.152   0.955 -1.1735  1.1430 -2.3708
-   87SOL    OW1  439   0.709   1.682   0.009  0.1085 -0.0412 -0.1992
-   87SOL    HW2  440   0.714   1.691  -0.090 -2.3892 -0.3615 -0.4814
-   87SOL    HW3  441   0.771   1.610   0.039  1.8354  0.8637 -1.2672
-   88SOL    OW1  442   1.227   2.334   1.567  0.4275  0.0392 -0.2805
-   88SOL    HW2  443   1.179   2.304   1.484  0.4090 -1.5305  0.2379
-   88SOL    HW3  444   1.309   2.278   1.579 -0.3833 -0.9087  1.5383
-   89SOL    OW1  445   2.091   0.753   1.557 -0.4029 -0.4395  0.2535
-   89SOL    HW2  446   2.117   0.671   1.608  2.4658 -0.4839 -0.8823
-   89SOL    HW3  447   2.163   0.822   1.568 -0.3322  0.1060 -2.4041
-   90SOL    OW1  448   0.826   1.253   1.638  0.0780 -0.2117  0.3012
-   90SOL    HW2  449   0.911   1.274   1.589  0.2874  0.2151  0.8341
-   90SOL    HW3  450   0.772   1.336   1.648 -0.7071 -0.5929 -0.5648
-   91SOL    OW1  451   1.732   1.190   0.502 -0.3850  0.2543 -0.2455
-   91SOL    HW2  452   1.647   1.242   0.507 -0.4100  0.2043 -0.1871
-   91SOL    HW3  453   1.713   1.093   0.510 -0.2593  0.2818  0.5556
-   92SOL    OW1  454   1.589   0.408   0.368 -0.0289  0.5768  0.0586
-   92SOL    HW2  455   1.626   0.345   0.436  2.3402  0.3968 -1.1661
-   92SOL    HW3  456   1.630   0.499   0.381  1.0059  0.3901 -1.3442
-   93SOL    OW1  457   0.434   1.727   1.888 -0.4139  0.4027  0.6709
-   93SOL    HW2  458   0.437   1.647   1.949  0.0183 -0.5331 -0.4929
-   93SOL    HW3  459   0.425   1.696   1.793 -1.4520  1.8077  0.2500
-   94SOL    OW1  460   0.117   0.952   0.818  0.3802 -0.3300 -0.2416
-   94SOL    HW2  461   0.215   0.960   0.802  0.5260 -1.0043  0.2051
-   94SOL    HW3  462   0.102   0.915   0.910 -0.3007  0.0226 -0.2033
-   95SOL    OW1  463   1.745   0.872   1.299  0.2360  0.2454  0.2302
-   95SOL    HW2  464   1.800   0.953   1.319  0.9130 -0.3560  0.9305
-   95SOL    HW3  465   1.743   0.857   1.200  1.1832  0.4069  0.1642
-   96SOL    OW1  466   0.969   1.631   0.126  0.2485  0.2280  0.0868
-   96SOL    HW2  467   0.941   1.578   0.206  1.2333  0.2168  0.4467
-   96SOL    HW3  468   1.017   1.570   0.062 -2.8046 -0.4916 -1.9320
-   97SOL    OW1  469   1.606   2.235   1.807 -0.2479 -0.2295  0.3422
-   97SOL    HW2  470   1.658   2.168   1.755  1.4497  0.8729  0.4719
-   97SOL    HW3  471   1.565   2.190   1.887  1.0330 -1.0970  0.5764
-   98SOL    OW1  472   0.868   0.099   1.839 -0.4913 -0.1475  0.3648
-   98SOL    HW2  473   0.807   0.097   1.918 -3.3226  1.6097 -1.4183
-   98SOL    HW3  474   0.925   0.181   1.842 -0.8614  0.1080  0.4576
-   99SOL    OW1  475   0.103   0.686   0.279 -0.1883 -0.1939 -0.5779
-   99SOL    HW2  476   0.127   0.624   0.354 -3.5269 -0.3742  0.6934
-   99SOL    HW3  477   0.074   0.774   0.317 -1.4352 -0.0878 -1.6727
-  100SOL    OW1  478   1.834   1.993   0.608 -0.2685 -0.1676 -0.2770
-  100SOL    HW2  479   1.929   1.971   0.589  0.4409  2.1449 -0.0633
-  100SOL    HW3  480   1.807   1.951   0.695  0.1483 -1.6956 -0.8263
-  101SOL    OW1  481   1.899   1.670   0.003 -0.0441 -0.5134  0.0147
-  101SOL    HW2  482   1.961   1.722   0.061 -0.4384 -0.4639  0.3974
-  101SOL    HW3  483   1.948   1.635  -0.076  0.1118  0.8932 -0.5487
-  102SOL    OW1  484   0.636   0.867   0.138  0.2646  0.1758 -0.0169
-  102SOL    HW2  485   0.629   0.959   0.099  1.9946  0.5852  0.4478
-  102SOL    HW3  486   0.548   0.821   0.132 -0.0784  0.8316 -2.7463
-  103SOL    OW1  487   0.541   0.315   0.142  0.0964  0.7028 -0.0473
-  103SOL    HW2  488   0.620   0.287   0.197 -0.2978  0.3988  0.3800
-  103SOL    HW3  489   0.459   0.268   0.176 -0.1150  0.2897 -1.0796
-  104SOL    OW1  490   1.076   0.027   2.052  0.2989 -0.3802  0.3914
-  104SOL    HW2  491   1.140  -0.028   1.998  1.8610 -0.2656  1.9810
-  104SOL    HW3  492   1.050   0.108   2.000  1.3656 -0.4924 -0.3771
-  105SOL    OW1  493   0.750   0.390   0.935  0.6192  0.4486 -0.1025
-  105SOL    HW2  494   0.820   0.319   0.945  0.7898 -0.0293 -2.9244
-  105SOL    HW3  495   0.677   0.356   0.875 -1.4485  1.4118  1.6289
-  106SOL    OW1  496   1.694   1.540   1.111 -0.4080 -0.2525 -0.0177
-  106SOL    HW2  497   1.739   1.592   1.184  0.4869 -1.2645  0.2206
-  106SOL    HW3  498   1.668   1.601   1.037  1.5190  0.4597 -0.2222
-  107SOL    OW1  499   1.589   0.373   0.675  0.0431 -0.2324 -0.3412
-  107SOL    HW2  500   1.524   0.346   0.605  1.1474 -1.9280 -0.8147
-  107SOL    HW3  501   1.582   0.311   0.754 -0.4761  1.0199  0.6715
-  108SOL    OW1  502   0.281   1.693   0.025 -0.0806  0.3256 -0.0739
-  108SOL    HW2  503   0.251   1.767  -0.034  0.1403  1.3766  1.0549
-  108SOL    HW3  504   0.335   1.628  -0.028  0.3225  1.3368 -0.9687
-  109SOL    OW1  505   2.041   0.405   0.398 -0.6164  0.2991 -0.0624
-  109SOL    HW2  506   2.139   0.424   0.410 -0.0768 -2.2881  0.6908
-  109SOL    HW3  507   1.991   0.492   0.399  1.4759  1.6866  1.1017
-  110SOL    OW1  508   0.892   0.835   0.932 -0.0875  0.0867  0.3771
-  110SOL    HW2  509   0.893   0.750   0.880 -1.6158 -0.5569  1.2592
-  110SOL    HW3  510   0.830   0.900   0.889  1.1151  0.8480 -0.3194
-  111SOL    OW1  511   0.934   1.138   0.372  0.1781 -0.1319 -0.2100
-  111SOL    HW2  512   0.865   1.167   0.438  0.6108 -1.1676  0.7707
-  111SOL    HW3  513   1.025   1.161   0.407  0.4165 -0.7609 -0.4099
-  112SOL    OW1  514   0.782   1.793   0.680  0.0927  0.3788 -0.3424
-  112SOL    HW2  515   0.805   1.717   0.618 -0.5805 -0.5298  0.4629
-  112SOL    HW3  516   0.712   1.850   0.637 -2.4495 -1.7474  0.3840
-  113SOL    OW1  517   1.209   1.346   1.175  0.0055  0.7532  0.1240
-  113SOL    HW2  518   1.213   1.249   1.201 -0.8872  0.3338 -1.1045
-  113SOL    HW3  519   1.299   1.375   1.143  0.3634  0.4498  0.8093
-  114SOL    OW1  520   1.471   2.085   0.591  0.0062  0.1481 -0.6743
-  114SOL    HW2  521   1.372   2.080   0.598  0.0651  0.1128  0.4044
-  114SOL    HW3  522   1.504   2.018   0.524 -0.6322 -0.4540 -0.3957
-  115SOL    OW1  523   0.675   0.621   1.777 -0.0413 -0.1256 -0.5737
-  115SOL    HW2  524   0.714   0.660   1.860 -0.3032 -0.1058 -0.4575
-  115SOL    HW3  525   0.743   0.622   1.704  0.9365 -2.0406  0.1692
-  116SOL    OW1  526   1.910   2.205   0.798  0.2704 -0.5038 -0.0757
-  116SOL    HW2  527   1.871   2.141   0.732  1.4127 -0.3892 -0.9105
-  116SOL    HW3  528   2.001   2.233   0.768 -0.4821  2.2762 -0.3314
-  117SOL    OW1  529   1.626   1.343   1.679 -0.4152 -0.0794 -0.2261
-  117SOL    HW2  530   1.643   1.263   1.622 -0.7488 -0.3894  0.1011
-  117SOL    HW3  531   1.532   1.341   1.713 -1.1148  1.4544 -1.7719
-  118SOL    OW1  532   0.300   1.483   0.597 -0.8682  0.4686 -0.6379
-  118SOL    HW2  533   0.334   1.574   0.621 -0.3277  0.6091 -1.8228
-  118SOL    HW3  534   0.301   1.472   0.498 -0.7581 -0.8909 -0.5202
-  119SOL    OW1  535   1.424   1.887   1.829 -0.5741 -1.0007  0.3895
-  119SOL    HW2  536   1.367   1.873   1.910 -0.3831  1.3658  1.0782
-  119SOL    HW3  537   1.503   1.826   1.833 -0.6660 -1.0922  1.9170
-  120SOL    OW1  538   2.002   1.848   0.403  0.2073 -0.0724 -0.1044
-  120SOL    HW2  539   1.960   1.803   0.482  1.2483 -1.1583 -0.1086
-  120SOL    HW3  540   2.097   1.870   0.425  0.1158  0.9183 -0.6028
-  121SOL    OW1  541   1.640   0.991   0.298  0.5609  0.4945 -0.1885
-  121SOL    HW2  542   1.657   1.012   0.202 -0.8550 -1.3743 -0.9846
-  121SOL    HW3  543   1.579   1.059   0.337 -1.6821 -0.3570 -1.7878
-  122SOL    OW1  544   1.850   0.668   1.479  0.2522  0.1197 -0.2780
-  122SOL    HW2  545   1.941   0.703   1.500 -0.6236  2.1573  0.6611
-  122SOL    HW3  546   1.798   0.738   1.430 -0.8633 -0.9380 -0.6969
-  123SOL    OW1  547   0.811   0.348   1.617  0.2784 -0.4820  0.5339
-  123SOL    HW2  548   0.778   0.353   1.712  0.1123 -0.8340  0.4974
-  123SOL    HW3  549   0.764   0.417   1.562 -0.8530 -1.3356  0.3660
-  124SOL    OW1  550   0.152   0.565   1.416  0.5757  0.5408 -0.0173
-  124SOL    HW2  551   0.082   0.518   1.470 -0.3704  2.0741  0.2246
-  124SOL    HW3  552   0.121   0.575   1.322  0.4026  1.2961  0.1099
-  125SOL    OW1  553   1.566   1.800   1.096 -0.0052  0.2192 -0.5025
-  125SOL    HW2  554   1.519   1.788   1.184 -0.0623 -0.6806 -0.6380
-  125SOL    HW3  555   1.507   1.768   1.022  1.1469 -2.2110 -0.5843
-  126SOL    OW1  556   0.414   0.470   1.928  0.2116  0.1795  0.1069
-  126SOL    HW2  557   0.357   0.401   1.972 -0.9264  0.7937 -0.3207
-  126SOL    HW3  558   0.406   0.462   1.829 -0.0213  0.9591  0.0495
-  127SOL    OW1  559   0.090   1.791   0.967  0.3167 -0.4991 -0.1999
-  127SOL    HW2  560   0.172   1.780   1.023  0.5117 -0.8389 -0.5445
-  127SOL    HW3  561   0.019   1.730   1.000 -0.7651  1.4973  1.7336
-  128SOL    OW1  562   0.057   0.339   0.161 -0.0525 -0.1842 -0.1555
-  128SOL    HW2  563   0.034   0.420   0.107  0.0223  0.0439  0.1489
-  128SOL    HW3  564   0.012   0.345   0.250 -0.2806 -0.6235 -0.2385
-  129SOL    OW1  565   0.348   0.855   1.050 -0.0623 -0.1359  0.3582
-  129SOL    HW2  566   0.433   0.843   0.999 -0.6392  0.0342 -0.7024
-  129SOL    HW3  567   0.363   0.917   1.127  0.4242  1.2778 -0.7963
-  130SOL    OW1  568   0.421   2.041   0.331 -0.4444  0.2754  0.0853
-  130SOL    HW2  569   0.452   2.127   0.290 -0.4246 -0.2667 -1.1317
-  130SOL    HW3  570   0.335   2.013   0.289  0.1732 -0.8984 -0.4933
-  131SOL    OW1  571   1.497   1.149   1.899 -0.1127  0.0895 -0.3529
-  131SOL    HW2  572   1.464   1.054   1.904  1.1609 -0.3773 -0.0086
-  131SOL    HW3  573   1.446   1.198   1.829 -1.6025 -0.4887  0.2258
-  132SOL    OW1  574   1.090   2.324   1.016  0.4978 -0.5111  0.5508
-  132SOL    HW2  575   1.061   2.234   0.985 -1.4229 -0.9019  2.8779
-  132SOL    HW3  576   1.174   2.350   0.969  0.8327 -3.1972 -0.7093
-  133SOL    OW1  577   0.303   1.272   1.675 -0.1953 -0.0608  0.1099
-  133SOL    HW2  578   0.214   1.262   1.631 -0.1178  3.9176 -1.8159
-  133SOL    HW3  579   0.297   1.338   1.750  1.0813  0.1111  0.1104
-  134SOL    OW1  580   1.750   2.011   1.733 -0.2233  0.0235  0.2833
-  134SOL    HW2  581   1.801   1.987   1.816 -0.2438 -0.2268  0.2252
-  134SOL    HW3  582   1.666   1.957   1.729 -0.9149  0.9933  0.7904
-  135SOL    OW1  583   0.041   0.139   2.156 -0.4666 -0.1268  0.3831
-  135SOL    HW2  584  -0.049   0.122   2.116  0.2879  1.9772 -3.0628
-  135SOL    HW3  585   0.030   0.191   2.241 -2.5085  0.3559 -0.0648
-  136SOL    OW1  586   1.347   1.885   0.372  0.1242 -0.2856  0.6527
-  136SOL    HW2  587   1.280   1.949   0.411  0.6183  0.3217  0.5346
-  136SOL    HW3  588   1.361   1.907   0.276 -0.1169 -0.9490  0.4574
-  137SOL    OW1  589   1.256   1.550   1.422 -0.0091 -0.5712 -0.1766
-  137SOL    HW2  590   1.281   1.453   1.425 -0.3430 -0.6465  0.8035
-  137SOL    HW3  591   1.170   1.561   1.372  0.1971 -0.7307 -0.5721
-  138SOL    OW1  592   1.250   1.008   2.049  0.0330  0.3953 -0.5330
-  138SOL    HW2  593   1.266   1.106   2.044 -2.3054  1.0843  1.6849
-  138SOL    HW3  594   1.328   0.964   2.094  0.1081  1.7358  0.7927
-  139SOL    OW1  595   1.507   0.730   1.325 -0.4714  0.4185  0.0916
-  139SOL    HW2  596   1.461   0.771   1.404 -3.4623  1.4345 -1.8530
-  139SOL    HW3  597   1.578   0.793   1.291  2.1870 -0.7512  2.5830
-  140SOL    OW1  598   0.455   1.742   0.595 -0.2740 -0.0007  0.3909
-  140SOL    HW2  599   0.439   1.828   0.644 -0.8287  1.1949 -1.6590
-  140SOL    HW3  600   0.535   1.752   0.535  1.1935 -1.8441  1.7970
-  141SOL    OW1  601   1.687   1.793   0.188  0.3177 -0.2593  0.3674
-  141SOL    HW2  602   1.626   1.836   0.122 -0.0786  0.1012  0.9539
-  141SOL    HW3  603   1.779   1.788   0.149  0.3912  1.1539  0.2679
-  142SOL    OW1  604   1.563   0.705   0.186  0.0140 -0.6182 -0.4736
-  142SOL    HW2  605   1.488   0.679   0.246 -0.2847  0.7640 -0.1706
-  142SOL    HW3  606   1.639   0.739   0.241 -0.0116  0.0414 -0.8248
-  143SOL    OW1  607   1.702   1.714   0.587 -0.0871 -0.2563  0.4727
-  143SOL    HW2  608   1.782   1.654   0.576  0.9125  1.0929 -0.2485
-  143SOL    HW3  609   1.640   1.700   0.510  0.6633  0.3203 -0.2690
-  144SOL    OW1  610   0.862   2.145   1.489  0.2455  0.3150  0.6359
-  144SOL    HW2  611   0.902   2.148   1.398 -1.1372  1.4585 -0.0183
-  144SOL    HW3  612   0.904   2.215   1.546  0.1404  0.5704  0.4006
-  145SOL    OW1  613   1.535   1.682   0.377  0.1536 -0.0681  0.2072
-  145SOL    HW2  614   1.467   1.751   0.400  2.2292  2.0656  0.7481
-  145SOL    HW3  615   1.582   1.708   0.293  0.8093 -1.0077  0.2535
-  146SOL    OW1  616   0.032   2.169   1.546 -0.0211  0.2842  0.0823
-  146SOL    HW2  617   0.122   2.143   1.513  0.4822  0.3521  1.3116
-  146SOL    HW3  618  -0.029   2.186   1.468  0.9170 -0.0888 -0.7646
-  147SOL    OW1  619   1.957   0.710   0.477 -0.1785  0.7365 -0.1392
-  147SOL    HW2  620   1.932   0.759   0.393 -0.3855 -0.5145 -0.8684
-  147SOL    HW3  621   2.036   0.753   0.519 -0.0169  1.3543 -1.0270
-  148SOL    OW1  622   1.861   1.304   0.273  0.2402 -0.0094 -0.1325
-  148SOL    HW2  623   1.824   1.242   0.342  0.2556 -0.8393 -0.8274
-  148SOL    HW3  624   1.788   1.363   0.239 -0.0474 -0.4021 -0.2198
-  149SOL    OW1  625   0.653   1.698   0.396 -0.4847  0.2238  0.2685
-  149SOL    HW2  626   0.732   1.745   0.356 -0.5963  0.8343  0.7422
-  149SOL    HW3  627   0.571   1.719   0.344 -0.2981 -0.7145 -0.4488
-  150SOL    OW1  628   0.787   1.019   1.472 -0.2957 -0.7313 -0.0828
-  150SOL    HW2  629   0.845   1.041   1.393 -0.8605 -0.6963 -0.4969
-  150SOL    HW3  630   0.814   1.076   1.549 -0.8463  0.5272 -0.7556
-  151SOL    OW1  631   1.495   0.925   0.003 -0.2499  0.0732 -0.5895
-  151SOL    HW2  632   1.590   0.958   0.004 -0.5942  1.1442 -0.8220
-  151SOL    HW3  633   1.492   0.833   0.042  0.9301 -0.1292 -0.8873
-  152SOL    OW1  634   0.178   1.724   0.708 -0.4638 -0.0788  0.4209
-  152SOL    HW2  635   0.156   1.659   0.781 -1.8781  0.6958  0.7567
-  152SOL    HW3  636   0.245   1.790   0.742 -0.7482 -0.0126  0.8716
-  153SOL    OW1  637   1.470   0.875   1.857  0.2012 -0.2387 -0.1237
-  153SOL    HW2  638   1.375   0.845   1.856  0.3837 -0.8347 -0.1678
-  153SOL    HW3  639   1.525   0.814   1.800  0.6956 -0.2024  0.3052
-  154SOL    OW1  640   1.467   1.222   0.382  0.3389  0.6624  0.1653
-  154SOL    HW2  641   1.526   1.302   0.395  0.9722  0.1175  0.7419
-  154SOL    HW3  642   1.432   1.222   0.288  0.9168  1.2266 -0.0668
-  155SOL    OW1  643   0.384   1.134   0.372 -0.4800 -0.1530 -0.3919
-  155SOL    HW2  644   0.323   1.169   0.443 -1.1248 -2.4534  0.3793
-  155SOL    HW3  645   0.334   1.069   0.315  1.0597 -1.9167  0.0669
-  156SOL    OW1  646   0.803   0.902   0.352 -0.0019  0.5576 -0.1973
-  156SOL    HW2  647   0.741   0.891   0.274 -0.6208  2.9318 -0.2066
-  156SOL    HW3  648   0.849   0.991   0.344  4.0522 -1.1474 -0.5164
-  157SOL    OW1  649   1.173   0.623   1.415  0.0266 -0.5275 -0.2205
-  157SOL    HW2  650   1.077   0.612   1.443  0.0724 -1.9214 -0.4759
-  157SOL    HW3  651   1.224   0.540   1.438  1.6931  0.8330  1.6444
-  158SOL    OW1  652   1.021   1.433   0.975 -0.4489  0.4447  0.0545
-  158SOL    HW2  653   1.082   1.403   1.048  0.5266  1.3794 -0.3371
-  158SOL    HW3  654   0.933   1.386   0.985  0.4164 -1.2907  0.3992
-  159SOL    OW1  655   0.403   0.655   0.806 -0.0401  0.3305  0.1337
-  159SOL    HW2  656   0.452   0.710   0.874  0.0340  0.0125  0.3387
-  159SOL    HW3  657   0.469   0.603   0.752 -0.1153  0.4120 -0.0279
-  160SOL    OW1  658   1.846   0.436   1.593 -0.3048  0.2915  0.1266
-  160SOL    HW2  659   1.827   0.524   1.548 -1.5172 -0.2518 -0.5401
-  160SOL    HW3  660   1.846   0.449   1.692 -1.3792  0.9370  0.0808
-  161SOL    OW1  661   0.437   0.781   2.083  0.0095 -1.2060  0.2252
-  161SOL    HW2  662   0.426   0.686   2.113  0.2122 -1.8353 -1.4770
-  161SOL    HW3  663   0.453   0.783   1.984  0.0920  0.6180  0.2134
-  162SOL    OW1  664   0.452   2.222   0.916 -0.6120  0.1469  0.1860
-  162SOL    HW2  665   0.361   2.190   0.942 -1.0830 -0.4433 -1.8996
-  162SOL    HW3  666   0.449   2.266   0.827  1.2079 -0.2943 -0.1825
-  163SOL    OW1  667   0.935   1.123   0.095 -0.2401  0.3174 -0.4180
-  163SOL    HW2  668   0.993   1.042   0.105  1.7893  1.6069 -0.5265
-  163SOL    HW3  669   0.907   1.156   0.185  0.4230  0.4200 -0.2380
-  164SOL    OW1  670   0.769   1.993   0.041 -0.0495 -0.3257  0.1228
-  164SOL    HW2  671   0.806   1.973   0.131 -0.5785  0.3032  0.4992
-  164SOL    HW3  672   0.670   2.005   0.048 -0.0127  0.3706 -0.4192
-  165SOL    OW1  673   0.217   1.153   0.565 -0.0990 -0.3276 -0.1299
-  165SOL    HW2  674   0.183   1.222   0.629  2.4918  0.3714  0.7391
-  165SOL    HW3  675   0.224   1.064   0.611  2.8380  0.3944  1.3269
-  166SOL    OW1  676   1.869   0.588   1.876 -0.3023 -0.2309  0.2519
-  166SOL    HW2  677   1.804   0.633   1.937  0.1743  1.6052 -0.4750
-  166SOL    HW3  678   1.886   0.645   1.796  1.6203 -0.9528  0.0218
-  167SOL    OW1  679   1.422   1.015   1.473 -0.0075  0.1342 -0.5369
-  167SOL    HW2  680   1.395   0.936   1.529 -0.0798  0.7241  0.2938
-  167SOL    HW3  681   1.521   1.023   1.473  0.3572 -1.7278 -3.1789
-  168SOL    OW1  682   1.607   0.650   0.700  0.2782  1.0724  0.1966
-  168SOL    HW2  683   1.518   0.690   0.724 -0.1831 -0.1319  0.6430
-  168SOL    HW3  684   1.599   0.550   0.697  1.6644  0.9210  0.3875
-  169SOL    OW1  685   1.178   0.403   1.108  0.5986 -0.5871  0.1392
-  169SOL    HW2  686   1.098   0.455   1.078  0.7783 -1.8790 -3.4652
-  169SOL    HW3  687   1.258   0.463   1.111  0.2804 -0.0749 -0.8886
-  170SOL    OW1  688   0.220   1.770   1.221 -0.2924 -0.0368  0.2000
-  170SOL    HW2  689   0.212   1.671   1.213 -1.9547  0.0426  0.1832
-  170SOL    HW3  690   0.310   1.793   1.258  0.7961 -1.4174 -1.3069
-  171SOL    OW1  691   0.866   0.337   1.231  0.3183 -0.4266 -0.2301
-  171SOL    HW2  692   0.877   0.292   1.319 -0.0839  2.3873  1.5149
-  171SOL    HW3  693   0.768   0.341   1.208 -0.2658  2.4013  1.7002
-  172SOL    OW1  694   1.311   0.361   0.549 -0.3189 -0.2118  0.0566
-  172SOL    HW2  695   1.212   0.365   0.539 -0.3338 -1.5399 -0.8133
-  172SOL    HW3  696   1.347   0.281   0.500  1.1329 -0.0823  0.7921
-  173SOL    OW1  697   1.369   1.126   0.940  0.0703 -0.1074 -0.0104
-  173SOL    HW2  698   1.398   1.092   0.850 -1.6292  0.7576 -0.9813
-  173SOL    HW3  699   1.270   1.118   0.948 -0.0663  1.6173  0.9684
-  174SOL    OW1  700   0.490   1.531   2.101 -0.3142 -0.2034 -0.0218
-  174SOL    HW2  701   0.532   1.573   2.181  0.1668  0.8101 -0.7578
-  174SOL    HW3  702   0.545   1.452   2.073 -0.7854 -0.8985  0.9184
-  175SOL    OW1  703   0.409   1.150   1.927 -0.4094  0.0594  0.2832
-  175SOL    HW2  704   0.446   1.105   2.009  0.3173  2.0924  1.2063
-  175SOL    HW3  705   0.483   1.193   1.877 -0.7977 -1.3774 -1.7446
-  176SOL    OW1  706   1.553   0.319   1.596  1.0173  0.6704  0.6473
-  176SOL    HW2  707   1.622   0.343   1.664 -0.2749 -0.0704  2.3291
-  176SOL    HW3  708   1.566   0.224   1.567 -0.0467  0.0138  2.0999
-  177SOL    OW1  709   0.037   1.562   1.300 -0.1944  0.2660 -0.2755
-  177SOL    HW2  710   0.077   1.590   1.387  1.4003  0.6788 -1.0633
-  177SOL    HW3  711   0.072   1.472   1.274  0.5610  0.7744 -1.1404
-  178SOL    OW1  712   1.912   1.557   1.478 -0.1816  0.0966 -0.3601
-  178SOL    HW2  713   1.984   1.545   1.410  1.1640  1.6529  0.6310
-  178SOL    HW3  714   1.839   1.613   1.439  0.1750  0.2880 -0.7820
-  179SOL    OW1  715   0.594   0.786   0.966 -0.1755 -0.2980 -0.0467
-  179SOL    HW2  716   0.623   0.795   1.062 -0.3751 -1.9217  0.2209
-  179SOL    HW3  717   0.641   0.855   0.911 -0.4262  1.0221  1.2627
-  180SOL    OW1  718   1.061   1.373   0.077  0.2085  0.3349 -0.0397
-  180SOL    HW2  719   1.096   1.375   0.171 -1.4745  0.5354  0.6623
-  180SOL    HW3  720   0.987   1.305   0.071  1.2854 -0.8419 -1.6848
-  181SOL    OW1  721   0.280   1.428   1.894 -0.4383 -0.1926  0.0340
-  181SOL    HW2  722   0.296   1.407   1.991 -1.2069 -2.0656 -0.1646
-  181SOL    HW3  723   0.188   1.465   1.882  0.4019  2.3055  0.1863
-  182SOL    OW1  724   1.551   0.057   1.541  0.6365 -0.1158 -0.1718
-  182SOL    HW2  725   1.482   0.047   1.469 -0.7483  1.2134  0.8578
-  182SOL    HW3  726   1.616  -0.019   1.535 -0.5573 -1.1409 -1.5682
-  183SOL    OW1  727   1.959   1.867   1.885 -0.0742 -0.4716  0.5309
-  183SOL    HW2  728   2.013   1.937   1.839 -2.0839  1.1694  0.3402
-  183SOL    HW3  729   1.966   1.781   1.835  0.4568  0.3251 -0.8702
-  184SOL    OW1  730   1.667   1.932   2.073 -0.0409  0.7001 -0.1997
-  184SOL    HW2  731   1.651   1.862   2.003  0.0770  1.9545 -1.5861
-  184SOL    HW3  732   1.764   1.932   2.099 -0.2911 -0.5783  0.9833
-  185SOL    OW1  733   1.325   0.406   1.488  0.5195  0.1676 -0.3890
-  185SOL    HW2  734   1.277   0.331   1.442  0.0256  1.7667 -2.9259
-  185SOL    HW3  735   1.413   0.373   1.522  0.7108 -1.4512 -2.0854
-  186SOL    OW1  736   0.574   0.779   0.492  0.2239  0.5640  0.0222
-  186SOL    HW2  737   0.565   0.867   0.539 -1.7082 -0.1004  1.1098
-  186SOL    HW3  738   0.566   0.793   0.393 -0.7699  1.5840  0.2103
-  187SOL    OW1  739   1.157   0.248   1.340 -0.1217 -0.3071 -0.5183
-  187SOL    HW2  740   1.193   0.155   1.331  0.2450 -0.3768  1.1698
-  187SOL    HW3  741   1.175   0.298   1.255  2.1698 -0.9637 -0.5707
-  188SOL    OW1  742   0.161   1.794   0.446 -0.8110  0.0841  0.3138
-  188SOL    HW2  743   0.188   1.803   0.542 -2.3818 -0.4592  0.8767
-  188SOL    HW3  744   0.165   1.698   0.418 -1.8121  0.0080  0.3627
-  189SOL    OW1  745   0.349   1.639   1.629  0.0392 -0.1262 -0.1540
-  189SOL    HW2  746   0.274   1.672   1.685 -1.7873  0.8696 -2.8050
-  189SOL    HW3  747   0.315   1.573   1.561  2.3917 -2.6787  0.7377
-  190SOL    OW1  748   1.342   1.284   1.440 -0.2950  0.0562  0.3305
-  190SOL    HW2  749   1.348   1.184   1.438 -0.3939 -0.0530  2.1054
-  190SOL    HW3  750   1.428   1.323   1.406  0.7217 -0.7497  1.7540
-  191SOL    OW1  751   1.406   0.811   0.778  0.6720  0.5929 -0.3196
-  191SOL    HW2  752   1.428   0.904   0.750 -0.4232  0.9320 -0.1214
-  191SOL    HW3  753   1.327   0.812   0.839  0.5703 -0.4798 -0.4004
-  192SOL    OW1  754   0.700   0.994   0.813  1.1074 -0.5002 -0.0158
-  192SOL    HW2  755   0.683   1.092   0.801  1.6522  0.0292  2.4064
-  192SOL    HW3  756   0.732   0.954   0.727 -1.4648  0.7945 -1.8249
-  193SOL    OW1  757   0.782   1.057   2.057  0.0264  0.4447  0.0530
-  193SOL    HW2  758   0.835   1.089   1.978 -1.7843  0.6596 -1.1826
-  193SOL    HW3  759   0.838   1.065   2.140  1.7809  0.8963 -1.0727
-  194SOL    OW1  760   0.479   0.103   2.025 -0.5797  0.6887 -0.2586
-  194SOL    HW2  761   0.462   0.026   2.085 -1.8118  1.1639  0.0553
-  194SOL    HW3  762   0.565   0.148   2.052 -0.5221  0.2113  0.3846
-  195SOL    OW1  763   0.483   2.156   0.036 -0.7147 -0.3670  0.7713
-  195SOL    HW2  764   0.451   2.062   0.042 -1.8879  0.0453  3.3508
-  195SOL    HW3  765   0.405   2.219   0.039  0.0530  0.7570 -0.5180
-  196SOL    OW1  766   1.270   2.306   1.879 -0.5172  0.0068  0.1912
-  196SOL    HW2  767   1.273   2.404   1.862  1.8605  0.0045 -0.0624
-  196SOL    HW3  768   1.290   2.256   1.795 -0.0143 -0.5746  0.6314
-  197SOL    OW1  769   2.012   1.085   0.463  0.8652  0.0841  0.1395
-  197SOL    HW2  770   1.953   1.154   0.504  0.1023 -0.7188  0.4400
-  197SOL    HW3  771   2.069   1.044   0.535  0.9856  0.0826  0.0405
-  198SOL    OW1  772   1.573   0.603   1.741  0.4222 -0.1978 -0.4899
-  198SOL    HW2  773   1.477   0.575   1.743 -0.6547  2.7477 -0.8728
-  198SOL    HW3  774   1.628   0.539   1.795 -2.2080 -0.6903  2.1344
-  199SOL    OW1  775   0.306   0.556   0.033 -0.2636  0.1231 -0.2672
-  199SOL    HW2  776   0.219   0.582  -0.008 -0.8636 -1.4908 -0.1772
-  199SOL    HW3  777   0.323   0.459   0.016 -0.5286 -0.7489  3.0715
-  200SOL    OW1  778   1.548   0.752   1.015 -0.3507  0.0468  0.5606
-  200SOL    HW2  779   1.537   0.845   1.049 -1.2341  1.7778 -3.3248
-  200SOL    HW3  780   1.518   0.748   0.919  3.1604 -3.3148 -0.9129
-  201SOL    OW1  781   1.891   0.353   0.747 -0.0313  0.1405  0.0081
-  201SOL    HW2  782   1.851   0.308   0.667 -0.6769 -0.4122  0.6093
-  201SOL    HW3  783   1.917   0.283   0.815  1.6864  0.5065 -0.2055
-  202SOL    OW1  784   0.821   0.007   0.837  0.0137  0.2150 -0.0930
-  202SOL    HW2  785   0.838   0.071   0.912 -1.1353  0.4274  0.0132
-  202SOL    HW3  786   0.749  -0.058   0.863  1.0818 -1.1099 -0.2309
-  203SOL    OW1  787   0.681   0.330   1.850  0.3431  0.3624 -0.8161
-  203SOL    HW2  788   0.718   0.300   1.938  2.1497  0.6528 -1.3927
-  203SOL    HW3  789   0.670   0.429   1.850  0.2084  0.3459 -0.8702
-  204SOL    OW1  790   0.673   2.091   0.806  0.2248 -0.2273 -0.5970
-  204SOL    HW2  791   0.590   2.121   0.853 -0.7719 -2.4140 -0.7221
-  204SOL    HW3  792   0.650   2.056   0.716  1.9138  2.5751 -2.4408
-  205SOL    OW1  793   1.862   0.180   1.515 -0.4790  0.1718 -0.4126
-  205SOL    HW2  794   1.851   0.274   1.545 -1.7644 -0.4605  1.4924
-  205SOL    HW3  795   1.845   0.118   1.592  2.7467 -1.6806 -0.8542
-  206SOL    OW1  796   0.951   0.668   0.372 -0.1340 -0.4240  0.0408
-  206SOL    HW2  797   0.883   0.741   0.374 -0.5862 -0.8339  0.9180
-  206SOL    HW3  798   0.915   0.590   0.321  0.8056  0.3079 -1.9539
-  207SOL    OW1  799   1.855   0.465   1.185 -0.1366  0.1802  0.1627
-  207SOL    HW2  800   1.797   0.478   1.265  1.2033  2.4143  0.9498
-  207SOL    HW3  801   1.801   0.480   1.102 -0.7696  3.0255  0.8675
-  208SOL    OW1  802   1.025   0.291   0.780 -0.4427  0.0834 -0.0165
-  208SOL    HW2  803   1.123   0.291   0.801 -0.1719 -0.5314 -1.1052
-  208SOL    HW3  804   0.976   0.239   0.850  0.5462 -2.7610 -1.1074
-  209SOL    OW1  805   0.075   0.869   1.068 -0.4918  0.1182 -0.4621
-  209SOL    HW2  806   0.174   0.862   1.079 -0.5615  0.4953  0.5608
-  209SOL    HW3  807   0.031   0.789   1.109 -0.7440  1.5214  2.4824
-  210SOL    OW1  808   0.973   2.083   0.945 -0.2425 -0.0130 -0.2203
-  210SOL    HW2  809   1.007   2.086   0.852 -1.4809  1.0332 -0.6997
-  210SOL    HW3  810   0.876   2.058   0.944 -0.6952  1.4488  0.5869
-  211SOL    OW1  811   0.071   0.866   0.577  0.0309  0.2476 -0.2138
-  211SOL    HW2  812   0.061   0.891   0.673  0.1544  0.8086 -0.3413
-  211SOL    HW3  813   0.155   0.813   0.565  0.6085  1.1184 -0.1728
-  212SOL    OW1  814   1.254   1.404   0.609 -0.1379  0.3185  0.4844
-  212SOL    HW2  815   1.342   1.390   0.656  0.2736  2.7504  0.6997
-  212SOL    HW3  816   1.240   1.331   0.543  2.9310  0.5347 -0.7532
-  213SOL    OW1  817   0.171   0.519   0.496 -0.5668 -0.0275 -0.1699
-  213SOL    HW2  818   0.245   0.586   0.504 -0.6710 -0.0120  0.9302
-  213SOL    HW3  819   0.203   0.430   0.526 -0.6857 -0.2829 -0.7839
-  214SOL    OW1  820   0.054   0.419   1.992 -0.2565  0.6495  0.4681
-  214SOL    HW2  821   0.132   0.362   2.018 -0.8265 -0.2158  0.3569
-  214SOL    HW3  822   0.036   0.486   2.064  1.0840  1.4419  0.1290
-  215SOL    OW1  823   1.875   1.101   1.344 -0.1734  0.1442 -0.3170
-  215SOL    HW2  824   1.896   1.188   1.390  1.5403  0.2351 -1.1023
-  215SOL    HW3  825   1.960   1.058   1.315 -0.9986 -1.6428 -0.3130
-  216SOL    OW1  826   1.980   0.286   1.822  0.1199 -0.6894  0.2519
-  216SOL    HW2  827   2.037   0.335   1.888  1.1110 -1.4020 -0.0213
-  216SOL    HW3  828   1.950   0.199   1.862 -1.1443 -0.1610  0.5285
-  217SOL    OW1  829   1.035   0.421   0.541 -0.2447 -0.4423  0.2604
-  217SOL    HW2  830   0.948   0.410   0.492  0.2421 -0.1260 -0.7443
-  217SOL    HW3  831   1.020   0.416   0.639 -1.3084 -0.9486  0.0905
-  218SOL    OW1  832   0.636   2.313   1.715  0.6696  0.0992 -0.3801
-  218SOL    HW2  833   0.726   2.356   1.728  0.3719  1.0585 -1.1632
-  218SOL    HW3  834   0.599   2.285   1.803  1.2241  0.8029  0.1065
-  219SOL    OW1  835   0.662   1.557   0.956  0.1848 -0.3105  0.1038
-  219SOL    HW2  836   0.660   1.565   0.856 -1.6341 -1.8911 -0.0878
-  219SOL    HW3  837   0.674   1.648   0.996 -1.4103  0.7798 -1.5685
-  220SOL    OW1  838   0.924   1.580   0.595  0.1161 -0.1201  0.0291
-  220SOL    HW2  839   0.917   1.640   0.675  1.9956  0.3666 -0.0738
-  220SOL    HW3  840   0.945   1.487   0.624  0.2213 -0.0692  0.1083
-  221SOL    OW1  841   0.670   0.808   1.217 -0.4153 -0.5267  0.4481
-  221SOL    HW2  842   0.625   0.773   1.299 -0.0833  0.4069  1.0660
-  221SOL    HW3  843   0.697   0.904   1.232  0.8835 -0.7403 -0.2501
-  222SOL    OW1  844   0.290   2.336   0.032 -0.1051  0.1941 -0.0143
-  222SOL    HW2  845   0.213   2.358  -0.028 -0.3537  0.5040  0.4109
-  222SOL    HW3  846   0.306   2.412   0.095  0.3015 -0.0309  0.1571
-  223SOL    OW1  847   1.204   1.866   1.069 -0.2716  0.2936 -0.1189
-  223SOL    HW2  848   1.268   1.795   1.041  1.6314  0.6822  2.4322
-  223SOL    HW3  849   1.113   1.844   1.037  0.2868 -2.9379 -0.1334
-  224SOL    OW1  850   0.082   1.210   1.527 -0.2478  0.0411  0.5473
-  224SOL    HW2  851   0.111   1.115   1.536 -0.6224 -0.4289 -1.7677
-  224SOL    HW3  852  -0.014   1.213   1.500  0.3096  0.7544 -1.8928
-  225SOL    OW1  853   1.716   2.156   0.107  0.0955 -0.2612  0.2071
-  225SOL    HW2  854   1.737   2.071   0.059  0.6789 -0.4693  0.8011
-  225SOL    HW3  855   1.628   2.146   0.153 -0.7544  0.1397 -1.2163
-  226SOL    OW1  856   1.728   2.204   1.480  0.6707  0.9221 -0.6426
-  226SOL    HW2  857   1.798   2.140   1.450 -1.4256 -2.0479 -0.0090
-  226SOL    HW3  858   1.643   2.186   1.432 -1.3714 -0.3787  2.7435
-  227SOL    OW1  859   1.288   1.630   0.984  0.2912  0.7037  0.3714
-  227SOL    HW2  860   1.339   1.573   1.048  0.4474 -0.3381 -0.6182
-  227SOL    HW3  861   1.196   1.591   0.971  0.7734 -0.0892 -1.1703
-  228SOL    OW1  862   1.888   1.521   0.509  0.3686 -0.4818  0.7969
-  228SOL    HW2  863   1.946   1.593   0.546  0.4245 -0.8561  1.4505
-  228SOL    HW3  864   1.942   1.462   0.448 -0.0598  1.0559 -1.2976
-  229SOL    OW1  865   1.028   2.242   0.706  0.0044  0.1051  1.1540
-  229SOL    HW2  866   0.965   2.304   0.753  0.8757  1.2016  0.9504
-  229SOL    HW3  867   1.121   2.280   0.709  0.2929 -0.3330 -0.4763
-  230SOL    OW1  868   1.312   0.799   1.575 -0.1011 -0.0488  0.2992
-  230SOL    HW2  869   1.254   0.749   1.511  0.3609 -0.1725 -0.0320
-  230SOL    HW3  870   1.276   0.790   1.668 -0.3965 -0.4381  0.1474
-  231SOL    OW1  871   1.746   0.569   0.062  0.4210 -0.1202  0.0070
-  231SOL    HW2  872   1.805   0.636   0.016 -1.4151  0.5003 -1.6923
-  231SOL    HW3  873   1.679   0.617   0.119 -0.2112 -0.5618 -0.3518
-  232SOL    OW1  874   2.073   0.782   1.995  0.0843  0.0517 -0.1017
-  232SOL    HW2  875   1.991   0.738   1.959 -0.3056  1.9441 -1.8699
-  232SOL    HW3  876   2.148   0.774   1.929  0.7683 -0.0164  0.6422
-  233SOL    OW1  877   0.145   1.795   1.990  0.0074 -0.7360 -0.1482
-  233SOL    HW2  878   0.189   1.883   2.004  2.2483 -1.7433  0.0662
-  233SOL    HW3  879   0.149   1.771   1.893 -0.3146 -0.7461 -0.1601
-  234SOL    OW1  880   0.306   0.740   0.560 -0.7314 -0.3855 -0.1185
-  234SOL    HW2  881   0.396   0.771   0.532 -1.1278  0.3944 -0.5830
-  234SOL    HW3  882   0.309   0.708   0.655  0.2000 -1.1864 -0.3855
-  235SOL    OW1  883   1.691   1.974   1.258 -0.1993 -0.5744  0.4667
-  235SOL    HW2  884   1.670   2.072   1.255  0.4307 -0.4199  0.8810
-  235SOL    HW3  885   1.638   1.926   1.189  0.9434  0.3275 -1.1500
-  236SOL    OW1  886   0.768   1.417   2.026 -0.3987 -0.3774  0.1575
-  236SOL    HW2  887   0.765   1.515   2.004  1.8007  0.1508  1.5372
-  236SOL    HW3  888   0.752   1.404   2.124 -0.9178 -1.4810 -0.0406
-  237SOL    OW1  889   1.132   2.031   1.679 -0.1771  0.1142  0.4719
-  237SOL    HW2  890   1.071   2.110   1.685  1.2946  1.5635 -1.2060
-  237SOL    HW3  891   1.227   2.062   1.678  0.4766 -1.4880 -1.3818
-  238SOL    OW1  892   1.575   1.419   1.385  0.2252 -0.1345 -0.5253
-  238SOL    HW2  893   1.595   1.459   1.475 -1.0329 -0.9650  0.1845
-  238SOL    HW3  894   1.625   1.469   1.315 -0.1451  1.7640  0.4296
-  239SOL    OW1  895   0.187   1.030   1.804  0.5710  0.0737  0.3446
-  239SOL    HW2  896   0.196   0.938   1.844  3.7927 -0.2552 -0.5535
-  239SOL    HW3  897   0.262   1.087   1.836 -0.3818  1.9029 -0.4304
-  240SOL    OW1  898   1.367   1.145   0.130  0.3495  0.1779  0.5064
-  240SOL    HW2  899   1.424   1.067   0.102 -0.1970 -0.1735  0.3571
-  240SOL    HW3  900   1.272   1.115   0.139  0.0773  0.9017  0.1382
-  241SOL    OW1  901   0.849   0.869   0.627 -0.1383  0.1409 -0.1084
-  241SOL    HW2  902   0.815   0.843   0.537 -0.8143 -0.4992  0.3196
-  241SOL    HW3  903   0.918   0.804   0.657  0.6518  0.7761 -0.4582
-  242SOL    OW1  904   1.148   0.629   2.129  0.4786  0.0085 -0.4960
-  242SOL    HW2  905   1.168   0.619   2.227 -0.4466  2.4357  0.0761
-  242SOL    HW3  906   1.234   0.639   2.079  1.1018 -2.8530 -0.3584
-  243SOL    OW1  907   0.952   1.112   1.286 -0.4415 -0.0059  0.1264
-  243SOL    HW2  908   1.042   1.128   1.327 -0.6071 -0.1923  0.5738
-  243SOL    HW3  909   0.907   1.200   1.269 -0.2001  0.0836 -0.0399
-  244SOL    OW1  910   0.281   0.290   2.104  0.0501  0.3815 -0.1521
-  244SOL    HW2  911   0.194   0.239   2.104 -1.1389  2.0368 -2.3656
-  244SOL    HW3  912   0.357   0.226   2.090 -1.1216 -0.9652 -0.8991
-  245SOL    OW1  913   1.217   0.909   0.461  0.3312  0.5867  0.2410
-  245SOL    HW2  914   1.312   0.881   0.446 -0.1797 -0.8132 -0.7712
-  245SOL    HW3  915   1.171   0.842   0.520 -0.6846 -0.3719 -1.4855
-  246SOL    OW1  916   0.898   0.960   1.780 -0.5373 -0.3096  0.5417
-  246SOL    HW2  917   0.938   0.901   1.850  1.8625  0.5291  0.0831
-  246SOL    HW3  918   0.964   1.032   1.756 -2.4532  1.3284 -0.4047
-  247SOL    OW1  919   1.525   1.923   1.515  0.0699  0.1041 -0.2481
-  247SOL    HW2  920   1.465   1.883   1.585  1.4862 -1.6207  0.1276
-  247SOL    HW3  921   1.513   1.874   1.429 -0.3507  0.9938 -0.7101
-  248SOL    OW1  922   0.270   0.617   1.118 -0.3647 -1.1497  0.2467
-  248SOL    HW2  923   0.214   0.594   1.039 -0.7250 -0.8062  0.3991
-  248SOL    HW3  924   0.299   0.713   1.112 -1.0109 -0.8966  0.8855
-  249SOL    OW1  925   1.180   0.774   0.944  0.1336 -0.0263 -0.2162
-  249SOL    HW2  926   1.216   0.734   1.028  0.0027  1.3557  0.5630
-  249SOL    HW3  927   1.082   0.791   0.954  0.2877  0.9889 -0.2536
-  250SOL    OW1  928   0.956   0.605   0.786  0.1068  0.1774 -0.0797
-  250SOL    HW2  929   0.893   0.579   0.713  2.7508 -1.1156 -2.3083
-  250SOL    HW3  930   0.937   0.552   0.868 -0.1445 -2.3430 -1.5557
-  251SOL    OW1  931   1.015   0.857   2.015  0.2381  0.3067  0.0365
-  251SOL    HW2  932   1.111   0.886   2.012  0.3099  0.0505 -0.9465
-  251SOL    HW3  933   0.988   0.839   2.109  1.1194  0.4981  0.3437
-  252SOL    OW1  934   1.332   1.631   1.675  0.5109  0.1798 -0.1515
-  252SOL    HW2  935   1.260   1.689   1.713 -0.2704  1.1089 -2.6244
-  252SOL    HW3  936   1.306   1.602   1.583  1.9034 -2.3392  0.0916
-  253SOL    OW1  937   0.755   1.229   0.545  0.1632  0.3442 -0.0762
-  253SOL    HW2  938   0.729   1.304   0.485  0.6018  0.9426  0.4554
-  253SOL    HW3  939   0.723   1.247   0.638  1.0571  0.3399  0.2595
-  254SOL    OW1  940   1.717   1.138   0.057 -0.4038 -0.2375  0.6024
-  254SOL    HW2  941   1.643   1.203   0.040  0.0313  0.1766  0.2458
-  254SOL    HW3  942   1.787   1.147  -0.015  1.1147  0.9823  2.0727
-  255SOL    OW1  943   1.009   0.851   1.176  0.2001 -0.2090  0.5317
-  255SOL    HW2  944   0.949   0.846   1.097  0.2459 -0.9283  0.5300
-  255SOL    HW3  945   1.032   0.947   1.194 -2.1474  0.3118  1.4502
-  256SOL    OW1  946   1.814   0.776   1.037  0.6002  0.0790  0.3822
-  256SOL    HW2  947   1.851   0.764   0.945  0.0460 -1.9432  0.3141
-  256SOL    HW3  948   1.714   0.771   1.034  0.3496  2.4510  0.9071
-  257SOL    OW1  949   0.858   0.172   0.615 -0.0079 -0.5948 -0.5931
-  257SOL    HW2  950   0.838   0.116   0.696 -0.5116 -0.8031 -0.8554
-  257SOL    HW3  951   0.944   0.220   0.629  0.1991 -1.0708 -0.1686
-  258SOL    OW1  952   2.030   1.032   1.701  0.4107  0.0500 -0.1015
-  258SOL    HW2  953   1.985   1.119   1.720  0.9095  0.3886 -0.4316
-  258SOL    HW3  954   2.126   1.036   1.729  0.9627  0.2973 -1.7729
-  259SOL    OW1  955   1.892   2.216   2.085  0.1296 -0.3379 -0.1510
-  259SOL    HW2  956   1.811   2.228   2.143  0.0083 -0.0105 -0.3835
-  259SOL    HW3  957   1.925   2.122   2.093 -0.3881 -0.5293 -0.2002
-  260SOL    OW1  958   1.785   0.924   0.562 -0.2890 -0.3779  0.5556
-  260SOL    HW2  959   1.843   0.853   0.602 -0.5468 -2.1529 -1.8082
-  260SOL    HW3  960   1.690   0.910   0.591 -0.0634  0.7309  2.0991
-  261SOL    OW1  961   1.921   2.304   1.685  0.1364  0.1818  0.4606
-  261SOL    HW2  962   1.999   2.262   1.638 -0.7556  1.4247 -2.6679
-  261SOL    HW3  963   1.837   2.256   1.659 -0.4812  1.3711  0.1019
-  262SOL    OW1  964   1.614   1.565   0.832  0.3797 -0.1073 -0.1023
-  262SOL    HW2  965   1.545   1.505   0.791 -1.1622 -1.4172  3.5048
-  262SOL    HW3  966   1.579   1.658   0.837  1.1102  0.3990 -2.3274
-  263SOL    OW1  967   1.497   1.353   0.704  0.1611 -0.1069  0.2288
-  263SOL    HW2  968   1.481   1.255   0.710 -2.6445  0.1620 -0.3910
-  263SOL    HW3  969   1.562   1.372   0.631 -0.0032 -1.4578 -0.3207
-  264SOL    OW1  970   1.875   1.644   0.849 -0.0714 -0.2426  0.0902
-  264SOL    HW2  971   1.906   1.657   0.943 -1.4938 -0.9485  0.7244
-  264SOL    HW3  972   1.786   1.598   0.850 -0.2811  0.0158 -1.6070
-  265SOL    OW1  973   1.064   2.086   2.142 -0.1044 -0.0325 -0.3753
-  265SOL    HW2  974   0.992   2.017   2.135  0.6492 -0.9878  0.6409
-  265SOL    HW3  975   1.023   2.177   2.148 -1.3739 -0.6155  1.5909
-  266SOL    OW1  976   0.046   2.187   1.980 -0.5149 -0.6850 -0.8837
-  266SOL    HW2  977   0.089   2.277   1.969 -1.1191 -0.4309 -1.1820
-  266SOL    HW3  978  -0.052   2.198   1.998 -0.4258 -1.2500  0.1065
-  267SOL    OW1  979   0.191   0.739   1.808  0.5220  0.2734 -0.0164
-  267SOL    HW2  980   0.152   0.663   1.756 -0.0782  0.3818  0.2702
-  267SOL    HW3  981   0.290   0.741   1.794  0.4638 -0.1609 -0.5463
-  268SOL    OW1  982   0.726   1.673   1.932  0.0207  0.0549 -0.1509
-  268SOL    HW2  983   0.769   1.622   1.858 -0.8982  0.1103 -0.7589
-  268SOL    HW3  984   0.636   1.705   1.902 -0.9405 -0.9577  1.3718
-  269SOL    OW1  985   1.972   2.141   1.330 -0.4534  0.1086  0.0010
-  269SOL    HW2  986   2.025   2.077   1.275 -0.8246 -0.3034  0.1138
-  269SOL    HW3  987   1.948   2.221   1.275 -0.6252 -0.1976 -0.3688
-  270SOL    OW1  988   1.658   1.117   1.528  0.2607 -0.5341 -0.0100
-  270SOL    HW2  989   1.730   1.101   1.460  0.4751 -0.3352  0.1681
-  270SOL    HW3  990   1.645   1.033   1.582 -0.6765 -1.0626 -0.9830
-  271SOL    OW1  991   1.119   1.542   2.054  0.0234 -0.3990 -0.3820
-  271SOL    HW2  992   1.210   1.561   2.091 -0.0331 -1.2025  0.2400
-  271SOL    HW3  993   1.075   1.471   2.110 -0.2812 -1.3285 -1.7155
-  272SOL    OW1  994   1.237   1.275   2.048 -0.5531  0.0225 -0.1349
-  272SOL    HW2  995   1.171   1.285   2.123 -1.7612 -1.3556 -0.8992
-  272SOL    HW3  996   1.208   1.332   1.971  0.4170  1.0569  0.2158
-  273SOL    OW1  997   0.540   0.171   1.038  0.3354 -0.6817 -0.0134
-  273SOL    HW2  998   0.520   0.245   1.102 -0.5285 -1.4808  0.6939
-  273SOL    HW3  999   0.467   0.103   1.041  0.7022 -1.1941 -1.2252
-  274SOL    OW1 1000   0.975   1.311   0.726  0.5964 -0.2290 -0.3184
-  274SOL    HW2 1001   1.025   1.358   0.799 -0.2221  0.1840  0.0004
-  274SOL    HW3 1002   0.976   1.213   0.743 -2.4172 -0.1446  2.3673
-  275SOL    OW1 1003   0.953   0.519   1.954  0.4663  0.0117  0.4285
-  275SOL    HW2 1004   1.018   0.584   1.994  1.3126 -0.4641 -0.1157
-  275SOL    HW3 1005   0.883   0.570   1.903  1.4991  0.5361 -0.5644
-  276SOL    OW1 1006   0.419   0.711   0.228 -0.4438 -0.1473 -0.3698
-  276SOL    HW2 1007   0.394   0.651   0.151 -0.2649  0.1585 -0.6684
-  276SOL    HW3 1008   0.347   0.778   0.243 -0.5010 -0.2414 -0.2350
-  277SOL    OW1 1009   1.116   1.454   1.805  0.1103  0.1292 -0.3284
-  277SOL    HW2 1010   1.024   1.448   1.764 -0.4522  0.3372  0.8395
-  277SOL    HW3 1011   1.111   1.504   1.891  0.9079 -1.6825  0.8948
-  278SOL    OW1 1012   1.584   1.639   1.607 -0.5431 -0.0793  0.1061
-  278SOL    HW2 1013   1.622   1.556   1.648  1.0321  0.2578 -0.5482
-  278SOL    HW3 1014   1.488   1.649   1.635 -0.7532 -2.0017  0.3451
-  279SOL    OW1 1015   0.954   2.046   0.262  0.4970 -0.1102 -0.0130
-  279SOL    HW2 1016   0.970   1.953   0.294  1.0066 -0.3130 -0.7977
-  279SOL    HW3 1017   1.029   2.105   0.291 -0.3206  0.3302  1.3667
-  280SOL    OW1 1018   1.693   0.757   2.013 -0.0274  0.1625  0.1846
-  280SOL    HW2 1019   1.595   0.736   2.020  0.0519 -1.0072 -1.2800
-  280SOL    HW3 1020   1.706   0.853   1.989 -0.6645  0.8550  2.1968
-  281SOL    OW1 1021   0.913   0.814   0.072  0.2924  0.0487  0.6119
-  281SOL    HW2 1022   0.976   0.829   0.148  0.2435  2.2686  0.3178
-  281SOL    HW3 1023   0.824   0.786   0.108  0.6651 -0.3940  1.2279
-  282SOL    OW1 1024   1.917   1.960   2.147 -0.3048 -0.5074  0.0672
-  282SOL    HW2 1025   1.968   1.925   2.067 -0.2317  0.6001 -0.4022
-  282SOL    HW3 1026   1.958   1.923   2.230  0.6829 -0.4139 -0.3422
-  283SOL    OW1 1027   0.933   1.247   1.896  0.7904 -0.1360  0.0571
-  283SOL    HW2 1028   0.899   1.240   1.802  1.2532 -0.2693 -0.0993
-  283SOL    HW3 1029   0.877   1.312   1.947  0.0390 -0.6455 -0.0867
-  284SOL    OW1 1030   1.075   0.276   1.941 -0.0296  0.2682 -0.0047
-  284SOL    HW2 1031   1.167   0.267   1.904  0.6220  1.1655  1.2566
-  284SOL    HW3 1032   1.044   0.370   1.933  0.8334  0.9939  2.8727
-  285SOL    OW1 1033   1.984   1.681   1.095 -0.3031 -0.2150 -0.3904
-  285SOL    HW2 1034   1.964   1.778   1.109  0.1490 -0.1971  0.1779
-  285SOL    HW3 1035   2.032   1.645   1.175  2.9218  0.0086 -1.9199
-  286SOL    OW1 1036   0.416   1.972   0.721  0.0236 -0.8542  0.4856
-  286SOL    HW2 1037   0.406   1.990   0.819  1.3393  1.0164  0.3743
-  286SOL    HW3 1038   0.367   2.042   0.669  1.2748 -0.3758 -0.1153
-  287SOL    OW1 1039   1.455   2.162   1.404  0.0789 -0.3076 -0.2559
-  287SOL    HW2 1040   1.405   2.132   1.323 -1.0966 -0.2658  0.4090
-  287SOL    HW3 1041   1.473   2.083   1.463 -1.2460 -0.0461  0.5554
-  288SOL    OW1 1042   0.259   2.155   0.589  0.1260  0.6444 -0.0772
-  288SOL    HW2 1043   0.164   2.123   0.585  0.0568  0.9313 -1.6776
-  288SOL    HW3 1044   0.311   2.116   0.514  1.3130  0.4927  0.7763
-  289SOL    OW1 1045   1.280   0.215   1.748  1.0047 -0.5879 -0.8177
-  289SOL    HW2 1046   1.344   0.215   1.671  0.5260 -0.0547 -1.2353
-  289SOL    HW3 1047   1.187   0.229   1.714  0.9365  1.5047 -0.0661
-  290SOL    OW1 1048   1.978   2.189   1.060 -0.1456 -0.1797  0.0410
-  290SOL    HW2 1049   1.975   2.198   0.961 -1.3919  1.5237  0.1591
-  290SOL    HW3 1050   2.055   2.241   1.097 -0.4933  0.3586  0.0212
-  291SOL    OW1 1051   1.256   2.020   0.851 -0.0820  0.2327  0.2151
-  291SOL    HW2 1052   1.175   1.994   0.797 -0.8015  1.1566  0.8055
-  291SOL    HW3 1053   1.257   1.969   0.937 -0.2796  0.5172  0.3853
-  292SOL    OW1 1054   1.644   2.238   1.203  0.2588  0.3076 -0.6026
-  292SOL    HW2 1055   1.650   2.216   1.105  2.4804  0.2945 -0.5715
-  292SOL    HW3 1056   1.679   2.331   1.218  0.1668  0.2244  0.1896
-  293SOL    OW1 1057   1.247   0.201   0.937 -0.5878 -0.0681  0.1382
-  293SOL    HW2 1058   1.222   0.282   0.989 -0.0725  0.1658  0.0337
-  293SOL    HW3 1059   1.347   0.197   0.927 -0.6251  1.4574 -3.1918
-  294SOL    OW1 1060   1.140   0.958   0.211 -0.0049  0.3410  0.1559
-  294SOL    HW2 1061   1.168   0.956   0.307  2.8205 -0.9272 -0.5224
-  294SOL    HW3 1062   1.183   0.884   0.161  0.8471  2.3716 -2.6039
-  295SOL    OW1 1063   0.889   2.106   0.513  0.9659 -0.5531  0.6999
-  295SOL    HW2 1064   0.936   2.115   0.426 -0.0005 -0.2868  0.1832
-  295SOL    HW3 1065   0.942   2.151   0.585  1.4576 -0.2157  0.1344
-  296SOL    OW1 1066   0.029   2.026   1.765 -0.4433 -0.5379  0.6112
-  296SOL    HW2 1067   0.018   2.077   1.680 -0.8408 -2.1014 -0.3715
-  296SOL    HW3 1068   0.045   2.089   1.841 -1.3062  1.0111 -0.3955
-  297SOL    OW1 1069   1.267   0.057   0.709  0.9387 -0.3073 -0.4524
-  297SOL    HW2 1070   1.362   0.043   0.680  1.1152  2.0742 -1.4971
-  297SOL    HW3 1071   1.265   0.124   0.783  0.1184  1.6341 -2.0669
-  298SOL    OW1 1072   1.259   1.929   2.044  0.2442  0.1771  0.3725
-  298SOL    HW2 1073   1.297   2.021   2.039 -1.0129  0.7674  0.8496
-  298SOL    HW3 1074   1.161   1.934   2.065 -0.0393 -1.2573 -0.3601
-  299SOL    OW1 1075   2.023   1.721   0.640  0.2865 -0.5265 -0.7926
-  299SOL    HW2 1076   2.120   1.705   0.656  0.1931 -3.3458 -1.8557
-  299SOL    HW3 1077   1.973   1.717   0.726  1.0495  3.6657  0.2647
-  300SOL    OW1 1078   0.380   0.947   1.335  0.8461  0.7453 -0.0901
-  300SOL    HW2 1079   0.357   0.870   1.394 -0.4477 -0.4841 -1.9476
-  300SOL    HW3 1080   0.427   1.017   1.387  0.8912 -0.7010  2.0392
-  301SOL    OW1 1081   1.918   1.646   1.739 -0.0535  0.6170  0.5572
-  301SOL    HW2 1082   1.830   1.671   1.778 -0.9732 -1.5312  0.1268
-  301SOL    HW3 1083   1.909   1.632   1.640  0.0305 -1.8481  0.7779
-  302SOL    OW1 1084   0.048   1.813   1.462  0.0335  0.0653 -0.1951
-  302SOL    HW2 1085   0.077   1.861   1.379 -1.0583  1.3938  0.1101
-  302SOL    HW3 1086  -0.045   1.842   1.486  0.3382 -0.1826  1.5425
-  303SOL    OW1 1087   0.596   1.425   0.458 -0.1987  0.2503 -0.1817
-  303SOL    HW2 1088   0.619   1.522   0.444 -1.0996  0.5916  0.5457
-  303SOL    HW3 1089   0.558   1.387   0.373  0.0408  0.5640 -0.4296
-  304SOL    OW1 1090   1.563   0.140   1.927  0.3645 -0.0913  0.0944
-  304SOL    HW2 1091   1.571   0.089   1.841 -1.5264 -1.2190  0.4652
-  304SOL    HW3 1092   1.546   0.076   2.002  0.3737  0.9595  1.0419
-  305SOL    OW1 1093   0.067   2.267   0.764 -0.0999  0.4859 -0.1641
-  305SOL    HW2 1094   0.124   2.219   0.830  0.9073  0.0300 -1.2879
-  305SOL    HW3 1095   0.118   2.281   0.679 -1.4279  0.7244 -0.9909
-  306SOL    OW1 1096   0.801   0.203   0.190  0.6493  0.1668  0.4170
-  306SOL    HW2 1097   0.832   0.108   0.194 -1.1922 -0.6337 -0.9809
-  306SOL    HW3 1098   0.869   0.258   0.142  0.5212 -1.2523 -1.6849
-  307SOL    OW1 1099   0.533   1.887   2.128  0.0226  0.6627 -0.2580
-  307SOL    HW2 1100   0.470   1.852   2.058 -2.4602 -0.7732  2.2595
-  307SOL    HW3 1101   0.585   1.812   2.166 -2.3913  0.0245  2.4930
-  308SOL    OW1 1102   0.528   1.412   1.632 -0.8352 -0.0469  0.5465
-  308SOL    HW2 1103   0.443   1.360   1.624 -1.3150  0.7869 -0.2050
-  308SOL    HW3 1104   0.506   1.508   1.653 -0.0500  0.0908  0.8007
-  309SOL    OW1 1105   1.381   0.093   1.233 -0.0587  0.1976  0.4752
-  309SOL    HW2 1106   1.412   0.001   1.208 -0.7652  0.5636 -2.5755
-  309SOL    HW3 1107   1.446   0.161   1.199 -0.2696  0.8705  1.3496
-  310SOL    OW1 1108   0.770   0.169   2.070  0.4545  0.5678  0.6666
-  310SOL    HW2 1109   0.753   0.071   2.060 -0.4028  0.8212 -1.8942
-  310SOL    HW3 1110   0.754   0.196   2.165  0.4253 -1.6691  1.4204
-  311SOL    OW1 1111   1.454   1.409   1.046  0.5445  0.2513 -0.0296
-  311SOL    HW2 1112   1.469   1.320   1.002  1.2183  1.0000 -1.4346
-  311SOL    HW3 1113   1.541   1.445   1.077  0.3879  0.7344 -0.1447
-  312SOL    OW1 1114   0.085   2.006   1.239 -0.1167 -0.4359  0.1726
-  312SOL    HW2 1115   0.133   1.923   1.211  1.4401 -0.0054  1.2985
-  312SOL    HW3 1116   0.140   2.086   1.215 -0.6655  0.1501  0.7875
-  313SOL    OW1 1117   1.461   2.105   2.033 -0.1383  0.4784  0.0319
-  313SOL    HW2 1118   1.478   2.186   2.089 -0.2246 -0.4473  1.5216
-  313SOL    HW3 1119   1.535   2.039   2.047 -0.2618  0.1197 -0.8496
-  314SOL    OW1 1120   0.340   1.308   0.799  0.9160 -0.1565 -0.2207
-  314SOL    HW2 1121   0.411   1.241   0.777  2.2208  0.4793  1.5386
-  314SOL    HW3 1122   0.348   1.387   0.739  1.9791  0.0400  0.1429
-  315SOL    OW1 1123   0.929   2.151   1.222 -0.5944  0.1197  0.1351
-  315SOL    HW2 1124   0.895   2.230   1.172  0.0852  0.3808  0.0725
-  315SOL    HW3 1125   0.964   2.083   1.157 -1.1072 -0.2027  0.1943
-  316SOL    OW1 1126   2.100   0.948   1.315  0.4221  0.4586 -0.4373
-  316SOL    HW2 1127   2.064   0.871   1.262 -1.7043  1.3522 -0.4889
-  316SOL    HW3 1128   2.126   0.916   1.406  0.0188 -0.4015 -0.6065
-  317SOL    OW1 1129   1.145   1.038   1.546 -0.1093  0.2955  0.0122
-  317SOL    HW2 1130   1.158   1.023   1.644 -2.2044 -2.3553  0.1003
-  317SOL    HW3 1131   1.224   1.002   1.496  1.4082  2.4793  0.5554
-  318SOL    OW1 1132   1.912   1.296   1.526  0.3522 -0.3134 -0.1810
-  318SOL    HW2 1133   1.885   1.282   1.622 -3.2052 -0.1144 -0.8638
-  318SOL    HW3 1134   1.911   1.394   1.506  1.9986 -0.2848 -0.3211
-  319SOL    OW1 1135   1.384   0.628   0.446  0.4008 -0.0933 -0.1623
-  319SOL    HW2 1136   1.420   0.534   0.445 -0.5526 -0.4827 -0.8141
-  319SOL    HW3 1137   1.301   0.631   0.502  0.8043  0.5429  0.4324
-  320SOL    OW1 1138   0.858   0.558   0.090 -0.0122  0.1778 -0.0083
-  320SOL    HW2 1139   0.911   0.635   0.054 -0.1280 -0.5815 -2.0910
-  320SOL    HW3 1140   0.781   0.540   0.029 -2.1907  0.5699  2.3116
-  321SOL    OW1 1141   1.860   0.831   0.254  0.7899  0.0549 -0.0619
-  321SOL    HW2 1142   1.916   0.882   0.189 -0.3759  0.1824 -1.0219
-  321SOL    HW3 1143   1.808   0.895   0.311 -0.3971  0.0190 -1.0279
-  322SOL    OW1 1144   1.844   1.229   1.776  0.1141  0.0489  0.6993
-  322SOL    HW2 1145   1.774   1.287   1.735  1.1835  1.2181  0.4048
-  322SOL    HW3 1146   1.848   1.247   1.874  0.2519  0.2844  0.6511
-  323SOL    OW1 1147   1.233   1.411   0.296  0.2309 -0.1874  0.3203
-  323SOL    HW2 1148   1.299   1.439   0.227 -0.6722  0.2931 -0.3849
-  323SOL    HW3 1149   1.221   1.485   0.362 -0.9687  0.5342 -0.6407
-  324SOL    OW1 1150   1.129   1.788   1.779 -0.6566  0.2734 -0.6771
-  324SOL    HW2 1151   1.123   1.876   1.733  1.2428  0.8152 -0.0582
-  324SOL    HW3 1152   1.104   1.799   1.876  1.1301  0.6399 -0.1725
-  325SOL    OW1 1153   0.737   0.026   1.221  0.0077  0.0778 -0.5632
-  325SOL    HW2 1154   0.673   0.091   1.181  1.6127  2.0068 -0.3141
-  325SOL    HW3 1155   0.784   0.069   1.298  2.2379 -0.7853 -1.2836
-  326SOL    OW1 1156   1.509   1.796   0.775 -0.2051  0.1182 -0.1425
-  326SOL    HW2 1157   1.480   1.891   0.789 -1.8179  0.0203 -2.0527
-  326SOL    HW3 1158   1.582   1.793   0.708  0.2218 -0.0019  0.3159
-  327SOL    OW1 1159   0.027   0.580   0.031  0.2837 -0.1428 -0.4424
-  327SOL    HW2 1160   0.086   0.601   0.109  0.7012 -0.5373 -0.6436
-  327SOL    HW3 1161   0.013   0.663  -0.023  2.3162 -0.3566 -1.4869
-  328SOL    OW1 1162   1.185   0.507   1.761  0.2547  0.1429  0.4548
-  328SOL    HW2 1163   1.221   0.488   1.670  0.7551  4.0340 -0.5010
-  328SOL    HW3 1164   1.086   0.494   1.760  0.4541 -2.2470  0.3296
-  329SOL    OW1 1165   0.365   1.621   0.943 -0.7039 -0.0471 -0.5873
-  329SOL    HW2 1166   0.450   1.575   0.916  0.0127  0.8943 -0.0353
-  329SOL    HW3 1167   0.287   1.564   0.915  0.0947 -1.1815 -0.6706
-  330SOL    OW1 1168   1.061   1.884   0.681  0.2105 -0.1813 -0.0737
-  330SOL    HW2 1169   0.965   1.866   0.702  0.0836  0.4474 -0.0774
-  330SOL    HW3 1170   1.118   1.808   0.713 -0.2677 -0.4826  0.0686
-  331SOL    OW1 1171   0.243   2.021   2.082  0.2709 -0.1350  0.3389
-  331SOL    HW2 1172   0.166   2.083   2.064 -0.1299 -0.3362  1.3095
-  331SOL    HW3 1173   0.324   2.054   2.033 -0.2382  0.4884 -0.1123
-  332SOL    OW1 1174   1.919   1.937   1.507  0.2408 -0.0323  0.4649
-  332SOL    HW2 1175   1.850   1.964   1.575 -1.5352 -1.1953 -0.6733
-  332SOL    HW3 1176   1.918   2.001   1.431 -0.4900 -0.6189 -0.0565
-  333SOL    OW1 1177   0.933   1.790   0.355 -0.3352  0.0057 -0.0255
-  333SOL    HW2 1178   0.957   1.756   0.446  1.0694  1.2429  0.1363
-  333SOL    HW3 1179   0.981   1.736   0.286 -0.8918 -0.5180 -0.0161
-  334SOL    OW1 1180   0.800   0.372   0.419  0.0355 -0.1714 -0.0748
-  334SOL    HW2 1181   0.777   0.317   0.339 -0.3391 -0.3275  0.1383
-  334SOL    HW3 1182   0.794   0.315   0.502  0.3118  0.0168  0.0759
-  335SOL    OW1 1183   1.512   1.331   2.115  0.0868  0.4288 -0.8723
-  335SOL    HW2 1184   1.521   1.271   2.036  0.4469  1.8393 -1.9765
-  335SOL    HW3 1185   1.418   1.329   2.148  0.1779 -1.0321 -0.5578
-  336SOL    OW1 1186   0.727   1.843   0.989  0.3361  0.5755 -0.0955
-  336SOL    HW2 1187   0.719   1.929   1.039  2.1985  2.5596 -2.6490
-  336SOL    HW3 1188   0.716   1.861   0.891  4.2448 -1.1747 -1.2396
-  337SOL    OW1 1189   1.617   2.308   0.699  0.3564  0.1586 -0.2502
-  337SOL    HW2 1190   1.609   2.361   0.615 -2.1644  0.3376 -0.0496
-  337SOL    HW3 1191   1.595   2.212   0.680  0.1679  0.1249  0.1341
-  338SOL    OW1 1192   0.339   0.164   0.237  0.2883  0.5473 -0.0562
-  338SOL    HW2 1193   0.260   0.183   0.295 -1.2717 -1.9668 -1.0349
-  338SOL    HW3 1194   0.397   0.095   0.281 -0.2030 -0.4120 -0.8363
-  339SOL    OW1 1195   0.631   1.006   1.788 -0.3762 -0.1030 -0.1886
-  339SOL    HW2 1196   0.713   0.950   1.788 -0.7522 -1.0567  3.2108
-  339SOL    HW3 1197   0.656   1.102   1.802  0.1590 -0.1925 -0.5066
-  340SOL    OW1 1198   1.618   1.446   0.483 -0.6540  0.2783  0.2438
-  340SOL    HW2 1199   1.714   1.457   0.459 -1.0449 -0.5335 -2.3743
-  340SOL    HW3 1200   1.563   1.516   0.436 -1.5434 -1.6326 -2.0173
-  341SOL    OW1 1201   1.395   1.785   1.314 -0.6522 -0.0111 -1.1168
-  341SOL    HW2 1202   1.323   1.848   1.340  1.6876  2.0763  1.6400
-  341SOL    HW3 1203   1.371   1.692   1.344 -1.8450  0.7648  0.6598
-  342SOL    OW1 1204   1.964   0.913   0.014 -0.3584 -0.0188  0.4452
-  342SOL    HW2 1205   1.867   0.937   0.004 -0.8084 -1.4691  0.9152
-  342SOL    HW3 1206   1.995   0.864  -0.068 -0.4902 -0.8971  0.9007
-  343SOL    OW1 1207   0.623   1.073   1.228 -0.2576  0.2708  0.0802
-  343SOL    HW2 1208   0.532   1.102   1.199 -0.4763  1.7749  1.8722
-  343SOL    HW3 1209   0.636   1.095   1.325  2.0537  0.2199 -0.1018
-  344SOL    OW1 1210   0.045   1.543   2.087  0.0121  0.4452  0.1073
-  344SOL    HW2 1211   0.096   1.484   2.149  0.3859 -0.4229 -0.9643
-  344SOL    HW3 1212   0.087   1.634   2.085  1.2304 -0.0871 -0.3117
-  345SOL    OW1 1213   2.076   1.812   0.142  0.2289  0.2330  0.1957
-  345SOL    HW2 1214   2.051   1.804   0.239 -2.0749 -0.9232 -0.3680
-  345SOL    HW3 1215   2.171   1.844   0.135  0.5722  0.2072  2.7961
-  346SOL    OW1 1216   0.973   2.308   1.649 -0.0363  0.6628 -0.4252
-  346SOL    HW2 1217   1.065   2.346   1.636  1.2491 -1.5838  0.9213
-  346SOL    HW3 1218   0.929   2.354   1.726 -0.5261  2.3091 -1.5627
-  347SOL    OW1 1219   1.052   0.266   1.596  0.2113  0.4111 -0.0833
-  347SOL    HW2 1220   1.085   0.245   1.504  2.7294  1.2937  0.4343
-  347SOL    HW3 1221   0.965   0.314   1.591  0.0805  0.0927 -1.9646
-  348SOL    OW1 1222   1.489   0.871   0.495  0.1547 -0.3292  0.0575
-  348SOL    HW2 1223   1.450   0.779   0.494  0.1465 -0.3234 -0.0264
-  348SOL    HW3 1224   1.557   0.879   0.422  1.1807 -0.6952  0.9225
-  349SOL    OW1 1225   0.938   0.549   1.101  0.1357  0.1533  0.2190
-  349SOL    HW2 1226   0.916   0.624   1.164 -0.0842  0.8688 -0.6756
-  349SOL    HW3 1227   0.910   0.463   1.143 -2.5885  0.7789  0.1099
-  350SOL    OW1 1228   0.704   0.626   0.668  0.6157  0.1806  0.0715
-  350SOL    HW2 1229   0.655   0.539   0.662  2.2438 -0.9351  1.2245
-  350SOL    HW3 1230   0.678   0.684   0.591 -1.9246 -0.5093  0.2291
-  351SOL    OW1 1231   0.630   1.282   1.829  0.8725 -0.4090 -0.2307
-  351SOL    HW2 1232   0.684   1.337   1.893  0.4285 -0.7096  0.4214
-  351SOL    HW3 1233   0.595   1.341   1.756 -1.5060  0.7973  1.6184
-  352SOL    OW1 1234   1.564   0.161   0.889 -0.3152  0.1492 -0.7084
-  352SOL    HW2 1235   1.592   0.076   0.845  2.0832  0.3671  0.0895
-  352SOL    HW3 1236   1.630   0.184   0.961 -2.2702  1.3953  0.9036
-  353SOL    OW1 1237   0.394   1.720   0.276  0.1173  0.0420 -0.3110
-  353SOL    HW2 1238   0.321   1.775   0.316 -0.8055 -1.5132  0.3387
-  353SOL    HW3 1239   0.367   1.692   0.183 -0.3823 -0.8813  0.0847
-  354SOL    OW1 1240   0.756   2.329   0.436  0.5990 -0.0603 -0.0024
-  354SOL    HW2 1241   0.801   2.242   0.458  0.5313 -0.5679 -1.6092
-  354SOL    HW3 1242   0.808   2.404   0.476  1.9649 -0.7294 -0.4040
-  355SOL    OW1 1243   0.885   2.251   0.085  0.6383 -0.2396 -0.6881
-  355SOL    HW2 1244   0.826   2.232   0.008 -0.3880  0.6365 -0.1671
-  355SOL    HW3 1245   0.858   2.195   0.163 -0.7030  1.2621  0.0525
-  356SOL    OW1 1246   0.197   1.989   0.151 -0.0589  0.3862 -0.4144
-  356SOL    HW2 1247   0.141   2.061   0.192 -1.2333  0.6664 -2.2701
-  356SOL    HW3 1248   0.204   2.004   0.052 -0.2276 -1.9258 -0.9016
-  357SOL    OW1 1249   1.223   1.073   1.234 -0.1838  0.8167 -0.0918
-  357SOL    HW2 1250   1.235   1.069   1.135 -0.3070  0.9161 -0.1089
-  357SOL    HW3 1251   1.295   1.019   1.278 -0.6642  0.0019 -0.2646
-  358SOL    OW1 1252   1.758   0.185   1.103  0.7252  0.3838  0.7167
-  358SOL    HW2 1253   1.699   0.243   1.159 -1.3011 -1.3475  0.6155
-  358SOL    HW3 1254   1.832   0.148   1.159  0.8983  1.4621  1.2472
-  359SOL    OW1 1255   0.138   1.505   0.848 -0.0638  0.1356 -0.1292
-  359SOL    HW2 1256   0.152   1.485   0.751 -1.9054 -0.4357 -0.3498
-  359SOL    HW3 1257   0.117   1.420   0.897  0.9665  0.3905  0.8413
-  360SOL    OW1 1258   0.981   1.709   0.948 -0.1266  0.0977 -0.1316
-  360SOL    HW2 1259   0.888   1.742   0.967  0.1471  0.0502  1.6697
-  360SOL    HW3 1260   0.986   1.612   0.970 -0.0920 -0.4444 -2.1942
-  361SOL    OW1 1261   0.498   0.500   0.414 -0.2412  0.2503  0.1252
-  361SOL    HW2 1262   0.589   0.536   0.394 -0.9357  1.6307 -0.8297
-  361SOL    HW3 1263   0.432   0.538   0.350 -1.3749 -1.4911  0.1255
-  362SOL    OW1 1264   0.800   1.211   1.007  1.2113 -0.5321  0.4601
-  362SOL    HW2 1265   0.863   1.230   1.083  0.7992  0.2314  0.6267
-  362SOL    HW3 1266   0.729   1.148   1.038  0.0668  1.0413  1.2860
-  363SOL    OW1 1267   1.255   0.495   0.829  0.2436  0.2108 -0.5205
-  363SOL    HW2 1268   1.208   0.581   0.848  0.2590  0.2289 -0.5742
-  363SOL    HW3 1269   1.280   0.491   0.732 -1.3244 -0.5928 -0.9613
-  364SOL    OW1 1270   0.437   1.421   0.231 -0.9420  0.0497  0.5702
-  364SOL    HW2 1271   0.414   1.513   0.263 -0.0214  1.0948 -1.3975
-  364SOL    HW3 1272   0.391   1.403   0.144  0.8339 -0.1955 -0.4199
-  365SOL    OW1 1273   1.460   0.494   1.002  0.0155 -0.2857 -0.6445
-  365SOL    HW2 1274   1.377   0.489   0.946 -1.6651 -1.6727  1.6206
-  365SOL    HW3 1275   1.475   0.589   1.029 -0.6572  0.0437 -1.3404
-  366SOL    OW1 1276   1.926   0.063   1.267  0.2483 -0.1883 -0.1945
-  366SOL    HW2 1277   2.010   0.107   1.237  0.2736  0.4869  0.8096
-  366SOL    HW3 1278   1.902   0.094   1.359 -1.5281  0.2719 -0.7414
-  367SOL    OW1 1279   1.617   0.457   1.356  0.4690  0.2356 -0.4113
-  367SOL    HW2 1280   1.623   0.423   1.450 -2.9891 -2.7892 -0.8426
-  367SOL    HW3 1281   1.564   0.542   1.354 -1.3832 -0.7857  0.4810
-  368SOL    OW1 1282   0.598   1.510   0.707 -0.0516  0.5519  0.4414
-  368SOL    HW2 1283   0.592   1.453   0.625 -2.2716 -0.8214  1.3958
-  368SOL    HW3 1284   0.566   1.602   0.685 -0.7429  0.1708 -0.2256
-  369SOL    OW1 1285   1.649   0.851   1.593 -0.0436  0.0262  0.5595
-  369SOL    HW2 1286   1.604   0.762   1.605  0.0920 -0.2687 -0.7439
-  369SOL    HW3 1287   1.739   0.850   1.636 -0.9417  0.4109  2.6545
-  370SOL    OW1 1288   0.523   1.020   2.125 -0.1503 -0.4224 -0.1771
-  370SOL    HW2 1289   0.614   1.035   2.086  0.2283  0.0730  0.8203
-  370SOL    HW3 1290   0.498   0.924   2.114  1.6699 -1.2915  1.7056
-  371SOL    OW1 1291   0.542   2.278   0.279  0.0314  0.1883 -0.1521
-  371SOL    HW2 1292   0.632   2.295   0.319  0.2941 -1.4280  0.0663
-  371SOL    HW3 1293   0.553   2.231   0.192 -0.5978 -0.2083 -0.0217
-  372SOL    OW1 1294   0.110   1.487   1.575  0.0351 -0.7548 -0.3625
-  372SOL    HW2 1295   0.105   1.391   1.546  0.9934 -1.2565  0.9413
-  372SOL    HW3 1296   0.077   1.495   1.669 -0.3170  0.2761 -0.5496
-  373SOL    OW1 1297   1.150   1.993   1.405 -0.5974  0.3356 -0.2624
-  373SOL    HW2 1298   1.193   2.069   1.355  0.7441  0.2856  0.7164
-  373SOL    HW3 1299   1.145   2.015   1.502 -1.6321 -0.2306 -0.1637
-  374SOL    OW1 1300   0.716   2.233   2.024  0.3004 -0.1334  0.0678
-  374SOL    HW2 1301   0.771   2.160   1.983  0.8764  0.8194 -0.9512
-  374SOL    HW3 1302   0.626   2.198   2.047  1.1929 -1.7222  1.6543
-  375SOL    OW1 1303   0.620   0.486   2.129  0.3881  0.5202  0.2084
-  375SOL    HW2 1304   0.595   0.414   2.194  0.0033  0.0080 -0.4925
-  375SOL    HW3 1305   0.576   0.469   2.041  2.2358  0.2248 -0.7452
-  376SOL    OW1 1306   0.738   0.766   2.000 -0.2642 -0.4550 -0.2552
-  376SOL    HW2 1307   0.758   0.863   2.013 -0.3771 -0.3098 -1.0841
-  376SOL    HW3 1308   0.683   0.733   2.077  0.0931  0.0367  0.2266
-  377SOL    OW1 1309   0.642   1.965   0.512  0.2993 -0.0891  0.2094
-  377SOL    HW2 1310   0.573   1.982   0.441 -0.8856  0.4081  1.4044
-  377SOL    HW3 1311   0.717   2.029   0.500 -1.0243  1.7262  0.7416
-  378SOL    OW1 1312   1.872   0.083   1.935 -0.5347  0.2032  0.0159
-  378SOL    HW2 1313   1.870   0.009   2.002  0.6811  1.2194  1.2930
-  378SOL    HW3 1314   1.880   0.045   1.843  1.2108 -1.3043  0.6806
-  379SOL    OW1 1315   0.832   0.155   1.438  0.2556 -0.4593  0.4941
-  379SOL    HW2 1316   0.796   0.215   1.509 -0.8868  0.3052 -0.6515
-  379SOL    HW3 1317   0.918   0.115   1.469  1.3358  2.0519  1.2105
-  380SOL    OW1 1318   1.775   1.909   0.856 -0.4436 -0.4835  0.1120
-  380SOL    HW2 1319   1.790   1.816   0.820  0.4624 -0.4765  0.4355
-  380SOL    HW3 1320   1.818   1.917   0.946 -0.7355  0.1846  0.1987
-  381SOL    OW1 1321   1.868   0.764   0.768 -0.0259 -0.0227 -0.3363
-  381SOL    HW2 1322   1.961   0.731   0.786 -0.0120  0.3945  0.4483
-  381SOL    HW3 1323   1.810   0.686   0.744 -0.1371 -0.8816  2.0730
-  382SOL    OW1 1324   2.081   0.375   1.517 -0.4671  0.6184  0.4154
-  382SOL    HW2 1325   1.987   0.402   1.534 -0.7423 -0.6888  1.2676
-  382SOL    HW3 1326   2.082   0.293   1.460  0.1717  0.7063  0.2864
-  383SOL    OW1 1327   0.177   0.932   1.560 -0.3843 -0.0472 -0.6301
-  383SOL    HW2 1328   0.180   0.966   1.654  0.6020  2.4626 -1.4114
-  383SOL    HW3 1329   0.230   0.847   1.554 -0.6400 -0.3870  1.0695
-  384SOL    OW1 1330   1.650   2.137   0.935 -0.1129 -0.3985 -0.0997
-  384SOL    HW2 1331   1.686   2.045   0.916  0.7573 -0.3583  1.1268
-  384SOL    HW3 1332   1.717   2.206   0.908  0.2210 -0.2618  0.9869
-  385SOL    OW1 1333   0.750   1.403   0.111 -0.6115 -0.1659 -0.2487
-  385SOL    HW2 1334   0.671   1.342   0.109 -0.5361 -0.2806 -1.4666
-  385SOL    HW3 1335   0.787   1.408   0.204 -0.4625 -2.1811 -0.1244
-  386SOL    OW1 1336   0.033   1.988   0.642 -0.0599  0.6337 -0.2454
-  386SOL    HW2 1337   0.024   2.036   0.729 -1.0164  0.9044 -0.4709
-  386SOL    HW3 1338   0.037   1.889   0.658  1.0552  0.7130  0.1605
-  387SOL    OW1 1339   1.707   1.499   0.174  0.1081  0.0095 -0.4323
-  387SOL    HW2 1340   1.785   1.562   0.181  0.9811 -1.0574  2.7464
-  387SOL    HW3 1341   1.626   1.550   0.145  0.7286  2.7605  1.7946
-  388SOL    OW1 1342   1.711   1.717   1.368  0.4610  0.4438  0.8829
-  388SOL    HW2 1343   1.737   1.813   1.362 -1.7634  1.1141 -0.4482
-  388SOL    HW3 1344   1.651   1.702   1.447  0.3085  0.2985  0.7396
-  389SOL    OW1 1345   1.506   0.989   1.132 -0.6062  0.4189 -0.0253
-  389SOL    HW2 1346   1.570   1.044   1.185 -0.8636  0.2733  0.4386
-  389SOL    HW3 1347   1.465   1.046   1.060  0.2117  0.4484 -0.4855
-  390SOL    OW1 1348   1.884   0.813   1.740 -0.1427 -0.1347 -0.0074
-  390SOL    HW2 1349   1.823   0.851   1.810 -1.0767 -1.0786 -0.2533
-  390SOL    HW3 1350   1.946   0.884   1.707  0.4213  0.3219  1.8382
-  391SOL    OW1 1351   1.629   1.231   1.216 -0.3626  0.4568 -0.1572
-  391SOL    HW2 1352   1.723   1.206   1.242 -0.2741  0.2659 -0.6372
-  391SOL    HW3 1353   1.597   1.305   1.274 -0.0901  0.1964  0.3370
-  392SOL    OW1 1354   0.485   2.286   0.583  0.1395 -0.2396 -0.3706
-  392SOL    HW2 1355   0.531   2.271   0.496  2.0663  1.0403  0.3082
-  392SOL    HW3 1356   0.388   2.263   0.574  0.2612 -0.2494 -2.7869
-  393SOL    OW1 1357   0.613   0.789   1.519 -0.4909 -0.1533 -0.2373
-  393SOL    HW2 1358   0.554   0.815   1.595 -0.5684 -2.1845  0.5120
-  393SOL    HW3 1359   0.684   0.857   1.507 -2.3703  1.9727 -0.6281
-   2.10085   2.34032   2.18488   0.00000   0.00000   0.00000   0.00000   0.00000   0.00000
diff --git a/share/top/urea.itp b/share/top/urea.itp
deleted file mode 100644 (file)
index 0342d6c..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-[ moleculetype ]
-; name  nrexcl
-Urea         3
-
-[ atoms ]
-;   nr    type   resnr  residu    atom    cgnr  charge
-#ifdef Boek
-     1       C       1    UREA      C1       1  0.38
-     2       O       1    UREA      O2       1 -0.38
-     3      NT       1    UREA      N3       2 -0.83
-     4       H       1    UREA      H4       2  0.415
-     5       H       1    UREA      H5       2  0.415
-     6      NT       1    UREA      N6       3 -0.83
-     7       H       1    UREA      H7       3   0.415
-     8       H       1    UREA      H8       3  0.415
-#else
-     1       C       1    UREA      C1       1  0.683  
-     2       O       1    UREA      O2       1 -0.683
-     3      NT       1    UREA      N3       2 -0.622
-     4       H       1    UREA      H4       2  0.346
-     5       H       1    UREA      H5       2  0.276
-     6      NT       1    UREA      N6       3 -0.622
-     7       H       1    UREA      H7       3   0.346
-     8       H       1    UREA      H8       3  0.276
-#endif
-
-[ bonds ]
-;  ai    aj funct           c0           c1
-    3     4     1 1.000000e-01 3.744680e+05 
-    3     5     1 1.000000e-01 3.744680e+05 
-    6     7     1 1.000000e-01 3.744680e+05 
-    6     8     1 1.000000e-01 3.744680e+05 
-    1     2     1 1.230000e-01 5.020800e+05 
-    1     3     1 1.330000e-01 3.765600e+05 
-    1     6     1 1.330000e-01 3.765600e+05 
-
-[ pairs ]
-;  ai    aj funct           c0           c1
-    2     4     1 0.000000e+00 0.000000e+00 
-    2     5     1 0.000000e+00 0.000000e+00 
-    2     7     1 0.000000e+00 0.000000e+00 
-    2     8     1 0.000000e+00 0.000000e+00 
-    3     7     1 0.000000e+00 0.000000e+00 
-    3     8     1 0.000000e+00 0.000000e+00 
-    4     6     1 0.000000e+00 0.000000e+00 
-    5     6     1 0.000000e+00 0.000000e+00 
-
-[ angles ]
-;  ai    aj    ak funct           c0           c1
-    1     3     4     1 1.200000e+02 2.928800e+02 
-    1     3     5     1 1.200000e+02 2.928800e+02 
-    4     3     5     1 1.200000e+02 3.347200e+02 
-    1     6     7     1 1.200000e+02 2.928800e+02 
-    1     6     8     1 1.200000e+02 2.928800e+02 
-    7     6     8     1 1.200000e+02 3.347200e+02 
-    2     1     3     1 1.215000e+02 5.020800e+02 
-    2     1     6     1 1.215000e+02 5.020800e+02 
-    3     1     6     1 1.170000e+02 5.020800e+02 
-
-[ dihedrals ]
-;  ai    aj    ak    al funct           c0           c1           c2
-    2     1     3     4     1 1.800000e+02 3.347200e+01 2.000000e+00 
-    6     1     3     4     1 1.800000e+02 3.347200e+01 2.000000e+00 
-    2     1     3     5     1 1.800000e+02 3.347200e+01 2.000000e+00 
-    6     1     3     5     1 1.800000e+02 3.347200e+01 2.000000e+00 
-    2     1     6     7     1 1.800000e+02 3.347200e+01 2.000000e+00 
-    3     1     6     7     1 1.800000e+02 3.347200e+01 2.000000e+00 
-    2     1     6     8     1 1.800000e+02 3.347200e+01 2.000000e+00 
-    3     1     6     8     1 1.800000e+02 3.347200e+01 2.000000e+00 
-
-[ dihedrals ]
-;  ai    aj    ak    al funct           c0           c1
-    3     4     5     1     2 0.000000e+00 1.673600e+02 
-    6     7     8     1     2 0.000000e+00 1.673600e+02 
-    1     3     6     2     2 0.000000e+00 1.673600e+02 
-
index 08f4597819686ddaf5add9a3fb195990dcae68cc..4c5e11576deaa34e5c2af7940c35d092390fd403 100644 (file)
@@ -10,7 +10,6 @@ EXTRA_DIST = config.win
 mdrun:         
        (cd $(top_builddir)/src/gmxlib && $(MAKE))
        (cd $(top_builddir)/src/mdlib && $(MAKE))
-       (cd $(top_builddir)/src/kernel && $(MAKE) lib_LTLIBRARIES)
        (cd $(top_builddir)/src/kernel && $(MAKE) mdrun)
 
 install-mdrun:
index 7fec54d9c7c26264dad4d20a271cb630a7740a4d..ba17faaa91591120d33f3fe19c270debc122244d 100644 (file)
 /* Define to 1 if you have the xml2 library (-lxml2). */
 #cmakedefine HAVE_LIBXML2
 
+/* Define to 1 if you have the dl library (-ldl). */
+#cmakedefine HAVE_LIBDL
+
 /* Define to 1 if you have the <limits.h> header file. */
 #cmakedefine HAVE_LIMITS_H
 
 /* Define to 1 if you have the <stdlib.h> header file. */
 #cmakedefine HAVE_SCHED_H
 
+/* Have copyfile.h */
+#cmakedefine HAVE_COPYFILE_H
+
+/* Have io.h (windows)*/
+#cmakedefine HAVE_IO_H
+
 /* Define to 1 if you have the strcasecmp() function. */
 #cmakedefine HAVE_STRCASECMP
 
 /* Define to 1 if you have the memcmp() function. */
 #cmakedefine HAVE_MEMCMP
 
+/* Define to 1 if you have the posix_memalign() function. */
+#cmakedefine HAVE_POSIX_MEMALIGN
+
+/* Define to 1 if you have the memalign() function. */
+#cmakedefine HAVE_MEMALIGN
+
+/* Define to 1 if you have the MSVC _aligned_malloc() function. */
+#cmakedefine HAVE__ALIGNED_MALLOC
+
 /* Define to 1 if you have the gettimeofday() function. */
 #cmakedefine HAVE_GETTIMEOFDAY
 
+/* Define to 1 if you have the cbrt() function. */
+#cmakedefine HAVE_CBRT
+
 /* Define to 1 if you have the isnan() function. */
 #cmakedefine HAVE_ISNAN
 
 /* Define to 1 if you have the _isfinite() function. */
 #cmakedefine HAVE__ISFINITE
 
+/* Define to 1 if you have the fsync() function. */
+#cmakedefine HAVE_FSYNC
+
+/* Define to 1 if you have the Windows _commit() function. */
+#cmakedefine HAVE__COMMIT
+
+/* Define to 1 if you have the fileno() function. */
+#cmakedefine HAVE_FILENO
+
+/* Define to 1 if you have the _fileno() function. */
+#cmakedefine HAVE__FILENO
+
+/* Define to 1 if you have the copyfile() function. */
+#cmakedefine HAVE_COPYFILE
+
+/* Define to 1 if you have the Windows CopyFile() function. */
+#cmakedefine HAVE_WIN_COPYFILE
+
 /* Define to 1 if you have the <string.h> header file. */
 #cmakedefine HAVE_STRING_H
 
index 4a9aaf81fd09c8457579c18859ad9530a762b628..1a215365ce5291cb319ef5e3e24bee1adaf877fb 100644 (file)
@@ -26,13 +26,3 @@ ehole_SOURCES = ehdata.c ehdata.h ehanal.c ehole.c
 # Note: you don't have to list sources for "prog" if it is the single file prog.c
 
 CLEANFILES   =         *~ \\\#*
-
-
-
-
-
-
-
-
-
-
index 47d4ba1fd34176310e9acf406b71a6b62853e3bd..be5fa44927c35d7fa29c199ee9502321f7311626 100644 (file)
@@ -104,9 +104,10 @@ int main(int argc,char *argv[])
     "[TT]xpm[tt] matrices) and in all time options."
   };
 
+  output_env_t oenv=NULL;
   CopyRight(stderr,argv[0]);
   parse_common_args(&argc,argv,0,
-                   0,NULL,0,NULL,asize(desc),desc,asize(bugs),bugs);
+                   0,NULL,0,NULL,asize(desc),desc,asize(bugs),bugs,&oenv);
   
   thanx(stderr);
   
index 62d543b7a6173767b0b61e6296c34d30028a556e..bfc5c4665ccb1592e1cff1138e96d15473ac1772 100644 (file)
@@ -105,6 +105,7 @@ endif(GMX_FAHCORE)
 add_library(gmx ${GMXLIB_SOURCES} ${BLAS_SOURCES} ${LAPACK_SOURCES} ${GMX_MORESSE_SOURCES} ${GMX_SSE2_SOURCES} ${THREAD_MPI_SRC})
 target_link_libraries(gmx ${GMX_EXTRA_LIBRARIES}  ${THREAD_LIB})
 add_dependencies(gmx gmx_version) 
+set_target_properties(gmx PROPERTIES OUTPUT_NAME "gmx${GMX_BINARY_SUFFIX}")
 
 install(TARGETS gmx DESTINATION ${LIB_INSTALL_DIR})
 
index 3eeb15ddeae406472f3408ad080409ce320756dc..82d803f2da55d10c48f4e6c51430c2aed4f9c56c 100644 (file)
@@ -51,8 +51,9 @@ libgmx@LIBSUFFIX@_la_SOURCES = \
        3dview.c        atomprop.c      bondfree.c      \
        calcgrid.c      calch.c         chargegroup.c   checkpoint.c    \
        confio.c        copyrite.c      disre.c         do_fit.c        \
-       enxio.c         ewald_util.c    gmx_fatal.c     ffscanf.c       \
-       filenm.c        futil.c         gbutil.c        gmxcpp.c \
+       enxio.c         ewald_util.c    ffscanf.c       \
+       filenm.c        futil.c         gbutil.c        gmx_fatal.c     \
+       gmx_sort.c      gmxcpp.c \
        gmxfio.c        ifunc.c         index.c         cinvsqrtdata.c  \
        invblock.c      macros.c        orires.c        sparsematrix.c  \
        main.c          maths.c         matio.c         mshift.c        \
@@ -61,33 +62,37 @@ libgmx@LIBSUFFIX@_la_SOURCES = \
        pargs.c         pbc.c           pdbio.c         princ.c         \
        rando.c         random.c        gmx_random.c    rbin.c          \
        readinp.c       replace.c       rmpbc.c         shift_util.c    \
-       sortwater.c     smalloc.c       statutil.c      \
+       sortwater.c     smalloc.c       statutil.c      sfactor.c       \
        strdb.c         string2.c       symtab.c        \
        topsort.c       tpxio.c         \
        trnio.c         trxio.c         txtdump.c       typedefs.c      \
        viewit.c        warninp.c       \
        wgms.c          wman.c          writeps.c       \
        xdrd.c          xtcio.c         xvgr.c          replace.h       \
-       libxdrf.c       gmx_arpack.c                    \
+       libxdrf.c       gmx_arpack.c    gmx_matrix.c            \
        dihres.c        gmx_random_gausstable.h         \
        tcontrol.c      splitter.c      gmx_cyclecounter.c              \
        gmx_system_xdr.c md5.c vmdio.c vmddlopen.c      sighandler.c    \
-       oenv.c          version.c
+       oenv.c          gmxfio_rw.c     gmxfio_asc.c    gmxfio_bin.c    \
+       gmxfio_xdr.c
 
 pkgconfigdir = ${libdir}/pkgconfig
 pkgconfig_DATA = libgmx@LIBSUFFIX@.pc
 
 # clean all libtool libraries, since the target names might have changed
-CLEANFILES     = *.la *~ \\\#* innerc.c innerf.f mkinl version.c
+CLEANFILES     = *.la *~ \\\#* innerc.c innerf.f mkinl
 
-#version.c contains git version information or version defined in VERSION
-#The empty target FORCE forces make to run the commands every time. But
+if USE_VERSION_H
+#version.c contains generated git version information
+libgmx@LIBSUFFIX@_la_SOURCES += version.c
+CLEANFILES += version.c
+#The empty target FORCE forces make to run the command every time. But
 #version.c is only changed if the version actually has changed, and hence
 #rebuilds are only triggered when they are needed.
 version.c: FORCE
        $(top_srcdir)/src/gmxlib/genversion.sh @VERSION@ $(top_srcdir)
 FORCE:
-
+endif
 
 
 
index 67f77f6dbac8cac6ccdcbec8c646737a1234307d..cd1eac8c8e66bc6202edad0b3d71b5c8f658f575 100644 (file)
@@ -128,7 +128,7 @@ static int get_prop_index(aprop_t *ap,t_aa_names *aan,
   if (debug) {
     fprintf(debug,"searching residue: %4s atom: %4s\n",resnm,atomnm);
     if (j == NOTFOUND)
-      fprintf(debug," not succesful\n");
+      fprintf(debug," not successful\n");
     else
       fprintf(debug," match: %4s %4s\n",ap->resnm[j],ap->atomnm[j]);
   }
index dd553fe23bb62d34101b2e3ca2ca296904bb4818..bde473e226b7a37d5822d60b80ab7cb4f8fac28a 100644 (file)
@@ -1,4 +1,5 @@
-/*
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
  * 
  *                This source code is part of
  * 
 #include "gmx_fatal.h"
 #include "calcgrid.h"
 
-#define facNR 6
-int factor[facNR] = {2,3,5,7,11,13};
-int decomp[facNR];
-int ng,ng_max,*list,n_list,n_list_alloc;
+#define facNR 4
+const int factor[facNR] = {2,3,5,7};
 
-static void make_list(int start_fac)
+static void make_list(int start_fac,int *ng,int ng_max,int *n_list,int **list)
 {
-  int i;
+    int i,fac;
   
-  if (ng < ng_max) {
-    if (n_list >= n_list_alloc) {
-      n_list_alloc += 100;
-      srenew(list,n_list_alloc);
+    if (*ng < ng_max)
+    {
+        if (*n_list % 100 == 0)
+        {
+            srenew(*list,*n_list+100);
+        }
+        (*list)[*n_list] = *ng;
+        (*n_list)++;
+        
+        for(i=start_fac; i<facNR; i++)
+        {
+            fac = factor[i];
+            /* The choice of grid size is based on benchmarks of fftw
+             * and the need for a lot of factors for nice DD decomposition.
+             * The base criterion is that a grid size is not included
+             * when there is a larger grid size that produces a faster 3D FFT.
+             * Allow any power for 2, two for 3 and 5, but only one for 7.
+             * Three for 3 are ok when there is also a factor of 2.
+             * Two factors of 5 are not allowed with a factor of 3 or 7.
+             * A factor of 7 does not go with a factor of 5, 7 or 9.
+             */
+            if ((fac == 2) ||
+                (fac == 3 && (*ng % 9 != 0 ||
+                              (*ng % 2 == 0 && *ng % 27 != 0))) ||
+                (fac == 5 && *ng % 15 && *ng % 25 != 0) ||
+                (fac == 7 && *ng % 5 != 0 && *ng % 7 != 0 && *ng % 9 != 0))
+            {
+                *ng *= fac;
+                make_list(i,ng,ng_max,n_list,list);
+                *ng /= fac;
+            }
+        }
     }
-    list[n_list] = ng;
-    n_list++;
-
-    for(i=start_fac; i<facNR; i++) {
-      /* allow any power of 2, 3, 5 and 7, but only one of 11 or 13 */
-      if (i<4 || (decomp[4]+decomp[5]==0)) {
-       ng*=factor[i];
-       decomp[i]++;
-       make_list(i);
-       ng/=factor[i];
-       decomp[i]--;
-      }
-    }
-  }
 }
 
 static int list_comp(const void *a,const void *b)
@@ -79,93 +92,102 @@ static int list_comp(const void *a,const void *b)
 }
 
 real calc_grid(FILE *fp,matrix box,real gr_sp,
-              int *nx,int *ny,int *nz,int nnodes)
+               int *nx,int *ny,int *nz)
 {
-  int  d,n[DIM];
-  int  i,j,nmin[DIM];
-  rvec box_size,spacing;
-  real max_spacing;
-  real tmp[3];
-  
-  if (gr_sp <= 0)
-    gmx_fatal(FARGS,"invalid fourier grid spacing: %g",gr_sp);
+    int  d,n[DIM];
+    int  i,j,nmin[DIM];
+    rvec box_size,spacing;
+    real max_spacing;
+    int  ng_max,ng;
+    int  n_list,*list;
 
-  /* New grid calculation setup:
-   *
-   * To maintain similar accuracy for triclinic PME grids as for rectangular
-   * ones, the max grid spacing should set along the box vectors rather than
-   * cartesian X/Y/Z directions. This will lead to slightly larger grids, but
-   * it is much better than having to go to pme_order=6.
-   *
-   * Thus, instead of just extracting the diagonal elements to box_size[d], we
-   * now calculate the cartesian length of the vectors.
-   *
-   * /Erik Lindahl, 20060402.
-   */
-  for(d=0; d<DIM; d++)
-  {
-         box_size[d] = 0;
-         for(i=0;i<DIM;i++)
-         {
-                 box_size[d] += box[d][i]*box[d][i];
-         }
-         box_size[d] = sqrt(box_size[d]);
-  }
-  
-  
-  n[XX] = *nx;
-  n[YY] = *ny;
-  n[ZZ] = *nz;
-
-  ng = 1;
-  ng_max = 1;
-  for(d=0; d<DIM; d++) {
-    nmin[d] = (int)(box_size[d]/gr_sp + 0.999);
-    if (2*nmin[d] > ng_max)
-      ng_max = 2*nmin[d];
-  }
-  n_list=0;
-  n_list_alloc=0;
-  list=NULL;
-  for(i=0; i<facNR; i++)
-    decomp[i]=0;
-  make_list(0);
-
-  if ((*nx<=0) || (*ny<=0) || (*nz<=0))
-    fprintf(fp,"Calculating fourier grid dimensions for%s%s%s\n",
-           *nx > 0 ? "":" X",*ny > 0 ? "":" Y",*nz > 0 ? "":" Z");
+    if (gr_sp <= 0)
+    {
+        gmx_fatal(FARGS,"invalid fourier grid spacing: %g",gr_sp);
+    }
 
-  qsort(list,n_list,sizeof(list[0]),list_comp);
-  if (debug)
-    for(i=0; i<n_list; i++)
-      fprintf(debug,"grid: %d\n",list[i]);
-  
-  if (((*nx>0) && (*nx != nnodes*(*nx/nnodes))) ||
-      ((*ny>0) && (*ny != nnodes*(*ny/nnodes))))
-    gmx_fatal(FARGS,"the x or y grid spacing (nx %d, ny %d) is not divisible by the number of nodes (%d)",*nx,*ny,nnodes);
-  
-  for(d=0; d<DIM; d++) {
-    for(i=0; (i<n_list) && (n[d]<=0); i++)
-      if ((list[i] >= nmin[d]) && 
-         ((d == ZZ) || (list[i] == nnodes*(list[i]/nnodes))))
-       n[d] = list[i];
-    if (n[d] <= 0)
-      gmx_fatal(FARGS ,"could not find a grid spacing with nx and ny divisible by the number of nodes (%d)",nnodes);
-  }
-  
-  max_spacing = 0;
-  for(d=0; d<DIM; d++) {
-    spacing[d] = box_size[d]/n[d];
-    if (spacing[d] > max_spacing)
-      max_spacing = spacing[d];
-  }
-  *nx = n[XX];
-  *ny = n[YY];
-  *nz = n[ZZ];
-  fprintf(fp,"Using a fourier grid of %dx%dx%d, spacing %.3f %.3f %.3f\n",
-         *nx,*ny,*nz,spacing[XX],spacing[YY],spacing[ZZ]);
+    /* New grid calculation setup:
+     *
+     * To maintain similar accuracy for triclinic PME grids as for rectangular
+     * ones, the max grid spacing should set along the box vectors rather than
+     * cartesian X/Y/Z directions. This will lead to slightly larger grids, but
+     * it is much better than having to go to pme_order=6.
+     *
+     * Thus, instead of just extracting the diagonal elements to box_size[d], we
+     * now calculate the cartesian length of the vectors.
+     *
+     * /Erik Lindahl, 20060402.
+     */
+    for(d=0; d<DIM; d++)
+    {
+        box_size[d] = 0;
+        for(i=0;i<DIM;i++)
+        {
+            box_size[d] += box[d][i]*box[d][i];
+        }
+        box_size[d] = sqrt(box_size[d]);
+    }
+    
+    n[XX] = *nx;
+    n[YY] = *ny;
+    n[ZZ] = *nz;
+    
+    ng = 1;
+    ng_max = 1;
+    for(d=0; d<DIM; d++)
+    {
+        nmin[d] = (int)(box_size[d]/gr_sp + 0.999);
+        if (2*nmin[d] > ng_max)
+        {
+            ng_max = 2*nmin[d];
+        }
+    }
+    n_list=0;
+    list=NULL;
+    make_list(0,&ng,ng_max,&n_list,&list);
+    
+    if ((*nx<=0) || (*ny<=0) || (*nz<=0))
+    {
+        fprintf(fp,"Calculating fourier grid dimensions for%s%s%s\n",
+                *nx > 0 ? "":" X",*ny > 0 ? "":" Y",*nz > 0 ? "":" Z");
+    }
+    
+    qsort(list,n_list,sizeof(list[0]),list_comp);
+    if (debug)
+    {
+        for(i=0; i<n_list; i++)
+            fprintf(debug,"grid: %d\n",list[i]);
+    }
+        
+    for(d=0; d<DIM; d++)
+    {
+        for(i=0; (i<n_list) && (n[d]<=0); i++)
+        {
+            if (list[i] >= nmin[d])
+            {
+                n[d] = list[i];
+            }
+        }
+    }
+    
+    sfree(list);
+    
+    max_spacing = 0;
+    for(d=0; d<DIM; d++)
+    {
+        spacing[d] = box_size[d]/n[d];
+        if (spacing[d] > max_spacing)
+        {
+            max_spacing = spacing[d];
+        }
+    }
+    *nx = n[XX];
+    *ny = n[YY];
+    *nz = n[ZZ];
+    fprintf(fp,"Using a fourier grid of %dx%dx%d, spacing %.3f %.3f %.3f\n",
+            *nx,*ny,*nz,spacing[XX],spacing[YY],spacing[ZZ]);
 
-  return max_spacing;
+    return max_spacing;
 }
 
 
index ac2348760bd6bfee4924b1744dbb7c060884f551..0aa28c24a1fe527fe0fd5ead4c669d7116d96c46 100644 (file)
@@ -78,7 +78,6 @@ static void gen_waterhydrogen(int nh,rvec xa[], rvec xh[],int *l)
 #undef AA
 #undef BB
 #undef CC
-  /*static int l=0; removed due to thread-safety issues*/
   int        m;
   rvec       kkk;
   
index e15767e72b0a9317897dc61ee11e77700b01f1be..7ea26afea50ccafcb102e62888a46d7492262a08 100644 (file)
@@ -935,57 +935,57 @@ static int do_cpt_files(XDR *xd, bool bRead,
                         gmx_file_position_t **p_outputfiles, int *nfiles, 
                         FILE *list, int file_version)
 {
-       int    i,j;
-       off_t  offset;
-       off_t  mask = 0xFFFFFFFFL;
-       int    offset_high,offset_low;
-       char   *buf;
-       gmx_file_position_t *outputfiles;
-       
+    int    i,j;
+    off_t  offset;
+    off_t  mask = 0xFFFFFFFFL;
+    int    offset_high,offset_low;
+    char   *buf;
+    gmx_file_position_t *outputfiles;
+
     if (do_cpt_int(xd,"number of output files",nfiles,list) != 0)
-       {
-               return -1;
-       }
+    {
+        return -1;
+    }
 
-       if(bRead)
-       {
-               snew(*p_outputfiles,*nfiles);
-       }
-       
-       outputfiles = *p_outputfiles;
-       
-       for(i=0;i<*nfiles;i++)
-       {
-               /* 64-bit XDR numbers are not portable, so it is stored as separate high/low fractions */
-               if(bRead)
-               {
-                       do_cpt_string_err(xd,bRead,"output filename",&buf,list);
-                       strncpy(outputfiles[i].filename,buf,CPTSTRLEN-1);
-                       if(list==NULL)
-                       {
-                               sfree(buf);                     
-                       }
-                       
-                       if (do_cpt_int(xd,"file_offset_high",&offset_high,list) != 0)
-                       {
-                               return -1;
-                       }
-                       if (do_cpt_int(xd,"file_offset_low",&offset_low,list) != 0)
-                       {
-                               return -1;
-                       }
+    if(bRead)
+    {
+        snew(*p_outputfiles,*nfiles);
+    }
+
+    outputfiles = *p_outputfiles;
+
+    for(i=0;i<*nfiles;i++)
+    {
+        /* 64-bit XDR numbers are not portable, so it is stored as separate high/low fractions */
+        if(bRead)
+        {
+            do_cpt_string_err(xd,bRead,"output filename",&buf,list);
+            strncpy(outputfiles[i].filename,buf,CPTSTRLEN-1);
+            if(list==NULL)
+            {
+                sfree(buf);                    
+            }
+
+            if (do_cpt_int(xd,"file_offset_high",&offset_high,list) != 0)
+            {
+                return -1;
+            }
+            if (do_cpt_int(xd,"file_offset_low",&offset_low,list) != 0)
+            {
+                return -1;
+            }
 #if (SIZEOF_OFF_T > 4)
-                       outputfiles[i].offset = ( ((off_t) offset_high) << 32 ) | ( (off_t) offset_low & mask );
+            outputfiles[i].offset = ( ((off_t) offset_high) << 32 ) | ( (off_t) offset_low & mask );
 #else
-                       outputfiles[i].offset = offset_low;
+            outputfiles[i].offset = offset_low;
 #endif
-               }
-               else
-               {
-                       buf = outputfiles[i].filename;
-                       do_cpt_string_err(xd,bRead,"output filename",&buf,list);
-                       /* writing */
-                       offset      = outputfiles[i].offset;
+        }
+        else
+        {
+            buf = outputfiles[i].filename;
+            do_cpt_string_err(xd,bRead,"output filename",&buf,list);
+            /* writing */
+            offset      = outputfiles[i].offset;
             if (offset == -1)
             {
                 offset_low  = -1;
@@ -1001,17 +1001,17 @@ static int do_cpt_files(XDR *xd, bool bRead,
                 offset_high = 0;
 #endif
             }
-                       if (do_cpt_int(xd,"file_offset_high",&offset_high,list) != 0)
-                       {
-                               return -1;
-                       }
-                       if (do_cpt_int(xd,"file_offset_low",&offset_low,list) != 0)
-                       {
-                               return -1;
-                       }
-               }
-               if (file_version >= 8)
-               {
+            if (do_cpt_int(xd,"file_offset_high",&offset_high,list) != 0)
+            {
+                return -1;
+            }
+            if (do_cpt_int(xd,"file_offset_low",&offset_low,list) != 0)
+            {
+                return -1;
+            }
+        }
+        if (file_version >= 8)
+        {
             if (do_cpt_int(xd,"file_checksum_size",&(outputfiles[i].chksum_size),
                            list) != 0)
             {
@@ -1021,21 +1021,22 @@ static int do_cpt_files(XDR *xd, bool bRead,
             {
                 return -1;
             }
-               
-               else 
-               {
-                   outputfiles[i].chksum_size = -1;
-               }
-       }
-       return 0;
+        } 
+        else 
+        {
+            outputfiles[i].chksum_size = -1;
+        }
+    }
+    return 0;
 }
 
 
-void write_checkpoint(const char *fn,FILE *fplog,t_commrec *cr,
+void write_checkpoint(const char *fn,bool bNumberAndKeep,
+                      FILE *fplog,t_commrec *cr,
                       int eIntegrator,int simulation_part,
                       gmx_large_int_t step,double t,t_state *state)
 {
-    int  fp;
+    t_fileio *fp;
     int  file_version;
     char *version;
     char *btime;
@@ -1043,12 +1044,14 @@ void write_checkpoint(const char *fn,FILE *fplog,t_commrec *cr,
     char *bmach;
     char *fprog;
     char *ftime;
+    char *fntemp; /* the temporary checkpoint file name */
     time_t now;
     int  nppnodes,npmenodes,flag_64bit;
-    char buf[1024];
-       gmx_file_position_t *outputfiles;
-       int  noutputfiles;
+    char buf[1024],suffix[5+STEPSTRSIZE],sbuf[STEPSTRSIZE];
+    gmx_file_position_t *outputfiles;
+    int  noutputfiles;
     int  flags_eks,flags_enh,i;
+    t_fileio *ret;
                
     if (PAR(cr))
     {
@@ -1068,26 +1071,20 @@ void write_checkpoint(const char *fn,FILE *fplog,t_commrec *cr,
         nppnodes  = 1;
         npmenodes = 0;
     }
-    
-    if (gmx_fexist(fn))
-    {
-        /* Rename the previous checkpoint file */
-        strcpy(buf,fn);
-        buf[strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1] = '\0';
-        strcat(buf,"_prev");
-        strcat(buf,fn+strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1);
-               (void)remove(buf); /* Unix will overwrite buf if it exists, but for windows we need to remove first */
-        if(rename(fn,buf) != 0)
-               {
-                       gmx_file("Cannot rename checkpoint file; maybe you are out of quota?");
-               }
-    }
-    
+
+    /* make the new temporary filename */
+    snew(fntemp, strlen(fn)+5+STEPSTRSIZE);
+    strcpy(fntemp,fn);
+    fntemp[strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1] = '\0';
+    sprintf(suffix,"_%s%s","step",gmx_step_str(step,sbuf));
+    strcat(fntemp,suffix);
+    strcat(fntemp,fn+strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1);
+   
     now = time(NULL);
     ftime = strdup(ctime(&now));
     ftime[strlen(ftime)-1] = '\0';
 
-       /* No need to pollute stderr every time we write a checkpoint file */
+    /* No need to pollute stderr every time we write a checkpoint file */
     /* fprintf(stderr,"\nWriting checkpoint, step %d at %s\n",step,ftime); */
     if (fplog)
     { 
@@ -1096,15 +1093,16 @@ void write_checkpoint(const char *fn,FILE *fplog,t_commrec *cr,
     }
     
     /* Get offsets for open files */
-       gmx_fio_get_output_file_positions(&outputfiles, &noutputfiles);
+    gmx_fio_get_output_file_positions(&outputfiles, &noutputfiles);
 
-    fp = gmx_fio_open(fn,"w");
+    fp = gmx_fio_open(fntemp,"w");
        
     if (state->ekinstate.bUpToDate)
     {
         flags_eks =
-            ((1<<eeksEKIN_N) | (1<<eeksEKINH) | (1<<eeksEKINF) | (1<<eeksEKINO) | 
-             (1<<eeksEKINSCALEF) | (1<<eeksEKINSCALEH) | (1<<eeksVSCALE) | (1<<eeksDEKINDL) | (1<<eeksMVCOS));
+            ((1<<eeksEKIN_N) | (1<<eeksEKINH) | (1<<eeksEKINF) | 
+             (1<<eeksEKINO) | (1<<eeksEKINSCALEF) | (1<<eeksEKINSCALEH) | 
+             (1<<eeksVSCALE) | (1<<eeksDEKINDL) | (1<<eeksMVCOS));
     }
     else
     {
@@ -1138,8 +1136,9 @@ void write_checkpoint(const char *fn,FILE *fplog,t_commrec *cr,
                   &version,&btime,&buser,&bmach,&fprog,&ftime,
                   &eIntegrator,&simulation_part,&step,&t,&nppnodes,
                   DOMAINDECOMP(cr) ? cr->dd->nc : NULL,&npmenodes,
-                  &state->natoms,&state->ngtc,&state->nnhpres,&state->nhchainlength,
-                  &state->flags,&flags_eks,&flags_enh,NULL);
+                  &state->natoms,&state->ngtc,&state->nnhpres,
+                  &state->nhchainlength, &state->flags,&flags_eks,&flags_enh,
+                  NULL);
     
     sfree(version);
     sfree(btime);
@@ -1147,31 +1146,85 @@ void write_checkpoint(const char *fn,FILE *fplog,t_commrec *cr,
     sfree(bmach);
     sfree(fprog);
 
-    if( (do_cpt_state(gmx_fio_getxdr(fp),FALSE,state->flags,state,TRUE,NULL) < 0)          ||
-               (do_cpt_ekinstate(gmx_fio_getxdr(fp),FALSE,flags_eks,&state->ekinstate,NULL) < 0)  ||
-               (do_cpt_enerhist(gmx_fio_getxdr(fp),FALSE,flags_enh,&state->enerhist,NULL) < 0)    ||
-           (do_cpt_files(gmx_fio_getxdr(fp),FALSE,&outputfiles,&noutputfiles,NULL,file_version) < 0))
-       {
-               gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of quota?");
-       }
+    if((do_cpt_state(gmx_fio_getxdr(fp),FALSE,state->flags,state,TRUE,NULL) < 0)        ||
+       (do_cpt_ekinstate(gmx_fio_getxdr(fp),FALSE,flags_eks,&state->ekinstate,NULL) < 0)||
+       (do_cpt_enerhist(gmx_fio_getxdr(fp),FALSE,flags_enh,&state->enerhist,NULL) < 0)  ||
+       (do_cpt_files(gmx_fio_getxdr(fp),FALSE,&outputfiles,&noutputfiles,NULL,
+                     file_version) < 0))
+    {
+        gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of quota?");
+    }
 
     do_cpt_footer(gmx_fio_getxdr(fp),FALSE,file_version);
 
+    /* we really, REALLY, want the checkpoint file and all files it depends 
+       on to be physically written out do disk: */
+    ret=gmx_fio_all_output_fsync();
+    if (ret)
+    {
+        char buf[STRLEN];
+        sprintf(buf,
+                "Cannot fsync '%s'; maybe you are out of disk space or quota?",
+                gmx_fio_getname(ret));
+
+        if (getenv(GMX_IGNORE_FSYNC_FAILURE_ENV)==NULL)
+        {
+            gmx_file(buf);
+        }
+        else
+        {
+            gmx_warning(buf);
+        }
+    }
+
     if( gmx_fio_close(fp) != 0)
-       {
-               gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of quota?");
-       }
-    
+    {
+        gmx_file("Cannot read/write checkpoint; corrupt file, or maybe you are out of quota?");
+    }
+
+    /* we don't move the checkpoint if the user specified they didn't want it,
+       or if the fsyncs failed */
+    if (!bNumberAndKeep && !ret)
+    {
+        if (gmx_fexist(fn))
+        {
+            /* Rename the previous checkpoint file */
+            strcpy(buf,fn);
+            buf[strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1] = '\0';
+            strcat(buf,"_prev");
+            strcat(buf,fn+strlen(fn) - strlen(ftp2ext(fn2ftp(fn))) - 1);
+#ifndef GMX_FAHCORE
+            /* we copy here so that if something goes wrong between now and
+             * the rename below, there's always a state.cpt.
+             * If renames are atomic (such as in POSIX systems),
+             * this copying should be unneccesary.
+             */
+            gmx_file_copy(fn, buf, FALSE);
+            /* We don't really care if this fails: 
+             * there's already a new checkpoint.
+             */
+#else
+            gmx_file_rename(fn, buf);
+#endif
+        }
+        if (gmx_file_rename(fntemp, fn) != 0)
+        {
+            gmx_file("Cannot rename checkpoint file; maybe you are out of quota?");
+        }
+    }
+
     sfree(ftime);
-       sfree(outputfiles);
-       #ifdef GMX_FAHCORE
-    /*code for alternate checkpointing scheme.  moved from top of loop over steps */
-      fcRequestCheckPoint();
-      if ( fcCheckPointParallel( cr->nodeid, NULL,0) == 0 ) {
-        gmx_fatal( 3,__FILE__,__LINE__, "Checkpoint error on step %d\n", step );
-      }
-       #endif /* end FAHCORE block */
+    sfree(outputfiles);
+    sfree(fntemp);
 
+#ifdef GMX_FAHCORE
+    /*code for alternate checkpointing scheme.  moved from top of loop over 
+      steps */
+    fcRequestCheckPoint();
+    if ( fcCheckPointParallel( cr->nodeid, NULL,0) == 0 ) {
+        gmx_fatal( 3,__FILE__,__LINE__, "Checkpoint error on step %d\n", step );
+    }
+#endif /* end GMX_FAHCORE block */
 }
 
 static void print_flag_mismatch(FILE *fplog,int sflags,int fflags)
@@ -1280,7 +1333,8 @@ static void read_checkpoint(const char *fn,FILE **pfplog,
                             t_state *state,bool *bReadRNG,bool *bReadEkin,
                             int *simulation_part,bool bAppendOutputFiles)
 {
-    int  fp,i,j,rc;
+    t_fileio *fp;
+    int  i,j,rc;
     int  file_version;
     char *version,*btime,*buser,*bmach,*fprog,*ftime;
        char filename[STRLEN],buf[STEPSTRSIZE];
@@ -1291,11 +1345,11 @@ static void read_checkpoint(const char *fn,FILE **pfplog,
     int  ret;
        gmx_file_position_t *outputfiles;
        int  nfiles;
-       int chksum_file;
+       t_fileio *chksum_file;
        FILE* fplog = *pfplog;
        unsigned char digest[16];
 #if !((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
-       struct flock fl = { F_WRLCK, SEEK_SET, 0,       0,     0 }; 
+       struct flock fl = { 0, SEEK_SET, 0,       F_WRLCK,     0 }; 
 #endif
        
     const char *int_warn=
@@ -1545,7 +1599,7 @@ static void read_checkpoint(const char *fn,FILE **pfplog,
                     " offsets. Can not append. Run mdrun without -append",
                     outputfiles[i].filename);
             }
-#ifdef FAHCORE
+#ifdef GMX_FAHCORE
             chksum_file=gmx_fio_open(outputfiles[i].filename,"a");
 
 #else
@@ -1592,7 +1646,7 @@ static void read_checkpoint(const char *fn,FILE **pfplog,
             {
                 gmx_fio_close(chksum_file);
             }
-#ifndef FAHCORE            
+#ifndef GMX_FAHCORE            
             /* compare md5 chksum */
             if (outputfiles[i].chksum_size != -1 &&
                 memcmp(digest,outputfiles[i].chksum,16)!=0) 
@@ -1654,12 +1708,15 @@ void load_checkpoint(const char *fn,FILE **fplog,
       gmx_bcast(sizeof(*bReadEkin),bReadEkin,cr);
     }
     ir->bContinuation    = TRUE;
-    ir->nsteps          += ir->init_step - step;
+    if (ir->nsteps >= 0)
+    {
+        ir->nsteps          += ir->init_step - step;
+    }
     ir->init_step        = step;
        ir->simulation_part += 1;
 }
 
-static void read_checkpoint_data(int fp,int *simulation_part,
+static void read_checkpoint_data(t_fileio *fp,int *simulation_part,
                                  gmx_large_int_t *step,double *t,t_state *state,
                                  bool bReadRNG,
                                  int *nfiles,gmx_file_position_t **outputfiles)
@@ -1729,7 +1786,7 @@ void
 read_checkpoint_state(const char *fn,int *simulation_part,
                       gmx_large_int_t *step,double *t,t_state *state)
 {
-    int  fp;
+    t_fileio *fp;
     
     fp = gmx_fio_open(fn,"r");
     read_checkpoint_data(fp,simulation_part,step,t,state,TRUE,NULL,NULL);
@@ -1739,7 +1796,7 @@ read_checkpoint_state(const char *fn,int *simulation_part,
        }
 }
 
-void read_checkpoint_trxframe(int fp,t_trxframe *fr)
+void read_checkpoint_trxframe(t_fileio *fp,t_trxframe *fr)
 {
     t_state state;
     int simulation_part;
@@ -1783,7 +1840,7 @@ void read_checkpoint_trxframe(int fp,t_trxframe *fr)
 
 void list_checkpoint(const char *fn,FILE *out)
 {
-    int  fp;
+    t_fileio *fp;
     int  file_version;
     char *version,*btime,*buser,*bmach,*fprog,*ftime;
     int  eIntegrator,simulation_part,nppnodes,npme;
@@ -1849,7 +1906,7 @@ bool read_checkpoint_simulation_part(const char *filename, int *simulation_part,
                                      bool bAppendReq,
                                      const char *part_suffix,bool *bAddPart)
 {
-    int  fp;
+    t_fileio *fp;
     gmx_large_int_t step=0;
        double t;
     t_state state;
@@ -1862,7 +1919,7 @@ bool read_checkpoint_simulation_part(const char *filename, int *simulation_part,
     bAppend = FALSE;
 
     if (SIMMASTER(cr)) {
-        if(!gmx_fexist(filename) || ( (fp = gmx_fio_open(filename,"r")) < 0 ))
+        if(!gmx_fexist(filename) || (!(fp = gmx_fio_open(filename,"r")) ))
         {
             *simulation_part = 0;
         }
index eb35304af24ba0f8f94ed301dcc722ce1481f42c..d292d73922c0f377ed44177531376feda02ccddb 100644 (file)
@@ -188,9 +188,8 @@ static int read_g96_vel(char line[],FILE *fp,const char *infile,
 
 int read_g96_conf(FILE *fp,const char *infile,t_trxframe *fr)
 {
-  static t_symtab *symtab=NULL;
-  static char line[STRLEN+1]; /* VERY DIRTY, you can not read two       *
-                              * Gromos96 trajectories at the same time */  
+  t_symtab *symtab=NULL;
+  char line[STRLEN+1]; 
   bool   bAtStart,bTime,bAtoms,bPos,bVel,bBox,bEnd,bFinished;
   int    natoms,nbp;
   double db1,db2,db3,db4,db5,db6,db7,db8,db9;
@@ -282,7 +281,7 @@ int read_g96_conf(FILE *fp,const char *infile,t_trxframe *fr)
     }
   } while (!bFinished && fgets2(line,STRLEN,fp));
   
-  close_symtab(symtab);
+  free_symtab(symtab);
 
   fr->natoms = natoms;
   
@@ -446,7 +445,7 @@ const char *esp_prop[espNR] = { "id", "pos", "type", "q", "v", "f",
 static void read_espresso_conf(const char *infile,
                               t_atoms *atoms,rvec x[],rvec *v,matrix box)
 {
-  static t_symtab *symtab=NULL;
+  t_symtab *symtab=NULL;
   FILE *fp;
   char word[STRLEN],buf[STRLEN];
   int  natoms,level,npar,r,nprop,p,i,m,molnr;
@@ -702,7 +701,7 @@ static void get_coordnum (const char *infile,int *natoms)
 static bool get_w_conf(FILE *in,const char *infile,char *title,
                       t_atoms *atoms, int *ndec, rvec x[],rvec *v, matrix box)
 {
-  static t_symtab *symtab=NULL;
+  t_symtab *symtab=NULL;
   char   name[6];
   char   line[STRLEN+1],*ptr;
   char   buf[256];
@@ -1450,6 +1449,11 @@ void read_stx_conf(const char *infile,char *title,t_atoms *atoms,
     tpx_make_chain_identifiers(atoms,&top.mols);
                
     sfree(mtop);
+    /* The strings in the symtab are still in use in the returned t_atoms
+     * structure, so we should not free them. But there is no place to put the
+     * symbols; the only choice is to leak the memory...
+     * So we clear the symbol table before freeing the topology structure. */
+    open_symtab(&top.symtab);
     done_top(&top);
                  
     break;
index dcb9f65a6457db3a4597a00dd90e571eeea175b9..51fb671a2801ecb389201f3a81eb0b6d6ed5b518 100644 (file)
@@ -492,7 +492,12 @@ void please_cite(FILE *fp,const char *key)
       "J. S. Hub and B. L. de Groot",
       "Mechanism of selectivity in aquaporins and aquaglyceroporins",
       "PNAS",
-      105, 2008, "1198-1203" }
+      105, 2008, "1198-1203" },
+    { "Engin2010",
+      "O. Engin, A. Villa, M. Sayar and B. Hess",
+      "Driving Forces for Adsorption of Amphiphilic Peptides to Air-Water Interface",
+      "J. Phys. Chem. B",
+      0, 2010, "???" }
   };
 #define NSTR (int)asize(citedb)
   
index 76aacbe5f87b5d09ed7d645cc764507e44476d4a..705167ce6fdd5edac97f1e4cf71f6c0d381e7bd0 100644 (file)
@@ -179,50 +179,38 @@ void init_disres(FILE *fplog,const gmx_mtop_t *mtop,
      */
     snew(dd->Rt_6,2*dd->nres);
     dd->Rtav_6 = &(dd->Rt_6[dd->nres]);
-    if (cr->ms)
+
+    ptr = getenv("GMX_DISRE_ENSEMBLE_SIZE");
+    if (cr->ms != NULL && ptr != NULL)
     {
-        ptr = getenv("GMX_DISRE_ENSEMBLE_SIZE");
 #ifdef GMX_MPI
-        if (ptr == NULL)
+        dd->nsystems = 0;
+        sscanf(ptr,"%d",&dd->nsystems);
+        if (fplog)
         {
-            dd->nsystems          = cr->ms->nsim;
-            dd->mpi_comm_ensemble = cr->ms->mpi_comm_masters;
-            if (fplog)
-            {
-                fprintf(fplog,"Will apply ensemble averaging over %d systems\n",
-                        dd->nsystems);
-            }
+            fprintf(fplog,"Found GMX_DISRE_ENSEMBLE_SIZE set to %d systems per ensemble\n",dd->nsystems);
         }
-        else
+        check_multi_int(fplog,cr->ms,dd->nsystems,
+                        "the number of systems per ensemble");
+        if (dd->nsystems <= 0 ||  cr->ms->nsim % dd->nsystems != 0)
         {
-            dd->nsystems = 0;
-            sscanf(ptr,"%d",&dd->nsystems);
-            if (fplog)
-            {
-                fprintf(fplog,"Found GMX_DISRE_ENSEMBLE_SIZE set to %d systems per ensemble\n",dd->nsystems);
-            }
-            check_multi_int(fplog,cr->ms,dd->nsystems,
-                            "the number of systems per ensemble");
-            if (dd->nsystems <= 0 ||  cr->ms->nsim % dd->nsystems != 0)
+            gmx_fatal(FARGS,"The number of systems %d is not divisible by the number of systems per ensemble %d\n",cr->ms->nsim,dd->nsystems);
+        }
+        /* Split the inter-master communicator into different ensembles */
+        MPI_Comm_split(cr->ms->mpi_comm_masters,
+                       cr->ms->sim/dd->nsystems,
+                       cr->ms->sim,
+                       &dd->mpi_comm_ensemble);
+        if (fplog)
+        {
+            fprintf(fplog,"Our ensemble consists of systems:");
+            for(i=0; i<dd->nsystems; i++)
             {
-                gmx_fatal(FARGS,"The number of systems %d is not divisible by the number of systems per ensemble %d\n",cr->ms->nsim,dd->nsystems);
+                fprintf(fplog," %d",
+                        (cr->ms->sim/dd->nsystems)*dd->nsystems+i);
             }
-            /* Split the inter-master communicator into different ensembles */
-            MPI_Comm_split(cr->ms->mpi_comm_masters,
-                           cr->ms->sim/dd->nsystems,
-                           cr->ms->sim,
-                           &dd->mpi_comm_ensemble);
-            if (fplog)
-            {
-                fprintf(fplog,"Our ensemble consists of systems:");
-                for(i=0; i<dd->nsystems; i++)
-                {
-                    fprintf(fplog," %d",
-                            (cr->ms->sim/dd->nsystems)*dd->nsystems+i);
-                }
-                fprintf(fplog,"\n");
+            fprintf(fplog,"\n");
             }
-        }
         snew(dd->Rtl_6,dd->nres);
 #endif
     }
index e0a52cb7c162011ca5a479823984baed88e6e1bf..54edb6ed6fa826206ca52ac4c9d8b27dbf33cdf3 100644 (file)
@@ -65,7 +65,7 @@ typedef struct {
 struct ener_file
 {
     ener_old_t eo;
-    int fp;
+    t_fileio *fio;
     int framenr;
     real frametime;
 };
@@ -147,13 +147,13 @@ void do_enxnms(ener_file_t ef,int *nre,gmx_enxnm_t **nms)
 {
     int  magic=-55555;
     XDR  *xdr;
-    bool bRead = gmx_fio_getread(ef->fp);
+    bool bRead = gmx_fio_getread(ef->fio);
     int  file_version;
     int  i;
-    
-    gmx_fio_select(ef->fp);
+   
+    gmx_fio_checktype(ef->fio); 
 
-    xdr = gmx_fio_getxdr(ef->fp);
+    xdr = gmx_fio_getxdr(ef->fio);
     
     if (!xdr_int(xdr,&magic))
     {
@@ -185,7 +185,7 @@ void do_enxnms(ener_file_t ef,int *nre,gmx_enxnm_t **nms)
         xdr_int(xdr,&file_version);
         if (file_version > enx_version)
         {
-            gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",gmx_fio_getname(ef->fp),file_version,enx_version);
+            gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",gmx_fio_getname(ef->fio),file_version,enx_version);
         }
         xdr_int(xdr,nre);
     }
@@ -204,7 +204,7 @@ static bool do_eheader(ener_file_t ef,int *file_version,t_enxframe *fr,
     int  magic=-7777777;
     real r;
     int  block,i,zero=0,dum=0;
-    bool bRead = gmx_fio_getread(ef->fp);
+    bool bRead = gmx_fio_getread(ef->fio);
     int  tempfix_nr=0;
     
     if (nre_test >= 0)
@@ -224,7 +224,7 @@ static bool do_eheader(ener_file_t ef,int *file_version,t_enxframe *fr,
      * number of blocks, where this number is read before).
      */
     r = -2e10;
-    if (!do_real(r))
+    if (!gmx_fio_do_real(ef->fio, r))
     {
         return FALSE;
     }
@@ -233,44 +233,44 @@ static bool do_eheader(ener_file_t ef,int *file_version,t_enxframe *fr,
         /* Assume we are reading an old format */
         *file_version = 1;
         fr->t = r;
-        if (!do_int(dum))   *bOK = FALSE;
+        if (!gmx_fio_do_int(ef->fio, dum))   *bOK = FALSE;
         fr->step = dum;
     }
     else
     {
-        if (!do_int(magic))       *bOK = FALSE;
+        if (!gmx_fio_do_int(ef->fio, magic))       *bOK = FALSE;
         if (magic != -7777777)
         {
             gmx_fatal(FARGS,"Energy header magic number mismatch, this is not a GROMACS edr file");
         }
         *file_version = enx_version;
-        if (!do_int (*file_version)) *bOK = FALSE;
+        if (!gmx_fio_do_int(ef->fio, *file_version)) *bOK = FALSE;
         if (*bOK && *file_version > enx_version)
         {
-            gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",gmx_fio_getname(ef->fp),file_version,enx_version);
+            gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",gmx_fio_getname(ef->fio),file_version,enx_version);
         }
-        if (!do_double(fr->t))       *bOK = FALSE;
-        if (!do_gmx_large_int(fr->step)) *bOK = FALSE;
+        if (!gmx_fio_do_double(ef->fio, fr->t))       *bOK = FALSE;
+        if (!gmx_fio_do_gmx_large_int(ef->fio, fr->step)) *bOK = FALSE;
         if (!bRead && fr->nsum == 1) {
             /* Do not store sums of length 1,
              * since this does not add information.
              */
-            if (!do_int (zero))      *bOK = FALSE;
+            if (!gmx_fio_do_int(ef->fio, zero))      *bOK = FALSE;
         } else {
-            if (!do_int (fr->nsum))  *bOK = FALSE;
+            if (!gmx_fio_do_int(ef->fio, fr->nsum))  *bOK = FALSE;
         }
         if (*file_version >= 3)
         {
-            do_gmx_large_int(fr->nsteps);
+            gmx_fio_do_gmx_large_int(ef->fio, fr->nsteps);
         }
         else
         {
             fr->nsteps = max(1,fr->nsum);
         }
     }
-    if (!do_int (fr->nre))     *bOK = FALSE;
-    if (!do_int (fr->ndisre))  *bOK = FALSE;
-    if (!do_int (fr->nblock))  *bOK = FALSE;
+    if (!gmx_fio_do_int(ef->fio, fr->nre))     *bOK = FALSE;
+    if (!gmx_fio_do_int(ef->fio, fr->ndisre))  *bOK = FALSE;
+    if (!gmx_fio_do_int(ef->fio, fr->nblock))  *bOK = FALSE;
 
     /* Frames could have nre=0, so we can not rely only on the fr->nre check */
     if (bRead && nre_test >= 0 &&
@@ -294,15 +294,15 @@ static bool do_eheader(ener_file_t ef,int *file_version,t_enxframe *fr,
     }
     for(block=0; block<fr->nblock; block++)
     {
-        if (!do_int (fr->nr[block])) 
+        if (!gmx_fio_do_int(ef->fio, fr->nr[block])) 
         {
             *bOK = FALSE;
         }
     }
-    if (!do_int (fr->e_size))  *bOK = FALSE;
-    if (!do_int (fr->d_size))  *bOK = FALSE;
+    if (!gmx_fio_do_int(ef->fio, fr->e_size))  *bOK = FALSE;
+    if (!gmx_fio_do_int(ef->fio, fr->d_size))  *bOK = FALSE;
     /* Do a dummy int to keep the format compatible with the old code */
-    if (!do_int (dum))         *bOK = FALSE;
+    if (!gmx_fio_do_int(ef->fio, dum))         *bOK = FALSE;
     
     if (*bOK && *file_version == 1 && nre_test < 0)
     {
@@ -343,7 +343,7 @@ void free_enxnms(int n,gmx_enxnm_t *nms)
 
 void close_enx(ener_file_t ef)
 {
-    if(gmx_fio_close(ef->fp) != 0)
+    if(gmx_fio_close(ef->fio) != 0)
     {
         gmx_file("Cannot close energy file; it might be corrupt, or maybe you are out of quota?");  
     }
@@ -377,9 +377,9 @@ ener_file_t open_enx(const char *fn,const char *mode)
     snew(ef,1);
 
     if (mode[0]=='r') {
-        ef->fp=gmx_fio_open(fn,mode);
-        gmx_fio_select(ef->fp);
-        gmx_fio_setprecision(ef->fp,FALSE);
+        ef->fio=gmx_fio_open(fn,mode);
+        gmx_fio_checktype(ef->fio);
+        gmx_fio_setprecision(ef->fio,FALSE);
         do_enxnms(ef,&nre,&nms);
         snew(fr,1);
         do_eheader(ef,&file_version,fr,nre,&bWrongPrecision,&bDum);
@@ -401,9 +401,9 @@ ener_file_t open_enx(const char *fn,const char *mode)
         }
         else
         {
-            gmx_fio_rewind(ef->fp);
-            gmx_fio_select(ef->fp);
-            gmx_fio_setprecision(ef->fp,TRUE);
+            gmx_fio_rewind(ef->fio);
+            gmx_fio_checktype(ef->fio);
+            gmx_fio_setprecision(ef->fio,TRUE);
             do_enxnms(ef,&nre,&nms);
             do_eheader(ef,&file_version,fr,nre,&bWrongPrecision,&bDum);
             if(!bDum)
@@ -430,10 +430,10 @@ ener_file_t open_enx(const char *fn,const char *mode)
         }
         free_enxframe(fr);
         sfree(fr);
-        gmx_fio_rewind(ef->fp);
+        gmx_fio_rewind(ef->fio);
     }
     else 
-        ef->fp = gmx_fio_open(fn,mode);
+        ef->fio = gmx_fio_open(fn,mode);
 
     ef->framenr=0;
     ef->frametime=0;
@@ -441,9 +441,9 @@ ener_file_t open_enx(const char *fn,const char *mode)
     return ef;
 }
 
-int enx_file_pointer(const ener_file_t ef)
+t_fileio *enx_file_pointer(const ener_file_t ef)
 {
-    return ef->fp;
+    return ef->fio;
 }
 
 static void convert_full_sums(ener_old_t *ener_old,t_enxframe *fr)
@@ -519,15 +519,15 @@ bool do_enx(ener_file_t ef,t_enxframe *fr)
     char      buf[22];
     
     bOK = TRUE;
-    bRead = gmx_fio_getread(ef->fp);
+    bRead = gmx_fio_getread(ef->fio);
     if (!bRead)
     {  
         fr->e_size = fr->nre*sizeof(fr->ener[0].e)*4;
         fr->d_size = fr->ndisre*(sizeof(fr->disre_rm3tav[0]) + 
                                  sizeof(fr->disre_rt[0]));
     }
-    gmx_fio_select(ef->fp);
-    
+    gmx_fio_checktype(ef->fio);
+
     if (!do_eheader(ef,&file_version,fr,-1,NULL,&bOK))
     {
         if (bRead)
@@ -568,7 +568,7 @@ bool do_enx(ener_file_t ef,t_enxframe *fr)
     if (!((fr->step >= 0) && bSane))
     {
         fprintf(stderr,"\nWARNING: there may be something wrong with energy file %s\n",
-                gmx_fio_getname(ef->fp));
+                gmx_fio_getname(ef->fio));
         fprintf(stderr,"Found: step=%s, nre=%d, ndisre=%d, nblock=%d, time=%g.\n"
                 "Trying to skip frame expect a crash though\n",
                 gmx_step_str(fr->step,buf),fr->nre,fr->ndisre,fr->nblock,fr->t);
@@ -587,7 +587,7 @@ bool do_enx(ener_file_t ef,t_enxframe *fr)
     
     for(i=0; i<fr->nre; i++)
     {
-        bOK = bOK && do_real(fr->ener[i].e);
+        bOK = bOK && gmx_fio_do_real(ef->fio, fr->ener[i].e);
         
         /* Do not store sums of length 1,
          * since this does not add information.
@@ -596,13 +596,13 @@ bool do_enx(ener_file_t ef,t_enxframe *fr)
             (bRead && fr->nsum > 0) || fr->nsum > 1)
         {
             tmp1 = fr->ener[i].eav;
-            bOK = bOK && do_real(tmp1);
+            bOK = bOK && gmx_fio_do_real(ef->fio, tmp1);
             if (bRead)
                 fr->ener[i].eav = tmp1;
             
             /* This is to save only in single precision (unless compiled in DP) */
             tmp2 = fr->ener[i].esum;
-            bOK = bOK && do_real(tmp2);
+            bOK = bOK && gmx_fio_do_real(ef->fio, tmp2);
             if (bRead)
                 fr->ener[i].esum = tmp2;
             
@@ -610,7 +610,7 @@ bool do_enx(ener_file_t ef,t_enxframe *fr)
             {
                 /* Old, unused real */
                 rdum = 0;
-                bOK = bOK && do_real(rdum);
+                bOK = bOK && gmx_fio_do_real(ef->fio, rdum);
             }
         }
     }
@@ -631,9 +631,9 @@ bool do_enx(ener_file_t ef,t_enxframe *fr)
             srenew(fr->disre_rt,fr->ndisre);
             fr->d_alloc = fr->ndisre;
         }
-        ndo_real(fr->disre_rm3tav,fr->ndisre,bOK1);
+        bOK1=gmx_fio_ndo_real(ef->fio, fr->disre_rm3tav,fr->ndisre);
         bOK = bOK && bOK1;
-        ndo_real(fr->disre_rt,fr->ndisre,bOK1);
+        bOK1=gmx_fio_ndo_real(ef->fio, fr->disre_rt,fr->ndisre);
         bOK = bOK && bOK1;
     }
     for(block=0; block<fr->nblock; block++)
@@ -643,13 +643,13 @@ bool do_enx(ener_file_t ef,t_enxframe *fr)
             srenew(fr->block[block],fr->nr[block]);
             fr->b_alloc[block] = fr->nr[block];
         }
-        ndo_real(fr->block[block],fr->nr[block],bOK1);
+        bOK1=gmx_fio_ndo_real(ef->fio, fr->block[block],fr->nr[block]);
         bOK = bOK && bOK1;
     }
     
     if(!bRead)
     {
-        if( gmx_fio_flush(ef->fp) != 0)
+        if( gmx_fio_flush(ef->fio) != 0)
         {
             gmx_file("Cannot write energy file; maybe you are out of quota?");
         }
@@ -716,7 +716,7 @@ void get_enx_state(const char *fn, real t, gmx_groups_t *groups, t_inputrec *ir,
   int nre,nfr,i,j,ni,npcoupl;
   char       buf[STRLEN];
   const char *bufi;
-  gmx_enxnm_t *enm;
+  gmx_enxnm_t *enm=NULL;
   t_enxframe *fr;
   ener_file_t in;
 
index ce6c4ceec8aabe723a9b0504098ebeabab1c983e..3aafd395ad84c511a3b4a35d78f35a88c08235e8 100644 (file)
@@ -1002,3 +1002,17 @@ t_filenm *dup_tfn(int nf, const t_filenm tfn[])
     return ret;
 }
 
+void done_filenms(int nf, t_filenm fnm[])
+{
+    int i, j;
+
+    for (i = 0; i < nf; ++i)
+    {
+        for (j = 0; j < fnm[i].nfiles; ++j)
+        {
+            sfree(fnm[i].fns[j]);
+        }
+        sfree(fnm[i].fns);
+        fnm[i].fns = NULL;
+    }
+}
index 2a040682483674c45157d0f1d61b5823d2272388..8483ad9ff1342d845e6eb2fdbbe85f4e0ad7771a 100644 (file)
 #include <sys/stat.h>
 #include <fcntl.h>
 
+#ifdef HAVE_COPYFILE_H
+/* BSD specific */
+#include <copyfile.h>
+#endif
+
 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
 #include <direct.h>
 #include <io.h>
@@ -57,6 +62,7 @@
 #include "smalloc.h"
 #include "statutil.h"
 
+
 #ifdef GMX_THREADS
 #include "thread_mpi.h"
 #endif
@@ -270,7 +276,7 @@ bool gmx_fexist(const char *fname)
     if (test == NULL) 
         return FALSE;
     else {
-        ffclose(test);
+        fclose(test);
         return TRUE;
     }
 }
@@ -305,17 +311,22 @@ bool gmx_eof(FILE *fp)
     }
 }
 
-char *backup_fn(const char *file)
+static char *backup_fn(const char *file,int count_max)
 {
     /* Use a reasonably low value for countmax; we might
      * generate 4-5 files in each round, and we dont
      * want to hit directory limits of 1024 or 2048 files.
      */
-#define COUNTMAX 128
+#define COUNTMAX 99
     int         i,count=1;
     char        *directory,*fn;
     char        *buf;
 
+    if (count_max == -1)
+    {
+        count_max = COUNTMAX;
+    }
+
     smalloc(buf, GMX_PATH_MAX);
 
     for(i=strlen(file)-1; ((i > 0) && (file[i] != '/')); i--)
@@ -336,12 +347,13 @@ char *backup_fn(const char *file)
     do {
         sprintf(buf,"%s/#%s.%d#",directory,fn,count);
         count++;
-    } while ((count < COUNTMAX) && gmx_fexist(buf));
+    } while ((count <= count_max) && gmx_fexist(buf));
 
     /* Arbitrarily bail out */
-    if (count == COUNTMAX) 
-        gmx_fatal(FARGS,"Won't make more than %d backups of %s for you",
-                COUNTMAX,fn);
+    if (count > count_max) 
+        gmx_fatal(FARGS,"Won't make more than %d backups of %s for you.\n"
+                  "The env.var. GMX_MAXBACKUP controls this maximum, -1 disables backups.",
+                  count_max,fn);
 
     sfree(directory);
     sfree(fn);
@@ -351,14 +363,33 @@ char *backup_fn(const char *file)
 
 bool make_backup(const char * name)
 {
+    char * env;
+    int  count_max;
     char * backup;
 
 #ifdef GMX_FAHCORE
     return FALSE; /* skip making backups */
 #else
 
-    if(gmx_fexist(name)) {
-        backup = backup_fn(name);
+    if (gmx_fexist(name))
+    {
+        env = getenv("GMX_MAXBACKUP");
+        if (env != NULL)
+        {
+            count_max = 0;
+            sscanf(env,"%d",&count_max);
+            if (count_max == -1)
+            {
+                /* Do not make backups and possibly overwrite old files */
+                return TRUE;
+            }
+        }
+        else
+        {
+            /* Use the default maximum */
+            count_max = -1;
+        }
+        backup = backup_fn(name,count_max);
         if(rename(name, backup) == 0) {
             fprintf(stderr, "\nBack Off! I just backed up %s to %s\n",
                     name, backup);
@@ -714,8 +745,7 @@ void gmx_tmpnam(char *buf)
     /* name in Buf should now be OK */
 }
 
-    int
-gmx_truncatefile(char *path, off_t length)
+int gmx_truncatefile(char *path, off_t length)
 {
 #ifdef _MSC_VER
     /* Microsoft visual studio does not have "truncate" */
@@ -735,3 +765,90 @@ gmx_truncatefile(char *path, off_t length)
     return truncate(path,length);
 #endif
 }
+
+
+int gmx_file_rename(const char *oldname, const char *newname)
+{
+#if (!(defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)))
+    /* under unix, rename() is atomic (at least, it should be). */
+    return rename(oldname, newname);
+#else
+    if (MoveFileEx(oldname, newname, 
+                   MOVEFILE_REPLACE_EXISTING|MOVEFILE_WRITE_THROUGH))
+        return 0;
+    else
+        return 1;
+#endif
+}
+
+int gmx_file_copy(const char *oldname, const char *newname, bool copy_if_empty)
+{
+#if defined(HAVE_COPYFILE_H) && !defined(GMX_FAHCORE)
+    /* this is BSD specific, but convenient */
+    return copyfile(oldname, newname, NULL, COPYFILE_DATA);
+#elif defined(HAVE_WIN_COPYFILE) && !defined(GMX_FAHCORE)
+    if (CopyFile(oldname, newname, FALSE))
+        return 0;
+    else
+        return 1;
+#else
+#define FILECOPY_BUFSIZE (1<<16)
+    /* POSIX doesn't support any of the above. */
+    FILE *in=NULL; 
+    FILE *out=NULL;
+    char *buf;
+
+    snew(buf, FILECOPY_BUFSIZE); 
+
+    in=fopen(oldname, "rb");
+    if (!in)
+        goto error;
+
+    /* If we don't copy when empty, we postpone opening the file
+       until we're actually ready to write. */
+    if (copy_if_empty)
+    {
+        out=fopen(newname, "wb");
+        if (!out)
+            goto error;
+    }
+
+    while(!feof(in))
+    {
+        size_t nread;
+        
+        nread=fread(buf, sizeof(char), FILECOPY_BUFSIZE, in);
+        if (nread>0)
+        {
+            size_t ret;
+            if (!out)
+            {
+                out=fopen(newname, "wb");
+                if (!out)
+                    goto error;
+            }
+            ret=fwrite(buf, sizeof(char), nread, out);
+            if (ret!=nread)
+            {
+                goto error;
+            }
+        }
+        if (ferror(in))
+            goto error;
+    }
+    sfree(buf);
+    fclose(in);
+    fclose(out);
+    return 0;
+error:
+    sfree(buf);
+    if (in)
+        fclose(in);
+    if (out)
+        fclose(out);
+    return 1;
+#undef FILECOPY_BUFSIZE
+#endif
+}
+
+
index c69bbaf1d47d4367f7ab164de90ad0de3efd8320..d148095bfa3ecdb28752dae29d68d9a70e495752 100644 (file)
@@ -83,6 +83,30 @@ static void low_rotate_conf(int natom,rvec *x,real alfa, real beta,real gamma)
   }
 }
 
+static void low_rotate_conf_indexed(int nindex,atom_id *index,rvec *x,real alfa, real beta,real gamma)
+{
+  int  i;
+  rvec x_old;
+  
+  for (i=0; i<nindex; i++) { 
+    copy_rvec(x[index[i]],x_old);
+    /*calculate new x[index[i]] by rotation alfa around the x-axis*/
+    x[index[i]][XX]=   x_old[XX];
+    x[index[i]][YY]=             cos(alfa)*x_old[YY] - sin(alfa)*x_old[ZZ];
+    x[index[i]][ZZ]=             sin(alfa)*x_old[YY] + cos(alfa)*x_old[ZZ];
+    copy_rvec(x[index[i]],x_old);
+    /*calculate new x[index[i]] by rotation beta around the y-axis*/
+    x[index[i]][XX]=   cos(beta)*x_old[XX]           + sin(beta)*x_old[ZZ];
+    x[index[i]][YY]=                       x_old[YY];
+    x[index[i]][ZZ]= - sin(beta)*x_old[XX]           + cos(beta)*x_old[ZZ];
+    copy_rvec(x[index[i]],x_old);
+    /*calculate new x[index[i]] by rotation gamma around the z-axis*/
+    x[index[i]][XX]= x_old[XX]*cos(gamma) - x_old[YY]*sin(gamma);
+    x[index[i]][YY]= x_old[XX]*sin(gamma) + x_old[YY]*cos(gamma);
+    x[index[i]][ZZ]=                                             x_old[ZZ];
+  }
+}
+
 void rotate_conf(int natom,rvec *x,rvec *v,real alfa, real beta,real gamma)
 {
   if (x)
@@ -91,6 +115,13 @@ void rotate_conf(int natom,rvec *x,rvec *v,real alfa, real beta,real gamma)
     low_rotate_conf(natom,v,alfa,beta,gamma);
 }
 
+void rotate_conf_indexed(int nindex,atom_id *index,rvec *x,rvec *v,real alfa, real beta,real gamma)
+{
+  if (x)
+    low_rotate_conf_indexed(nindex,index,x,alfa,beta,gamma);
+  if (v)
+    low_rotate_conf_indexed(nindex,index,v,alfa,beta,gamma);
+}
 
 void orient(int natom,rvec *x,rvec *v, rvec angle,matrix box)
 {
index ed27e5d3a98608cd5bcc48760057c2a4e8f1ca1e..5edc5dcb0700589bbc8b83ec2c49b2fca117fc52 100755 (executable)
@@ -1,6 +1,7 @@
 #!/bin/sh
 
 # usage: genversion.sh PKGVERSION top_srcdir
+# Requires git 1.5.1 or later
 
 PKGVERSION=$1
 SRCDIR=$2
@@ -10,7 +11,17 @@ if which git >/dev/null && test -d $GITDIR ; then
     # Get either -dirty or an empty string, depending on whether there are local changes.
     dirtystr=`(cd $SRCDIR && git diff-index --quiet HEAD) || echo "-dirty"`
     # Get date of the head commit as YYYYMMDD (commit date).
-    date=`git --git-dir=$GITDIR rev-list -n1 --pretty=format:%ci HEAD | sed -ne '/commit/!{s/-\| .*$//g;p;}'`
+    # Git before 1.5.3 does not support any sensible date format,
+    # so we need to massage the output.
+    if test "`git --version`" \< "git version 1.5.3" ; then
+        date=`git --git-dir=$GITDIR rev-list -n1 --pretty=format:%cD HEAD | \
+              sed -ne '/commit/!{s/^.*, *\([ 0-9][0-9]\) \([a-zA-Z]*\) \([0-9]*\) .*$/\3\2\1/;y/ /0/;\
+                   s/Jan/01/;s/Feb/02/;s/Mar/03/;s/Apr/04/;s/May/05/;s/Jun/06/;
+                   s/Jul/07/;s/Aug/08/;s/Sep/09/;s/Oct/10/;s/Nov/11/;s/Dec/12/;
+                   p;}'`
+    else
+        date=`git --git-dir=$GITDIR rev-list -n1 --pretty=format:%ci HEAD | sed -ne '/commit/!{s/-\| .*$//g;p;}'`
+    fi
     # Get a 7-character hash for the HEAD commit.
     shorthash=`git --git-dir=$GITDIR rev-parse --short=7 HEAD 2>/dev/null`
     # Get the full hash for the HEAD commit.
index 9d2aef5a33f8a80f4ee9bf9e404af266174b9b01..f1f403ce8ba1d09e62b8b6e6cecf56e7a6016656 100644 (file)
 #include "smalloc.h"
 #include "gmxfio.h"
 
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
 #ifdef GMX_THREADS
-#include "thread_mpi.h"
+#include "tmpi.h"
 #endif
 
 static bool bDebug = FALSE;
@@ -192,10 +195,12 @@ static void quit_gmx(const char *msg)
 #ifdef GMX_THREADS
     tMPI_Thread_mutex_lock(&debug_mutex);
 #endif
-    if (!fatal_errno
+    if (fatal_errno == 0
     {
-        if (log_file) 
+        if (log_file)
+        {
             fprintf(log_file,"%s\n",msg);
+        }
         fprintf(stderr,"%s\n",msg);
         /* we set it to no-zero because if this function is called, something 
            has gone wrong */
@@ -204,12 +209,15 @@ static void quit_gmx(const char *msg)
     else 
     {
         if (fatal_errno != -1)
+        {
             errno=fatal_errno;
+        }
         perror(msg);
     }
 
 #ifndef GMX_THREADS 
-    if (gmx_parallel_env_initialized()) {
+    if (gmx_parallel_env_initialized())
+    {
         int  nnodes;
         int  noderank;
 
@@ -240,6 +248,47 @@ static void quit_gmx(const char *msg)
 #endif
 }
 
+/* The function below should be identical to quit_gmx,
+ * except that is does not actually quit and call gmx_abort.
+ */
+static void quit_gmx_noquit(const char *msg)
+{
+#ifdef GMX_THREADS
+    tMPI_Thread_mutex_lock(&debug_mutex);
+#endif
+    if (!fatal_errno) 
+    {
+        if (log_file) 
+            fprintf(log_file,"%s\n",msg);
+        fprintf(stderr,"%s\n",msg);
+        /* we set it to no-zero because if this function is called, something 
+           has gone wrong */
+        fatal_errno=255;
+    }
+    else 
+    {
+        if (fatal_errno != -1)
+            errno=fatal_errno;
+        perror(msg);
+    }
+
+    if (!gmx_parallel_env_initialized())
+    {
+        if (debug)
+            fflush(debug);
+        if (bDebugMode()) {
+            fprintf(stderr,"dump core (y/n):"); 
+            fflush(stderr);
+            if (toupper(getc(stdin))!='N') 
+                (void) abort(); 
+        }
+    }
+
+#ifdef GMX_THREADS
+    tMPI_Thread_mutex_unlock(&debug_mutex);
+#endif
+}
+
 void _set_fatal_tmp_file(const char *fn, const char *file, int line)
 {
 #ifdef GMX_THREADS
@@ -392,13 +441,37 @@ void gmx_fatal(int f_errno,const char *file,int line,const char *fmt,...)
 }
 
 void gmx_fatal_collective(int f_errno,const char *file,int line,
-                          bool bMaster,
+                          t_commrec *cr,gmx_domdec_t *dd,
                           const char *fmt,...)
 {
+    bool    bFinalize;
     va_list ap;
     char    msg[STRLEN];
-    
-    if (bMaster)
+#ifdef GMX_MPI
+    int     result;
+#endif
+
+    bFinalize = TRUE;
+
+#ifdef GMX_MPI
+    if (gmx_parallel_env_initialized())
+    {
+        /* Check if we are calling on all processes in MPI_COMM_WORLD */ 
+        if (cr != NULL)
+        {
+            MPI_Comm_compare(cr->mpi_comm_mysim,MPI_COMM_WORLD,&result);
+        }
+        else
+        {
+            MPI_Comm_compare(dd->mpi_comm_all,MPI_COMM_WORLD,&result);
+        }
+        /* Any result except MPI_UNEQUAL allows us to call MPI_Finalize */
+        bFinalize = (result != MPI_UNEQUAL);
+    }
+#endif
+
+    if ((cr != NULL && MASTER(cr)  ) ||
+        (dd != NULL && DDMASTER(dd)))
     {
         va_start(ap,fmt);
         
@@ -418,15 +491,42 @@ void gmx_fatal_collective(int f_errno,const char *file,int line,
         tMPI_Thread_mutex_unlock(&debug_mutex);
 #endif
 
+        if (bFinalize)
+        {
+            /* Use an error handler that does not quit */
+            set_gmx_error_handler(quit_gmx_noquit);
+        }
+
         _gmx_error("fatal",msg,file,line);
     }
 
 #ifdef GMX_MPI
-    /* Let all other processes wait till the master has printed
-     * the error message and issued MPI_Abort.
-     */
-    MPI_Barrier(MPI_COMM_WORLD);
+    if (gmx_parallel_env_initialized())
+    {
+        if (bFinalize)
+        {
+            /* Broadcast the fatal error number possibly modified
+             * on the master process, in case the user would like
+             * to use the return status on a non-master process.
+             * The master process in cr and dd always has global rank 0.
+             */
+            MPI_Bcast(&fatal_errno,sizeof(fatal_errno),MPI_BYTE,
+                      0,MPI_COMM_WORLD);
+
+            /* Finalize nicely instead of aborting */
+            MPI_Finalize();
+        }
+        else
+        {
+            /* Let all other processes wait till the master has printed
+             * the error message and issued MPI_Abort.
+             */
+            MPI_Barrier(MPI_COMM_WORLD);
+        }
+    }
 #endif
+
+    exit(fatal_errno);
 }
 
 void _invalid_case(const char *fn,int line)
@@ -588,8 +688,8 @@ void _gmx_error(const char *key,const char *msg,const char *file,int line)
     strerr = gmx_strerror(key);
     sprintf(buf,"\n%s\nProgram %s, %s\n"
             "Source code file: %s, line: %d\n\n"
-            "%s:\n%s\nFor more information and tips for trouble shooting please check the GROMACS website at\n"
-            "http://www.gromacs.org/Documentation/Errors\n%s\n\n%s\n",
+            "%s:\n%s\nFor more information and tips for troubleshooting, please check the GROMACS\n"
+            "website at http://www.gromacs.org/Documentation/Errors\n%s\n\n%s\n",
             llines,ShortProgram(),GromacsVersion(),file,line,
             strerr,msg ? msg : errerrbuf,llines,tmpbuf);
     free(strerr);
diff --git a/src/gmxlib/gmx_matrix.c b/src/gmxlib/gmx_matrix.c
new file mode 100644 (file)
index 0000000..c0a71b6
--- /dev/null
@@ -0,0 +1,215 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ * $Id: gmx_matrix.c,v 1.4 2008/12/02 18:27:57 spoel Exp $
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 4.0.99
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Groningen Machine for Chemical Simulation
+ */
+#include <stdlib.h>
+#include "typedefs.h"
+#include "smalloc.h"
+#include "vec.h"
+#include "gmx_fatal.h"
+#include "gmx_matrix.h"
+#include "gmx_lapack.h"
+
+double **alloc_matrix(int n,int m)
+{
+    double **ptr;
+    int i;
+  
+    /* There's always time for more pointer arithmetic! */
+    /* This is necessary in order to be able to work with LAPACK */
+    snew(ptr,n);
+    snew(ptr[0],n*m);
+    for(i=1; (i<n); i++) 
+        ptr[i] = ptr[i-1]+m;
+    return ptr;
+}
+
+void free_matrix(double **a,int n)
+{
+    int i;
+    
+    sfree(a[0]);
+    sfree(a);
+}
+
+#define DEBUG_MATRIX
+void matrix_multiply(FILE *fp,int n,int m,double **x,double **y,double **z)
+{
+    int i,j,k;
+  
+#ifdef DEBUG_MATRIX
+    if (fp)
+        fprintf(fp,"Multiplying %d x %d matrix with a %d x %d matrix\n",
+                n,m,m,n);
+    if (fp)
+        for(i=0; (i<n); i++) 
+        {
+            for(j=0; (j<m); j++) 
+                fprintf(fp," %7g",x[i][j]);
+            fprintf(fp,"\n");
+        }
+#endif
+    for(i=0; (i<m); i++) 
+    {
+        for(j=0; (j<m); j++) 
+        {
+            z[i][j] = 0;
+            for(k=0; (k<n); k++)
+                z[i][j] += x[k][i]*y[j][k];
+        }
+    }
+}
+
+static void dump_matrix(FILE *fp,const char *title,int n,double **a)
+{
+    double d=1;
+    int i,j;
+
+    fprintf(fp,"%s\n",title);
+    for(i=0; (i<n); i++)  
+    {
+        d = d*a[i][i];
+        for(j=0; (j<n); j++)  
+        {
+            fprintf(fp," %8.2f",a[i][j]);
+        }
+        fprintf(fp,"\n");
+    }
+    fprintf(fp,"Prod a[i][i] = %g\n",d);
+}
+
+int matrix_invert(FILE *fp,int n,double **a)
+{
+    int i,j,m,lda,*ipiv,lwork,info;
+    double **test=NULL,**id,*work;
+  
+#ifdef DEBUG_MATRIX
+    if (fp) 
+    {
+        fprintf(fp,"Inverting %d square matrix\n",n);
+        test = alloc_matrix(n,n);  
+        for(i=0; (i<n); i++)  
+        {
+            for(j=0; (j<n); j++)  
+            {
+                test[i][j] = a[i][j];
+            }
+        }
+        dump_matrix(fp,"before inversion",n,a);
+    }
+#endif
+    snew(ipiv,n);
+    lwork = n*n;
+    snew(work,lwork);
+    m = lda   = n;
+    info  = 0;
+    F77_FUNC(dgetrf,DGETRF)(&n,&m,a[0],&lda,ipiv,&info);
+#ifdef DEBUG_MATRIX
+    if (fp)
+        dump_matrix(fp,"after dgetrf",n,a);
+#endif
+    if (info != 0)
+        return info;
+    F77_FUNC(dgetri,DGETRI)(&n,a[0],&lda,ipiv,work,&lwork,&info);
+#ifdef DEBUG_MATRIX
+    if (fp)
+        dump_matrix(fp,"after dgetri",n,a);
+#endif
+    if (info != 0)
+        return info;
+    
+#ifdef DEBUG_MATRIX
+    if (fp) 
+    {
+        id = alloc_matrix(n,n);
+        matrix_multiply(fp,n,n,test,a,id);
+        dump_matrix(fp,"And here is the product of A and Ainv",n,id);
+        free_matrix(id,n);
+        free_matrix(test,n);
+    }
+#endif
+    sfree(ipiv);
+    sfree(work);
+  
+    return 0;
+}
+
+double multi_regression(FILE *fp,int nrow,double *y,int ncol,
+                        double **xx,double *a0)
+{
+  int    row,niter,i,j;
+  double ax,chi2,**a,**at,**ata,*atx;
+  
+  a   = alloc_matrix(nrow,ncol);
+  at  = alloc_matrix(ncol,nrow);
+  ata = alloc_matrix(ncol,ncol);
+  for(i=0; (i<nrow); i++)
+      for(j=0; (j<ncol); j++)
+          at[j][i] = a[i][j] = xx[j][i];
+  matrix_multiply(fp,nrow,ncol,a,at,ata);
+  if ((row = matrix_invert(fp,ncol,ata)) != 0) {
+      gmx_fatal(FARGS,"Matrix inversion failed. Incorrect row = %d.\nThis probably indicates that you do not have sufficient data points, or that some parameters are linearly dependent.",
+                row);
+  }
+  snew(atx,ncol);
+  
+  for(i=0; (i<ncol); i++)  
+  {
+      atx[i] = 0;
+      for(j=0; (j<nrow); j++)
+          atx[i] += at[i][j]*y[j];
+  }
+  for(i=0; (i<ncol); i++) 
+  {
+      a0[i] = 0;
+      for(j=0; (j<ncol); j++)
+          a0[i] += ata[i][j]*atx[j];
+  }
+  chi2 = 0;
+  for(j=0; (j<nrow); j++)
+  {
+      ax = 0;
+      for(i=0; (i<ncol); i++)  
+          ax += a0[i]*a[j][i];
+      chi2 += sqr(y[j]-ax);
+  }
+  
+  sfree(atx);
+  free_matrix(a,nrow);
+  free_matrix(at,ncol);
+  free_matrix(ata,ncol);
+  
+  return chi2;
+}
+
diff --git a/src/gmxlib/gmx_sort.c b/src/gmxlib/gmx_sort.c
new file mode 100644 (file)
index 0000000..2c9407f
--- /dev/null
@@ -0,0 +1,230 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ * This file is part of Gromacs        Copyright (c) 1991-2010
+ * David van der Spoel, Erik Lindahl, Berk Hess, University of Groningen.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the research papers on the package. Check out http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gnomes, ROck Monsters And Chili Sauce
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include "gmx_sort.h"
+
+
+static void 
+qsort_swapfunc(void *        a,
+               void *        b,
+               size_t        n, 
+               int           swaptype)
+{
+    int *  ia;
+    int *  ib;
+    int    itmp;
+    
+    char *  ca;
+    char *  cb;
+    char    ctmp;    
+    
+    if (swaptype <= 1) 
+    {
+        ia = (int *)a;
+        ib = (int *)b;
+        for( ; n > 0; ia += 1, ib += 1, n -= sizeof(int))
+        {
+            itmp      = *ia;
+            *ia       = *ib;
+            *ib       = itmp;
+        } 
+    } 
+    else 
+    {
+        ca = (char *)a;
+        cb = (char *)b;
+        for( ; n > 0; ca += 1, cb += 1, n -= 1)
+        {
+            ctmp       = *ca;
+            *ca        = *cb;
+            *cb        = ctmp;
+        }
+    }
+}
+
+
+static void *
+qsort_med3(void *        a,
+           void *        b, 
+           void *        c, 
+           int          (*compar) (const void *a, const void *b))
+{   
+    if(compar(a,b) < 0)
+    {
+        if(compar(b,c) < 0)
+            return b;
+        else if(compar(a,c) < 0)
+            return c;
+        else
+            return a;
+    }
+    else
+    {
+        if(compar(b,c) > 0)
+            return b;
+        else if(compar(a,c) > 0)
+            return c;
+        else
+            return a;
+    }
+}
+
+
+void
+gmx_qsort(void *           base,
+          size_t           nmemb,
+          size_t           size,
+          int            (*compar)(const void *, const void *))
+{
+#define QSORT_EXCH(a, b, t) (t = a, a = b, b = t);
+#define QSORT_SWAP(a, b) swaptype != 0 ? qsort_swapfunc(a, b, size, swaptype) : \
+                            (void)QSORT_EXCH(*(int *)(a), *(int *)(b), t)    
+    
+    char *pa, *pb, *pc, *pd, *pl, *pm, *pn, *pv, *cbase;
+    int r, swaptype;
+    int t, v;
+    size_t s, st;
+        
+    cbase = (char *)base;
+    
+    swaptype = (size_t)(cbase - (char *)0) % sizeof(int) || size % sizeof(int) ? 2 : size == sizeof(int)? 0 : 1;
+    
+    if (nmemb < 7)
+    {
+        /* Insertion sort on smallest arrays */
+        for (pm = cbase + size; pm < cbase + nmemb*size; pm += size)
+        {
+            for (pl = pm; (pl > cbase) && compar((void *)(pl-size),(void *) pl) > 0; pl -= size)
+            {
+                QSORT_SWAP(pl, pl-size);
+            }
+        }
+        return;
+    }
+    
+    /* Small arrays, middle element */
+    pm = cbase + (nmemb/2)*size;      
+    
+    if (nmemb > 7)
+    {
+        pl = cbase;
+        pn = cbase + (nmemb-1)*size;
+        if (nmemb > 40)
+        {      
+            /* Big arrays, pseudomedian of 9 */
+            s = (nmemb/8)*size;
+            pl = (char *)qsort_med3((void *)pl, (void *)((size_t)pl+s), (void *)((size_t)pl+2*s), compar);
+            pm = (char *)qsort_med3((void *)((size_t)pm-s), (void *)pm, (void *)((size_t)pm+s), compar);
+            pn = (char *)qsort_med3((void *)((size_t)pn-2*s), (void *)((size_t)pn-s), (void *)pn, compar);
+        }
+        /* Mid-size, med of 3 */
+        pm = (char *)qsort_med3((void *)pl, (void *)pm, (void *)pn, compar);    
+    }
+    
+    /* pv points to partition value */
+    if (swaptype != 0) 
+    { 
+        pv = cbase;
+        QSORT_SWAP(pv, pm); 
+    } 
+    else 
+    {
+        pv = (char*)(void*)&v; 
+        v = *(int *)pm; 
+    }
+    
+    pa = pb = cbase;
+    pc = pd = cbase + (nmemb-1)*size;
+    
+    for (;;) 
+    {
+        while (pb <= pc && (r = compar((void *)pb,(void *) pv)) <= 0)
+        {
+            if (r == 0) 
+            { 
+                QSORT_SWAP(pa, pb); 
+                pa += size;
+            }
+            pb += size;
+        }
+        while (pc >= pb && (r = compar((void *)pc,(void *) pv)) >= 0) 
+        {
+            if (r == 0)
+            { 
+                QSORT_SWAP(pc, pd); 
+                pd -= size; 
+            }
+            pc -= size;
+        }
+        if (pb > pc) 
+        {
+            break;
+        }
+        QSORT_SWAP(pb, pc);
+        pb += size;
+        pc -= size;
+    }
+    pn = cbase + nmemb*size;
+    
+    s  = pa-cbase;
+    st = pb-pa;
+    if(st<s)
+    {
+        s = st;
+    }
+    
+    if(s>0)
+    {
+        qsort_swapfunc(cbase, pb-s, s, swaptype);
+    }
+    
+    s = pd-pc;
+    st = pn-pd-size;
+    if(st<s)
+    {
+        s = st;
+    }
+    
+    if(s>0)
+    {
+        qsort_swapfunc(pb, pn-s, s, swaptype);
+    }
+    
+    if ((s = pb-pa) > size) 
+    {
+        gmx_qsort(cbase, s/size, size, compar);
+    }
+    
+    if ((s = pd-pc) > size) 
+    {
+        gmx_qsort(pn-s, s/size, size, compar);
+    }
+    
+#undef QSORT_EXCH
+#undef QSORT_SWAP
+    
+    return;
+}
+
+
+
index 37495fcca46221e216698a4e4893e0a9adcb0ea2..184faac77b8685a8ae66d5ed327603c5566185ee 100644 (file)
@@ -95,7 +95,7 @@
 /*
  * for unit alignment
  */
-static char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
+const static char xdr_zero[BYTES_PER_XDR_UNIT] = {0, 0, 0, 0};
 
 static xdr_uint32_t xdr_swapbytes(xdr_uint32_t x)
 {
@@ -351,7 +351,7 @@ bool_t
 xdr_opaque (XDR *xdrs, char *cp, unsigned int cnt)
 {
   unsigned int rndup;
-  static char crud[BYTES_PER_XDR_UNIT];
+  char crud[BYTES_PER_XDR_UNIT];
 
   /*
    * if no data we are done
@@ -515,8 +515,14 @@ xdr_double(xdrs, dp)
   /* Windows and some other systems dont define double-precision
    * word order in the header files, so unfortunately we have
    * to calculate it!
+   *
+   * For thread safety, we calculate it every time: locking this would
+   * be more expensive.
    */
-  static int LSW=-1; /* Least significant fp word */
+  /*static int LSW=-1;*/ /* Least significant fp word */
+  int LSW=-1; /* Least significant fp word */
+  
+
   int *ip;
   xdr_int32_t tmp[2];
 
index f40c290183669f912daadad0ff7a3b34f8eb7a97..5411fbf327be114375600b6a0b3540adbc00fa2f 100644 (file)
@@ -151,18 +151,10 @@ static void add_include(const char *include)
   }
 }
 
-static void add_define(const char *define)
+static void add_define(const char *name, const char *value)
 {
   int  i;
-  const char *ptr;
-  char name[256];
-  
-  sscanf(define,"%s%n",name,&i);
-  ptr = define + i;
-  
-  while ((*ptr != '\0') && isspace(*ptr))
-    ptr++;
-    
+
   for(i=0; (i<ndef); i++) {
     if (strcmp(defs[i].name,name) == 0) {
       break;
@@ -179,8 +171,8 @@ static void add_define(const char *define)
       fprintf(debug,"Overriding define %s\n",name);
     sfree(defs[i].def);
   }
-  if (strlen(ptr) > 0)
-    defs[i].def  = strdup(ptr);
+  if (value && strlen(value) > 0)
+    defs[i].def  = strdup(value);
   else
     defs[i].def  = NULL;
 }
@@ -191,7 +183,7 @@ int cpp_open_file(const char *filenm,gmx_cpp_t *handle, char **cppopts)
 {
   gmx_cpp_t cpp;
   char *buf,*pdum;
-  const char *ptr;
+  char *ptr;
   int i;
   unsigned int i1;
   
@@ -203,7 +195,20 @@ int cpp_open_file(const char *filenm,gmx_cpp_t *handle, char **cppopts)
       if (strstr(cppopts[i],"-I") == cppopts[i])
        add_include(cppopts[i]+2);
       if (strstr(cppopts[i],"-D") == cppopts[i])
-       add_define(cppopts[i]+2);
+      {
+        /* If the option contains a =, split it into name and value. */
+        ptr = strchr(cppopts[i], '=');
+        if (ptr)
+        {
+          buf = strndup(cppopts[i] + 2, ptr - cppopts[i] - 2);
+          add_define(buf, ptr + 1);
+          sfree(buf);
+        }
+        else
+        {
+          add_define(cppopts[i] + 2, NULL);
+        }
+      }
       i++;
     }
   }
@@ -212,22 +217,51 @@ int cpp_open_file(const char *filenm,gmx_cpp_t *handle, char **cppopts)
   
   snew(cpp,1);
   *handle      = cpp;
-  ptr = strrchr(filenm,'/');
-  if (NULL == ptr) {
+  cpp->fn      = NULL;
+  /* Find the file. First check whether it is in the current directory. */
+  if (gmx_fexist(filenm))
+  {
+    cpp->fn = strdup(filenm);
+  }
+  else
+  {
+    /* If not, check all the paths given with -I. */
+    for (i = 0; i < nincl; ++i)
+    {
+      snew(buf, strlen(incl[i]) + strlen(filenm) + 2);
+      sprintf(buf, "%s%c%s", incl[i], DIR_SEPARATOR, filenm);
+      if (gmx_fexist(buf))
+      {
+        cpp->fn = buf;
+        break;
+      }
+      sfree(buf);
+    }
+    /* If still not found, check the Gromacs library search path. */
+    if (!cpp->fn)
+    {
+      cpp->fn = low_gmxlibfn(filenm, FALSE);
+    }
+  }
+  if (!cpp->fn)
+  {
+    gmx_fatal(FARGS, "Topology include file \"%s\" not found", filenm);
+  }
+  /* If the file name has a path component, we need to change to that
+   * directory. */
+  ptr = strrchr(cpp->fn, DIR_SEPARATOR);
+  if (!ptr)
+  {
     cpp->path = NULL;
     cpp->cwd  = NULL;
-    cpp->fn   = strdup(filenm);
   }
-  else {
-    buf = strdup(filenm);
-    buf[ptr-filenm] = '\0';
+  else
+  {
+    cpp->path = cpp->fn;
+    *ptr      = '\0';
     cpp->fn   = strdup(ptr+1);
     snew(cpp->cwd,STRLEN);
 
-    /* Search for the directory in cwd and the GROMACS search path */
-    cpp->path = gmxlibfn(buf);
-    sfree(buf);
-      
 #if ((defined WIN32 || defined _WIN32 || defined WIN64 || defined _WIN64) && !defined __CYGWIN__ && !defined __CYGWIN32__)
       pdum=_getcwd(cpp->cwd,STRLEN);
       _chdir(cpp->path);
@@ -249,19 +283,8 @@ int cpp_open_file(const char *filenm,gmx_cpp_t *handle, char **cppopts)
   cpp->ifdefs  = NULL;
   cpp->child   = NULL;
   cpp->parent  = NULL;
-  i = 0;
-  while (((cpp->fp = fopen(cpp->fn,"r")) == NULL) && (i<nincl)) {
-    snew(buf,strlen(incl[i])+strlen(filenm)+2);
-    sprintf(buf,"%s/%s",incl[i],filenm);
-    sfree(cpp->fn);
-    cpp->fn = strdup(buf);
-    sfree(buf);
-    i++;
-  }
   if (cpp->fp == NULL) {
-    sfree(cpp->fn);
-    cpp->fn = strdup(filenm);
-    cpp->fp = libopen(filenm);
+    cpp->fp = fopen(cpp->fn, "r");
   }
   if (cpp->fp == NULL) {
     switch(errno) {
@@ -280,6 +303,7 @@ process_directive(gmx_cpp_t *handlep, const char *dname, const char *dval)
   int  i,i0,len,status;
   unsigned int i1;
   char *inc_fn,*name;
+  const char *ptr;
   int  bIfdef,bIfndef;
 
   /* #ifdef or ifndef statement */
@@ -373,7 +397,17 @@ process_directive(gmx_cpp_t *handlep, const char *dname, const char *dval)
   
   /* #define statement */
   if (strcmp(dname,"define") == 0) {
-    add_define(dval);
+    /* Split it into name and value. */
+    ptr = dval;
+    while ((*ptr != '\0') && !isspace(*ptr))
+      ptr++;
+    name = strndup(dval, ptr - dval);
+
+    while ((*ptr != '\0') && isspace(*ptr))
+      ptr++;
+
+    add_define(name, ptr);
+    sfree(name);
     return eCPP_OK;
   }
   
index 9291f1e278a34e4bdac53abe980ea152f399d484..f9f5041b385450ad8e3523abd6754786c4d64c59 100644 (file)
 
 #include <ctype.h>
 #include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
 
 #include "gmx_fatal.h"
 #include "macros.h"
 #include "thread_mpi.h"
 #endif
 
-/* The source code in this file should be thread-safe. 
- * But some functions are NOT THREADSAFE when multiple threads
- * use the same file pointer.
- * Please keep it that way.
- */
+#include "gmxfio_int.h"
 
-/* XDR should be available on all platforms now, 
- * but we keep the possibility of turning it off...
- */
-#define USE_XDR
+/* This is the new improved and thread safe version of gmxfio. */
+
+
+
+/* the list of open files is a linked list, with a dummy element at its head; 
+       it is initialized when the first file is opened. */
+static t_fileio *open_files = NULL;
+
+
+#ifdef GMX_THREADS
+/* this mutex locks the open_files structure so that no two threads can 
+   modify it.        
+
+   For now, we use this as a coarse grained lock on all file 
+   insertion/deletion operations because it makes avoiding deadlocks 
+   easier, and adds almost no overhead . */
+static tMPI_Thread_mutex_t open_file_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
+#endif
 
-typedef struct
-{
-    int iFTP;
-    bool bOpen, bRead, bDouble, bDebug, bStdio;
-    char *fn;
-    FILE *fp;
-    XDR *xdr;
-    bool bLargerThan_off_t, bReadWrite;
-} t_fileio;
 
 /* These simple lists define the I/O type for these files */
 static const int ftpXDR[] =
@@ -86,7 +91,62 @@ static const int ftpXML[] =
     {   efXML};
 #endif
 
-bool in_ftpset(int ftp, int nset, const int set[])
+const char *itemstr[eitemNR] =
+    { "[header]", "[inputrec]", "[box]", "[topology]", "[coordinates]",
+                "[velocities]", "[forces]" };
+
+const char *eioNames[eioNR] =
+    { "REAL", "INT", "GMX_STE_T", "UCHAR", "NUCHAR", "USHORT", "RVEC", "NRVEC",
+                "IVEC", "STRING" };
+
+
+
+/* Comment strings for TPA only */
+const char *comment_str[eitemNR] = {
+"; The header holds information on the number of atoms etc. and on whether\n"
+"; certain items are present in the file or not.\n"
+"; \n"
+";                             WARNING\n"
+";                   DO NOT EDIT THIS FILE BY HAND\n"
+"; The GROMACS preprocessor performs a lot of checks on your input that\n"
+"; you ignore when editing this. Your simulation may crash because of this\n",
+"; The inputrec holds the parameters for MD such as the number of steps,\n"
+"; the timestep and the cut-offs.\n",
+"; The simulation box in nm.\n",
+"; The topology section describes the topology of the molecules\n"
+"; i.e. bonds, angles and dihedrals etc. and also holds the force field\n"
+"; parameters.\n", 
+"; The atomic coordinates in nm\n",
+"; The atomic velocities in nm/ps\n",
+"; The forces on the atoms in nm/ps^2\n" };
+
+
+
+
+/******************************************************************
+ *
+ * Internal functions: 
+ *
+ ******************************************************************/
+
+static int gmx_fio_int_flush(t_fileio* fio)
+{
+    int rc = 0;
+
+    if (fio->fp)
+    {
+        rc = fflush(fio->fp);
+    }
+    else if (fio->xdr)
+    {
+        rc = fflush((FILE *) fio->xdr->x_private);
+    }
+
+    return rc;
+}
+
+/* returns TRUE if the file type ftp is in the set set */
+static bool in_ftpset(int ftp, int nset, const int set[])
 {
     int i;
     bool bResult;
@@ -99,750 +159,288 @@ bool in_ftpset(int ftp, int nset, const int set[])
     return bResult;
 }
 
-static bool do_dummy(void *item, int nitem, int eio, const char *desc,
-                     const char *srcfile, int line)
-{
-    gmx_fatal(FARGS, "gmx_fio_select not called!");
 
-    return FALSE;
-}
 
-/* Global variables */
-do_func *do_read = do_dummy;
-do_func *do_write = do_dummy;
-const char *itemstr[eitemNR] =
-    { "[header]", "[inputrec]", "[box]", "[topology]", "[coordinates]",
-        "[velocities]", "[forces]" };
-/* Comment strings for TPA only */
-const char
-*comment_str[eitemNR] =
-    {
-        "; The header holds information on the number of atoms etc. and on whether\n"
-        "; certain items are present in the file or not.\n"
-        "; \n"
-        ";                             WARNING\n"
-        ";                   DO NOT EDIT THIS FILE BY HAND\n"
-        "; The GROMACS preprocessor performs a lot of checks on your input that\n"
-        "; you ignore when editing this. Your simulation may crash because of this\n",
-
-        "; The inputrec holds the parameters for MD such as the number of steps,\n"
-        "; the timestep and the cut-offs.\n",
-        "; The simulation box in nm.\n",
-        "; The topology section describes the topology of the molcecules\n"
-        "; i.e. bonds, angles and dihedrals etc. and also holds the force field\n"
-        "; parameters.\n", "; The atomic coordinates in nm\n",
-        "; The atomic velocities in nm/ps\n",
-        "; The forces on the atoms in nm/ps^2\n" };
-
-/* Local variables */
-static t_fileio *FIO = NULL;
-static t_fileio *curfio = NULL;
-static int nFIO = 0;
-static const char *eioNames[eioNR] =
-    { "REAL", "INT", "GMX_STE_T", "UCHAR", "NUCHAR", "USHORT", "RVEC", "NRVEC",
-        "IVEC", "STRING" };
-static char *add_comment = NULL;
+extern void gmx_fio_set_comment(t_fileio *fio, const char *comment)
+{
+    fio->comment=comment;
+}
 
-#ifdef GMX_THREADS
-static tMPI_Thread_mutex_t fio_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
-/* this mutex locks concurrent access to the FIO and curfio arrays, the
- nFIO counter, and the add_comment string.  For now this is 
- the easiest way to make this all thread-safe. Because I/O is mostly
- done by the master node, this won't cause any performance issues 
- (locking/unlocking mutexes is very cheap as long as no thread get 
- scheduled out). */
-#endif
+extern void gmx_fio_unset_comment(t_fileio *fio)
+{
+    fio->comment=NULL;
+}
 
-/* these functions are all called from functions that lock the fio_mutex
- themselves, and need to make sure that the called function doesn't 
- try to lock that mutex again. */
-static int gmx_fio_flush_lock(int fio, bool do_lock);
-static int gmx_fio_close_lock(int fio, bool do_lock);
-static bool do_xdr_lock(void *item, int nitem, int eio, const char *desc,
-                        const char *srcfile, int line, bool do_lock);
 
-static const char *dbgstr(const char *desc)
+const char *gmx_fio_dbgstr(t_fileio *fio, const char *desc, char *buf)
 {
-    static const char *null_str = "";
-    static char buf[STRLEN];
-
-    if (!curfio->bDebug)
+    if (!fio->bDebug)
     {
-        return null_str;
+        /* set to empty string */
+        buf[0]=0;
     }
     else
     {
-        sprintf(buf, "  ; %s %s", add_comment ? add_comment : "", desc);
-        return buf;
-    }
-}
-
-void set_comment(const char *comment)
-{
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    if (comment)
-        add_comment = strdup(comment);
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
+#if (defined( _WIN32 ) || defined( _WIN64 ) )
+        /* windows doesn't do standard C */
+#define snprintf sprintf_s
 #endif
+        snprintf(buf, GMX_FIO_BUFLEN, "  ; %s %s", 
+                 fio->comment ? fio->comment : "", desc);
+    }
+    return buf;
 }
 
-void unset_comment(void)
-{
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    if (add_comment)
-        sfree(add_comment);
-    add_comment = NULL;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
-}
 
-static void _check_nitem(int eio, int nitem, const char *file, int line)
+/* check the number of items given against the type */
+void gmx_fio_check_nitem(t_fileio *fio, int eio, int nitem, const char *file, 
+                         int line)
 {
     if ((nitem != 1) && !((eio == eioNRVEC) || (eio == eioNUCHAR)))
-        gmx_fatal(FARGS, "nitem (%d) may differ from 1 only for %s or %s, not for %s"
+        gmx_fatal(FARGS, 
+                  "nitem (%d) may differ from 1 only for %s or %s, not   for %s"
                   "(%s, %d)",nitem,eioNames[eioNUCHAR],eioNames[eioNRVEC],
                   eioNames[eio],file,line);
 }
 
-#define check_nitem() _check_nitem(eio,nitem,__FILE__,__LINE__)
 
-static void fe(int eio, const char *desc, const char *srcfile, int line)
+/* output a data type error. */
+void gmx_fio_fe(t_fileio *fio, int eio, const char *desc, 
+                const char *srcfile, int line)
 {
 
     gmx_fatal(FARGS, "Trying to %s %s type %d (%s), src %s, line %d",
-              curfio->bRead ? "read" : "write",desc,eio,
-                  ((eio >= 0) && (eio < eioNR)) ? eioNames[eio] : "unknown",
-                      srcfile,line);
+              fio->bRead ? "read" : "write",desc,eio,
+              ((eio >= 0) && (eio < eioNR)) ? eioNames[eio] : "unknown",
+              srcfile,line);
 }
 
-#define FE() fe(eio,desc,__FILE__,__LINE__)
 
-static void encode_string(int maxlen, char dst[], char src[])
+/* set the reader/writer functions based on the file type */
+static void gmx_fio_set_iotype(t_fileio *fio)
 {
-    int i;
-
-    for (i = 0; (src[i] != '\0') && (i < maxlen - 1); i++)
-        if ((src[i] == ' ') || (src[i] == '\t'))
-            dst[i] = '_';
-        else
-            dst[i] = src[i];
-    dst[i] = '\0';
-
-    if (i == maxlen)
-        fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
-}
-
-static void decode_string(int maxlen, char dst[], char src[])
-{
-    int i;
-
-    for (i = 0; (src[i] != '\0') && (i < maxlen - 1); i++)
+    if (in_ftpset(fio->iFTP, asize(ftpXDR), ftpXDR))
     {
-        if (src[i] == '_')
-        {
-            dst[i] = ' ';
-        }
-        else
-        {
-            dst[i] = src[i];
-        }
+#ifdef USE_XDR    
+        fio->iotp=&xdr_iotype;
+#else
+        gmx_fatal(FARGS,"Sorry, no XDR");
+#endif
     }
-    dst[i] = '\0';
-
-    if (i == maxlen)
+    else if (in_ftpset(fio->iFTP, asize(ftpASC), ftpASC))
+    {
+        fio->iotp=&asc_iotype;
+    }
+    else if (in_ftpset(fio->iFTP, asize(ftpBIN), ftpBIN))
+    {
+        fio->iotp=&bin_iotype;
+    }
+#ifdef HAVE_XMl
+    else if (in_ftpset(fio->iFTP,asize(ftpXML),ftpXML))
     {
-        fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
+        fio->iotp=&dummy_iotype;
     }
+#endif
+    else
+        fio->iotp=&dummy_iotype;
 }
 
-static bool do_ascwrite(void *item, int nitem, int eio, const char *desc,
-                        const char *srcfile, int line)
-{
-    int i;
-    int res = 0, *iptr;
-    real *ptr;
-    char strbuf[256];
-    unsigned char *ucptr;
 
+/* lock the mutex associated with this fio. This needs to be done for every
+   type of access to the fio's elements. */
+void gmx_fio_lock(t_fileio *fio)
+{
 #ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
+    tMPI_Spinlock_lock(&(fio->mtx));
 #endif
-    check_nitem();
-    switch (eio)
-    {
-    case eioREAL:
-    case eioDOUBLE:
-        res = fprintf(curfio->fp, "%18.10e%s\n", *((real *) item), dbgstr(desc));
-        break;
-    case eioINT:
-        res = fprintf(curfio->fp, "%18d%s\n", *((int *) item), dbgstr(desc));
-        break;
-    case eioGMX_LARGE_INT:
-        sprintf(strbuf, "%s%s%s", "%", gmx_large_int_fmt, "\n");
-        res = fprintf(curfio->fp, strbuf, *((gmx_large_int_t *) item),
-                      dbgstr(desc));
-        break;
-    case eioUCHAR:
-        res = fprintf(curfio->fp, "%4d%s\n", *((unsigned char *) item),
-                      dbgstr(desc));
-        break;
-    case eioNUCHAR:
-        ucptr = (unsigned char *) item;
-        for (i = 0; (i < nitem); i++)
-            res = fprintf(curfio->fp, "%4d", (int) ucptr[i]);
-        fprintf(curfio->fp, "%s\n", dbgstr(desc));
-        break;
-    case eioUSHORT:
-        res = fprintf(curfio->fp, "%18d%s\n", *((unsigned short *) item),
-                      dbgstr(desc));
-        break;
-    case eioRVEC:
-        ptr = (real *) item;
-        res = fprintf(curfio->fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
-                      ptr[YY], ptr[ZZ], dbgstr(desc));
-        break;
-    case eioNRVEC:
-        for (i = 0; (i < nitem); i++)
-        {
-            ptr = ((rvec *) item)[i];
-            res = fprintf(curfio->fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
-                          ptr[YY], ptr[ZZ], dbgstr(desc));
-        }
-        break;
-    case eioIVEC:
-        iptr = (int *) item;
-        res = fprintf(curfio->fp, "%18d%18d%18d%s\n", iptr[XX], iptr[YY],
-                      iptr[ZZ], dbgstr(desc));
-        break;
-    case eioSTRING:
-        encode_string(256, strbuf, (char *) item);
-        res = fprintf(curfio->fp, "%-18s%s\n", strbuf, dbgstr(desc));
-        break;
-    default:
-        FE();
-    }
-    if ((res <= 0) && curfio->bDebug)
-        fprintf(stderr,
-                "Error writing %s %s to file %s (source %s, line %d)\n",
-                eioNames[eio], desc, curfio->fn, srcfile, line);
+}
+/* unlock the mutex associated with this fio.  */
+void gmx_fio_unlock(t_fileio *fio)
+{
 #ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
+    tMPI_Spinlock_unlock(&(fio->mtx));
 #endif
-    return (res > 0);
 }
 
-/* This is a global variable that is reset when a file is opened. */
-/*static  int  nbuf=0;*/
-
-static char *next_item(FILE *fp, char *buf, int buflen)
+/* make a dummy head element, assuming we locked everything. */
+static void gmx_fio_make_dummy(void)
 {
-    int rd;
-    bool in_comment = FALSE;
-    bool in_token = FALSE;
-    int i = 0;
-    /* This routine reads strings from the file fp, strips comment
-     * and buffers. For thread-safety reasons, It reads through getc()  */
-
-    rd = getc(fp);
-    if (rd == EOF)
-        gmx_file("End of file");
-    do
+    if (!open_files)
     {
-        if (in_comment)
-        {
-            if (rd == '\n')
-                in_comment = FALSE;
-        }
-        else if (in_token)
-        {
-            if (isspace(rd) || rd == ';')
-                break;
-            buf[i++] = (char) rd;
-        }
-        else
-        {
-            if (!isspace(rd))
-            {
-                if (rd == ';')
-                    in_comment = TRUE;
-                else
-                {
-                    in_token = TRUE;
-                    buf[i++] = (char) (rd);
-                }
-            }
-        }
-        if (i >= buflen - 2)
-            break;
-    } while ((rd = getc(fp)) != EOF);
+        snew(open_files,1);
+        open_files->fp=NULL;
+        open_files->fn=NULL;
+        open_files->next=open_files;
+        open_files->prev=open_files;
+#ifdef GMX_THREADS
+        tMPI_Spinlock_init(&(open_files->mtx));
+#endif
+    }
+}
 
-    fprintf(stderr, "WARNING, ftpASC file type not tested!\n");
 
-    buf[i] = 0;
 
-    return buf;
-}
 
-static bool do_ascread(void *item, int nitem, int eio, const char *desc,
-                       const char *srcfile, int line)
-{
-    FILE *fp = curfio->fp;
-    int i, m, res = 0, *iptr, ix;
-    gmx_large_int_t s;
-    double d, x;
-    real *ptr;
-    unsigned char uc, *ucptr;
-    char *cptr;
-#define NEXT_ITEM_BUF_LEN 128
-    char ni_buf[NEXT_ITEM_BUF_LEN];
-
-    check_nitem();
-    switch (eio)
-    {
-    case eioREAL:
-    case eioDOUBLE:
-        res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf", &d);
-        if (item)
-            *((real *) item) = d;
-        break;
-    case eioINT:
-        res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
-        if (item)
-            *((int *) item) = i;
-        break;
-    case eioGMX_LARGE_INT:
-        res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN),
-                     gmx_large_int_pfmt, &s);
-        if (item)
-            *((gmx_large_int_t *) item) = s;
-        break;
-    case eioUCHAR:
-        res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%c", &uc);
-        if (item)
-            *((unsigned char *) item) = uc;
-        break;
-    case eioNUCHAR:
-        ucptr = (unsigned char *) item;
-        for (i = 0; (i < nitem); i++)
-        {
-            res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &ix);
-            if (item)
-                ucptr[i] = ix;
-        }
-        break;
-    case eioUSHORT:
-        res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
-        if (item)
-            *((unsigned short *) item) = i;
-        break;
-    case eioRVEC:
-        ptr = (real *) item;
-        for (m = 0; (m < DIM); m++)
-        {
-            res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n", &x);
-            ptr[m] = x;
-        }
-        break;
-    case eioNRVEC:
-        for (i = 0; (i < nitem); i++)
-        {
-            ptr = ((rvec *) item)[i];
-            for (m = 0; (m < DIM); m++)
-            {
-                res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n",
-                             &x);
-                if (item)
-                    ptr[m] = x;
-            }
-        }
-        break;
-    case eioIVEC:
-        iptr = (int *) item;
-        for (m = 0; (m < DIM); m++)
-        {
-            res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d\n", &ix);
-            if (item)
-                iptr[m] = ix;
-        }
-        break;
-    case eioSTRING:
-        cptr = next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN);
-        if (item)
-        {
-            decode_string(strlen(cptr) + 1, (char *) item, cptr);
-            /* res = sscanf(cptr,"%s",(char *)item);*/
-            res = 1;
-        }
-        break;
-    default:
-        FE();
-    }
 
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    if ((res <= 0) && curfio->bDebug)
-        fprintf(stderr,
-                "Error reading %s %s from file %s (source %s, line %d)\n",
-                eioNames[eio], desc, curfio->fn, srcfile, line);
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
-    return (res > 0);
-}
 
-static bool do_binwrite(void *item, int nitem, int eio, const char *desc,
-                        const char *srcfile, int line)
-{
-    size_t size = 0, wsize;
-    int ssize;
 
-    check_nitem();
-    switch (eio)
-    {
-    case eioREAL:
-        size = sizeof(real);
-        break;
-    case eioDOUBLE:
-        size = sizeof(double);
-        break;
-    case eioINT:
-        size = sizeof(int);
-        break;
-    case eioGMX_LARGE_INT:
-        size = sizeof(gmx_large_int_t);
-        break;
-    case eioUCHAR:
-        size = sizeof(unsigned char);
-        break;
-    case eioNUCHAR:
-        size = sizeof(unsigned char);
-        break;
-    case eioUSHORT:
-        size = sizeof(unsigned short);
-        break;
-    case eioRVEC:
-        size = sizeof(rvec);
-        break;
-    case eioNRVEC:
-        size = sizeof(rvec);
-        break;
-    case eioIVEC:
-        size = sizeof(ivec);
-        break;
-    case eioSTRING:
-        size = ssize = strlen((char *) item) + 1;
-        do_binwrite(&ssize, 1, eioINT, desc, srcfile, line);
-        break;
-    default:
-        FE();
-    }
+/***********************************************************************
+ *
+ * FILE LIST OPERATIONS
+ *
+***********************************************************************/
 
-    wsize = fwrite(item, size, nitem, curfio->fp);
 
+/* insert a new t_fileio into the list */
+static void gmx_fio_insert(t_fileio *fio)
+{
+    t_fileio *prev;
 #ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    if ((wsize != nitem) && curfio->bDebug)
+    /* first lock the big open_files mutex. */
+    tMPI_Thread_mutex_lock(&open_file_mutex);
+#endif
+    /* now check whether the dummy element has been allocated, 
+       and allocate it if it hasn't */
+    gmx_fio_make_dummy();
+
+    /* and lock the fio we got and the list's head **/
+    gmx_fio_lock(fio);
+    gmx_fio_lock(open_files);
+    prev=open_files->prev;
+    /* lock the element after the current one */
+    if (prev != open_files)
     {
-        fprintf(stderr,
-                "Error writing %s %s to file %s (source %s, line %d)\n",
-                eioNames[eio], desc, curfio->fn, srcfile, line);
-        fprintf(stderr, "written size %u bytes, source size %u bytes\n",
-                (unsigned int) wsize, (unsigned int) size);
+        gmx_fio_lock(prev);
     }
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
-    return (wsize == nitem);
-}
 
-static bool do_binread(void *item, int nitem, int eio, const char *desc,
-                       const char *srcfile, int line)
-{
-    size_t size = 0, rsize;
-    int ssize;
+    /* now do the actual insertion: */
+    fio->next=open_files;
+    open_files->prev=fio;
+    prev->next=fio;
+    fio->prev=prev;
 
-    check_nitem();
-    switch (eio)
+    /* now unlock all our locks */
+    if (prev != open_files)
     {
-    case eioREAL:
-        if (curfio->bDouble)
-            size = sizeof(double);
-        else
-            size = sizeof(float);
-        break;
-    case eioDOUBLE:
-        size = sizeof(double);
-        break;
-    case eioINT:
-        size = sizeof(int);
-        break;
-    case eioGMX_LARGE_INT:
-        size = sizeof(gmx_large_int_t);
-        break;
-    case eioUCHAR:
-        size = sizeof(unsigned char);
-        break;
-    case eioNUCHAR:
-        size = sizeof(unsigned char);
-        break;
-    case eioUSHORT:
-        size = sizeof(unsigned short);
-        break;
-    case eioRVEC:
-    case eioNRVEC:
-        if (curfio->bDouble)
-            size = sizeof(double) * DIM;
-        else
-            size = sizeof(float) * DIM;
-        break;
-    case eioIVEC:
-        size = sizeof(ivec);
-        break;
-    case eioSTRING:
-        do_binread(&ssize, 1, eioINT, desc, srcfile, line);
-        size = ssize;
-        break;
-    default:
-        FE();
+        gmx_fio_unlock(prev);
     }
+    gmx_fio_unlock(open_files);
+    gmx_fio_unlock(fio);
 
 #ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
+    /* now unlock the big open_files mutex.  */
+    tMPI_Thread_mutex_unlock(&open_file_mutex);
 #endif
-    if (item)
-        rsize = fread(item, size, nitem, curfio->fp);
-    else
-    {
-        /* Skip over it if we have a NULL pointer here */
-#ifdef HAVE_FSEEKO
-        fseeko(curfio->fp, (off_t) (size * nitem), SEEK_CUR);
-#else
-        fseek(curfio->fp,(size*nitem),SEEK_CUR);
-#endif    
-        rsize = nitem;
-    }
-    if ((rsize != nitem) && (curfio->bDebug))
-        fprintf(stderr,
-                "Error reading %s %s from file %s (source %s, line %d)\n",
-                eioNames[eio], desc, curfio->fn, srcfile, line);
+}
 
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
-    return (rsize == nitem);
+/* remove a t_fileio into the list. We assume the fio is locked, and we leave 
+   it locked. */
+static void gmx_fio_remove(t_fileio *fio)
+{    
+    t_fileio *prev;
+
+    /* this looks a bit complicated because we're trying to avoid a 
+       deadlock with threads that are walking through the structure
+       with gmx_fio_get_next(): if they're trying to lock our current structure
+       while we are trying to lock the previous structure, we get a deadlock.
+       */
+    do
+    {
+        /* we remember the prev */
+        prev=fio->prev;
+        /* and unlock it to prevent deadlocks */
+        gmx_fio_unlock(fio);
+        /* lock the prev nbr */
+        gmx_fio_lock(prev);
+        /* now that that one is locked, we can safely lock original one again */
+        gmx_fio_lock(fio);
+
+        /* and normally, we should be able to get out of this loop, but maybe
+           things have changed when we unlocked our original fio */
+    } while((prev->next != fio) || (fio->prev != prev)); 
+    /* now set the prev's pointer */
+    fio->prev->next=fio->next;
+    gmx_fio_unlock(fio->prev);
+
+    /* with the next ptr, we can simply lock while the original was locked */
+    gmx_fio_lock(fio->next);
+    fio->next->prev=fio->prev;
+    gmx_fio_unlock(fio->next);
+
+    /* and make sure we point nowhere in particular */
+    fio->next=fio->prev=fio;
 }
 
-#ifdef USE_XDR
 
-/* this is a recursive function that does mutex locking, so
- there is an a function that locks (do_xdr) and the real function
- that calls itself without locking.  */
-static bool do_xdr_lock(void *item, int nitem, int eio, const char *desc,
-                        const char *srcfile, int line, bool do_lock)
+/* get the first open file, or NULL if there is none. 
+   Returns a locked fio. */
+static t_fileio *gmx_fio_get_first(void)
 {
-    unsigned char ucdum, *ucptr;
-    bool_t res = 0;
-    float fvec[DIM];
-    double dvec[DIM];
-    int j, m, *iptr, idum;
-    gmx_large_int_t sdum;
-    real *ptr;
-    unsigned short us;
-    double d = 0;
-    float f = 0;
+    t_fileio *ret;
+    /* first lock the big open_files mutex and the dummy's mutex */
 
+    gmx_fio_make_dummy();
 #ifdef GMX_THREADS
-    if (do_lock)
-        tMPI_Thread_mutex_lock(&fio_mutex);
+    /* first lock the big open_files mutex. */
+    tMPI_Thread_mutex_lock(&open_file_mutex);
 #endif
-    check_nitem();
-    switch (eio)
-    {
-    case eioREAL:
-        if (curfio->bDouble)
-        {
-            if (item && !curfio->bRead)
-                d = *((real *) item);
-            res = xdr_double(curfio->xdr, &d);
-            if (item)
-                *((real *) item) = d;
-        }
-        else
-        {
-            if (item && !curfio->bRead)
-                f = *((real *) item);
-            res = xdr_float(curfio->xdr, &f);
-            if (item)
-                *((real *) item) = f;
-        }
-        break;
-    case eioDOUBLE:
-        if (item && !curfio->bRead)
-            d = *((double *) item);
-        res = xdr_double(curfio->xdr, &d);
-        if (item)
-            *((double *) item) = d;
-        break;
-    case eioINT:
-        if (item && !curfio->bRead)
-            idum = *(int *) item;
-        res = xdr_int(curfio->xdr, &idum);
-        if (item)
-            *(int *) item = idum;
-        break;
-    case eioGMX_LARGE_INT:
-        /* do_xdr will not generate a warning when a 64bit gmx_large_int_t
-         * value that is out of 32bit range is read into a 32bit gmx_large_int_t.
-         */
-        if (item && !curfio->bRead)
-            sdum = *(gmx_large_int_t *) item;
-        res = xdr_gmx_large_int(curfio->xdr, &sdum, NULL);
-        if (item)
-            *(gmx_large_int_t *) item = sdum;
-        break;
-    case eioUCHAR:
-        if (item && !curfio->bRead)
-            ucdum = *(unsigned char *) item;
-        res = xdr_u_char(curfio->xdr, &ucdum);
-        if (item)
-            *(unsigned char *) item = ucdum;
-        break;
-    case eioNUCHAR:
-        ucptr = (unsigned char *) item;
-        res = 1;
-        for (j = 0; (j < nitem) && res; j++)
-        {
-            res = xdr_u_char(curfio->xdr, &(ucptr[j]));
-        }
-        break;
-    case eioUSHORT:
-        if (item && !curfio->bRead)
-            us = *(unsigned short *) item;
-        res = xdr_u_short(curfio->xdr, (unsigned short *) &us);
-        if (item)
-            *(unsigned short *) item = us;
-        break;
-    case eioRVEC:
-        if (curfio->bDouble)
-        {
-            if (item && !curfio->bRead)
-                for (m = 0; (m < DIM); m++)
-                    dvec[m] = ((real *) item)[m];
-            res = xdr_vector(curfio->xdr, (char *) dvec, DIM,
-                             (unsigned int) sizeof(double),
-                             (xdrproc_t) xdr_double);
-            if (item)
-                for (m = 0; (m < DIM); m++)
-                    ((real *) item)[m] = dvec[m];
-        }
-        else
-        {
-            if (item && !curfio->bRead)
-                for (m = 0; (m < DIM); m++)
-                    fvec[m] = ((real *) item)[m];
-            res = xdr_vector(curfio->xdr, (char *) fvec, DIM,
-                             (unsigned int) sizeof(float),
-                             (xdrproc_t) xdr_float);
-            if (item)
-                for (m = 0; (m < DIM); m++)
-                    ((real *) item)[m] = fvec[m];
-        }
-        break;
-    case eioNRVEC:
-        ptr = NULL;
-        res = 1;
-        for (j = 0; (j < nitem) && res; j++)
-        {
-            if (item)
-                ptr = ((rvec *) item)[j];
-            res = do_xdr_lock(ptr, 1, eioRVEC, desc, srcfile, line, FALSE);
-        }
-        break;
-    case eioIVEC:
-        iptr = (int *) item;
-        res = 1;
-        for (m = 0; (m < DIM) && res; m++)
-        {
-            if (item && !curfio->bRead)
-                idum = iptr[m];
-            res = xdr_int(curfio->xdr, &idum);
-            if (item)
-                iptr[m] = idum;
-        }
-        break;
-    case eioSTRING:
-    {
-        char *cptr;
-        int slen;
 
-        if (item)
-        {
-            if (!curfio->bRead)
-                slen = strlen((char *) item) + 1;
-            else
-                slen = 0;
-        }
-        else
-            slen = 0;
+    gmx_fio_lock(open_files);
+    ret=open_files->next;
 
-        if (xdr_int(curfio->xdr, &slen) <= 0)
-            gmx_fatal(FARGS, "wrong string length %d for string %s"
-                      " (source %s, line %d)",slen,desc,srcfile,line);
-        if (!item && curfio->bRead)
-            snew(cptr,slen);
-        else
-            cptr=(char *)item;
-        if (cptr)
-            res = xdr_string(curfio->xdr,&cptr,slen);
-        else
-            res = 1;
-        if (!item && curfio->bRead)
-            sfree(cptr);
-        break;
+#ifdef GMX_THREADS
+    tMPI_Thread_mutex_unlock(&open_file_mutex);
+#endif
+
+    /* check whether there were any to begin with */
+    if (ret==open_files)
+    {
+        /* after this, the open_file pointer should never change */
+        ret=NULL;
     }
-    default:
-        FE();
+    else
+    {
+        gmx_fio_lock(open_files->next);
     }
-    if ((res == 0) && (curfio->bDebug))
-        fprintf(stderr,"Error in xdr I/O %s %s to file %s (source %s, line %d)\n",
-                eioNames[eio],desc,curfio->fn,srcfile,line);
+    gmx_fio_unlock(open_files);
 
-#ifdef GMX_THREADS
-    if (do_lock)
-        tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
-    return (res != 0);
+
+    return ret;
 }
 
-static bool do_xdr(void *item, int nitem, int eio, const char *desc,
-                   const char *srcfile, int line)
+/* get the next open file, or NULL if there is none. 
+   Unlocks the previous fio and locks the next one. */
+static t_fileio *gmx_fio_get_next(t_fileio *fio)
 {
-    /* this is a recursive function that does mutex locking, so
-     it needs to be called with locking here, but without locking
-     from itself */
-    return do_xdr_lock(item, nitem, eio, desc, srcfile, line, TRUE);
+    t_fileio *ret;
+
+    ret=fio->next;
+    /* check if that was the last one */
+    if (fio->next==open_files)
+    {
+        ret=NULL;
+    }
+    else
+    {
+        gmx_fio_lock(ret);
+    }
+    gmx_fio_unlock(fio);
+
+    return ret;
 }
-#endif
 
-#define gmx_fio_check(fio) range_check(fio,0,nFIO)
+
+
 
 /*****************************************************************
  *
  *                     EXPORTED SECTION
  *
  *****************************************************************/
-int gmx_fio_open(const char *fn, const char *mode)
+t_fileio *gmx_fio_open(const char *fn, const char *mode)
 {
     t_fileio *fio = NULL;
-    int i, nfio = 0;
+    int i;
     char newmode[5];
     bool bRead, bReadWrite;
     int xdrid;
@@ -853,6 +451,7 @@ int gmx_fio_open(const char *fn, const char *mode)
     }
     else
     {
+        /* sanitize the mode string */
         if (strncmp(mode, "r+", 2) == 0)
         {
             strcpy(newmode, "r+");
@@ -893,28 +492,10 @@ int gmx_fio_open(const char *fn, const char *mode)
         }
     }
 
+    snew(fio, 1);
 #ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
+    tMPI_Spinlock_init(&(fio->mtx));
 #endif
-    /* Determine whether we have to make a new one */
-    for(i=0; (i<nFIO); i++)
-    {
-        if (!FIO[i].bOpen)
-        {
-            fio = &(FIO[i]);
-            nfio = i;
-            break;
-        }
-    }
-
-    if (i == nFIO)
-    {
-        nFIO++;
-        srenew(FIO,nFIO);
-        fio = &(FIO[nFIO-1]);
-        nfio = nFIO-1;
-    }
-
     bRead = (newmode[0]=='r' && newmode[1]!='+');
     bReadWrite = (newmode[1]=='+');
     fio->fp = NULL;
@@ -935,22 +516,7 @@ int gmx_fio_open(const char *fn, const char *mode)
             {
 #ifndef GMX_FAHCORE
                 /* only make backups for normal gromacs */
-                if (gmx_fexist(fn))
-                {
-                    char *bf=(char *)backup_fn(fn);
-                    if (rename(fn,bf) == 0)
-                    {
-                        fprintf(stderr,
-                                "\nBack Off! I just backed up %s to %s\n",
-                                fn,bf);
-                    }
-                    else
-                    {
-                        fprintf(stderr,"Sorry, I couldn't backup %s to %s\n",
-                                fn,bf);
-                    }
-                    sfree(bf);
-                }
+                make_backup(fn);
 #endif
             }
             else 
@@ -961,16 +527,21 @@ int gmx_fio_open(const char *fn, const char *mode)
                     gmx_open(fn);
                 }
             }
-            snew(fio->xdr,1);
-            xdrid = xdropen(fio->xdr,fn,newmode); 
-            if (xdrid == 0)
+            /* Open the file */
+            fio->fp = ffopen(fn,newmode);
+
+            /* determine the XDR direction */
+            if (newmode[0] == 'w' || newmode[0]=='a')
             {
-                if(newmode[0]=='r' && newmode[1]!='+') 
-                    gmx_fatal(FARGS,"Cannot open file %s for reading\nCheck permissions if it exists.",fn); 
-                else
-                    gmx_fatal(FARGS,"Cannot open file %s for writing.\nCheck your permissions, disk space and/or quota.",fn);
+                fio->xdrmode=XDR_ENCODE;
             }
-            fio->fp = xdr_get_fp(xdrid);
+            else
+            {
+                fio->xdrmode=XDR_DECODE;
+            }
+
+            snew(fio->xdr,1);
+            xdrstdio_create(fio->xdr, fio->fp, fio->xdrmode);
         }
         else
         {
@@ -993,213 +564,162 @@ int gmx_fio_open(const char *fn, const char *mode)
     fio->bOpen  = TRUE;
     fio->bLargerThan_off_t = FALSE;
 
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
-    return nfio;
+    /* set the reader/writer functions */
+    gmx_fio_set_iotype(fio);
+
+    /* and now insert this file into the list of open files. */
+    gmx_fio_insert(fio);
+    return fio;
 }
 
-/* this function may be called from a function that locks the fio_mutex, 
-   which is why it exists in the first place. */
-static int gmx_fio_close_lock(int fio, bool do_lock)
+int gmx_fio_close(t_fileio *fio)
 {
     int rc = 0;
 
-#ifdef GMX_THREADS
-    if (do_lock)
-        tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
+    gmx_fio_lock(fio);
+    /* first remove it from the list */
+    gmx_fio_remove(fio);
 
-    if (in_ftpset(FIO[fio].iFTP, asize(ftpXDR), ftpXDR))
+    if (in_ftpset(fio->iFTP, asize(ftpXDR), ftpXDR))
     {
-        rc = !xdrclose(FIO[fio].xdr); /* xdrclose returns 1 if happy, 
-         negate it */
-        sfree(FIO[fio].xdr);
-    }
-    else
-    {
-        /* Don't close stdin and stdout! */
-        if (!FIO[fio].bStdio && FIO[fio].fp!=NULL)
-            rc = ffclose(FIO[fio].fp); /* fclose returns 0 if happy */
+        xdr_destroy(fio->xdr);
+        sfree(fio->xdr);
     }
 
-    sfree(FIO[fio].fn);
-    FIO[fio].bOpen = FALSE;
-    do_read = do_dummy;
-    do_write = do_dummy;
-#ifdef GMX_THREADS
-    if (do_lock)
-        tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+    /* Don't close stdin and stdout! */
+    if (!fio->bStdio && fio->fp!=NULL)
+        rc = ffclose(fio->fp); /* fclose returns 0 if happy */
 
-    return rc;
-}
+    fio->bOpen = FALSE;
 
-int gmx_fio_close(int fio)
-{
-    return gmx_fio_close_lock(fio, TRUE);
+    gmx_fio_unlock(fio);
+
+    sfree(fio);
+
+    return rc;
 }
 
 /* close only fp but keep FIO entry. */
-int gmx_fio_fp_close(int fio)
+int gmx_fio_fp_close(t_fileio *fio)
 {
     int rc=0;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    if (!in_ftpset(FIO[fio].iFTP,asize(ftpXDR),ftpXDR) && !FIO[fio].bStdio)
+    gmx_fio_lock(fio);
+    if (!in_ftpset(fio->iFTP,asize(ftpXDR),ftpXDR) && !fio->bStdio)
     {
-        rc = ffclose(FIO[fio].fp); /* fclose returns 0 if happy */
-        FIO[fio].fp = NULL; 
+        rc = ffclose(fio->fp); /* fclose returns 0 if happy */
+        fio->fp = NULL; 
     }
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+    gmx_fio_unlock(fio);
+
     return rc;
 }
 
 FILE * gmx_fio_fopen(const char *fn, const char *mode)
 {
     FILE *fp, *ret;
-    int fd;
+    t_fileio *fio;
+
+    fio = gmx_fio_open(fn, mode);
+    gmx_fio_lock(fio);
+    ret = fio->fp;
+    gmx_fio_unlock(fio);
 
-    fd = gmx_fio_open(fn, mode);
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    ret = FIO[fd].fp;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
     return ret;
 }
 
 int gmx_fio_fclose(FILE *fp)
 {
-    int i, rc, found;
-
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    found = 0;
-    rc = -1;
+    t_fileio *cur;
+    t_fileio *found=NULL;
 
-    for (i = 0; i < nFIO && !found; i++)
+    cur=gmx_fio_get_first();
+    while(cur)
     {
-        if (fp == FIO[i].fp)
+        if (cur->fp == fp)
         {
-            rc = gmx_fio_close_lock(i, FALSE);
-            found = 1;
+            gmx_fio_unlock(cur);
+            found=cur;
+            /* we let it loop until  the end */
         }
+        cur=gmx_fio_get_next(cur);
     }
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
-    return rc;
+
+    if (!found)
+        return -1;
+    return gmx_fio_close(found);
 }
 
-/*
- * fio: file to computer md5 from
- * offset: starting pointer of region to use for md5
- * digest: return array of md5 sum 
- * do_lock: whether to lock the fio array
- *
- * this function may be called from a function that locks the fio_mutex, 
- which is why it exists in the first place. 
- */
-int gmx_fio_get_file_md5_lock(int fio, off_t offset, unsigned char digest[],
-                              bool do_lock)
+/* internal variant of get_file_md5 that operates on a locked file */
+static int gmx_fio_int_get_file_md5(t_fileio *fio, off_t offset, 
+                                    unsigned char digest[])
 {
     /*1MB: large size important to catch almost identical files */
 #define CPT_CHK_LEN  1048576 
-
     md5_state_t state;
     unsigned char buf[CPT_CHK_LEN];
     off_t read_len;
     off_t seek_offset;
     int ret = -1;
-    seek_offset = offset - CPT_CHK_LEN;
 
+    seek_offset = offset - CPT_CHK_LEN;
     if (seek_offset < 0)
     {
         seek_offset = 0;
     }
     read_len = offset - seek_offset;
 
-#ifdef GMX_THREADS 
-    if (do_lock)
-    {
-        tMPI_Thread_mutex_lock(&fio_mutex);
-    }
-#endif
 
-    gmx_fio_check(fio);
-    if (FIO[fio].fp && FIO[fio].bReadWrite)
+    if (fio->fp && fio->bReadWrite)
     {
 #ifdef HAVE_FSEEKO
-        ret = fseeko(FIO[fio].fp, seek_offset, SEEK_SET);
+        ret = fseeko(fio->fp, seek_offset, SEEK_SET);
 #else
-        ret=fseek(FIO[fio].fp,seek_offset,SEEK_SET);
+        ret=fseek(fio->fp,seek_offset,SEEK_SET);
 #endif
         if (ret)
         {
-            fseek(FIO[fio].fp, 0, SEEK_END);
+            fseek(fio->fp, 0, SEEK_END);
         }
     }
     if (ret) /*either no fp, not readwrite, or fseek not successful */
     {
-#ifdef GMX_THREADS 
-        if (do_lock)
-        {
-            tMPI_Thread_mutex_unlock(&fio_mutex);
-        }
-#endif
         return -1;
     }
 
     /* the read puts the file position back to offset */
-    if (fread(buf, 1, read_len, FIO[fio].fp) != read_len)
+    if (fread(buf, 1, read_len, fio->fp) != read_len)
     {
         /* not fatal: md5sum check to prevent overwriting files
          * works (less safe) without
          * */
-        if (ferror(FIO[fio].fp))
+        if (ferror(fio->fp))
         {
-            fprintf(stderr, "\nTrying to get md5sum: %s: %s\n", FIO[fio].fn,
+            fprintf(stderr, "\nTrying to get md5sum: %s: %s\n", fio->fn,
                     strerror(errno));
         }
-        else if (feof(FIO[fio].fp))
+        else if (feof(fio->fp))
         {
-            fprintf(stderr, "\nTrying to get md5sum: EOF: %s\n", FIO[fio].fn);
+            fprintf(stderr, "\nTrying to get md5sum: EOF: %s\n", fio->fn);
         }
         else
         {
             fprintf(
                 stderr,
                 "\nTrying to get md5sum: Unknown reason for short read: %s\n",
-                FIO[fio].fn);
+                fio->fn);
         }
 
-        fseek(FIO[fio].fp, 0, SEEK_END);
+        fseek(fio->fp, 0, SEEK_END);
 
         ret = -1;
     }
-    fseek(FIO[fio].fp, 0, SEEK_END); /*is already at end, but under windows 
+    fseek(fio->fp, 0, SEEK_END); /*is already at end, but under windows 
      it gives problems otherwise*/
 
     if (debug)
     {
-        fprintf(debug, "chksum %s readlen %ld\n", FIO[fio].fn,
-                (long int) read_len);
+        fprintf(debug, "chksum %s readlen %ld\n", fio->fn, (long int)read_len);
     }
-#ifdef GMX_THREADS 
-    if (do_lock)
-    {
-        tMPI_Thread_mutex_unlock(&fio_mutex);
-    }
-#endif
 
     if (!ret)
     {
@@ -1214,29 +734,36 @@ int gmx_fio_get_file_md5_lock(int fio, off_t offset, unsigned char digest[],
     }
 }
 
+
 /*
- * fio: file to computer md5 from
+ * fio: file to compute md5 for
  * offset: starting pointer of region to use for md5
  * digest: return array of md5 sum 
  */
-int gmx_fio_get_file_md5(int fio, off_t offset, unsigned char digest[])
+int gmx_fio_get_file_md5(t_fileio *fio, off_t offset, unsigned char digest[])
 {
-    return gmx_fio_get_file_md5_lock(fio, offset, digest, TRUE);
+    int ret;
+
+    gmx_fio_lock(fio);
+    ret=gmx_fio_int_get_file_md5(fio, offset, digest);
+    gmx_fio_unlock(fio);
+
+    return ret;
 }
 
 /* The fio_mutex should ALWAYS be locked when this function is called */
-static int gmx_fio_get_file_position(int fio, off_t *offset)
+static int gmx_fio_int_get_file_position(t_fileio *fio, off_t *offset)
 {
     char buf[STRLEN];
 
     /* Flush the file, so we are sure it is written */
-    if (gmx_fio_flush_lock(fio, FALSE))
+    if (gmx_fio_int_flush(fio))
     {
         char buf[STRLEN];
         sprintf(
             buf,
             "Cannot write file '%s'; maybe you are out of disk space or quota?",
-            FIO[fio].fn);
+            fio->fn);
         gmx_file(buf);
     }
 
@@ -1247,15 +774,15 @@ static int gmx_fio_get_file_position(int fio, off_t *offset)
      this when exabyte-size output files are common...
      */
 #ifdef HAVE_FSEEKO
-    *offset = ftello(FIO[fio].fp);
+    *offset = ftello(fio->fp);
 #else
-    *offset = ftell(FIO[fio].fp);
+    *offset = ftell(fio->fp);
 #endif
 
     return 0;
 }
 
-int gmx_fio_check_file_position(int fio)
+int gmx_fio_check_file_position(t_fileio *fio)
 {
     /* If off_t is 4 bytes we can not store file offset > 2 GB.
      * If we do not have ftello, we will play it safe.
@@ -1263,20 +790,16 @@ int gmx_fio_check_file_position(int fio)
 #if (SIZEOF_OFF_T == 4 || !defined HAVE_FSEEKO)
     off_t offset;
 
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_get_file_position(fio,&offset);
+    gmx_fio_lock(fio);
+    gmx_fio_int_get_file_position(fio,&offset);
     /* We have a 4 byte offset,
      * make sure that we will detect out of range for all possible cases.
      */
     if (offset < 0 || offset > 2147483647)
     {
-        FIO[fio].bLargerThan_off_t = TRUE;
+        fio->bLargerThan_off_t = TRUE;
     }
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+    gmx_fio_unlock(fio);
 #endif
 
     return 0;
@@ -1290,21 +813,25 @@ int gmx_fio_get_output_file_positions(gmx_file_position_t **p_outputfiles,
     long pos;
     gmx_file_position_t * outputfiles;
     char buf[STRLEN];
+    t_fileio *cur;
 
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
     nfiles = 0;
 
+    /* pre-allocate 100 files */
     nalloc = 100;
     snew(outputfiles,nalloc);
 
-    for (i = 0; i < nFIO; i++)
+    cur=gmx_fio_get_first();
+    while(cur)
     {
-        /* Skip the checkpoint files themselves, since they could be open when we call this routine... */
+        /* Skip the checkpoint files themselves, since they could be open when 
+           we call this routine... */
         /* also skip debug files (shoud be the only iFTP==efNR) */
-        if (FIO[i].bOpen && !FIO[i].bRead && !FIO[i].bStdio && FIO[i].iFTP
-            != efCPT && FIO[i].iFTP != efNR)
+        if (cur->bOpen && 
+            !cur->bRead && 
+            !cur->bStdio && 
+            cur->iFTP != efCPT && 
+            cur->iFTP != efNR)
         {
             int ret;
             /* This is an output file currently open for writing, add it */
@@ -1314,10 +841,10 @@ int gmx_fio_get_output_file_positions(gmx_file_position_t **p_outputfiles,
                 srenew(outputfiles,nalloc);
             }
 
-            strncpy(outputfiles[nfiles].filename, FIO[i].fn, STRLEN - 1);
+            strncpy(outputfiles[nfiles].filename, cur->fn, STRLEN - 1);
 
             /* Get the file position */
-            if (FIO[i].bLargerThan_off_t)
+            if (cur->bLargerThan_off_t)
             {
                 /* -1 signals out of range */
                 outputfiles[nfiles].offset = -1;
@@ -1325,289 +852,333 @@ int gmx_fio_get_output_file_positions(gmx_file_position_t **p_outputfiles,
             }
             else
             {
-                gmx_fio_get_file_position(i, &outputfiles[nfiles].offset);
+                gmx_fio_int_get_file_position(cur, &outputfiles[nfiles].offset);
 #ifndef GMX_FAHCORE
                 outputfiles[nfiles].chksum_size
-                = gmx_fio_get_file_md5_lock(i, outputfiles[nfiles].offset,
-                                            outputfiles[nfiles].chksum,
-                                            FALSE);
+                    = gmx_fio_int_get_file_md5(cur, 
+                                               outputfiles[nfiles].offset,
+                                               outputfiles[nfiles].chksum);
 #endif
             }
 
             nfiles++;
         }
+
+        cur=gmx_fio_get_next(cur);
     }
     *p_nfiles = nfiles;
     *p_outputfiles = outputfiles;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
 
     return 0;
 }
 
-void gmx_fio_select(int fio)
-{
-#ifdef DEBUG
-    fprintf(stderr,"Select fio called with type %d for file %s\n",
-            FIO[fio].iFTP,FIO[fio].fn);
-#endif
 
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    if (in_ftpset(FIO[fio].iFTP, asize(ftpXDR), ftpXDR))
+void gmx_fio_checktype(t_fileio *fio)
+{
+    if (in_ftpset(fio->iFTP, asize(ftpXDR), ftpXDR))
     {
-#ifdef USE_XDR    
-        do_read = do_xdr;
-        do_write = do_xdr;
-#else
-        gmx_fatal(FARGS,"Sorry, no XDR");
-#endif
+        return;
     }
-    else if (in_ftpset(FIO[fio].iFTP, asize(ftpASC), ftpASC))
+    else if (in_ftpset(fio->iFTP, asize(ftpASC), ftpASC))
     {
-        do_read = do_ascread;
-        do_write = do_ascwrite;
+        return;
     }
-    else if (in_ftpset(FIO[fio].iFTP, asize(ftpBIN), ftpBIN))
+    else if (in_ftpset(fio->iFTP, asize(ftpBIN), ftpBIN))
     {
-        do_read = do_binread;
-        do_write = do_binwrite;
+        return;
     }
 #ifdef HAVE_XMl
-    else if (in_ftpset(FIO[fio].iFTP,asize(ftpXML),ftpXML))
+    else if (in_ftpset(fio->iFTP,asize(ftpXML),ftpXML))
     {
-        do_read = do_dummy;
-        do_write = do_dummy;
+        return;
     }
 #endif
     else
         gmx_fatal(FARGS, "Can not read/write topologies to file type %s",
-                  ftp2ext(curfio->iFTP));
+                  ftp2ext(fio->iFTP));
 
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
-    curfio = &(FIO[fio]);
 }
 
-void gmx_fio_setprecision(int fio, bool bDouble)
+
+void gmx_fio_setprecision(t_fileio *fio, bool bDouble)
 {
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    FIO[fio].bDouble = bDouble;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+    gmx_fio_lock(fio);
+    fio->bDouble = bDouble;
+    gmx_fio_unlock(fio);
 }
 
-bool gmx_fio_getdebug(int fio)
+bool gmx_fio_getdebug(t_fileio *fio)
 {
     bool ret;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    ret = FIO[fio].bDebug;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
-    return FIO[fio].bDebug;
+
+    gmx_fio_lock(fio);
+    ret = fio->bDebug;
+    gmx_fio_unlock(fio);
+
+    return ret;
 }
 
-void gmx_fio_setdebug(int fio, bool bDebug)
+void gmx_fio_setdebug(t_fileio *fio, bool bDebug)
 {
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    FIO[fio].bDebug = bDebug;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+    gmx_fio_lock(fio);
+    fio->bDebug = bDebug;
+    gmx_fio_unlock(fio);
 }
 
-char *gmx_fio_getname(int fio)
+char *gmx_fio_getname(t_fileio *fio)
 {
     char *ret;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    ret = curfio->fn;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+    gmx_fio_lock(fio);
+    ret = fio->fn;
+    gmx_fio_unlock(fio);
+
     return ret;
 }
 
-void gmx_fio_setftp(int fio, int ftp)
+int gmx_fio_getftp(t_fileio* fio)
 {
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    FIO[fio].iFTP = ftp;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+    int ret;
+
+    gmx_fio_lock(fio);
+    ret = fio->iFTP;
+    gmx_fio_unlock(fio);
+
+    return ret;
 }
 
-int gmx_fio_getftp(int fio)
+void gmx_fio_rewind(t_fileio* fio)
+{
+    gmx_fio_lock(fio);
+
+    if (fio->xdr)
+    {
+        xdr_destroy(fio->xdr);
+        frewind(fio->fp);
+        xdrstdio_create(fio->xdr, fio->fp, fio->xdrmode);
+    }
+    else
+    {
+        frewind(fio->fp);
+    }
+    gmx_fio_unlock(fio);
+}
+
+
+int gmx_fio_flush(t_fileio* fio)
 {
     int ret;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    ret = FIO[fio].iFTP;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+
+    gmx_fio_lock(fio);
+    ret=gmx_fio_int_flush(fio);
+    gmx_fio_unlock(fio);
+
     return ret;
 }
 
-void gmx_fio_rewind(int fio)
+
+
+static int gmx_fio_int_fsync(t_fileio *fio)
 {
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
+    int rc = 0;
+    int filen=-1;
+
+#if ( ( (defined(HAVE_FILENO) || (defined(HAVE__FILENO) ) ) && \
+       (defined(HAVE_FSYNC))  || defined(HAVE__COMMIT)  ) || \
+        defined(FAHCORE) )
+    if (fio->fp)
+    {
+#ifdef GMX_FAHCORE
+       /* the fahcore defines its own os-independent fsync */
+       rc=fah_fsync(fio->fp); 
+#elif defined(HAVE_FILENO)
+        filen=fileno(fio->fp);
+#elif defined(HAVE__FILENO)
+        filen=_fileno(fio->fp);
 #endif
-    gmx_fio_check(fio);
-    if (FIO[fio].xdr)
+    }
+    else if (fio->xdr)
     {
-        xdrclose(FIO[fio].xdr);
-        /* File is always opened as binary by xdropen */
-        xdropen(FIO[fio].xdr, FIO[fio].fn, FIO[fio].bRead ? "r" : "w");
+#ifdef GMX_FAHCORE
+       /* the fahcore defines its own os-independent fsync */
+        rc=fah_fsync((FILE *) fio->xdr->x_private);
+#elif defined(HAVE_FILENO)
+        filen=fileno((FILE *) fio->xdr->x_private);
+#elif defined(HAVE__FILENO)
+        filen=_fileno((FILE *) fio->xdr->x_private);
+#endif
     }
-    else
-        frewind(FIO[fio].fp);
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
+
+#ifndef GMX_FAHCORE
+    if (filen>0)
+    {
+#if (defined(HAVE_FSYNC))
+        /* fahcore also defines HAVE_FSYNC */
+        rc=fsync(filen);
+#elif (defined(HAVE__COMMIT)) 
+        rc=_commit(filen);
 #endif
+    }
+#endif
+
+    /* We check for these error codes this way because POSIX requires them
+       to be defined, and using anything other than macros is unlikely: */
+#ifdef EINTR
+    /* we don't want to report an error just because fsync() caught a signal.
+       For our purposes, we can just ignore this. */
+    if (rc && errno==EINTR)
+        rc=0;
+#endif
+#ifdef EINVAL
+    /* we don't want to report an error just because we tried to fsync() 
+       stdout, a socket or a pipe. */
+    if (rc && errno==EINVAL)
+        rc=0;
+#endif
+#endif
+
+    return rc;
 }
 
-static int gmx_fio_flush_lock(int fio, bool do_lock)
+
+int gmx_fio_fsync(t_fileio *fio)
 {
-    int rc = 0;
+    int rc;
 
-#ifdef GMX_THREADS
-    if (do_lock)
-        tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    if (FIO[fio].fp)
-        rc = fflush(FIO[fio].fp);
-    else if (FIO[fio].xdr)
-        rc = fflush((FILE *) FIO[fio].xdr->x_private);
-#ifdef GMX_THREADS
-    if (do_lock)
-        tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+    gmx_fio_lock(fio);
+    rc=gmx_fio_int_fsync(fio);
+    gmx_fio_unlock(fio);
 
     return rc;
 }
 
-int gmx_fio_flush(int fio)
+
+
+t_fileio *gmx_fio_all_output_fsync(void)
 {
-    return gmx_fio_flush_lock(fio, TRUE);
+    t_fileio *ret=NULL;
+    t_fileio *cur;
+
+    cur=gmx_fio_get_first();
+    while(cur)
+    {
+        /* skip debug files (shoud be the only iFTP==efNR) */
+        if (cur->bOpen && 
+            !cur->bRead && 
+            !cur->bStdio && 
+            cur->iFTP != efNR)
+        {
+            /* if any of them fails, return failure code */
+            int rc=gmx_fio_int_fsync(cur);
+            if (rc != 0 && !ret) 
+            {
+                ret=cur;
+            }
+        }
+        cur=gmx_fio_get_next(cur);
+    }
+
+    /* in addition, we force these to be written out too, if they're being
+       redirected. We don't check for errors because errors most likely mean
+       that they're not redirected. */
+    fflush(stdout);
+    fflush(stderr);
+#if (defined(HAVE_FSYNC))
+    /* again, fahcore defines HAVE_FSYNC and fsync() */
+    fsync(STDOUT_FILENO);
+    fsync(STDERR_FILENO);
+#endif
+
+    return ret;
 }
 
-off_t gmx_fio_ftell(int fio)
+
+off_t gmx_fio_ftell(t_fileio* fio)
 {
     off_t ret = 0;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    if (FIO[fio].fp)
-        ret = ftell(FIO[fio].fp);
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+
+    gmx_fio_lock(fio);
+    if (fio->fp)
+        ret = ftell(fio->fp);
+    gmx_fio_unlock(fio);
     return ret;
 }
 
-int gmx_fio_seek(int fio, off_t fpos)
+int gmx_fio_seek(t_fileio* fio, off_t fpos)
 {
     int rc;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    if (FIO[fio].fp)
+
+    gmx_fio_lock(fio);
+    if (fio->fp)
     {
 #ifdef HAVE_FSEEKO
-        rc = fseeko(FIO[fio].fp, fpos, SEEK_SET);
+        rc = fseeko(fio->fp, fpos, SEEK_SET);
 #else
-        rc = fseek(FIO[fio].fp,fpos,SEEK_SET);
+        rc = fseek(fio->fp,fpos,SEEK_SET);
 #endif
     }
     else
     {
-        gmx_file(FIO[fio].fn);
+        gmx_file(fio->fn);
         rc = -1;
     }
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+    gmx_fio_unlock(fio);
     return rc;
 }
 
-FILE *gmx_fio_getfp(int fio)
+FILE *gmx_fio_getfp(t_fileio *fio)
 {
     FILE *ret = NULL;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    if (FIO[fio].fp)
-        ret = FIO[fio].fp;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+
+    gmx_fio_lock(fio);
+    if (fio->fp)
+        ret = fio->fp;
+    gmx_fio_unlock(fio);
     return ret;
 }
 
-XDR *gmx_fio_getxdr(int fio)
+XDR *gmx_fio_getxdr(t_fileio* fio)
 {
     XDR *ret = NULL;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    if (FIO[fio].xdr)
-        ret = FIO[fio].xdr;
 
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+    gmx_fio_lock(fio);
+    if (fio->xdr)
+        ret = fio->xdr;
+    gmx_fio_unlock(fio);
+
     return ret;
 }
 
-bool gmx_fio_getread(int fio)
+bool gmx_fio_getread(t_fileio* fio)
 {
     bool ret;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_lock(&fio_mutex);
-#endif
-    gmx_fio_check(fio);
-    ret = FIO[fio].bRead;
-#ifdef GMX_THREADS
-    tMPI_Thread_mutex_unlock(&fio_mutex);
-#endif
+
+    gmx_fio_lock(fio);
+    ret = fio->bRead;
+    gmx_fio_unlock(fio);
+
     return ret;
 }
 
-int xtc_seek_frame(int frame, int fio, int natoms)
+int xtc_seek_frame(t_fileio *fio, int frame, int natoms)
 {
-    return xdr_xtc_seek_frame(frame, FIO[fio].fp, FIO[fio].xdr, natoms);
+    int ret;
+
+    gmx_fio_lock(fio);
+    ret=xdr_xtc_seek_frame(frame, fio->fp, fio->xdr, natoms);
+    gmx_fio_unlock(fio);
+
+    return ret;
 }
 
-int xtc_seek_time(real time, int fio, int natoms)
+int xtc_seek_time(t_fileio *fio, real time, int natoms)
 {
-    return xdr_xtc_seek_time(time, FIO[fio].fp, FIO[fio].xdr, natoms);
+    int ret;
+
+    gmx_fio_lock(fio);
+    ret=xdr_xtc_seek_time(time, fio->fp, fio->xdr, natoms);
+    gmx_fio_unlock(fio);
+
+    return ret;
 }
+
+
diff --git a/src/gmxlib/gmxfio_asc.c b/src/gmxlib/gmxfio_asc.c
new file mode 100644 (file)
index 0000000..937a807
--- /dev/null
@@ -0,0 +1,370 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#include "gmx_fatal.h"
+#include "macros.h"
+#include "smalloc.h"
+#include "futil.h"
+#include "filenm.h"
+#include "string2.h"
+#include "gmxfio.h"
+#include "md5.h"
+
+#ifdef GMX_THREADS
+#include "thread_mpi.h"
+#endif
+
+#include "gmxfio_int.h"
+
+
+/* This is the part that reads dummy and ascii files.  */
+
+
+
+
+/* file type functions */
+static bool do_ascread(t_fileio *fio, void *item, int nitem, int eio, 
+                       const char *desc, const char *srcfile, int line);
+static bool do_ascwrite(t_fileio *fio, const void *item, int nitem, int eio, 
+                        const char *desc, const char *srcfile, int line);
+static bool do_dummyread(t_fileio *fio, void *item, int nitem, int eio,
+                         const char *desc, const char *srcfile, int line);
+static bool do_dummywrite(t_fileio *fio, const void *item, int nitem, int eio,
+                          const char *desc, const char *srcfile, int line);
+
+
+const t_iotype asc_iotype={do_ascread, do_ascwrite};
+const t_iotype dummy_iotype={do_dummyread, do_dummywrite};
+
+
+
+
+
+
+static bool do_dummyread(t_fileio *fio, void *item, int nitem, int eio,
+                         const char *desc, const char *srcfile, int line)
+{
+    gmx_fatal(FARGS, "File type not set!");
+    return FALSE;
+}
+
+static bool do_dummywrite(t_fileio *fio, const void *item, int nitem, int eio,
+                          const char *desc, const char *srcfile, int line)
+{
+    gmx_fatal(FARGS, "File type not set!");
+    return FALSE;
+}
+
+
+
+static void encode_string(int maxlen, char dst[], const char src[])
+{
+    int i;
+
+    for (i = 0; (src[i] != '\0') && (i < maxlen - 1); i++)
+        if ((src[i] == ' ') || (src[i] == '\t'))
+            dst[i] = '_';
+        else
+            dst[i] = src[i];
+    dst[i] = '\0';
+
+    if (i == maxlen)
+        fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
+}
+
+static void decode_string(int maxlen, char dst[], const char src[])
+{
+    int i;
+
+    for (i = 0; (src[i] != '\0') && (i < maxlen - 1); i++)
+    {
+        if (src[i] == '_')
+        {
+            dst[i] = ' ';
+        }
+        else
+        {
+            dst[i] = src[i];
+        }
+    }
+    dst[i] = '\0';
+
+    if (i == maxlen)
+    {
+        fprintf(stderr, "String '%s' truncated to '%s'\n", src, dst);
+    }
+}
+
+static bool do_ascwrite(t_fileio *fio, const void *item, int nitem, int eio, 
+                        const char *desc, const char *srcfile, int line)
+{
+    int i;
+    int res = 0, *iptr;
+    real *ptr;
+    char strbuf[256];
+    char buf[GMX_FIO_BUFLEN];
+    unsigned char *ucptr;
+    FILE *fp=fio->fp;
+
+    gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
+    switch (eio)
+    {
+    case eioREAL:
+    case eioDOUBLE:
+        res = fprintf(fp, "%18.10e%s\n", *((real *) item), 
+                      gmx_fio_dbgstr(fio, desc, buf));
+        break;
+    case eioINT:
+        res = fprintf(fp, "%18d%s\n", *((int *) item), gmx_fio_dbgstr(fio, 
+                                                                      desc, 
+                                                                      buf));
+        break;
+    case eioGMX_LARGE_INT:
+        sprintf(strbuf, "%s%s%s", "%", gmx_large_int_fmt, "\n");
+        res = fprintf(fp, strbuf, *((gmx_large_int_t *) item),
+                      gmx_fio_dbgstr(fio, desc, buf));
+        break;
+    case eioUCHAR:
+        res = fprintf(fp, "%4d%s\n", *((unsigned char *) item),
+                      gmx_fio_dbgstr(fio, desc, buf));
+        break;
+    case eioNUCHAR:
+        ucptr = (unsigned char *) item;
+        for (i = 0; (i < nitem); i++)
+            res = fprintf(fp, "%4d", (int) ucptr[i]);
+        fprintf(fio->fp, "%s\n", gmx_fio_dbgstr(fio, desc, buf));
+        break;
+    case eioUSHORT:
+        res = fprintf(fp, "%18d%s\n", *((unsigned short *) item),
+                      gmx_fio_dbgstr(fio, desc, buf));
+        break;
+    case eioRVEC:
+        ptr = (real *) item;
+        res = fprintf(fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
+                      ptr[YY], ptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
+        break;
+    case eioNRVEC:
+        for (i = 0; (i < nitem); i++)
+        {
+            ptr = ((rvec *) item)[i];
+            res = fprintf(fp, "%18.10e%18.10e%18.10e%s\n", ptr[XX],
+                          ptr[YY], ptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
+        }
+        break;
+    case eioIVEC:
+        iptr = (int *) item;
+        res = fprintf(fp, "%18d%18d%18d%s\n", iptr[XX], iptr[YY],
+                      iptr[ZZ], gmx_fio_dbgstr(fio, desc, buf));
+        break;
+    case eioSTRING:
+        encode_string(256, strbuf, (char *) item);
+        res = fprintf(fp, "%-18s%s\n", strbuf, gmx_fio_dbgstr(fio, desc, buf));
+        break;
+    default:
+        gmx_fio_fe(fio, eio, desc, srcfile, line);
+    }
+    if ((res <= 0) && fio->bDebug)
+        fprintf(stderr,
+                "Error writing %s %s to file %s (source %s, line %d)\n",
+                eioNames[eio], desc, fio->fn, srcfile, line);
+
+    return (res > 0);
+}
+
+
+static char *next_item(FILE *fp, char *buf, int buflen)
+{
+    int rd;
+    bool in_comment = FALSE;
+    bool in_token = FALSE;
+    int i = 0;
+    /* This routine reads strings from the file fp, strips comment
+     * and buffers. For thread-safety reasons, It reads through getc()  */
+
+    rd = getc(fp);
+    if (rd == EOF)
+        gmx_file("End of file");
+    do
+    {
+        if (in_comment)
+        {
+            if (rd == '\n')
+                in_comment = FALSE;
+        }
+        else if (in_token)
+        {
+            if (isspace(rd) || rd == ';')
+                break;
+            buf[i++] = (char) rd;
+        }
+        else
+        {
+            if (!isspace(rd))
+            {
+                if (rd == ';')
+                    in_comment = TRUE;
+                else
+                {
+                    in_token = TRUE;
+                    buf[i++] = (char) (rd);
+                }
+            }
+        }
+        if (i >= buflen - 2)
+            break;
+    } while ((rd = getc(fp)) != EOF);
+
+    fprintf(stderr, "WARNING, ftpASC file type not tested!\n");
+
+    buf[i] = 0;
+
+    return buf;
+}
+
+static bool do_ascread(t_fileio *fio, void *item, int nitem, int eio, 
+                       const char *desc, const char *srcfile, int line)
+{
+    FILE *fp = fio->fp;
+    int i, m, res = 0, *iptr, ix;
+    gmx_large_int_t s;
+    double d, x;
+    real *ptr;
+    unsigned char uc, *ucptr;
+    char *cptr;
+#define NEXT_ITEM_BUF_LEN 128
+    char ni_buf[NEXT_ITEM_BUF_LEN];
+
+    gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
+    switch (eio)
+    {
+    case eioREAL:
+    case eioDOUBLE:
+        res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf", &d);
+        if (item)
+            *((real *) item) = d;
+        break;
+    case eioINT:
+        res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
+        if (item)
+            *((int *) item) = i;
+        break;
+    case eioGMX_LARGE_INT:
+        res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN),
+                     gmx_large_int_pfmt, &s);
+        if (item)
+            *((gmx_large_int_t *) item) = s;
+        break;
+    case eioUCHAR:
+        res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%c", &uc);
+        if (item)
+            *((unsigned char *) item) = uc;
+        break;
+    case eioNUCHAR:
+        ucptr = (unsigned char *) item;
+        for (i = 0; (i < nitem); i++)
+        {
+            res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &ix);
+            if (item)
+                ucptr[i] = ix;
+        }
+        break;
+    case eioUSHORT:
+        res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d", &i);
+        if (item)
+            *((unsigned short *) item) = i;
+        break;
+    case eioRVEC:
+        ptr = (real *) item;
+        for (m = 0; (m < DIM); m++)
+        {
+            res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n", &x);
+            ptr[m] = x;
+        }
+        break;
+    case eioNRVEC:
+        for (i = 0; (i < nitem); i++)
+        {
+            ptr = ((rvec *) item)[i];
+            for (m = 0; (m < DIM); m++)
+            {
+                res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%lf\n",
+                             &x);
+                if (item)
+                    ptr[m] = x;
+            }
+        }
+        break;
+    case eioIVEC:
+        iptr = (int *) item;
+        for (m = 0; (m < DIM); m++)
+        {
+            res = sscanf(next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN), "%d\n", &ix);
+            if (item)
+                iptr[m] = ix;
+        }
+        break;
+    case eioSTRING:
+        cptr = next_item(fp, ni_buf, NEXT_ITEM_BUF_LEN);
+        if (item)
+        {
+            decode_string(strlen(cptr) + 1, (char *) item, cptr);
+            /* res = sscanf(cptr,"%s",(char *)item);*/
+            res = 1;
+        }
+        break;
+    default:
+        gmx_fio_fe(fio, eio, desc, srcfile, line);
+    }
+
+    if ((res <= 0) && fio->bDebug)
+        fprintf(stderr,
+                "Error reading %s %s from file %s (source %s, line %d)\n",
+                eioNames[eio], desc, fio->fn, srcfile, line);
+    return (res > 0);
+}
+
diff --git a/src/gmxlib/gmxfio_bin.c b/src/gmxlib/gmxfio_bin.c
new file mode 100644 (file)
index 0000000..578e546
--- /dev/null
@@ -0,0 +1,204 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#include "gmx_fatal.h"
+#include "macros.h"
+#include "smalloc.h"
+#include "futil.h"
+#include "filenm.h"
+#include "string2.h"
+#include "gmxfio.h"
+#include "md5.h"
+
+#ifdef GMX_THREADS
+#include "thread_mpi.h"
+#endif
+
+#include "gmxfio_int.h"
+
+/* This is the part that reads dummy and ascii files.  */
+
+
+static bool do_binread(t_fileio *fio, void *item, int nitem, int eio, 
+                       const char *desc, const char *srcfile, int line);
+static bool do_binwrite(t_fileio *fio, const void *item, int nitem, int eio, 
+                        const char *desc, const char *srcfile, int line);
+
+
+const t_iotype bin_iotype={do_binread, do_binwrite};
+
+
+static bool do_binwrite(t_fileio *fio, const void *item, int nitem, int eio, 
+                        const char *desc, const char *srcfile, int line)
+{
+    size_t size = 0, wsize;
+    int ssize;
+
+    gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
+    switch (eio)
+    {
+    case eioREAL:
+        size = sizeof(real);
+        break;
+    case eioDOUBLE:
+        size = sizeof(double);
+        break;
+    case eioINT:
+        size = sizeof(int);
+        break;
+    case eioGMX_LARGE_INT:
+        size = sizeof(gmx_large_int_t);
+        break;
+    case eioUCHAR:
+        size = sizeof(unsigned char);
+        break;
+    case eioNUCHAR:
+        size = sizeof(unsigned char);
+        break;
+    case eioUSHORT:
+        size = sizeof(unsigned short);
+        break;
+    case eioRVEC:
+        size = sizeof(rvec);
+        break;
+    case eioNRVEC:
+        size = sizeof(rvec);
+        break;
+    case eioIVEC:
+        size = sizeof(ivec);
+        break;
+    case eioSTRING:
+        size = ssize = strlen((char *) item) + 1;
+        do_binwrite(fio, &ssize, 1, eioINT, desc, srcfile, line);
+        break;
+    default:
+        gmx_fio_fe(fio, eio, desc, srcfile, line);
+    }
+
+    wsize = fwrite(item, size, nitem, fio->fp);
+
+    if ((wsize != nitem) && fio->bDebug)
+    {
+        fprintf(stderr,
+                "Error writing %s %s to file %s (source %s, line %d)\n",
+                eioNames[eio], desc, fio->fn, srcfile, line);
+        fprintf(stderr, "written size %u bytes, source size %u bytes\n",
+                (unsigned int) wsize, (unsigned int) size);
+    }
+    return (wsize == nitem);
+}
+
+static bool do_binread(t_fileio *fio, void *item, int nitem, int eio, 
+                       const char *desc, const char *srcfile, int line)
+{
+    size_t size = 0, rsize;
+    int ssize;
+
+    gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
+    switch (eio)
+    {
+    case eioREAL:
+        if (fio->bDouble)
+            size = sizeof(double);
+        else
+            size = sizeof(float);
+        break;
+    case eioDOUBLE:
+        size = sizeof(double);
+        break;
+    case eioINT:
+        size = sizeof(int);
+        break;
+    case eioGMX_LARGE_INT:
+        size = sizeof(gmx_large_int_t);
+        break;
+    case eioUCHAR:
+        size = sizeof(unsigned char);
+        break;
+    case eioNUCHAR:
+        size = sizeof(unsigned char);
+        break;
+    case eioUSHORT:
+        size = sizeof(unsigned short);
+        break;
+    case eioRVEC:
+    case eioNRVEC:
+        if (fio->bDouble)
+            size = sizeof(double) * DIM;
+        else
+            size = sizeof(float) * DIM;
+        break;
+    case eioIVEC:
+        size = sizeof(ivec);
+        break;
+    case eioSTRING:
+        do_binread(fio, &ssize, 1, eioINT, desc, srcfile, line);
+        size = ssize;
+        break;
+    default:
+        gmx_fio_fe(fio, eio, desc, srcfile, line);
+    }
+    if (item)
+        rsize = fread(item, size, nitem, fio->fp);
+    else
+    {
+        /* Skip over it if we have a NULL pointer here */
+#ifdef HAVE_FSEEKO
+        fseeko(fio->fp, (off_t) (size * nitem), SEEK_CUR);
+#else
+        fseek(fio->fp,(size*nitem),SEEK_CUR);
+#endif    
+        rsize = nitem;
+    }
+    if ((rsize != nitem) && (fio->bDebug))
+        fprintf(stderr,
+                "Error reading %s %s from file %s (source %s, line %d)\n",
+                eioNames[eio], desc, fio->fn, srcfile, line);
+
+    return (rsize == nitem);
+}
+
+
diff --git a/src/gmxlib/gmxfio_int.h b/src/gmxlib/gmxfio_int.h
new file mode 100644 (file)
index 0000000..0b84154
--- /dev/null
@@ -0,0 +1,132 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+
+
+
+/* This is the new improved and thread safe version of gmxfio.  */
+
+
+/* WARNING WARNING WARNING WARNING
+   The data types used here are PRIVATE to gmxfio routines. DO NOT use them
+   directly in your own code, but use the external functions provided in 
+   include/gmxfio.h 
+
+   If you don't heed this warning, your code will suddenly stop working 
+   at some point in the not-so-distant future. 
+
+   WARNING WARNING WARNING WARNING */
+
+
+/* XDR should be available on all platforms now, 
+ * but we keep the possibility of turning it off...
+ */
+#define USE_XDR
+
+
+
+/* the reader/writer functions  for t_iotype */
+typedef bool read_func(t_fileio *fio, void *item, int nitem, int eio,
+                       const char *desc,const char *srcfile,int line);
+typedef bool write_func(t_fileio *fio, const void *item, int nitem, int eio,
+                        const char *desc,const char *srcfile,int line);
+
+
+/* these are pointers to the actual reading & writing functions */
+typedef struct
+{
+    read_func *nread;
+    write_func *nwrite;
+} t_iotype;
+
+
+
+struct t_fileio
+{
+    FILE *fp; /* the file pointer */
+    const t_iotype *iotp;  /* file type */
+    bool bOpen,  /* the file is open */
+         bRead,  /* the file is open for reading */
+         bDouble, /* write doubles instead of floats */
+         bDebug, /* the file ops should come with debug info */
+         bStdio, /* the file is actually stdin or stdout */
+         bLargerThan_off_t,  /* if the file position is largen than off_t 
+                                could hold */
+         bReadWrite; /* the file is open for reading and writing */
+    char *fn; /* the file name */
+    XDR *xdr; /* the xdr data pointer */
+    enum xdr_op xdrmode; /* the xdr mode */
+    int iFTP; /* the file type identifier */
+
+    const char *comment; /* a comment string for debugging */
+
+    t_fileio *next, *prev; /* next and previous file pointers in the
+                              linked list */
+#ifdef GMX_THREADS
+    tMPI_Spinlock_t  mtx;  /* content locking mutex. This is a spinlock
+                              for performance reasons: in some cases every
+                              single byte that gets read/written requires
+                              a lock */
+#endif
+}; 
+
+
+
+extern const t_iotype asc_iotype;
+extern const t_iotype bin_iotype;
+extern const t_iotype xdr_iotype;
+extern const t_iotype dummy_iotype;
+
+extern const char *eioNames[eioNR];
+
+
+
+#define GMX_FIO_BUFLEN 256
+
+/* make a debug string if that is requested in the fio */
+const char *gmx_fio_dbgstr(t_fileio *fio, const char *desc, char *buf);
+/* check the number of items against the allowed number of items */
+void gmx_fio_check_nitem(t_fileio *fio, int eio, int nitem, const char *file, 
+                         int line);
+/* check the output type against allowed values */
+void gmx_fio_fe(t_fileio *fio, int eio, const char *desc, const char *srcfile, 
+                int line);
+
+/* lock/unlock the mutex associated with a fio  */
+void gmx_fio_lock(t_fileio *fio);
+void gmx_fio_unlock(t_fileio *fio);
+
+
+
diff --git a/src/gmxlib/gmxfio_rw.c b/src/gmxlib/gmxfio_rw.c
new file mode 100644 (file)
index 0000000..e250536
--- /dev/null
@@ -0,0 +1,882 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#include "gmx_fatal.h"
+#include "macros.h"
+#include "smalloc.h"
+#include "futil.h"
+#include "filenm.h"
+#include "string2.h"
+#include "gmxfio.h"
+#include "md5.h"
+
+#ifdef GMX_THREADS
+#include "thread_mpi.h"
+#endif
+
+#include "gmxfio_int.h"
+
+
+/*******************************************************************
+ *
+ * READ/WRITE FUNCTIONS 
+ *
+*******************************************************************/
+
+bool gmx_fio_reade_real(t_fileio *fio, real *item,
+                        const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nread(fio, item, 1, eioREAL, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_reade_double(t_fileio *fio, double *item,
+                          const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nread(fio, item, 1, eioDOUBLE, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_reade_int(t_fileio *fio, int *item,
+                       const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nread(fio, item, 1, eioINT, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_reade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item,
+                             const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nread(fio, item, 1, eioGMX_LARGE_INT, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_reade_uchar(t_fileio *fio, unsigned char *item,
+                         const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nread(fio, item, 1, eioUCHAR, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+bool gmx_fio_reade_ushort(t_fileio *fio, unsigned short *item,
+                         const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nread(fio, item, 1, eioUSHORT, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_reade_rvec(t_fileio *fio, rvec *item,
+                        const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nread(fio, item, 1, eioRVEC, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_reade_ivec(t_fileio *fio, ivec *item,
+                        const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nread(fio, item, 1, eioIVEC, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_reade_string(t_fileio *fio, char *item,
+                          const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nread(fio, item, 1, eioSTRING, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+/* Write */
+
+bool gmx_fio_writee_real(t_fileio *fio, real item,
+                         const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nwrite(fio, &item, 1, eioREAL, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_writee_double(t_fileio *fio, double item,
+                           const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nwrite(fio, &item, 1, eioDOUBLE, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+bool gmx_fio_writee_int(t_fileio *fio, int item,
+                        const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nwrite(fio, &item, 1, eioINT, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_writee_gmx_large_int(t_fileio *fio, gmx_large_int_t item,
+                              const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nwrite(fio, &item, 1, eioGMX_LARGE_INT, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_writee_uchar(t_fileio *fio, unsigned char item,
+                          const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nwrite(fio, &item, 1, eioUCHAR, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_writee_ushort(t_fileio *fio, unsigned short item,
+                          const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nwrite(fio, &item, 1, eioUSHORT, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_writee_rvec(t_fileio *fio, rvec *item,
+                         const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nwrite(fio, item, 1, eioRVEC, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_writee_ivec(t_fileio *fio, ivec *item,
+                         const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nwrite(fio, item, 1, eioIVEC, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_writee_string(t_fileio *fio, const char *item,
+                           const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nwrite(fio, item, 1, eioSTRING, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+/* Read/write functions */
+
+bool gmx_fio_doe_real(t_fileio *fio, real *item,
+                      const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+        ret=fio->iotp->nread(fio, item, 1, eioREAL, desc, srcfile, line);
+    else
+        ret=fio->iotp->nwrite(fio, item, 1, eioREAL, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+bool gmx_fio_doe_double(t_fileio *fio, double *item,
+                        const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+        ret=fio->iotp->nread(fio, item, 1, eioDOUBLE, desc, srcfile, line);
+    else
+        ret=fio->iotp->nwrite(fio, item, 1, eioDOUBLE, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+bool gmx_fio_doe_bool(t_fileio *fio, bool *item,
+                      const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    int itmp;
+    
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+    {
+        ret=fio->iotp->nread(fio, &itmp, 1, eioINT, desc, srcfile, line);
+        *item = itmp;
+    }
+    else
+    {
+        itmp = *item;
+        ret=fio->iotp->nwrite(fio, &itmp, 1, eioINT, desc, srcfile, line);
+    }
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_doe_int(t_fileio *fio, int *item,
+                     const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+        ret=fio->iotp->nread(fio, item, 1, eioINT, desc, srcfile, line);
+    else
+        ret=fio->iotp->nwrite(fio, item, 1, eioINT, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_doe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item,
+                           const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+        ret=fio->iotp->nread(fio, item, 1, eioGMX_LARGE_INT, desc, srcfile, line);
+    else
+        ret=fio->iotp->nwrite(fio, item, 1, eioGMX_LARGE_INT, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_doe_uchar(t_fileio *fio, unsigned char *item,
+                       const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+        ret=fio->iotp->nread(fio, item, 1, eioUCHAR, desc, srcfile, line);
+    else
+        ret=fio->iotp->nwrite(fio, item, 1, eioUCHAR, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_doe_ushort(t_fileio *fio, unsigned short *item,
+                       const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+        ret=fio->iotp->nread(fio, item, 1, eioUSHORT, desc, srcfile, line);
+    else
+        ret=fio->iotp->nwrite(fio, item, 1, eioUSHORT, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_doe_rvec(t_fileio *fio, rvec *item,
+                      const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+        ret=fio->iotp->nread(fio, item, 1, eioRVEC, desc, srcfile, line);
+    else
+        ret=fio->iotp->nwrite(fio, item, 1, eioRVEC, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_doe_ivec(t_fileio *fio, ivec *item,
+                      const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+        ret=fio->iotp->nread(fio, item, 1, eioIVEC, desc, srcfile, line);
+    else
+        ret=fio->iotp->nwrite(fio, item, 1, eioIVEC, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_doe_string(t_fileio *fio, char *item,
+                        const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+        ret=fio->iotp->nread(fio, item, 1, eioSTRING, desc, srcfile, line);
+    else
+        ret=fio->iotp->nwrite(fio, item, 1, eioSTRING, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+
+
+
+
+/* Array reading & writing */
+
+bool gmx_fio_nreade_real(t_fileio *fio, real *item, int n,
+                          const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioREAL, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_nreade_double(t_fileio *fio, double *item, int n,
+                            const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret= ret && fio->iotp->nread(fio, &(item[i]), 1, eioDOUBLE, desc, srcfile, 
+                               line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_nreade_int(t_fileio *fio, int *item, int n,
+                         const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioINT, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_nreade_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n,
+                               const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioGMX_LARGE_INT, desc, 
+                              srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+bool gmx_fio_nreade_uchar(t_fileio *fio, unsigned char *item, int n,
+                           const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nread(fio, item, n, eioNUCHAR, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_nreade_ushort(t_fileio *fio, unsigned short *item, int n,
+                           const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioUSHORT, desc, 
+                                    srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_nreade_rvec(t_fileio *fio, rvec *item, int n,
+                          const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nread(fio, item, n, eioNRVEC, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_nreade_ivec(t_fileio *fio, ivec *item, int n,
+                          const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nread(fio, item[i], 1, eioIVEC, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_nreade_string(t_fileio *fio, char *item[], int n,
+                           const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nread(fio, item[i], 1, eioSTRING, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+
+/* Array writing */
+
+bool gmx_fio_nwritee_real(t_fileio *fio, const real *item, int n,
+                          const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioREAL, desc, 
+                                     srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+bool gmx_fio_nwritee_double(t_fileio *fio, const double *item, int n,
+                            const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioDOUBLE, desc, 
+                                     srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+bool gmx_fio_nwritee_int(t_fileio *fio, const int *item, int n,
+                         const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioINT, desc, srcfile, 
+                                     line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_nwritee_gmx_large_int(t_fileio *fio, 
+                               const gmx_large_int_t *item, int n,
+                               const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioGMX_LARGE_INT, 
+                                     desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_nwritee_uchar(t_fileio *fio, const unsigned char *item, int n,
+                           const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nwrite(fio, item, n, eioNUCHAR, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_nwritee_ushort(t_fileio *fio, const unsigned short *item, int n,
+                           const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioUSHORT, desc, 
+                                     srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+bool gmx_fio_nwritee_rvec(t_fileio *fio, const rvec *item, int n,
+                          const char *desc, const char *srcfile, int line)
+{
+    bool ret;
+    gmx_fio_lock(fio);
+    ret=fio->iotp->nwrite(fio, item, n, eioNRVEC, desc, srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_nwritee_ivec(t_fileio *fio, const ivec *item, int n,
+                          const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioIVEC, desc, 
+                                     srcfile, line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+bool gmx_fio_nwritee_string(t_fileio *fio, const char *item[], int n,
+                            const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+        ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioSTRING, desc, srcfile, 
+                               line);
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+/* array read/write functions */
+
+bool gmx_fio_ndoe_real(t_fileio *fio, real *item, int n,
+                       const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+    {
+        if (fio->bRead)
+        {
+            ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioREAL, desc, 
+                                  srcfile, line);
+        }
+        else
+        {
+            ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioREAL, desc, 
+                                   srcfile, line);
+        }
+    }
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+bool gmx_fio_ndoe_double(t_fileio *fio, double *item, int n,
+                         const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+    {
+        if (fio->bRead)
+        {
+            ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioDOUBLE, desc, 
+                                  srcfile, line);
+        }
+        else
+        {
+            ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioDOUBLE, desc, 
+                                   srcfile, line);
+        }
+    }
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+bool gmx_fio_ndoe_bool(t_fileio *fio, bool *item, int n,
+                      const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i,itmp;
+    
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+    {
+        if (fio->bRead)
+        {
+            ret=ret && fio->iotp->nread(fio, &itmp, 1, eioINT, desc, 
+                                  srcfile, line);
+            item[i] = itmp;
+        }
+        else
+        {
+            itmp = item[i];
+            ret=ret && fio->iotp->nwrite(fio, &itmp, 1, eioINT, desc, 
+                                   srcfile, line);
+        }
+    }
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+bool gmx_fio_ndoe_int(t_fileio *fio, int *item, int n,
+                      const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+    {
+        if (fio->bRead)
+        {
+            ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioINT, desc, 
+                                  srcfile, line);
+        }
+        else
+        {
+            ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioINT, desc, 
+                                   srcfile, line);
+        }
+    }
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+bool gmx_fio_ndoe_gmx_large_int(t_fileio *fio, gmx_large_int_t *item, int n,
+                            const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+    {
+        if (fio->bRead)
+        {
+            ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioGMX_LARGE_INT, desc, 
+                                  srcfile, line);
+        }
+        else
+        {
+            ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioGMX_LARGE_INT, desc, 
+                                   srcfile, line);
+        }
+    }
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+bool gmx_fio_ndoe_uchar(t_fileio *fio, unsigned char *item, int n,
+                        const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+    {
+        ret=ret && fio->iotp->nread(fio, item, n, eioNUCHAR, desc, 
+                                    srcfile, line);
+    }
+    else
+    {
+        ret=ret && fio->iotp->nwrite(fio, item, n, eioNUCHAR, desc, 
+                                     srcfile, line);
+    }
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+bool gmx_fio_ndoe_ushort(t_fileio *fio, unsigned short *item, int n,
+                        const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+    {
+        if (fio->bRead)
+        {
+            ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioUSHORT, desc, 
+                                  srcfile, line);
+        }
+        else
+        {
+            ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioUSHORT, desc, 
+                                   srcfile, line);
+        }
+    }
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+bool gmx_fio_ndoe_rvec(t_fileio *fio, rvec *item, int n,
+                       const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    gmx_fio_lock(fio);
+    if (fio->bRead)
+    {
+        ret=ret && fio->iotp->nread(fio, item, n, eioNRVEC, desc, srcfile, line);
+    }
+    else
+    {
+        ret=ret && fio->iotp->nwrite(fio, item, n, eioNRVEC, desc, srcfile, 
+                               line);
+    }
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+bool gmx_fio_ndoe_ivec(t_fileio *fio, ivec *item, int n,
+                       const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+    {
+        if (fio->bRead)
+        {
+            ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioIVEC, desc, 
+                                  srcfile, line);
+        }
+        else
+        {
+            ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioIVEC, desc, 
+                                   srcfile, line);
+        }
+    }
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+bool gmx_fio_ndoe_string(t_fileio *fio, char *item[], int n,
+                         const char *desc, const char *srcfile, int line)
+{
+    bool ret=TRUE;
+    int i;
+    gmx_fio_lock(fio);
+    for(i=0;i<n;i++)
+    {
+        if (fio->bRead)
+        {
+            ret=ret && fio->iotp->nread(fio, &(item[i]), 1, eioSTRING, desc, 
+                                  srcfile, line);
+        }
+        else
+        {
+            ret=ret && fio->iotp->nwrite(fio, &(item[i]), 1, eioSTRING, desc, 
+                                   srcfile, line);
+        }
+    }
+    gmx_fio_unlock(fio);
+    return ret;
+}
+
+
+
+
+
diff --git a/src/gmxlib/gmxfio_xdr.c b/src/gmxlib/gmxfio_xdr.c
new file mode 100644 (file)
index 0000000..c451c85
--- /dev/null
@@ -0,0 +1,263 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef HAVE_IO_H
+#include <io.h>
+#endif
+
+#include "gmx_fatal.h"
+#include "macros.h"
+#include "smalloc.h"
+#include "futil.h"
+#include "filenm.h"
+#include "string2.h"
+#include "gmxfio.h"
+#include "md5.h"
+
+#ifdef GMX_THREADS
+#include "thread_mpi.h"
+#endif
+
+#include "gmxfio_int.h"
+
+/* This is the part that reads xdr files.  */
+
+
+/* file type functions */
+static bool do_xdrread(t_fileio *fio, void *item, int nitem, int eio, 
+                       const char *desc, const char *srcfile, int line);
+static bool do_xdrwrite(t_fileio *fio, const void *item, int nitem, int eio, 
+                        const char *desc, const char *srcfile, int line);
+
+
+const t_iotype xdr_iotype={do_xdrread, do_xdrwrite};
+
+
+#ifdef USE_XDR
+
+static bool do_xdr(t_fileio *fio, void *item, int nitem, int eio, 
+                   const char *desc, const char *srcfile, int line)
+{
+    unsigned char ucdum, *ucptr;
+    bool_t res = 0;
+    float fvec[DIM];
+    double dvec[DIM];
+    int j, m, *iptr, idum;
+    gmx_large_int_t sdum;
+    real *ptr;
+    unsigned short us;
+    double d = 0;
+    float f = 0;
+
+    gmx_fio_check_nitem(fio, eio, nitem, srcfile, line);
+    switch (eio)
+    {
+    case eioREAL:
+        if (fio->bDouble)
+        {
+            if (item && !fio->bRead)
+                d = *((real *) item);
+            res = xdr_double(fio->xdr, &d);
+            if (item)
+                *((real *) item) = d;
+        }
+        else
+        {
+            if (item && !fio->bRead)
+                f = *((real *) item);
+            res = xdr_float(fio->xdr, &f);
+            if (item)
+                *((real *) item) = f;
+        }
+        break;
+    case eioDOUBLE:
+        if (item && !fio->bRead)
+            d = *((double *) item);
+        res = xdr_double(fio->xdr, &d);
+        if (item)
+            *((double *) item) = d;
+        break;
+    case eioINT:
+        if (item && !fio->bRead)
+            idum = *(int *) item;
+        res = xdr_int(fio->xdr, &idum);
+        if (item)
+            *(int *) item = idum;
+        break;
+    case eioGMX_LARGE_INT:
+        /* do_xdr will not generate a warning when a 64bit gmx_large_int_t
+         * value that is out of 32bit range is read into a 32bit gmx_large_int_t.
+         */
+        if (item && !fio->bRead)
+            sdum = *(gmx_large_int_t *) item;
+        res = xdr_gmx_large_int(fio->xdr, &sdum, NULL);
+        if (item)
+            *(gmx_large_int_t *) item = sdum;
+        break;
+    case eioUCHAR:
+        if (item && !fio->bRead)
+            ucdum = *(unsigned char *) item;
+        res = xdr_u_char(fio->xdr, &ucdum);
+        if (item)
+            *(unsigned char *) item = ucdum;
+        break;
+    case eioNUCHAR:
+        ucptr = (unsigned char *) item;
+        res = 1;
+        for (j = 0; (j < nitem) && res; j++)
+        {
+            res = xdr_u_char(fio->xdr, &(ucptr[j]));
+        }
+        break;
+    case eioUSHORT:
+        if (item && !fio->bRead)
+            us = *(unsigned short *) item;
+        res = xdr_u_short(fio->xdr, (unsigned short *) &us);
+        if (item)
+            *(unsigned short *) item = us;
+        break;
+    case eioRVEC:
+        if (fio->bDouble)
+        {
+            if (item && !fio->bRead)
+                for (m = 0; (m < DIM); m++)
+                    dvec[m] = ((real *) item)[m];
+            res = xdr_vector(fio->xdr, (char *) dvec, DIM,
+                             (unsigned int) sizeof(double),
+                             (xdrproc_t) xdr_double);
+            if (item)
+                for (m = 0; (m < DIM); m++)
+                    ((real *) item)[m] = dvec[m];
+        }
+        else
+        {
+            if (item && !fio->bRead)
+                for (m = 0; (m < DIM); m++)
+                    fvec[m] = ((real *) item)[m];
+            res = xdr_vector(fio->xdr, (char *) fvec, DIM,
+                             (unsigned int) sizeof(float),
+                             (xdrproc_t) xdr_float);
+            if (item)
+                for (m = 0; (m < DIM); m++)
+                    ((real *) item)[m] = fvec[m];
+        }
+        break;
+    case eioNRVEC:
+        ptr = NULL;
+        res = 1;
+        for (j = 0; (j < nitem) && res; j++)
+        {
+            if (item)
+                ptr = ((rvec *) item)[j];
+            res = do_xdr(fio, ptr, 1, eioRVEC, desc, srcfile, line);
+        }
+        break;
+    case eioIVEC:
+        iptr = (int *) item;
+        res = 1;
+        for (m = 0; (m < DIM) && res; m++)
+        {
+            if (item && !fio->bRead)
+                idum = iptr[m];
+            res = xdr_int(fio->xdr, &idum);
+            if (item)
+                iptr[m] = idum;
+        }
+        break;
+    case eioSTRING:
+    {
+        char *cptr;
+        int slen;
+
+        if (item)
+        {
+            if (!fio->bRead)
+                slen = strlen((char *) item) + 1;
+            else
+                slen = 0;
+        }
+        else
+            slen = 0;
+
+        if (xdr_int(fio->xdr, &slen) <= 0)
+            gmx_fatal(FARGS, "wrong string length %d for string %s"
+                      " (source %s, line %d)",slen,desc,srcfile,line);
+        if (!item && fio->bRead)
+            snew(cptr,slen);
+        else
+            cptr=(char *)item;
+        if (cptr)
+            res = xdr_string(fio->xdr,&cptr,slen);
+        else
+            res = 1;
+        if (!item && fio->bRead)
+            sfree(cptr);
+        break;
+    }
+    default:
+        gmx_fio_fe(fio, eio, desc, srcfile, line);
+    }
+    if ((res == 0) && (fio->bDebug))
+        fprintf(stderr,"Error in xdr I/O %s %s to file %s (source %s, line %d)\n",
+                eioNames[eio],desc,fio->fn,srcfile,line);
+
+    return (res != 0);
+}
+
+
+static bool do_xdrread(t_fileio *fio, void *item, int nitem, int eio, 
+                       const char *desc, const char *srcfile, int line)
+{
+    return do_xdr(fio, item, nitem, eio, desc, srcfile, line);
+}
+
+
+static bool do_xdrwrite(t_fileio *fio, const void *item, int nitem, int eio, 
+                        const char *desc, const char *srcfile, int line)
+{
+    void *it=(void*)item; /* ugh.. */
+    return do_xdr(fio, it, nitem, eio, desc, srcfile, line);
+}
+
+#endif
+
+
index 7c6586b6f9b7ff9d17e6dd582698c6845b33fad2..0b640e5ebe7fe8a08c4cedfa3e87afcbfb8fe436 100644 (file)
 #include "txtdump.h"
 #include "gmxfio.h"
 
-typedef enum { etOther, etProt, etDNA, erestNR } eRestp;
-static const char *ResTP[erestNR] = { "OTHER", "PROTEIN", "DNA" };
+typedef enum { etOther, etProt, etDNA, etRNA, erestNR } eRestp;
+static const char *ResTP[erestNR] = { "OTHER", "PROTEIN", "DNA", "RNA" };
 
-static const char   *Sugars[]     = { "A", "T", "G", "C", "U" };
-#define  NDNA asize(Sugars)
+static const char *DNA[]          = { "DA", "DT", "DG", "DC", "DU" };
+#define  NDNA asize(DNA)
+
+static const char *RNA[]          = {  "A",  "T",  "G",  "C",  "U" };
+#define  NRNA asize(RNA)
 
 static const char *Negate[] = { "SOL" };
 #define  NNEGATE asize(Negate)
@@ -282,9 +285,9 @@ static void analyse_prot(eRestp restp[],t_atoms *atoms,
                             "MCD1", "MCD2", "MCE1", "MCE2", "MNZ1", "MNZ2" };
   static const char *calpha[]  = { "CA" };
   static const char *bb[]      = { "N","CA","C" };
-  static const char *mc[]      = { "N","CA","C","O","O1","O2","OXT" };
-  static const char *mcb[]     = { "N","CA","CB","C","O","O1","O2","OT","OXT" };
-  static const char *mch[]     = { "N","CA","C","O","O1","O2","OT","OXT",
+  static const char *mc[]      = { "N","CA","C","O","O1","O2","OC1","OC2","OT","OXT" };
+  static const char *mcb[]     = { "N","CA","CB","C","O","O1","O2","OC1","OC2","OT","OXT" };
+  static const char *mch[]     = { "N","CA","C","O","O1","O2","OC1","OC2","OT","OXT",
                             "H1","H2","H3","H" };
   /* array of arrays of atomnames: */
   static const char **chains[] = { NULL,pnoh,calpha,bb,mc,mcb,mch,mch,mch,pnodum };
@@ -452,6 +455,30 @@ t_aa_names *get_aa_names(void)
   return aan;
 }
 
+bool is_residue(t_aa_names *aan,char *resnm)
+{
+  /* gives true if resnm occurs in aminoacids.dat */
+  int i;
+  
+  for(i=0; i<aan->n; i++) {
+    if (strcasecmp(aan->aa[i],resnm) == 0) {
+      return TRUE;
+    }
+  }
+  for(i=0; i<NDNA; i++) {
+    if (strcasecmp(DNA[i],resnm) == 0) {
+      return TRUE;
+    }
+  }
+  for(i=0; i<NRNA; i++) {
+    if (strcasecmp(RNA[i],resnm) == 0) {
+      return TRUE;
+    }
+  }
+
+  return FALSE;
+}
+
 bool is_protein(t_aa_names *aan,char *resnm)
 {
   /* gives true if resnm occurs in aminoacids.dat */
@@ -498,11 +525,16 @@ void analyse(t_atoms *atoms,t_blocka *gb,char ***gn,bool bASK,bool bVerb)
     resnm = *atoms->resinfo[i].name;
     if ((restp[i] == etOther) && is_protein(aan,resnm))
       restp[i] = etProt;
-    if (restp[i] == etOther)
+    if (restp[i] == etOther) {
       for(j=0; (j<NDNA);  j++) {
-       if (strcasecmp(Sugars[j],resnm) == 0)
+       if (strcasecmp(DNA[j],resnm) == 0)
          restp[i] = etDNA;
       }
+      for(j=0; (j<NRNA);  j++) {
+       if (strcasecmp(RNA[j],resnm) == 0)
+         restp[i] = etRNA;
+      }
+    }
   }
   p_status(atoms->nres,restp,bVerb);
   done_aa_names(&aan);
@@ -528,6 +560,14 @@ void analyse(t_atoms *atoms,t_blocka *gb,char ***gn,bool bASK,bool bVerb)
   }
   sfree(aid);
 
+  /* RNA */
+  aid=mk_aid(atoms,restp,etRNA,&nra,TRUE);
+  if (nra > 0) {
+    add_grp(gb,gn,nra,aid,"RNA"); 
+    analyse_dna(restp,atoms,gb,gn,bASK,bVerb);
+  }
+  sfree(aid);
+
   /* Other */
   analyse_other(restp,atoms,gb,gn,bASK,bVerb);
 
index 50bb164866bfe6b343332bf6337f81fe08e02f3e..bba3eb78289a474e3fbd94cf64649f49ad4c6555 100644 (file)
 #endif
 
 
+/* This is just for clarity - it can never be anything but 4! */
+#define XDR_INT_SIZE 4
+
+
+
+#ifndef GMX_THREADS
+
+/* NOTE: DO NOT USE THESE ANYWHERE IN GROMACS ITSELF. 
+   These are necessary for the backward-compatile io routines for 3d party
+   tools */
 #define MAXID 256
 static FILE *xdrfiles[MAXID];
 static XDR *xdridptr[MAXID];
 static char xdrmodes[MAXID];
 static unsigned int cnt;
 
-/* This is just for clarity - it can never be anything but 4! */
-#define XDR_INT_SIZE 4
+#endif
 
 #ifdef GMX_FORTRAN
 
+
+/* the open&close prototypes */
+int xdropen(XDR *xdrs, const char *filename, const char *type);
+int xdrclose(XDR *xdrs);
+
 typedef void (* F77_FUNC(xdrfproc,XDRFPROC))(int *, void *, int *);
 
 int ftocstr(char *ds, int dl, char *ss, int sl)
@@ -275,48 +289,18 @@ F77_FUNC(xdrfopen,XDRFOPEN)(int *xdrid, char *fp_ptr, char *mode_ptr,
 }
 #endif /* GMX_FORTRAN */
 
-/*___________________________________________________________________________
- |
- | what follows are the C routines for opening, closing xdr streams
- | and the routine to read/write compressed coordinates together
- | with some routines to assist in this task (those are marked
- | static and cannot be called from user programs)
-*/
-#define MAXABS INT_MAX-2
-
-#ifndef MIN
-#define MIN(x,y) ((x) < (y) ? (x):(y))
-#endif
-#ifndef MAX
-#define MAX(x,y) ((x) > (y) ? (x):(y))
-#endif
-#ifndef SQR
-#define SQR(x) ((x)*(x))
-#endif
-static int magicints[] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0,
-    8, 10, 12, 16, 20, 25, 32, 40, 50, 64,
-    80, 101, 128, 161, 203, 256, 322, 406, 512, 645,
-    812, 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501,
-    8192, 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536,
-    82570, 104031, 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561,
-    832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304, 5284491, 6658042,
-    8388607, 10568983, 13316085, 16777216 };
-
-#define FIRSTIDX 9
-/* note that magicints[FIRSTIDX-1] == 0 */
-#define LASTIDX (sizeof(magicints) / sizeof(*magicints))
-
-
+#ifndef GMX_THREADS
 /*__________________________________________________________________________
  |
  | xdropen - open xdr file
  |
  | This versions differs from xdrstdio_create, because I need to know
- | the state of the file (read or write) so I can use xdr3dfcoord
- | in eigther read or write mode, and the file descriptor
+ | the state of the file (read or write)  and the file descriptor
  | so I can close the file (something xdr_destroy doesn't do).
  |
+ | NOTE: THIS FUNCTION IS NOW OBSOLETE AND ONLY PROVIDED FOR BACKWARD
+ |       COMPATIBILITY OF 3D PARTY TOOLS. IT SHOULD NOT BE USED ANYWHERE 
+ |       IN GROMACS ITSELF. 
 */
 
 int xdropen(XDR *xdrs, const char *filename, const char *type) {
@@ -369,7 +353,7 @@ int xdropen(XDR *xdrs, const char *filename, const char *type) {
        return 0;
     }
     
-    /* next test isn't usefull in the case of C language
+    /* next test isn't useful in the case of C language
      * but is used for the Fortran interface
      * (C users are expected to pass the address of an already allocated
      * XDR staructure)
@@ -383,7 +367,6 @@ int xdropen(XDR *xdrs, const char *filename, const char *type) {
     }
     return xdrid;
 }
-
 /*_________________________________________________________________________
  |
  | xdrclose - close a xdr file
@@ -392,6 +375,9 @@ int xdropen(XDR *xdrs, const char *filename, const char *type) {
  | It also closes the associated file descriptor (this is *not*
  | done by xdr_destroy).
  |
+ | NOTE: THIS FUNCTION IS NOW OBSOLETE AND ONLY PROVIDED FOR BACKWARD
+ |       COMPATIBILITY OF 3D PARTY TOOLS. IT SHOULD NOT BE USED ANYWHERE 
+ |       IN GROMACS ITSELF. 
 */
  
 int xdrclose(XDR *xdrs) {
@@ -418,11 +404,39 @@ int xdrclose(XDR *xdrs) {
     return 0;    
 }
 
-FILE *
-xdr_get_fp(int xdrid)
-{
-       return xdrfiles[xdrid];
-}
+#endif
+
+
+/*___________________________________________________________________________
+ |
+ | what follows are the C routine to read/write compressed coordinates together
+ | with some routines to assist in this task (those are marked
+ | static and cannot be called from user programs)
+*/
+#define MAXABS INT_MAX-2
+
+#ifndef MIN
+#define MIN(x,y) ((x) < (y) ? (x):(y))
+#endif
+#ifndef MAX
+#define MAX(x,y) ((x) > (y) ? (x):(y))
+#endif
+#ifndef SQR
+#define SQR(x) ((x)*(x))
+#endif
+static const int magicints[] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0,
+    8, 10, 12, 16, 20, 25, 32, 40, 50, 64,
+    80, 101, 128, 161, 203, 256, 322, 406, 512, 645,
+    812, 1024, 1290, 1625, 2048, 2580, 3250, 4096, 5060, 6501,
+    8192, 10321, 13003, 16384, 20642, 26007, 32768, 41285, 52015, 65536,
+    82570, 104031, 131072, 165140, 208063, 262144, 330280, 416127, 524287, 660561,
+    832255, 1048576, 1321122, 1664510, 2097152, 2642245, 3329021, 4194304, 5284491, 6658042,
+    8388607, 10568983, 13316085, 16777216 };
+
+#define FIRSTIDX 9
+/* note that magicints[FIRSTIDX-1] == 0 */
+#define LASTIDX (sizeof(magicints) / sizeof(*magicints))
 
 
 /*____________________________________________________________________________
@@ -696,9 +710,8 @@ static void receiveints(int buf[], const int num_of_ints, int num_of_bits,
  |
  */
  
-int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision) {
-    
-
+int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision, bool bRead) 
+{
     static int *ip = NULL;
     static int oldsize;
     static int *buf;
@@ -721,18 +734,9 @@ int xdr3dfcoord(XDR *xdrs, float *fp, int *size, float *precision) {
        
     bitsizeint[0] = bitsizeint[1] = bitsizeint[2] = 0;
     prevcoord[0]  = prevcoord[1]  = prevcoord[2]  = 0;
-    
-    /* find out if xdrs is opened for reading or for writing */
-    xdrid = 0;
-    while (xdridptr[xdrid] != xdrs) {
-       xdrid++;
-       if (xdrid >= MAXID) {
-           fprintf(stderr, "xdr error. no open xdr stream\n");
-           exit (1);
-       }
-    }
-    if ((xdrmodes[xdrid] == 'w') || (xdrmodes[xdrid] == 'a')) {
-
+   
+    if (!bRead)
+    {
        /* xdrs is open for writing */
 
        if (xdr_int(xdrs, size) == 0)
index 2a5b318346daa60827162f68d75837524510a694..0c426f7c39d303336d65393a48e352d4df64f435 100644 (file)
@@ -458,16 +458,18 @@ t_commrec *init_par(int *argc,char ***argv_ptr)
     return cr;
 }
 
-t_commrec *init_par_threads(t_commrec *cro)
+t_commrec *init_par_threads(const t_commrec *cro)
 {
 #ifdef GMX_THREADS
     int initialized;
     t_commrec *cr;
 
+    /* make a thread-specific commrec */
     snew(cr,1);
     /* now copy the whole thing, so settings like the number of PME nodes
        get propagated. */
     *cr=*cro;
+
     /* and we start setting our own thread-specific values for things */
     MPI_Initialized(&initialized);
     if (!initialized)
@@ -491,27 +493,6 @@ t_commrec *init_par_threads(t_commrec *cro)
 #endif
 }
 
-void cancel_par_threads(t_commrec *cr)
-{
-#ifdef GMX_THREADS
-    if (MASTERTHREAD(cr))
-    {
-        fprintf(stderr, "\nCANCELING %d THREADS\n", cr->nthreads-1);
-        cr->nnodes     = 1; 
-        cr->nthreads   = 1;
-        cr->sim_nodeid = 0;
-        cr->nodeid     = 0;
-        cr->threadid   = 0;
-        cr->duty       = (DUTY_PP | DUTY_PME);
-    }
-    else
-    {
-        tMPI_Finalize();
-    }
-#else
-    gmx_incons("cancel_par_threads called without thread support");
-#endif
-}
 
 t_commrec *init_cr_nopar(void)
 {
index 1567cffe2a59f537bc050467a1fcc87920cc0466..7ad68c12250bb18d591f64b8911a4710bddef05c 100644 (file)
@@ -187,20 +187,23 @@ void do_wmap(FILE *out,int i0,int imax,
   }
 }
 
-char *fgetline(char **line,int llmax,FILE *in)
+static char *fgetline(char **line,int llmax,int *llalloc,FILE *in)
 {
-  static char *line0=NULL;
-  static int  linelengthmax=0;
   char *fg;
-  
-  if (llmax > linelengthmax) {
-    linelengthmax = llmax;
-    srenew(line0,linelengthmax);
+
+  if (!(*line))
+  {
+      snew(*line, llmax);
+      *llalloc=llmax;
   }
-  fg=fgets(line0,linelengthmax,in);
-  *line=line0;
+  else if (llmax > *llalloc)
+  {
+      srenew(*line,llmax);
+      *llalloc=llmax;
+  }
+  fg=fgets(*line,llmax,in);
   trim(*line);
-  
+
   return fg;
 }
 
@@ -251,6 +254,7 @@ void read_xpm_entry(FILE *in,t_matrix *mm)
   t_mapping *map;
   char *line=NULL,*str,buf[256];
   int i,m,col_len,nch,n_axis_x,n_axis_y,llmax;
+  int llalloc=0;
   unsigned int r,g,b;
   double u;
   bool bGetOnWithIt;
@@ -268,7 +272,7 @@ void read_xpm_entry(FILE *in,t_matrix *mm)
 
   llmax = STRLEN;
 
-  while (fgetline(&line,llmax,in) && (strncmp(line,"static",6) != 0)) {
+  while (fgetline(&line,llmax,&llalloc,in) && (strncmp(line,"static",6) != 0)) {
     parsestring(line,"title",(mm->title));
     parsestring(line,"legend",(mm->legend));
     parsestring(line,"x-label",(mm->label_x));
@@ -286,7 +290,7 @@ void read_xpm_entry(FILE *in,t_matrix *mm)
     gmx_input("Invalid XPixMap");
   /* Read sizes */
   bGetOnWithIt=FALSE;
-  while (!bGetOnWithIt && fgetline(&line,llmax,in)) {
+  while (!bGetOnWithIt && fgetline(&line,llmax,&llalloc,in)) {
     while (( line[0] != '\"' ) && ( line[0] != '\0' ))
       line++;
 
@@ -306,7 +310,7 @@ void read_xpm_entry(FILE *in,t_matrix *mm)
   /* Read color map */
   snew(map,mm->nmap);
   m=0;
-  while ((m < mm->nmap) && fgetline(&line,llmax,in)) {
+  while ((m < mm->nmap) && fgetline(&line,llmax,&llalloc,in)) {
     line=strchr(line,'\"');
     if  (line) {
       line++;
@@ -394,7 +398,7 @@ void read_xpm_entry(FILE *in,t_matrix *mm)
        skipstr(&line);
       }
     }
-  } while ((line[0] != '\"') && fgetline(&line,llmax,in));
+  } while ((line[0] != '\"') && fgetline(&line,llmax,&llalloc,in));
 
   /* Read matrix */
   snew(mm->matrix,mm->nx);
@@ -420,21 +424,24 @@ void read_xpm_entry(FILE *in,t_matrix *mm)
        }
       m--;
     }
-  } while ((m>=0) && fgetline(&line,llmax,in));
+  } while ((m>=0) && fgetline(&line,llmax,&llalloc,in));
   if (m>=0)
     gmx_incons("Not enough rows in the matrix");
+
+  sfree(line);
 }
 
 int read_xpm_matrix(const char *fnm,t_matrix **matrix)
 {
   FILE *in;
-  char *line;
+  char *line=NULL;
   int nmat;
+  int llalloc=0;
 
   in=gmx_fio_fopen(fnm,"r");
   
   nmat=0;
-  while (fgetline(&line,STRLEN,in)) {
+  while (fgetline(&line,STRLEN,&llalloc,in)) {
     if (strstr(line,"/* XPM */")) {
       srenew(*matrix,nmat+1);
       read_xpm_entry(in,&(*matrix)[nmat]);
@@ -446,6 +453,8 @@ int read_xpm_matrix(const char *fnm,t_matrix **matrix)
   if (nmat==0)
     gmx_file("Invalid XPixMap");
 
+  sfree(line);
+
   return nmat;
 }
 
index c73ed8f6deb65fec43fc9a087db2d5f3282e3a03..b650767b75d63c5358b2ede7ee599a204689338e 100644 (file)
@@ -254,10 +254,13 @@ static void compact_graph(FILE *fplog,t_graph *g)
     for(j=0; j<g->nedge[i]; j++) {
       g->edge[0][n++] = g->edge[i][j];
     }
-    g->edge[i] = g->edge[0] + n - g->nedge[i];
     max_nedge = max(max_nedge,g->nedge[i]);
   }
   srenew(g->edge[0],n);
+  /* set pointers after srenew because edge[0] might move */
+  for(i=1; i<g->nnodes; i++) {
+    g->edge[i] = g->edge[i-1] + g->nedge[i-1];
+  }
 
   if (fplog) {
     fprintf(fplog,"Max number of graph edges per atom is %d\n",
@@ -847,47 +850,3 @@ void unshift_self(t_graph *g,matrix box,rvec x[])
   }
 }
 #undef GCHECK
-
-#ifdef DEBUGMSHIFT
-void main(int argc,char *argv[])
-{
-  FILE         *out;
-  t_args       targ;
-  t_topology   top;
-  t_statheader sh;
-  rvec         *x;
-  ivec         *mshift;
-  matrix       box;
-
-  t_graph      *g;
-  int          i,idum,pid;
-  real         rdum;
-
-  CopyRight(stderr,argv[0]);
-  parse_common_args(&argc,argv,&targ,PCA_NEED_INOUT,NULL);
-  if (argc > 1)
-    pid=strtol(argv[1], NULL, 10);
-  else
-    pid=0;
-  
-  read_status_header(targ.infile,&sh);
-  snew(x,sh.natoms);
-  snew(mshift,sh.natoms);
-
-  fprintf(stderr,"Reading Status %s\n",targ.infile);
-  read_status(targ.infile,&idum,&rdum,&rdum,NULL,
-             box,NULL,NULL,&idum,x,NULL,NULL,&idum,NULL,&top);
-
-  fprintf(stderr,"Making Graph Structure...\n");
-  g=mk_graph(&(top.idef),top.atoms.nr,FALSE,FALSE);
-
-  out=gmx_fio_fopen(targ.outfile,"w");
-
-  fprintf(stderr,"Making Shift...\n");
-  mk_mshift(out,g,box,x,mshift);
-
-  p_graph(out,"In Den Haag daar woont een graaf...",g);
-  gmx_fio_fclose(out);
-}
-#endif
-
index ee4e5705eb413eee8874a9060e0c4e5536385cb3..8ce63561fd89d1476ca3021e790e50b30496488c 100644 (file)
@@ -894,10 +894,6 @@ t_topology gmx_mtop_t_to_t_topology(gmx_mtop_t *mtop)
 
     gen_local_top(mtop,NULL,FALSE,&ltop);
 
-    open_symtab(&top.symtab);
-
-    open_symtab(&top.symtab);
-
     top.name      = mtop->name;
     top.idef      = ltop.idef;
     top.atomtypes = ltop.atomtypes;
@@ -905,9 +901,13 @@ t_topology gmx_mtop_t_to_t_topology(gmx_mtop_t *mtop)
     top.excls     = ltop.excls;
     top.atoms     = gmx_mtop_global_atoms(mtop);
     top.mols      = mtop->mols;
+    top.symtab    = mtop->symtab;
 
     /* We only need to free the moltype and molblock data,
      * all other pointers have been copied to top.
+     *
+     * Well, except for the group data, but we can't free those, because they
+     * are used somewhere even after a call to this function.
      */
     for(mt=0; mt<mtop->nmoltype; mt++)
     {
index d019e4fb5951ef190f195c68c949a9d1640bd612..9faacbc34bfe612c7d3cd8815ad628a27c97fbc1 100644 (file)
@@ -47,6 +47,7 @@
 #include "copyrite.h"
 #include "gmx_fatal.h"
 #include "mtxio.h"
+#include "gmxfio.h"
 
 
 /* Just a number to identify our file type */
  *         Each entry consists of an integer column index and floating-point data value.
  */
 
-void
-gmx_mtxio_write(const char *             filename,
-                int                      nrow,
-                int                      ncol,
-                real *                   full_matrix,
-                gmx_sparsematrix_t *     sparse_matrix)
+void gmx_mtxio_write(const char *             filename,
+                     int                      nrow,
+                     int                      ncol,
+                     real *                   full_matrix,
+                     gmx_sparsematrix_t *     sparse_matrix)
 {
-    int     fd;
+    t_fileio *fio;
     XDR *   xd;
     int     i,j,prec;
     bool    bDum = TRUE;
@@ -97,58 +97,58 @@ gmx_mtxio_write(const char *             filename,
         gmx_fatal(FARGS,"Both full AND sparse matrix specified to gmx_mtxio_write().\n");
     }
     
-    fd = gmx_fio_open(filename,"w");
-    gmx_fio_select(fd);
-    xd = gmx_fio_getxdr(fd);
+    fio = gmx_fio_open(filename,"w");
+    gmx_fio_checktype(fio);
+    xd = gmx_fio_getxdr(fio);
     
     /* Write magic number */
     i = GMX_MTXIO_MAGIC_NUMBER;
-    do_int(i);
+    gmx_fio_do_int(fio, i);
     
     /* Write generating Gromacs version */
-    do_string(GromacsVersion());
+    gmx_fio_write_string(fio, GromacsVersion());
     
     /* Write 1 for double, 0 for single precision */
     if(sizeof(real)==sizeof(double))
         prec = 1;
     else
         prec = 0;
-    do_int(prec);
+    gmx_fio_do_int(fio, prec);
     
-    do_int(nrow);
-    do_int(ncol);
+    gmx_fio_do_int(fio, nrow);
+    gmx_fio_do_int(fio, ncol);
     
     if(full_matrix!=NULL)
     {
         /* Full matrix storage format */
         i = GMX_MTXIO_FULL_MATRIX;
-        do_int(i);
+        gmx_fio_do_int(fio, i);
         sz = nrow*ncol;        
-        ndo_real(full_matrix,sz,bDum);
+        bDum=gmx_fio_ndo_real(fio, full_matrix,sz);
     }
     else
     {
         /* Sparse storage */
         i = GMX_MTXIO_SPARSE_MATRIX;
-        do_int(i);
-        
-        do_int(sparse_matrix->compressed_symmetric);
-        do_int(sparse_matrix->nrow);
+        gmx_fio_do_int(fio, i);
+
+        gmx_fio_do_bool(fio, sparse_matrix->compressed_symmetric);
+        gmx_fio_do_int(fio, sparse_matrix->nrow);
         if(sparse_matrix->nrow != nrow)
         {
             gmx_fatal(FARGS,"Internal inconsistency in sparse matrix.\n");
         }
-        ndo_int(sparse_matrix->ndata,sparse_matrix->nrow,bDum);
+        bDum=gmx_fio_ndo_int(fio, sparse_matrix->ndata,sparse_matrix->nrow);
         for(i=0;i<sparse_matrix->nrow;i++)
         {
             for(j=0;j<sparse_matrix->ndata[i];j++)
             {
-                do_int(sparse_matrix->data[i][j].col);
-                do_real(sparse_matrix->data[i][j].value);
+                gmx_fio_do_int(fio, sparse_matrix->data[i][j].col);
+                gmx_fio_do_real(fio, sparse_matrix->data[i][j].value);
             }
         }
     }
-    gmx_fio_close(fd);
+    gmx_fio_close(fio);
 }
 
 
@@ -159,7 +159,7 @@ gmx_mtxio_read (const char *            filename,
                 real **                 full_matrix,
                 gmx_sparsematrix_t **   sparse_matrix)
 {
-    int     fd;
+    t_fileio  *fio;
     XDR *   xd;
     int     i,j,prec;
     bool    bDum = TRUE;
@@ -167,13 +167,13 @@ gmx_mtxio_read (const char *            filename,
     char    gmxver[256];
     size_t  sz;
     
-    fd = gmx_fio_open(filename,"r");
-    gmx_fio_select(fd);
-    xd = gmx_fio_getxdr(fd);
+    fio = gmx_fio_open(filename,"r");
+    gmx_fio_checktype(fio);
+    xd = gmx_fio_getxdr(fio);
     
     /* Read and check magic number */
     i = GMX_MTXIO_MAGIC_NUMBER;
-    do_int(i);
+    gmx_fio_do_int(fio, i);
 
     if(i!=GMX_MTXIO_MAGIC_NUMBER)
     {
@@ -183,24 +183,24 @@ gmx_mtxio_read (const char *            filename,
     }
     
     /* Read generating Gromacs version */
-    do_string(gmxver);
+    gmx_fio_do_string(fio, gmxver);
     
     /* Write 1 for double, 0 for single precision */
     if(sizeof(real)==sizeof(double))
         prec = 1;
     else
         prec = 0;
-    do_int(prec);
+    gmx_fio_do_int(fio, prec);
 
     fprintf(stderr,"Reading %s precision matrix generated by Gromacs %s\n",
             (prec == 1) ? "double" : "single",gmxver);
     
-    do_int(i);
+    gmx_fio_do_int(fio, i);
     *nrow=i;
-    do_int(i);
+    gmx_fio_do_int(fio, i);
     *ncol=i;
 
-    do_int(i);
+    gmx_fio_do_int(fio, i);
     
     if(i==GMX_MTXIO_FULL_MATRIX)
     {
@@ -208,7 +208,7 @@ gmx_mtxio_read (const char *            filename,
 
         sz = (*nrow) * (*ncol);
         snew((*full_matrix),sz);
-        ndo_real((*full_matrix),sz,bDum);
+        bDum=gmx_fio_ndo_real(fio, (*full_matrix),sz);
     }
     else
     {
@@ -216,8 +216,8 @@ gmx_mtxio_read (const char *            filename,
         printf("Sparse matrix storage format, nrow=%d, ncols=%d\n",*nrow,*ncol);
 
         snew((*sparse_matrix),1);
-        do_int((*sparse_matrix)->compressed_symmetric);
-        do_int((*sparse_matrix)->nrow);        
+        gmx_fio_do_bool(fio, (*sparse_matrix)->compressed_symmetric);
+        gmx_fio_do_int(fio, (*sparse_matrix)->nrow);        
         if((*sparse_matrix)->nrow != *nrow)
         {
             gmx_fatal(FARGS,"Internal inconsistency in sparse matrix.\n");
@@ -225,7 +225,8 @@ gmx_mtxio_read (const char *            filename,
         snew((*sparse_matrix)->ndata,(*sparse_matrix)->nrow);
         snew((*sparse_matrix)->nalloc,(*sparse_matrix)->nrow);
         snew((*sparse_matrix)->data,(*sparse_matrix)->nrow);
-        ndo_int((*sparse_matrix)->ndata,(*sparse_matrix)->nrow,bDum);
+        bDum=gmx_fio_ndo_int(fio, (*sparse_matrix)->ndata,
+                             (*sparse_matrix)->nrow);
 
         for(i=0;i<(*sparse_matrix)->nrow;i++)
         {
@@ -234,12 +235,12 @@ gmx_mtxio_read (const char *            filename,
             
             for(j=0;j<(*sparse_matrix)->ndata[i];j++)
             {
-                do_int((*sparse_matrix)->data[i][j].col);
-                do_real((*sparse_matrix)->data[i][j].value);
+                gmx_fio_do_int(fio, (*sparse_matrix)->data[i][j].col);
+                gmx_fio_do_real(fio, (*sparse_matrix)->data[i][j].value);
             }
         }
     }
-    gmx_fio_close(fd);
+    gmx_fio_close(fio);
 }
 
 
index ef113a31ba1896d4f3a3d9077805eb26c646b332..f2fd4131927db6821eda3e709c06535dae46479a 100644 (file)
@@ -236,9 +236,11 @@ int gmx_setup(int *argc,char **argv,int *nnodes)
   }
   MPE_Init_log();
 #endif
-  
+#ifdef GMX_LIB_MPI 
   fprintf(stderr,"NNODES=%d, MYRANK=%d, HOSTNAME=%s\n",
          mpi_num_nodes,mpi_my_rank,mpi_hostname);
+#endif
   
   *nnodes=mpi_num_nodes;
   
@@ -375,6 +377,7 @@ void gmx_abort(int noderank,int nnodes,int errorno)
 #else
 #ifdef GMX_THREADS
   fprintf(stderr,"Halting program %s\n",ShortProgram());
+  thanx(stderr);
   exit(1);
 #else
   if (nnodes > 1)
index ad42b6675e0bf6a63477326faa74f1e5df5c66c8..6d62a93eb57324a9eb2f81140cd1904afe879fc3 100644 (file)
@@ -90,9 +90,9 @@ void nb_kernel400_ia32_sse(int *           p_nri,
        __m128   vgb,vgbB,fijGB,fijGBB,dvdatmp,dvdatmpB;
        __m128   facel,gbtabscale,mask,dvdaj;
     
-    __m128   mask1 = _mm_castsi128_ps( _mm_set_epi32(0, 0, 0, 0xffffffff) );
-       __m128   mask2 = _mm_castsi128_ps( _mm_set_epi32(0, 0, 0xffffffff, 0xffffffff) );
-       __m128   mask3 = _mm_castsi128_ps( _mm_set_epi32(0, 0xffffffff, 0xffffffff, 0xffffffff) );
+    __m128   mask1 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0, 0, 0xffffffff) );
+       __m128   mask2 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0, 0xffffffff, 0xffffffff) );
+       __m128   mask3 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0xffffffff, 0xffffffff, 0xffffffff) );
     
        __m128i  n0, nnn;
        __m128i  n0B, nnnB;
@@ -512,7 +512,9 @@ void nb_kernel400_ia32_sse(int *           p_nri,
                gmx_mm_update_iforce_1atom_ps(fix,fiy,fiz,faction+ii3,fshift+is3);
                
         ggid             = gid[n];         
-               gmx_mm_update_2pot_ps(vctot,vc+ggid,vgbtot,gpol+ggid);
+
+               gmx_mm_update_1pot_ps(vctot,vc+ggid);
+               gmx_mm_update_1pot_ps(vgbtot,gpol+ggid);
                gmx_mm_update_1pot_ps(dvdasum,dvda+ii);
     }
        
index 384b115d87e8de7c121f92c2d349f710296ba33e..ab25d66be4e1468310952aac68f6083feadb1951 100644 (file)
@@ -94,9 +94,9 @@ void nb_kernel410_ia32_sse(int *           p_nri,
        __m128   rinvsixB,vvdw6B,vvdw12B;
        __m128   facel,gbtabscale,mask,dvdaj;
     
-    __m128   mask1 = _mm_castsi128_ps( _mm_set_epi32(0, 0, 0, 0xffffffff) );
-       __m128   mask2 = _mm_castsi128_ps( _mm_set_epi32(0, 0, 0xffffffff, 0xffffffff) );
-       __m128   mask3 = _mm_castsi128_ps( _mm_set_epi32(0, 0xffffffff, 0xffffffff, 0xffffffff) );
+    __m128   mask1 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0, 0, 0xffffffff) );
+       __m128   mask2 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0, 0xffffffff, 0xffffffff) );
+       __m128   mask3 = gmx_mm_castsi128_ps( _mm_set_epi32(0, 0xffffffff, 0xffffffff, 0xffffffff) );
     
        __m128i  n0, nnn;
        __m128i  n0B, nnnB;
@@ -126,7 +126,7 @@ void nb_kernel410_ia32_sse(int *           p_nri,
     jz               = _mm_setzero_ps();
     c6               = _mm_setzero_ps();
     c12              = _mm_setzero_ps();
-
+       
     
     for(n=0; (n<nri); n++)
     {
index 23ee89e755ec62c012379201a9439d6b88e1acfc..c0978fb8295ffe33edbf185205be16eab1e9e494 100644 (file)
@@ -21,7 +21,7 @@
 
 #include <xmmintrin.h>
 #include <emmintrin.h>
-
+#include <gmx_sse2_single.h>
 
 /* get gmx_gbdata_t */
 #include "../nb_kerneltype.h"
@@ -35,12 +35,12 @@ _mm_cvtsi128_si32(_mm_srli_si128((x), 4 * (imm)))
 static inline __m128
 my_invrsq_ps(__m128 x)
 {
-       const __m128 three = (const __m128) {3.0f, 3.0f, 3.0f, 3.0f};
-       const __m128 half  = (const __m128) {0.5f, 0.5f, 0.5f, 0.5f};
+       const __m128 three = {3.0f, 3.0f, 3.0f, 3.0f};
+       const __m128 half  = {0.5f, 0.5f, 0.5f, 0.5f};
        
        __m128 t1 = _mm_rsqrt_ps(x);
        
-       return (__m128) _mm_mul_ps(half,_mm_mul_ps(t1,_mm_sub_ps(three,_mm_mul_ps(x,_mm_mul_ps(t1,t1)))));
+       return gmx_mm_castps_ps128(_mm_mul_ps(half,_mm_mul_ps(t1,_mm_sub_ps(three,_mm_mul_ps(x,_mm_mul_ps(t1,t1))))));
 }
 
 void nb_kernel430_ia32_sse(int *           p_nri,
@@ -120,15 +120,15 @@ void nb_kernel430_ia32_sse(int *           p_nri,
        gpol            = gbdata->gpol;
        
        nri              = *p_nri;         
-    ntype            = *p_ntype;       
-    nthreads         = *p_nthreads;    
-    facel            = *p_facel; 
+  ntype            = *p_ntype;       
+  nthreads         = *p_nthreads;    
+  facel            = *p_facel; 
        scl_gb           = (1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent);
-    krf              = *p_krf;         
-    crf              = *p_crf;         
-    tabscale         = *p_tabscale;    
-    gbtabscale       = *p_gbtabscale;  
-    nj1              = 0;
+  krf              = *p_krf;         
+  crf              = *p_crf;         
+  tabscale         = *p_tabscale;    
+  gbtabscale       = *p_gbtabscale;  
+  nj1              = 0;
 
        /* Splat variables */
        fac_sse        = _mm_load1_ps(&facel);
@@ -624,15 +624,15 @@ void nb_kernel430_ia32_sse(int *           p_nri,
                                mask  = _mm_set_epi32(0,0xffffffff,0xffffffff,0xffffffff);
                        }
                        
-                       jx      = _mm_and_ps( (__m128) mask, xmm6);
-                       jy      = _mm_and_ps( (__m128) mask, xmm4);
-                       jz      = _mm_and_ps( (__m128) mask, xmm5);
+                       jx      = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm6);
+                       jy      = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm4);
+                       jz      = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm5);
                        
-                       c6      = _mm_and_ps( (__m128) mask, c6);
-                       c12     = _mm_and_ps( (__m128) mask, c12);
-                       dvdaj   = _mm_and_ps( (__m128) mask, dvdaj);
-                       isaj    = _mm_and_ps( (__m128) mask, isaj);                     
-                       q       = _mm_and_ps( (__m128) mask, q);
+                       c6      = _mm_and_ps( gmx_mm_castsi128_ps(mask), c6);
+                       c12     = _mm_and_ps( gmx_mm_castsi128_ps(mask), c12);
+                       dvdaj   = _mm_and_ps( gmx_mm_castsi128_ps(mask), dvdaj);
+                       isaj    = _mm_and_ps( gmx_mm_castsi128_ps(mask), isaj);                 
+                       q       = _mm_and_ps( gmx_mm_castsi128_ps(mask), q);
                        
                        dx1     = _mm_sub_ps(ix,jx);
                        dy1     = _mm_sub_ps(iy,jy);
@@ -710,8 +710,8 @@ void nb_kernel430_ia32_sse(int *           p_nri,
                        xmm1    = _mm_mul_ps(xmm1,isaj);
                        dvdaj   = _mm_add_ps(dvdaj,xmm1);
                        
-                       vcoul   = _mm_and_ps( (__m128) mask, vcoul);
-                       vgb     = _mm_and_ps( (__m128) mask, vgb);
+                       vcoul   = _mm_and_ps( gmx_mm_castsi128_ps(mask), vcoul);
+                       vgb     = _mm_and_ps( gmx_mm_castsi128_ps(mask), vgb);
                        
                        vctot   = _mm_add_ps(vctot,vcoul);
                        vgbtot  = _mm_add_ps(vgbtot,vgb);
@@ -897,9 +897,9 @@ void nb_kernel430_ia32_sse(int *           p_nri,
                                _mm_store_ss(faction+j33+2,xmm7); 
                        }
                        
-                       t1 = _mm_and_ps( (__m128) mask, t1);
-                       t2 = _mm_and_ps( (__m128) mask, t2);
-                       t3 = _mm_and_ps( (__m128) mask, t3);
+                       t1 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t1);
+                       t2 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t2);
+                       t3 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t3);
                        
                        fix = _mm_add_ps(fix,t1);
                        fiy = _mm_add_ps(fiy,t2);
@@ -924,7 +924,7 @@ void nb_kernel430_ia32_sse(int *           p_nri,
                
                xmm2    = _mm_unpacklo_ps(fix,fiy); /* fx, fy, - - */
                xmm2    = _mm_movelh_ps(xmm2,fiz); 
-               xmm2    = _mm_and_ps( (__m128) maski, xmm2);
+               xmm2    = _mm_and_ps( gmx_mm_castsi128_ps(maski), xmm2);
                
                /* load, add and store i forces */
                xmm4    = _mm_loadl_pi(xmm4, (__m64 *) (faction+ii3));
@@ -949,7 +949,7 @@ void nb_kernel430_ia32_sse(int *           p_nri,
                _mm_store_ss(fshift+is3+2,xmm4);
                
                /* Coulomb potential */
-        ggid             = gid[n];         
+    ggid             = gid[n];         
                
                vcoul   = _mm_movehl_ps(vcoul,vctot);
                vctot   = _mm_add_ps(vctot,vcoul);
index a3a4fc9afea59259412613d69b029ec62ce9f23d..9f7b48236845c590a54c1a14c1c31b6b1366cbdf 100644 (file)
@@ -90,7 +90,7 @@ void nb_kernel400_ia32_sse2(int *           p_nri,
        __m128d           q,iq,qq,isai,isaj,isaprod,vcoul,gbscale,dvdai,dvdaj;
        __m128d       Y,F,G,H,Fp,VV,FF,vgb,fijC,dvdatmp,dvdasum,vctot,vgbtot,n0d;
        __m128d           xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
-       __m128d       fac,tabscale,gbtabscale;
+       __m128d       fac,tabscale,gbtabscale,gbfactor;
        __m128i       n0,nnn;
        
        const __m128d neg    = {-1.0f,-1.0f};
@@ -105,7 +105,7 @@ void nb_kernel400_ia32_sse2(int *           p_nri,
        nri        = *p_nri;
        ntype      = *p_ntype;
        nthreads   = *p_nthreads; 
-    facel      = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));       
+  facel      = *p_facel;    
        krf        = *p_krf;
        crf        = *p_crf;
        tabscl     = *p_tabscale;
@@ -116,6 +116,7 @@ void nb_kernel400_ia32_sse2(int *           p_nri,
        fac        = _mm_load1_pd(&facel);
        tabscale   = _mm_load1_pd(&tabscl);
        gbtabscale = _mm_load1_pd(&gbtabscl);
+  gbfactor   = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
                
        /* Keep compiler happy */
        dvdatmp = _mm_setzero_pd();
@@ -202,6 +203,7 @@ void nb_kernel400_ia32_sse2(int *           p_nri,
                        fscal   = _mm_mul_pd(vcoul,rinv);
                        qq              = _mm_mul_pd(isaprod,qq);
                        qq              = _mm_mul_pd(qq,neg);
+      qq      = _mm_mul_pd(qq,gbfactor);
                        gbscale = _mm_mul_pd(isaprod,gbtabscale);
                        
                        /* Load dvdaj */
@@ -327,6 +329,7 @@ void nb_kernel400_ia32_sse2(int *           p_nri,
                        fscal   = _mm_mul_sd(vcoul,rinv);
                        qq              = _mm_mul_sd(isaprod,qq);
                        qq              = _mm_mul_sd(qq,neg);
+      qq      = _mm_mul_sd(qq,gbfactor);
                        gbscale = _mm_mul_sd(isaprod,gbtabscale);
                        
                        r               = _mm_mul_sd(rsq11,rinv);
index 39f6a29833f868dcde3ab164f44f8b50d481457d..99f6ef37ef2befaa704e88a03ef497f61874e01f 100644 (file)
@@ -91,7 +91,7 @@ void nb_kernel410_ia32_sse2(int *           p_nri,
        __m128d       Y,F,G,H,Fp,VV,FF,vgb,fijC,dvdatmp,dvdasum,vctot,vgbtot,n0d;
        __m128d           xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
        __m128d       c6,c12,Vvdw6,Vvdw12,Vvdwtmp,Vvdwtot,rinvsq,rinvsix;
-       __m128d       fac,tabscale,gbtabscale;
+       __m128d       fac,tabscale,gbtabscale,gbfactor;
        __m128i       n0,nnn;
        
        const __m128d neg    = {-1.0f,-1.0f};
@@ -108,7 +108,7 @@ void nb_kernel410_ia32_sse2(int *           p_nri,
        nri        = *p_nri;
        ntype      = *p_ntype;
        nthreads   = *p_nthreads; 
-    facel      = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));       
+  facel      = *p_facel;     
        krf        = *p_krf;
        crf        = *p_crf;
        tabscl     = *p_tabscale;
@@ -119,6 +119,7 @@ void nb_kernel410_ia32_sse2(int *           p_nri,
        fac        = _mm_load1_pd(&facel);
        tabscale   = _mm_load1_pd(&tabscl);
        gbtabscale = _mm_load1_pd(&gbtabscl);
+  gbfactor   = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
                
        /* Keep compiler happy */
        Vvdwtmp = _mm_setzero_pd();
@@ -212,6 +213,7 @@ void nb_kernel410_ia32_sse2(int *           p_nri,
                        vcoul   = _mm_mul_pd(qq,rinv);
                        fscal   = _mm_mul_pd(vcoul,rinv);
                        qq              = _mm_mul_pd(isaprod,qq);
+      qq      = _mm_mul_pd(qq,gbfactor);
                        qq              = _mm_mul_pd(qq,neg);
                        gbscale = _mm_mul_pd(isaprod,gbtabscale);
                        
@@ -364,6 +366,7 @@ void nb_kernel410_ia32_sse2(int *           p_nri,
                        vcoul   = _mm_mul_sd(qq,rinv);
                        fscal   = _mm_mul_sd(vcoul,rinv);
                        qq              = _mm_mul_sd(isaprod,qq);
+      qq      = _mm_mul_sd(qq,gbfactor);
                        qq              = _mm_mul_sd(qq,neg);
                        gbscale = _mm_mul_sd(isaprod,gbtabscale);
                        
index 0ff30e246226f40da22b72d5b9fb7dadbe8ff054..e0d5545e85d74605810b9f75845963460bb968be 100644 (file)
@@ -91,7 +91,7 @@ void nb_kernel430_ia32_sse2(int *           p_nri,
        __m128d       Y,F,G,H,Fp,VV,FF,vgb,fijC,fijD,fijR,dvdatmp,dvdasum,vctot,n0d;
        __m128d           xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
        __m128d       c6,c12,Vvdw6,Vvdw12,Vvdwtmp,Vvdwtot,vgbtot,rinvsq,rinvsix;
-       __m128d       fac,tabscale,gbtabscale;
+       __m128d       fac,tabscale,gbtabscale,gbfactor;
        __m128i       n0,nnn;
        
        const __m128d neg    = {-1.0f,-1.0f};
@@ -110,7 +110,7 @@ void nb_kernel430_ia32_sse2(int *           p_nri,
        nri        = *p_nri;
        ntype      = *p_ntype;
        nthreads   = *p_nthreads; 
-    facel      = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));       
+  facel      = *p_facel;      
        krf        = *p_krf;
        crf        = *p_crf;
        tabscl     = *p_tabscale;
@@ -121,6 +121,7 @@ void nb_kernel430_ia32_sse2(int *           p_nri,
        fac        = _mm_load1_pd(&facel);
        tabscale   = _mm_load1_pd(&tabscl);
        gbtabscale = _mm_load1_pd(&gbtabscl);
+  gbfactor   = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
                
        /* Keep compiler happy */
        Vvdwtmp = _mm_setzero_pd();
@@ -215,6 +216,7 @@ void nb_kernel430_ia32_sse2(int *           p_nri,
                        fscal   = _mm_mul_pd(vcoul,rinv);
                        qq              = _mm_mul_pd(isaprod,qq);
                        qq              = _mm_mul_pd(qq,neg);
+      qq      = _mm_mul_pd(qq,gbfactor);
                        gbscale = _mm_mul_pd(isaprod,gbtabscale);
                        
                        /* Load VdW parameters */
@@ -414,6 +416,7 @@ void nb_kernel430_ia32_sse2(int *           p_nri,
                        fscal   = _mm_mul_sd(vcoul,rinv);
                        qq              = _mm_mul_sd(isaprod,qq);
                        qq              = _mm_mul_sd(qq,neg);
+      qq      = _mm_mul_sd(qq,gbfactor);
                        gbscale = _mm_mul_sd(isaprod,gbtabscale);
                        
                        /* Load VdW parameters */
index ddc6e273342da0164c05aae7afa55b4586d09a6a..79ad695b8438213a4a628bd1d9fb86dc624daaac 100644 (file)
@@ -512,7 +512,9 @@ void nb_kernel400_sse2_single(int *           p_nri,
                gmx_mm_update_iforce_1atom_ps(fix,fiy,fiz,faction+ii3,fshift+is3);
                
         ggid             = gid[n];         
-               gmx_mm_update_2pot_ps(vctot,vc+ggid,vgbtot,gpol+ggid);
+
+               gmx_mm_update_1pot_ps(vctot,vc+ggid);
+               gmx_mm_update_1pot_ps(vgbtot,gpol+ggid);
                gmx_mm_update_1pot_ps(dvdasum,dvda+ii);
     }
        
index 893cfc848b0440c703a73dc94177c25027e1247f..c4f181af91203ee6d61cdba8669ad567432002d2 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <xmmintrin.h>
 #include <emmintrin.h>
+#include <gmx_sse2_single.h>
 
 /* get gmx_gbdata_t */
 #include "../nb_kerneltype.h"
@@ -34,12 +35,12 @@ _mm_cvtsi128_si32(_mm_srli_si128((x), 4 * (imm)))
 static inline __m128
 my_invrsq_ps(__m128 x)
 {
-       const __m128 three = (const __m128) {3.0f, 3.0f, 3.0f, 3.0f};
-       const __m128 half  = (const __m128) {0.5f, 0.5f, 0.5f, 0.5f};
+       const __m128 three = {3.0f, 3.0f, 3.0f, 3.0f};
+       const __m128 half  = {0.5f, 0.5f, 0.5f, 0.5f};
        
        __m128 t1 = _mm_rsqrt_ps(x);
        
-       return (__m128) _mm_mul_ps(half,_mm_mul_ps(t1,_mm_sub_ps(three,_mm_mul_ps(x,_mm_mul_ps(t1,t1)))));
+       return gmx_mm_castps_ps128(_mm_mul_ps(half,_mm_mul_ps(t1,_mm_sub_ps(three,_mm_mul_ps(x,_mm_mul_ps(t1,t1))))));
 }
 
 void nb_kernel430_sse2_single(int *           p_nri,
@@ -119,14 +120,14 @@ void nb_kernel430_sse2_single(int *           p_nri,
        gpol            = gbdata->gpol;
                
        nri              = *p_nri;         
-    ntype            = *p_ntype;       
-    nthreads         = *p_nthreads;    
-    facel            = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));       
-    krf              = *p_krf;         
-    crf              = *p_crf;         
-    tabscale         = *p_tabscale;    
-    gbtabscale       = *p_gbtabscale;  
-    nj1              = 0;
+  ntype            = *p_ntype;       
+  nthreads         = *p_nthreads;    
+  facel            = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));       
+  krf              = *p_krf;         
+  crf              = *p_crf;         
+  tabscale         = *p_tabscale;    
+  gbtabscale       = *p_gbtabscale;  
+  nj1              = 0;
 
        /* Splat variables */
        fac_sse        = _mm_load1_ps(&facel);
@@ -620,15 +621,15 @@ void nb_kernel430_sse2_single(int *           p_nri,
                                mask  = _mm_set_epi32(0,0xffffffff,0xffffffff,0xffffffff);
                        }
                        
-                       jx      = _mm_and_ps( (__m128) mask, xmm6);
-                       jy      = _mm_and_ps( (__m128) mask, xmm4);
-                       jz      = _mm_and_ps( (__m128) mask, xmm5);
+                       jx      = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm6);
+                       jy      = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm4);
+                       jz      = _mm_and_ps( gmx_mm_castsi128_ps(mask), xmm5);
                        
-                       c6      = _mm_and_ps( (__m128) mask, c6);
-                       c12     = _mm_and_ps( (__m128) mask, c12);
-                       dvdaj   = _mm_and_ps( (__m128) mask, dvdaj);
-                       isaj    = _mm_and_ps( (__m128) mask, isaj);                     
-                       q       = _mm_and_ps( (__m128) mask, q);
+                       c6      = _mm_and_ps( gmx_mm_castsi128_ps(mask), c6);
+                       c12     = _mm_and_ps( gmx_mm_castsi128_ps(mask), c12);
+                       dvdaj   = _mm_and_ps( gmx_mm_castsi128_ps(mask), dvdaj);
+                       isaj    = _mm_and_ps( gmx_mm_castsi128_ps(mask), isaj);                 
+                       q       = _mm_and_ps( gmx_mm_castsi128_ps(mask), q);
                        
                        dx1     = _mm_sub_ps(ix,jx);
                        dy1     = _mm_sub_ps(iy,jy);
@@ -705,8 +706,8 @@ void nb_kernel430_sse2_single(int *           p_nri,
                        xmm1    = _mm_mul_ps(xmm1,isaj);
                        dvdaj   = _mm_add_ps(dvdaj,xmm1);
                        
-                       vcoul   = _mm_and_ps( (__m128) mask, vcoul);
-                       vgb     = _mm_and_ps( (__m128) mask, vgb);
+                       vcoul   = _mm_and_ps( gmx_mm_castsi128_ps(mask), vcoul);
+                       vgb     = _mm_and_ps( gmx_mm_castsi128_ps(mask), vgb);
                        
                        vctot   = _mm_add_ps(vctot,vcoul);
                        vgbtot  = _mm_add_ps(vgbtot,vgb);
@@ -892,9 +893,9 @@ void nb_kernel430_sse2_single(int *           p_nri,
                                _mm_store_ss(faction+j33+2,xmm7); 
                        }
                        
-                       t1 = _mm_and_ps( (__m128) mask, t1);
-                       t2 = _mm_and_ps( (__m128) mask, t2);
-                       t3 = _mm_and_ps( (__m128) mask, t3);
+                       t1 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t1);
+                       t2 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t2);
+                       t3 = _mm_and_ps( gmx_mm_castsi128_ps(mask), t3);
                        
                        fix = _mm_add_ps(fix,t1);
                        fiy = _mm_add_ps(fiy,t2);
@@ -919,7 +920,7 @@ void nb_kernel430_sse2_single(int *           p_nri,
                
                xmm2    = _mm_unpacklo_ps(fix,fiy); /* fx, fy, - - */
                xmm2    = _mm_movelh_ps(xmm2,fiz); 
-               xmm2    = _mm_and_ps( (__m128) maski, xmm2);
+               xmm2    = _mm_and_ps( gmx_mm_castsi128_ps(maski), xmm2);
                
                /* load i force from memory */
                xmm4    = _mm_loadl_pi(xmm4, (__m64 *) (faction+ii3));
@@ -934,7 +935,19 @@ void nb_kernel430_sse2_single(int *           p_nri,
                xmm4    = _mm_shuffle_ps(xmm4,xmm4,_MM_SHUFFLE(2,2,2,2));
                _mm_store_ss(faction+ii3+2,xmm4);
                
-        ggid             = gid[n];         
+    /* Load, add and store i shift forces */
+    xmm4 = _mm_loadl_pi(xmm4, (__m64 *) (fshift+is3));
+    xmm5 = _mm_load1_ps(fshift+is3+2);
+    xmm4 = _mm_shuffle_ps(xmm4,xmm5,_MM_SHUFFLE(3,2,1,0));
+      
+    xmm4 = _mm_add_ps(xmm4,xmm2);
+      
+    _mm_storel_pi( (__m64 *) (fshift+is3),xmm4);
+    xmm4 = _mm_shuffle_ps(xmm4,xmm4,_MM_SHUFFLE(2,2,2,2));
+    _mm_store_ss(fshift+is3+2,xmm4);
+      
+    /* Coulomb potential */
+    ggid             = gid[n];         
                
                vcoul   = _mm_movehl_ps(vcoul,vctot);
                vctot   = _mm_add_ps(vctot,vcoul);
index 536b48b7efdb9184889c8526c00744587f76c9fa..d87325d4550a21d2a46d72aa5e571baaa8ce8845 100644 (file)
@@ -512,7 +512,9 @@ void nb_kernel400_x86_64_sse(int *           p_nri,
                gmx_mm_update_iforce_1atom_ps(fix,fiy,fiz,faction+ii3,fshift+is3);
                
         ggid             = gid[n];         
-               gmx_mm_update_2pot_ps(vctot,vc+ggid,vgbtot,gpol+ggid);
+
+               gmx_mm_update_1pot_ps(vctot,vc+ggid);
+               gmx_mm_update_1pot_ps(vgbtot,gpol+ggid);
                gmx_mm_update_1pot_ps(dvdasum,dvda+ii);
     }
        
index c0affb15342c96f394fede60d0ffc0e6df90331e..8b8265634813c4c44b818a8c5fce12d3e69e2417 100644 (file)
@@ -934,7 +934,19 @@ void nb_kernel430_x86_64_sse(int *           p_nri,
                xmm4    = _mm_shuffle_ps(xmm4,xmm4,_MM_SHUFFLE(2,2,2,2));
                _mm_store_ss(faction+ii3+2,xmm4);
                
-        ggid             = gid[n];         
+    /* Load, add and store i shift forces */
+    xmm4 = _mm_loadl_pi(xmm4, (__m64 *) (fshift+is3));
+    xmm5 = _mm_load1_ps(fshift+is3+2);
+    xmm4 = _mm_shuffle_ps(xmm4,xmm5,_MM_SHUFFLE(3,2,1,0));
+      
+    xmm4 = _mm_add_ps(xmm4,xmm2);
+      
+    _mm_storel_pi( (__m64 *) (fshift+is3),xmm4);
+    xmm4 = _mm_shuffle_ps(xmm4,xmm4,_MM_SHUFFLE(2,2,2,2));
+    _mm_store_ss(fshift+is3+2,xmm4);
+      
+    /* Coulomb potential */
+    ggid             = gid[n];         
                
                vcoul   = _mm_movehl_ps(vcoul,vctot);
                vctot   = _mm_add_ps(vctot,vcoul);
index 31c659dc39df458d626df5a3632634c70f86f0d2..dcb83ebba3b227b255dfc89d3159cba2a1beb825 100644 (file)
@@ -24,6 +24,8 @@
 /* get gmx_gbdata_t */
 #include "../nb_kerneltype.h"
 
+#include "nb_kernel400_x86_64_sse2.h"
+
 static inline __m128d
 my_invrsq_pd(__m128d x)
 {
@@ -89,7 +91,7 @@ void nb_kernel400_x86_64_sse2(int *           p_nri,
        __m128d           q,iq,qq,isai,isaj,isaprod,vcoul,gbscale,dvdai,dvdaj;
        __m128d       Y,F,G,H,Fp,VV,FF,vgb,fijC,dvdatmp,dvdasum,vctot,vgbtot,n0d;
        __m128d           xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
-       __m128d       fac,tabscale,gbtabscale;
+       __m128d       fac,tabscale,gbtabscale,gbfactor;
        __m128i       n0,nnn;
        
        const __m128d neg    = {-1.0f,-1.0f};
@@ -104,7 +106,7 @@ void nb_kernel400_x86_64_sse2(int *           p_nri,
        nri        = *p_nri;
        ntype      = *p_ntype;
        nthreads   = *p_nthreads; 
-    facel      = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));       
+       facel      = *p_facel;
        krf        = *p_krf;
        crf        = *p_crf;
        tabscl     = *p_tabscale;
@@ -115,6 +117,7 @@ void nb_kernel400_x86_64_sse2(int *           p_nri,
        fac        = _mm_load1_pd(&facel);
        tabscale   = _mm_load1_pd(&tabscl);
        gbtabscale = _mm_load1_pd(&gbtabscl);
+       gbfactor   = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
                
        /* Keep compiler happy */
        dvdatmp = _mm_setzero_pd();
@@ -201,6 +204,7 @@ void nb_kernel400_x86_64_sse2(int *           p_nri,
                        fscal   = _mm_mul_pd(vcoul,rinv);
                        qq              = _mm_mul_pd(isaprod,qq);
                        qq              = _mm_mul_pd(qq,neg);
+                       qq      = _mm_mul_pd(qq,gbfactor);
                        gbscale = _mm_mul_pd(isaprod,gbtabscale);
                        
                        /* Load dvdaj */
@@ -296,7 +300,7 @@ void nb_kernel400_x86_64_sse2(int *           p_nri,
                        
                        /* .. then fz */
                        _mm_storel_pd(faction+j13+2,xmm7);
-                       _mm_storel_pd(faction+j23+2,xmm7);
+                       _mm_storeh_pd(faction+j23+2,xmm7);
                }
 
                /* In double precision, offset can only be either 0 or 1 */
@@ -326,6 +330,7 @@ void nb_kernel400_x86_64_sse2(int *           p_nri,
                        fscal   = _mm_mul_sd(vcoul,rinv);
                        qq              = _mm_mul_sd(isaprod,qq);
                        qq              = _mm_mul_sd(qq,neg);
+                       qq      = _mm_mul_pd(qq,gbfactor);
                        gbscale = _mm_mul_sd(isaprod,gbtabscale);
                        
                        r               = _mm_mul_sd(rsq11,rinv);
index 12c6083406d9d67efef181adaef75630f31a3a47..91be3f7d72d88b5cb66729c7757ee3683544fd05 100644 (file)
@@ -24,6 +24,7 @@
 /* get gmx_gbdata_t */
 #include "../nb_kerneltype.h"
 
+#include "nb_kernel410_x86_64_sse2.h"
 
 static inline __m128d
 my_invrsq_pd(__m128d x)
@@ -91,7 +92,7 @@ void nb_kernel410_x86_64_sse2(int *           p_nri,
        __m128d       Y,F,G,H,Fp,VV,FF,vgb,fijC,dvdatmp,dvdasum,vctot,vgbtot,n0d;
        __m128d           xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
        __m128d       c6,c12,Vvdw6,Vvdw12,Vvdwtmp,Vvdwtot,rinvsq,rinvsix;
-       __m128d       fac,tabscale,gbtabscale;
+       __m128d       fac,tabscale,gbtabscale,gbfactor;
        __m128i       n0,nnn;
        
        const __m128d neg    = {-1.0f,-1.0f};
@@ -108,7 +109,7 @@ void nb_kernel410_x86_64_sse2(int *           p_nri,
        nri        = *p_nri;
        ntype      = *p_ntype;
        nthreads   = *p_nthreads; 
-    facel      = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));       
+       facel      = *p_facel;
        krf        = *p_krf;
        crf        = *p_crf;
        tabscl     = *p_tabscale;
@@ -119,6 +120,7 @@ void nb_kernel410_x86_64_sse2(int *           p_nri,
        fac        = _mm_load1_pd(&facel);
        tabscale   = _mm_load1_pd(&tabscl);
        gbtabscale = _mm_load1_pd(&gbtabscl);
+       gbfactor   = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
                
        /* Keep compiler happy */
        Vvdwtmp = _mm_setzero_pd();
@@ -212,6 +214,7 @@ void nb_kernel410_x86_64_sse2(int *           p_nri,
                        vcoul   = _mm_mul_pd(qq,rinv);
                        fscal   = _mm_mul_pd(vcoul,rinv);
                        qq              = _mm_mul_pd(isaprod,qq);
+                       qq      = _mm_mul_pd(qq,gbfactor);
                        qq              = _mm_mul_pd(qq,neg);
                        gbscale = _mm_mul_pd(isaprod,gbtabscale);
                        
@@ -335,7 +338,7 @@ void nb_kernel410_x86_64_sse2(int *           p_nri,
                        
                        /* .. then fz */
                        _mm_storel_pd(faction+j13+2,xmm7);
-                       _mm_storel_pd(faction+j23+2,xmm7);
+                       _mm_storeh_pd(faction+j23+2,xmm7);
                }
                
                /* In double precision, offset can only be either 0 or 1 */
@@ -364,6 +367,7 @@ void nb_kernel410_x86_64_sse2(int *           p_nri,
                        vcoul   = _mm_mul_sd(qq,rinv);
                        fscal   = _mm_mul_sd(vcoul,rinv);
                        qq              = _mm_mul_sd(isaprod,qq);
+                       qq      = _mm_mul_pd(qq,gbfactor);
                        qq              = _mm_mul_sd(qq,neg);
                        gbscale = _mm_mul_sd(isaprod,gbtabscale);
                        
index 714d6c3a3b5459856deaa8e16a34fd1d69e9a0ab..0b47b091890900043a54d8c726b1a8da8768da8e 100644 (file)
@@ -24,6 +24,7 @@
 /* get gmx_gbdata_t */
 #include "../nb_kerneltype.h"
 
+#include "nb_kernel430_x86_64_sse2.h"
 
 static inline __m128d
 my_invrsq_pd(__m128d x)
@@ -91,7 +92,7 @@ void nb_kernel430_x86_64_sse2(int *           p_nri,
        __m128d       Y,F,G,H,Fp,VV,FF,vgb,fijC,fijD,fijR,dvdatmp,dvdasum,vctot,n0d;
        __m128d           xmm0,xmm1,xmm2,xmm3,xmm4,xmm5,xmm6,xmm7,xmm8;
        __m128d       c6,c12,Vvdw6,Vvdw12,Vvdwtmp,Vvdwtot,vgbtot,rinvsq,rinvsix;
-       __m128d       fac,tabscale,gbtabscale;
+       __m128d       fac,tabscale,gbtabscale,gbfactor;
        __m128i       n0,nnn;
        
        const __m128d neg    = {-1.0f,-1.0f};
@@ -110,7 +111,7 @@ void nb_kernel430_x86_64_sse2(int *           p_nri,
        nri        = *p_nri;
        ntype      = *p_ntype;
        nthreads   = *p_nthreads; 
-    facel      = (*p_facel) * ((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent));       
+  facel      = *p_facel;       
        krf        = *p_krf;
        crf        = *p_crf;
        tabscl     = *p_tabscale;
@@ -121,6 +122,7 @@ void nb_kernel430_x86_64_sse2(int *           p_nri,
        fac        = _mm_load1_pd(&facel);
        tabscale   = _mm_load1_pd(&tabscl);
        gbtabscale = _mm_load1_pd(&gbtabscl);
+  gbfactor   = _mm_set1_pd(((1.0/gbdata->epsilon_r) - (1.0/gbdata->gb_epsilon_solvent)));
                
        /* Keep compiler happy */
        Vvdwtmp = _mm_setzero_pd();
@@ -214,6 +216,7 @@ void nb_kernel430_x86_64_sse2(int *           p_nri,
                        vcoul   = _mm_mul_pd(qq,rinv);
                        fscal   = _mm_mul_pd(vcoul,rinv);
                        qq              = _mm_mul_pd(isaprod,qq);
+      qq      = _mm_mul_pd(qq,gbfactor);
                        qq              = _mm_mul_pd(qq,neg);
                        gbscale = _mm_mul_pd(isaprod,gbtabscale);
                        
@@ -414,6 +417,7 @@ void nb_kernel430_x86_64_sse2(int *           p_nri,
                        fscal   = _mm_mul_sd(vcoul,rinv);
                        qq              = _mm_mul_sd(isaprod,qq);
                        qq              = _mm_mul_sd(qq,neg);
+      qq      = _mm_mul_sd(qq,gbfactor);
                        gbscale = _mm_mul_sd(isaprod,gbtabscale);
                        
                        /* Load VdW parameters */
index 50e2a9266fd9b2d9fcc6fca6c882adeb43b74acf..05143f0e564ec767aa970088e1362b965c4148f0 100644 (file)
@@ -73,8 +73,11 @@ static void calc_dihs(t_xrama *xr)
   rvec   r_ij,r_kj,r_kl,m,n;
   real   sign;
   t_dih  *dd;
-
-  rm_pbc(xr->idef,xr->ePBC,xr->natoms,xr->box,xr->x,xr->x);
+  gmx_rmpbc_t  gpbc=NULL;
+  
+  gpbc = gmx_rmpbc_init(xr->idef,xr->ePBC,xr->natoms,xr->box);
+  gmx_rmpbc(gpbc,xr->box,xr->x,xr->x);
+  gmx_rmpbc_done(gpbc);
 
   for(i=0; (i<xr->ndih); i++) {
     dd=&(xr->dih[i]);
index 3c79eb4c45c84b8995dafec67c3b638cee4992e4..e99331eda7a85280be868ef0f6e13da1141103e1 100644 (file)
@@ -200,7 +200,7 @@ static const t_nrnb_data nbdata[eNRNB] = {
     { "Spread Q",                        6 },
     { "Spread Q Bspline",                2 }, 
     { "Gather F",                      23  },
-    { "Gather F Bspline",              12  }, 
+    { "Gather F Bspline",                }, 
     { "3D-FFT",                        8   },
     { "Convolution",                   4   },
     { "Solve PME",                     64  },
index c12418373bc7f2175750ff99d650259420377945..66489938f7273e1963ea6617128d6e3c3648b2f4 100644 (file)
@@ -116,7 +116,7 @@ void output_env_init(output_env_t oenv,  int argc, char *argv[],
             oenv->program_name=strdup(argvzero);
     }
     if (oenv->program_name == NULL)
-        oenv->program_name="GROMACS";
+        oenv->program_name = strdup("GROMACS");
    
     /* copy command line */ 
     if (argv) 
@@ -144,6 +144,14 @@ void output_env_init_default(output_env_t oenv)
 }
 
 
+void output_env_done(output_env_t oenv)
+{
+    sfree(oenv->program_name);
+    sfree(oenv->cmd_line);
+    sfree(oenv);
+}
+
+
 
 int output_env_get_verbosity(const output_env_t oenv)
 {
@@ -231,8 +239,9 @@ const char *output_env_get_short_program_name(const output_env_t oenv)
     pr=ret=oenv->program_name; 
     if ((pr=strrchr(ret,'/')) != NULL)
         ret=pr+1;
-    /*else
-        ret=ret;*/
+    /* Strip away the libtool prefix if it's still there. */
+    if(strlen(ret) > 3 && !strncmp(ret, "lt-", 3))
+        ret = ret + 3;
     return ret;
 }
 
index 0708c11075ca436cc4dc8c654c67760869f91116..7eba2eefc41ae474466d6e97725f1822ea413fc7 100644 (file)
@@ -67,6 +67,10 @@ void init_orires(FILE *fplog,const gmx_mtop_t *mtop,
     od->nex = 0;
     od->S   = NULL;
 
+    od->M=NULL;
+    od->eig=NULL;
+    od->v=NULL;
+
     od->nr = gmx_mtop_ftype_count(mtop,F_ORIRES);
     if (od->nr == 0)
     {
@@ -235,20 +239,19 @@ void diagonalize_orires_tensors(t_oriresdata *od)
 {
     int           ex,i,j,nrot,ord[DIM],t;
     matrix        S,TMP;
-    static double **M=NULL,*eig,**v;
     
-    if (M == NULL)
+    if (od->M == NULL)
     {
-        snew(M,DIM);
+        snew(od->M,DIM);
         for(i=0; i<DIM; i++)
         {
-            snew(M[i],DIM);
+            snew(od->M[i],DIM);
         }
-        snew(eig,DIM);
-        snew(v,DIM);
+        snew(od->eig_diag,DIM);
+        snew(od->v,DIM);
         for(i=0; i<DIM; i++)
         {
-            snew(v[i],DIM);
+            snew(od->v[i],DIM);
         }
     }
 
@@ -261,11 +264,11 @@ void diagonalize_orires_tensors(t_oriresdata *od)
         {
             for(j=0; j<DIM; j++)
             {
-                M[i][j] = S[i][j];
+                od->M[i][j] = S[i][j];
             }
         }
         
-        jacobi(M,DIM,eig,v,&nrot);
+        jacobi(od->M,DIM,od->eig_diag,od->v,&nrot);
         
         for(i=0; i<DIM; i++)
         {
@@ -275,7 +278,7 @@ void diagonalize_orires_tensors(t_oriresdata *od)
         {
             for(j=i+1; j<DIM; j++)
             {
-                if (sqr(eig[ord[j]]) > sqr(eig[ord[i]]))
+                if (sqr(od->eig_diag[ord[j]]) > sqr(od->eig_diag[ord[i]]))
                 {
                     t = ord[i];
                     ord[i] = ord[j];
@@ -286,13 +289,13 @@ void diagonalize_orires_tensors(t_oriresdata *od)
             
         for(i=0; i<DIM; i++)
         {
-            od->eig[ex*12 + i] = eig[ord[i]];
+            od->eig[ex*12 + i] = od->eig_diag[ord[i]];
         }
         for(i=0; i<DIM; i++)
         {
             for(j=0; j<DIM; j++)
             {
-                od->eig[ex*12 + 3 + 3*i + j] = v[j][ord[i]];
+                od->eig[ex*12 + 3 + 3*i + j] = od->v[j][ord[i]];
             }
         }
     }
index 4f1f3cd263d21731fa1cc45ef5d8ac4047a57996..121bfedc106c33156f9828d3bd34cf6fa6c1b182 100644 (file)
@@ -159,6 +159,7 @@ real max_cutoff2(int ePBC,matrix box)
     return min(min_hv2,min_ss*min_ss);
 }
 
+/* this one is mostly harmless... */
 static bool bWarnedGuess=FALSE;
 
 int guess_ePBC(matrix box)
@@ -1163,13 +1164,16 @@ void calc_compact_unitcell_vertices(int ecenter,matrix box,rvec vert[])
 int *compact_unitcell_edges()
 {
     /* this is an index in vert[] (see calc_box_vertices) */
-    static int edge[NCUCEDGE*2];
-    static int hexcon[24] = { 0,9, 1,19, 2,15, 3,21, 
+    /*static int edge[NCUCEDGE*2];*/
+    int *edge;
+    static const int hexcon[24] = { 0,9, 1,19, 2,15, 3,21, 
         4,17, 5,11, 6,23, 7,13,
         8,20, 10,18, 12,16, 14,22 };
     int e,i,j;
     bool bFirst = TRUE;
 
+    snew(edge,NCUCEDGE*2);
+
     if (bFirst) {
         e = 0;
         for(i=0; i<6; i++)
index dae4b2e5be2e7f77bbdfcd73f41727ebbb2ce228..33455a32eb4c9ffceab296c0bee01ec44ac89e69 100644 (file)
@@ -69,6 +69,9 @@ static const char *pdbtp[epdbNR]={
   "CONECT"
 };
 
+
+/* this is not very good, 
+   but these are only used in gmx_trjconv and gmx_editconv */
 static bool bTER=FALSE;
 static bool bWideFormat=FALSE;
 #define REMARK_SIM_BOX "REMARK    THIS IS A SIMULATION BOX"
@@ -670,8 +673,7 @@ int read_pdbfile(FILE *in,char *title,int *model_nr,
                 gmx_conect conect)
 {
   gmx_conect_t *gc = (gmx_conect_t *)conect;
-  static t_symtab symtab;
-  static bool bFirst=TRUE;
+  t_symtab symtab;
   bool bCOMPND;
   bool bConnWarn = FALSE;
   char line[STRLEN+1];
@@ -688,10 +690,7 @@ int read_pdbfile(FILE *in,char *title,int *model_nr,
   if (box != NULL) 
     clear_mat(box);
 
-  if (bFirst) {
-    open_symtab(&symtab);
-    bFirst=FALSE;
-  }
+  open_symtab(&symtab);
 
   bCOMPND=FALSE;
   title[0]='\0';
@@ -765,21 +764,23 @@ int read_pdbfile(FILE *in,char *title,int *model_nr,
         * without identifier or with identical identifiers.
         */
        nterread++;
-       if (nterread == 2 && atoms->resinfo[0].chain == ' ') {
-         set_chainid(atoms,0,nres_ter_prev,chidmax);
-         chidmax = 'A';
-       }
-       if (nterread >= 2 && 
-           (atoms->resinfo[nres_ter_prev].chain == ' ' ||
-            (nres_ter_prev > 0 &&
-             atoms->resinfo[nres_ter_prev-1].chain !=
-             atoms->resinfo[nres_ter_prev].chain)) &&
-           chidmax < 'Z') {
-         chidmax++;
-         set_chainid(atoms,nres_ter_prev,atoms->nres,chidmax);
+       if (NULL != atoms->resinfo) {
+         if (nterread == 2 && atoms->resinfo[0].chain == ' ') {
+           set_chainid(atoms,0,nres_ter_prev,chidmax);
+           chidmax = 'A';
+         }
+         if (nterread >= 2 && 
+             (atoms->resinfo[nres_ter_prev].chain == ' ' ||
+              (nres_ter_prev > 0 &&
+               atoms->resinfo[nres_ter_prev-1].chain !=
+               atoms->resinfo[nres_ter_prev].chain)) &&
+             chidmax < 'Z') {
+           chidmax++;
+           set_chainid(atoms,nres_ter_prev,atoms->nres,chidmax);
+         }
+         chidmax = max(chidmax,atoms->resinfo[nres_ter_prev].chain);
+         nres_ter_prev = atoms->nres;
        }
-       chidmax = max(chidmax,atoms->resinfo[nres_ter_prev].chain);
-       nres_ter_prev = atoms->nres;
       }
       break;
     case epdbMODEL:
@@ -802,6 +803,7 @@ int read_pdbfile(FILE *in,char *title,int *model_nr,
     }
   }
   
+  free_symtab(&symtab);
   return natom;
 }
 
index d49ed5379a5417376a05340c7ada7d0f6c9e5e26..e87520f5d2a080ee4b47b36acbee077b509f8269 100644 (file)
@@ -51,8 +51,6 @@
 #include "warninp.h"
 #include "gmx_fatal.h"
 
-static int inp_count = 1;
-
 /* find an entry; return index, or -1 if not found */
 static int search_einp(int ninp, const t_inpfile *inp, const char *name);
 
@@ -75,7 +73,7 @@ t_inpfile *read_inpfile(const char *fn,int *ninp,
     
   if (debug)
     fprintf(debug,"Reading MDP file %s\n",fn);
-  inp_count = 1;
+
   if (!cppopts)
     cppopts_given=cppopts;
   else
@@ -87,6 +85,7 @@ t_inpfile *read_inpfile(const char *fn,int *ninp,
   {
     sprintf(warn_buf, "%s", cpp_error(&in, status));
     warning_error(wi,warn_buf);
+    *ninp = 0;
     return NULL;
   }
   nin = lc  = 0;
@@ -100,7 +99,8 @@ t_inpfile *read_inpfile(const char *fn,int *ninp,
       {
        sprintf(warn_buf, "%s", cpp_error(&in, status));
        warning_error(wi,warn_buf);
-       return NULL;
+       *ninp = nin;
+       return inp;
       }
       else
        ptr=0;
@@ -180,6 +180,7 @@ t_inpfile *read_inpfile(const char *fn,int *ninp,
              {
                /* add a new item */
                srenew(inp,++nin);
+                inp[nin-1].inp_count  = 1;
                inp[nin-1].count      = 0;
                inp[nin-1].bObsolete  = FALSE;
                inp[nin-1].bSet       = FALSE;
@@ -214,10 +215,13 @@ t_inpfile *read_inpfile(const char *fn,int *ninp,
   } while (ptr);
   cpp_close_file(&in);
 
-  if (debug)
+  if (debug) {
     fprintf(debug,"Done reading MDP file, there were %d entries in there\n",
            nin);
-  *ninp=nin;
+  }
+
+  *ninp = nin;
+
   return inp;
 }
 
@@ -327,7 +331,7 @@ static int get_einp(int *ninp,t_inpfile **inp,const char *name)
     (*inp)[i].name=strdup(name);
     (*inp)[i].bSet=TRUE;
   }
-  (*inp)[i].count = inp_count++;
+  (*inp)[i].count = (*inp)[0].inp_count++;
   (*inp)[i].bSet  = TRUE;
   if (debug) 
     fprintf(debug,"Inp %d = %s\n",(*inp)[i].count,(*inp)[i].name);
@@ -442,7 +446,8 @@ const char *get_estr(int *ninp,t_inpfile **inp,const char *name,const char *def)
 int get_eeenum(int *ninp,t_inpfile **inp,const char *name,const char **defs,
               warninp_t wi)
 {
-  int  ii,i,j,n;
+  int  ii,i,j;
+  int n=0;
   char buf[STRLEN];
   
   ii=get_einp(ninp,inp,name);
@@ -458,12 +463,12 @@ int get_eeenum(int *ninp,t_inpfile **inp,const char *name,const char **defs,
       break;
   
   if (defs[i] == NULL) {
-    n = sprintf(buf,"Invalid enum '%s' for variable %s, using '%s'\n",
+    n += sprintf(buf,"Invalid enum '%s' for variable %s, using '%s'\n",
                (*inp)[ii].value,name,defs[0]);
-    n = sprintf(buf+n,"Next time use one of:");
+    n += sprintf(buf+n,"Next time use one of:");
     j=0;
     while (defs[j]) {
-      n = sprintf(buf+n," '%s'",defs[j]);
+      n += sprintf(buf+n," '%s'",defs[j]);
       j++;
     }
     if (wi != NULL) {
index 785f95cac8622ecb190a54f8ab2dd05f47d5e3f5..33e543b41096dad864e9ad64eb52f51c6ef100c5 100644 (file)
 #include "futil.h"
 #include "vec.h"       
 
-typedef struct {
-    int     natoms;
-    t_graph *gr;
-} multi_graph;
+typedef struct gmx_rmpbc {
+  int     natoms;
+  int     ePBC;
+  t_graph *gr;
+} koeiepoep;
 
-
-void rm_pbc(t_idef *idef,int ePBC,int natoms,matrix box,rvec x[],rvec x_s[])
+gmx_rmpbc_t gmx_rmpbc_init(t_idef *idef,int ePBC,int natoms,
+                          matrix box)
 {
-  static int ngraph=0;
-  static multi_graph *mgraph=NULL;
-  static bool bFirst=TRUE;
-  rvec   sv[SHIFTS];
-  int    n,i;
-  bool   bNeedToCopy;
+  gmx_rmpbc_t gpbc;
+  
+  snew(gpbc,1);
+  
+  gpbc->natoms=natoms;
 
   if (ePBC == -1)
-    ePBC = guess_ePBC(box);
+    gpbc->ePBC = guess_ePBC(box);
+  else
+    gpbc->ePBC = ePBC;
+    
+  if ((ePBC != epbcNONE) && (idef->ntypes!=-1)) {
+    gpbc->gr = mk_graph(NULL,idef,0,natoms,FALSE,FALSE);
+  } 
+  else {
+    fprintf(stderr,
+           "\nWarning: if there are broken molecules in the trajectory file,\n"
+           "         they can not be made whole without a run input file\n\n");
+  }
+  return gpbc;
+}
 
-  bNeedToCopy = (x != x_s);
+void gmx_rmpbc_done(gmx_rmpbc_t gpbc)
+{
+  done_graph(gpbc->gr);
+}
 
-  if (ePBC != epbcNONE) {
-    if (idef->ntypes!=-1) {
-      n=-1;
-      for(i=0; i<ngraph; i++)
-       if (mgraph[i].natoms==natoms)
-         n=i;
-      if (n==-1) {
-       /* make a new graph if there isn't one with this number of atoms */
-       n=ngraph;
-       ngraph++;
-       srenew(mgraph,ngraph);
-       mgraph[n].natoms=natoms;
-       mgraph[n].gr=mk_graph(NULL,idef,0,natoms,FALSE,FALSE);
-      }
-      mk_mshift(stdout,mgraph[n].gr,ePBC,box,x);
-      calc_shifts(box,sv);
-      shift_x(mgraph[n].gr,box,x,x_s);
-      bNeedToCopy=FALSE;
-    } else if (bFirst) {
-      fprintf(stderr,
-             "\nWarning: if there are broken molecules in the trajectory file,\n"
-             "         they can not be made whole without a run input file\n\n");
-      bFirst=FALSE;
-    }
-  }
-  if (bNeedToCopy)
-    for (i=0; i<natoms; i++)
+void gmx_rmpbc(gmx_rmpbc_t gpbc,matrix box,rvec x[],rvec x_s[])
+{
+  int    i;
+
+  mk_mshift(stdout,gpbc->gr,gpbc->ePBC,box,x);
+  shift_x(gpbc->gr,box,x,x_s);
+  if (x != x_s)
+    for (i=0; i<gpbc->natoms; i++)
       copy_rvec(x[i],x_s[i]);
 }
 
index fde3447ffdd06803f4a98002cd86544c8164fed0..c0bdb2e9a5352473c509d65acb0a46a18284942b 100644 (file)
@@ -7,6 +7,7 @@ noinst_LTLIBRARIES = libselection.la
 
 libselection_la_SOURCES =      \
        compiler.c      evaluate.c      evaluate.h      keywords.h      \
+       mempool.c       mempool.h       \
        params.c        parser.c        parser.h        parsetree.c     \
        parsetree.h     \
        scanner.c       scanner.h       scanner_flex.h  scanner_internal.c \
index db12129624277cdf55dd41b12c1db225aaf279f1..ae6ce161ac568e8312cb18b67a68ab3161649150 100644 (file)
  *
  * \todo
  * Better error handling and memory management in error situations.
- * For example, memory handling in atom-valued method parameters within common
- * subexpressions may currently result in memory leaks.
- * Also, the main compilation function leaves the selection collection in
+ * At least, the main compilation function leaves the selection collection in
  * a bad state if an error occurs.
  *
  * \todo
- * The memory usage could be optimized.
+ * The memory usage could still be optimized.
+ * Use of memory pooling could still be extended, and a lot of redundant
+ * gmin/gmax data could be eliminated for complex arithmetic expressions.
  */
 /*! \internal
  * \page selcompiler Selection compilation
  *       function from evaluate.h.
  *    -# The compiler data structure is allocated for each element, and
  *       the fields are initialized, with the exception of the contents of
- *       \c gmax and \c gmin fields.
+ *       \c gmax and \c gmin fields.  In reality, several passes are made
+ *       to completely initialize the structure, because some flags are set
+ *       recursively based on which elements refer to an element, and these
+ *       flags need to be set to initialize other fields.
  *    .
  *  -# The evaluation function of all elements is replaced with the
  *     analyze_static() function to be able to initialize the element before
@@ -95,7 +98,7 @@
  *     To be able to do this for all possible values of dynamical expressions,
  *     special care needs to be taken with boolean expressions because they
  *     are short-circuiting. This is done through the
- *     \c t_compiler_data::bEvalMax flag, which makes dynamic child expressions
+ *     \c SEL_CDATA_EVALMAX flag, which makes dynamic child expressions
  *     of \c BOOL_OR expressions evaluate to empty groups, while subexpressions
  *     of \c BOOL_AND are evaluated to largest possible groups.
  *     Memory is also allocated to store the results of the evaluation.
  *     one reference to them. These cannot be completely processed during the
  *     first pass, because it is not known whether later references require
  *     additional evaluation of static expressions.
+ *  -# Unused subexpressions are removed. For efficiency reasons (and to avoid
+ *     some checks), this is actually done several times already earlier in
+ *     the compilation process.
  *  -# Most of the processing is now done, and the next pass simply sets the
  *     evaluation group of root elements to the largest selection as determined
- *     in pass 3. Subexpressions that were evaluated to constants are no
- *     longer referenced at this time, and are removed.
- *  -# The next pass eliminates some unnecessary evaluation calls from
- *     subexpressions that are referenced only once, as well as initializing
- *     the position calculation data for selection method elements that require
- *     it. Compiler data is also freed as it is no longer needed.
+ *     in pass 3.  For root elements of subexpressions that should not be
+ *     evaluated before they are referred to, the evaluation group/function is
+ *     cleared.  At the same time, position calculation data is initialized for
+ *     for selection method elements that require it.  Compiler data is also
+ *     freed as it is no longer needed.
  *  -# A final pass initializes the total masses and charges in the
  *     \c gmx_ana_selection_t data structures.
  *
  *  -# A selection that should be evaluated.
  *     These elements appear in the same order as the selections in the input.
  *     For these elements, \ref t_selelem::v has been set to the maximum
- *     possible group that the selection can evaluate to, and
- *     \ref t_selelem::cgrp has been set to use a NULL group for evaluation.
+ *     possible group that the selection can evaluate to (only for dynamic
+ *     selections), and \ref t_selelem::cgrp has been set to use a NULL group
+ *     for evaluation.
  *  -# A subexpression that appears in one or more selections.
  *     Each selection that gives a value for a method parameter is a
  *     potential subexpression, as is any variable value.
  *     For these elements, \c t_selelem::cgrp has been set to the group
  *     that should be used to evaluate the subexpression.
  *     If \c t_selelem::cgrp is empty, the total evaluation group is not known
- *     in advance. If this is the case, \c t_selelem::evaluate is also NULL.
+ *     in advance or it is more efficient to evaluate the subexpression only
+ *     when it is referenced.  If this is the case, \c t_selelem::evaluate is
+ *     also NULL.
  *
  * The children of the \ref SEL_ROOT elements can be used to distinguish
  * the two types of root elements from each other; the rules are the same
  *
  * For \ref SEL_SUBEXPR elements, memory has been allocated for
  * \c t_selelem::cgrp to store the group for which the expression has been
- * evaluated during the current frame.
+ * evaluated during the current frame.  This is only done if full subexpression
+ * evaluation by _gmx_sel_evaluate_subexpr() is needed; the other evaluation
+ * functions do not require this memory.
  *
  * \ref SEL_SUBEXPRREF elements are used to describe references to
  * subexpressions. They have always a single child, which is the
  * \ref SEL_SUBEXPR element being referenced.
  *
- * If a subexpression is used only once and can be evaluated statically,
- * the evaluation has been optimized by setting the child of the
- * \ref SEL_SUBEXPR element to evaluate the value of \ref SEL_SUBEXPRREF
- * directly. In this case, the evaluation routines for the \ref SEL_SUBEXPRREF
- * and \ref SEL_SUBEXPR elements only propagate some status information,
- * but do not unnecessarily copy the values.
+ * If a subexpression is used only once, the evaluation has been optimized by
+ * setting the child of the \ref SEL_SUBEXPR element to evaluate the value of
+ * \ref SEL_SUBEXPRREF directly (in the case of memory pooling, this is managed
+ * by the evaluation functions).  In such cases, the evaluation routines for the
+ * \ref SEL_SUBEXPRREF and \ref SEL_SUBEXPR elements only propagate some status
+ * information, but do not unnecessarily copy the values.
  *
  *
  * \subsection selcompiler_tree_bool Boolean elements
  * The static parts of the expressions have been evaluated, and are placed
  * in the first child. These are followed by the dynamic expressions, in the
  * order provided by the user.
+ *
+ *
+ * \subsection selcompiler_tree_arith Arithmetic elements
+ *
+ * Constant and static expressions in \ref SEL_ARITHMETIC elements have been
+ * calculated.
+ * Currently, no other processing is done.
  */
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 
 #include "evaluate.h"
 #include "keywords.h"
+#include "mempool.h"
 #include "selcollection.h"
 #include "selelem.h"
 
 /*! \internal \brief
- * Internal data structure used by the compiler.
+ * Compiler flags.
  */
-typedef struct t_compiler_data
+enum
 {
-    /** The real evaluation method. */
-    sel_evalfunc  evaluate; 
     /*! \brief
-     * Whether the element is a method parameter.
+     * Whether a subexpression needs to evaluated for all atoms.
      *
      * This flag is set for \ref SEL_SUBEXPR elements that are used to
-     * evaluate non-atom-valued selection method parameters.
+     * evaluate non-atom-valued selection method parameters, as well as
+     * those that are used directly as values of selections.
      */
-    bool          bMethodParam;
+    SEL_CDATA_FULLEVAL    =  1,
     /*! \brief
-     * TRUE if the whole subexpression should be treated static.
+     * Whether the whole subexpression should be treated as static.
      *
      * This flag is always FALSE if \ref SEL_DYNAMIC is set for the element,
      * but it is also FALSE for static elements within common subexpressions.
      */
-    bool          bStatic;
-    /** TRUE if the subexpression will always be evaluated with the same group. */
-    bool          bStaticEval;
-    /** TRUE if the compiler evaluation routine should return the maximal selection. */
-    bool          bEvalMax;
+    SEL_CDATA_STATIC      =  2,
+    /** Whether the subexpression will always be evaluated in the same group. */
+    SEL_CDATA_STATICEVAL  =  4,
+    /** Whether the compiler evaluation routine should return the maximal selection. */
+    SEL_CDATA_EVALMAX     =  8,
+    /** Whether memory has been allocated for \p gmin and \p gmax. */
+    SEL_CDATA_MINMAXALLOC = 16,
+    /** Whether subexpressions use simple pass evaluation functions. */
+    SEL_CDATA_SIMPLESUBEXPR = 32,
+    /** Whether this expressions is a part of a common subexpression. */
+    SEL_CDATA_COMMONSUBEXPR = 64 
+};
+
+/*! \internal \brief
+ * Internal data structure used by the compiler.
+ */
+typedef struct t_compiler_data
+{
+    /** The real evaluation method. */
+    sel_evalfunc     evaluate;
+    /** Flags for specifying how to treat this element during compilation. */
+    int              flags;
     /** Smallest selection that can be selected by the subexpression. */
     gmx_ana_index_t *gmin;
     /** Largest selection that can be selected by the subexpression. */
     gmx_ana_index_t *gmax;
-    /** TRUE if memory has been allocated for \p gmin and \p gmax. */
-    bool             bMinMaxAlloc;
 } t_compiler_data;
 
 
@@ -298,6 +330,80 @@ typedef struct t_compiler_data
  * COMPILER UTILITY FUNCTIONS
  ********************************************************************/
 
+static void
+print_group_info(FILE *fp, const char *name, t_selelem *sel, gmx_ana_index_t *g)
+{
+    fprintf(fp, " %s=", name);
+    if (!g)
+    {
+        fprintf(fp, "(null)");
+    }
+    else if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
+    {
+        fprintf(fp, "(%d atoms, %p)", g->isize, (void*)g);
+    }
+    else if (sel->v.type == GROUP_VALUE && g == sel->v.u.g)
+    {
+        fprintf(fp, "(static, %p)", (void*)g);
+    }
+    else
+    {
+        fprintf(fp, "%p", (void*)g);
+    }
+}
+
+/*!
+ * \param[in] fp      File handle to receive the output.
+ * \param[in] sel     Selection element to print.
+ * \param[in] level   Indentation level, starting from zero.
+ */
+void
+_gmx_selelem_print_compiler_info(FILE *fp, t_selelem *sel, int level)
+{
+    if (!sel->cdata)
+    {
+        return;
+    }
+    fprintf(fp, "%*c cdata: flg=", level*2+1, ' ');
+    if (sel->cdata->flags & SEL_CDATA_FULLEVAL)
+    {
+        fprintf(fp, "F");
+    }
+    if (!(sel->cdata->flags & SEL_CDATA_STATIC))
+    {
+        fprintf(fp, "D");
+    }
+    if (sel->cdata->flags & SEL_CDATA_STATICEVAL)
+    {
+        fprintf(fp, "S");
+    }
+    if (sel->cdata->flags & SEL_CDATA_EVALMAX)
+    {
+        fprintf(fp, "M");
+    }
+    if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
+    {
+        fprintf(fp, "A");
+    }
+    if (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+    {
+        fprintf(fp, "Ss");
+    }
+    if (sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
+    {
+        fprintf(fp, "Sc");
+    }
+    if (!sel->cdata->flags)
+    {
+        fprintf(fp, "0");
+    }
+    fprintf(fp, " eval=");
+    _gmx_sel_print_evalfunc_name(fp, sel->cdata->evaluate);
+    print_group_info(fp, "gmin", sel, sel->cdata->gmin);
+    print_group_info(fp, "gmax", sel, sel->cdata->gmax);
+    fprintf(fp, "\n");
+}
+
 /*!
  * \param  sel Selection to free.
  *
@@ -311,7 +417,7 @@ _gmx_selelem_free_compiler_data(t_selelem *sel)
     if (sel->cdata)
     {
         sel->evaluate = sel->cdata->evaluate;
-        if (sel->cdata->bMinMaxAlloc)
+        if (sel->cdata->flags & SEL_CDATA_MINMAXALLOC)
         {
             sel->cdata->gmin->name = NULL;
             sel->cdata->gmax->name = NULL;
@@ -342,6 +448,10 @@ alloc_selection_data(t_selelem *sel, int isize, bool bChildEval)
 {
     int        nalloc;
 
+    if (sel->mempool)
+    {
+        return TRUE;
+    }
     /* Find out the number of elements to allocate */
     if (sel->flags & SEL_SINGLEVAL)
     {
@@ -374,9 +484,7 @@ alloc_selection_data(t_selelem *sel, int isize, bool bChildEval)
         nalloc = 1;
     }
     /* Allocate memory for sel->v.u if needed */
-    if ((sel->flags & SEL_ALLOCVAL)
-        || (sel->type == SEL_SUBEXPRREF && sel->u.param
-            && (sel->u.param->flags & (SPAR_VARNUM | SPAR_ATOMVAL))))
+    if (sel->flags & SEL_ALLOCVAL)
     {
         _gmx_selvalue_reserve(&sel->v, nalloc);
     }
@@ -417,10 +525,78 @@ set_evaluation_function(t_selelem *sel, sel_evalfunc eval)
     }
 }
 
+
 /********************************************************************
- * SUBEXPRESSION EXTRACTION COMPILER PASS
+ * SUBEXPRESSION PROCESSING
  ********************************************************************/
 
+/*! \brief
+ * Reverses the chain of selection elements starting at \p root.
+ *
+ * \param   root First selection in the whole selection chain.
+ * \returns The new first element for the chain.
+ */
+static t_selelem *
+reverse_selelem_chain(t_selelem *root)
+{
+    t_selelem *item;
+    t_selelem *prev;
+    t_selelem *next;
+
+    prev = NULL;
+    item = root;
+    while (item)
+    {
+        next = item->next;
+        item->next = prev;
+        prev = item;
+        item = next;
+    }
+    return prev;
+}
+
+/*! \brief
+ * Removes subexpressions that don't have any references.
+ *
+ * \param     root First selection in the whole selection chain.
+ * \returns   The new first element for the chain.
+ *
+ * The elements are processed in reverse order to correctly detect
+ * subexpressions only referred to by other subexpressions.
+ */
+static t_selelem *
+remove_unused_subexpressions(t_selelem *root)
+{
+    t_selelem *item;
+    t_selelem *prev;
+    t_selelem *next;
+
+    root = reverse_selelem_chain(root);
+    while (root->child->type == SEL_SUBEXPR && root->child->refcount == 1)
+    {
+        next = root->next;
+        _gmx_selelem_free(root);
+        root = next;
+    }
+    prev = root;
+    item = root->next;
+    while (item)
+    {
+        next = item->next;
+        if (item->child->type == SEL_SUBEXPR && item->child->refcount == 1)
+        {
+            prev->next = next;
+            _gmx_selelem_free(item);
+        }
+        else
+        {
+            prev = item;
+        }
+        item = next;
+    }
+    return reverse_selelem_chain(root);
+}
+
 /*! \brief
  * Creates a name with a running number for a subexpression.
  *
@@ -457,8 +633,7 @@ create_subexpression_name(t_selelem *sel, int i)
  * Processes and extracts subexpressions from a given selection subtree.
  *
  * \param   sel      Root of the subtree to process.
- * \param[in] gall     Index group that contains all the input atoms.
- * \param     subexprn Pointer to a subexpression counter.
+ * \param   subexprn Pointer to a subexpression counter.
  * \returns Pointer to a chain of subselections, or NULL if none were found.
  *
  * This function finds recursively all \ref SEL_SUBEXPRREF elements below
@@ -468,7 +643,7 @@ create_subexpression_name(t_selelem *sel, int i)
  * of these root elements.
  */
 static t_selelem *
-extract_item_subselections(t_selelem *sel, gmx_ana_index_t *gall, int *subexprn)
+extract_item_subselections(t_selelem *sel, int *subexprn)
 {
     t_selelem *root;
     t_selelem *subexpr;
@@ -480,18 +655,25 @@ extract_item_subselections(t_selelem *sel, gmx_ana_index_t *gall, int *subexprn)
     {
         if (!root)
         {
-            root = subexpr = extract_item_subselections(child, gall, subexprn);
+            root = subexpr = extract_item_subselections(child, subexprn);
         }
         else
         {
-            subexpr->next = extract_item_subselections(child, gall, subexprn);
+            subexpr->next = extract_item_subselections(child, subexprn);
         }
         while (subexpr && subexpr->next)
         {
             subexpr = subexpr->next;
         }
-        /* The latter check excludes variable references */
-        if (child->type == SEL_SUBEXPRREF && child->child->type != SEL_SUBEXPR)
+        /* The latter check excludes variable references.
+         * It also excludes subexpression elements that have already been
+         * processed, because they are given a name when they are first
+         * encountered.
+         * TODO: There should be a more robust mechanism (probably a dedicated
+         * flag) for detecting parser-generated subexpressions than relying on
+         * a NULL name field. */
+        if (child->type == SEL_SUBEXPRREF && (child->child->type != SEL_SUBEXPR
+                                              || child->child->name == NULL))
         {
             /* Create the root element for the subexpression */
             if (!root)
@@ -503,19 +685,21 @@ extract_item_subselections(t_selelem *sel, gmx_ana_index_t *gall, int *subexprn)
                 subexpr->next = _gmx_selelem_create(SEL_ROOT);
                 subexpr       = subexpr->next;
             }
-            /* Set the evaluation group to all atoms */
-            if (!(child->flags & SEL_ATOMVAL))
+            /* Create the subexpression element and/or
+             * move the actual subexpression under the created element. */
+            if (child->child->type != SEL_SUBEXPR)
+            {
+                subexpr->child = _gmx_selelem_create(SEL_SUBEXPR);
+                _gmx_selelem_set_vtype(subexpr->child, child->v.type);
+                subexpr->child->child = child->child;
+                child->child          = subexpr->child;
+            }
+            else
             {
-                gmx_ana_index_set(&subexpr->u.cgrp, gall->isize, gall->index, NULL, 0);
+                subexpr->child = child->child;
             }
-            /* Create the subexpression element */
-            subexpr->child = _gmx_selelem_create(SEL_SUBEXPR);
-            _gmx_selelem_set_vtype(subexpr->child, child->v.type);
             create_subexpression_name(subexpr->child, ++*subexprn);
-            /* Move the actual subexpression under the created element */
-            subexpr->child->child    = child->child;
-            child->child             = subexpr->child;
-            subexpr->child->refcount = 2;
+            subexpr->child->refcount++;
             /* Set the flags for the created elements */
             subexpr->flags          |= (child->flags & SEL_VALFLAGMASK);
             subexpr->child->flags   |= (child->flags & SEL_VALFLAGMASK);
@@ -530,7 +714,6 @@ extract_item_subselections(t_selelem *sel, gmx_ana_index_t *gall, int *subexprn)
  * Extracts subexpressions of the selection chain.
  * 
  * \param   sel First selection in the whole selection chain.
- * \param[in] gall Index group that contains all the input atoms.
  * \returns The new first element for the chain.
  *
  * Finds all the subexpressions (and their subexpressions) in the
@@ -541,7 +724,7 @@ extract_item_subselections(t_selelem *sel, gmx_ana_index_t *gall, int *subexprn)
  * refer to them.
  */
 static t_selelem *
-extract_subexpressions(t_selelem *sel, gmx_ana_index_t *gall)
+extract_subexpressions(t_selelem *sel)
 {
     t_selelem   *root, *item, *next;
     int          subexprn;
@@ -551,7 +734,7 @@ extract_subexpressions(t_selelem *sel, gmx_ana_index_t *gall)
     next = sel;
     while (next)
     {
-        item = extract_item_subselections(next, gall, &subexprn);
+        item = extract_item_subselections(next, &subexprn);
         if (item)
         {
             if (!root)
@@ -578,8 +761,9 @@ extract_subexpressions(t_selelem *sel, gmx_ana_index_t *gall)
     return root;
 }
 
+
 /********************************************************************
- * BOOLEAN OPERATION REORDERING COMPILER PASS
+ * BOOLEAN OPERATION REORDERING
  ********************************************************************/
 
 /*! \brief
@@ -733,57 +917,100 @@ reorder_boolean_static_children(t_selelem *sel)
     }
 }
 
+
 /********************************************************************
- * EVALUATION PREPARATION COMPILER PASS
+ * ARITHMETIC EXPRESSION PROCESSING
  ********************************************************************/
 
 /*! \brief
- * Initializes the evaluation groups for the selections.
+ * Processes arithmetic expressions to simplify and speed up evaluation.
  *
- * \param[in,out] sc   Selection collection data.
+ * \param  sel Root of the selection subtree to process.
  *
- * The evaluation group of each \ref SEL_ROOT element corresponding to a
- * selection in \p sc is set to \p gall.
+ * Currently, this function only converts integer constants to reals
+ * within arithmetic expressions.
  */
-static void
-initialize_evalgrps(gmx_ana_selcollection_t *sc)
+static bool
+optimize_arithmetic_expressions(t_selelem *sel)
 {
-    t_selelem   *item;
-    int          i;
+    t_selelem  *child;
+    bool        bOk;
 
-    /* Initialize the output */
-    for (i = 0; i < sc->nr; ++i)
+    /* Do recursively for children. */
+    if (sel->type != SEL_SUBEXPRREF)
     {
-        item = sc->sel[i]->selelem;
-        /* Set the evaluation group to all atoms */
-        gmx_ana_index_set(&item->u.cgrp, sc->gall.isize, sc->gall.index,
-                          item->u.cgrp.name, 0);
+        child = sel->child;
+        while (child)
+        {
+            bOk = optimize_arithmetic_expressions(child);
+            if (!bOk)
+            {
+                return bOk;
+            }
+            child = child->next;
+        }
     }
+
+    if (sel->type != SEL_ARITHMETIC)
+    {
+        return TRUE;
+    }
+
+    /* Convert integer constants to reals. */
+    child = sel->child;
+    while (child)
+    {
+        if (child->v.type == INT_VALUE)
+        {
+            real  *r;
+
+            if (child->type != SEL_CONST)
+            {
+                gmx_impl("Non-constant integer expressions not implemented in arithmetic evaluation");
+                return FALSE;
+            }
+            snew(r, 1);
+            r[0] = child->v.u.i[0];
+            sfree(child->v.u.i);
+            child->v.u.r = r;
+            child->v.type = REAL_VALUE;
+        }
+        else if (child->v.type != REAL_VALUE)
+        {
+            gmx_bug("Internal error");
+            return FALSE;
+        }
+        child = child->next;
+    }
+    return TRUE;
 }
 
+
+/********************************************************************
+ * EVALUATION PREPARATION COMPILER
+ ********************************************************************/
+
 /*! \brief
- * Prepares the selection (sub)tree for evaluation.
+ * Sets the evaluation functions for the selection (sub)tree.
  *
- * \param[in,out] sel Root of the selection subtree to prepare.
+ * \param[in,out] sel Root of the selection subtree to process.
  * \returns       TRUE on success, FALSE if any subexpression fails.
  *
  * This function sets the evaluation function (\c t_selelem::evaluate)
  * for the selection elements.
- * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
- * structure if required.
  */
 static bool
-init_item_evaluation(t_selelem *sel)
+init_item_evalfunc(t_selelem *sel)
 {
-    t_selelem         *child;
-
-    /* Process children */
+    /* Process children. */
     if (sel->type != SEL_SUBEXPRREF)
     {
+        t_selelem *child;
+
         child = sel->child;
         while (child)
         {
-            if (!init_item_evaluation(child))
+            if (!init_item_evalfunc(child))
             {
                 return FALSE;
             }
@@ -791,16 +1018,6 @@ init_item_evaluation(t_selelem *sel)
         }
     }
 
-    /* Make sure that the group/position structure is allocated */
-    if (!sel->v.u.ptr && (sel->flags & SEL_ALLOCVAL))
-    {
-        if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
-        {
-            _gmx_selvalue_reserve(&sel->v, 1);
-            sel->v.nr = 1;
-        }
-    }
-
     /* Set the evaluation function */
     switch (sel->type)
     {
@@ -812,9 +1029,18 @@ init_item_evaluation(t_selelem *sel)
             break;
 
         case SEL_EXPRESSION:
+            if (!(sel->flags & SEL_DYNAMIC) && sel->u.expr.method
+                && sel->u.expr.method->init_frame)
+            {
+                sel->flags |= SEL_INITFRAME;
+            }
             sel->evaluate = &_gmx_sel_evaluate_method;
             break;
 
+        case SEL_ARITHMETIC:
+            sel->evaluate = &_gmx_sel_evaluate_arithmetic;
+            break;
+
         case SEL_MODIFIER:
             if (sel->v.type != NO_VALUE)
             {
@@ -839,21 +1065,131 @@ init_item_evaluation(t_selelem *sel)
             break;
 
         case SEL_SUBEXPR:
-            sel->evaluate = &_gmx_sel_evaluate_subexpr;
+            sel->evaluate = (sel->refcount == 2
+                             ? &_gmx_sel_evaluate_subexpr_simple
+                             : &_gmx_sel_evaluate_subexpr);
             break;
 
         case SEL_SUBEXPRREF:
             sel->name     = sel->child->name;
-            sel->evaluate = &_gmx_sel_evaluate_subexprref;
+            sel->evaluate = (sel->child->refcount == 2
+                             ? &_gmx_sel_evaluate_subexprref_simple
+                             : &_gmx_sel_evaluate_subexprref);
             break;
     }
 
     return TRUE;
 }
 
+/*! \brief
+ * Sets the memory pool for selection elements that can use it.
+ *
+ * \param     sel      Root of the selection subtree to process.
+ * \param[in] mempool  Memory pool to use.
+ */
+static void
+setup_memory_pooling(t_selelem *sel, gmx_sel_mempool_t *mempool)
+{
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        t_selelem         *child;
+
+        child = sel->child;
+        while (child)
+        {
+            if ((sel->type == SEL_BOOLEAN && (child->flags & SEL_DYNAMIC))
+                || (sel->type == SEL_ARITHMETIC && child->type != SEL_CONST
+                    && !(child->flags & SEL_SINGLEVAL))
+                || (sel->type == SEL_SUBEXPR && sel->refcount > 2))
+            {
+                child->mempool = mempool;
+                if (child->type == SEL_SUBEXPRREF
+                    && child->child->refcount == 2)
+                {
+                    child->child->child->mempool = mempool;
+                }
+            }
+            setup_memory_pooling(child, mempool);
+            child = child->next;
+        }
+    }
+}
+
+/*! \brief
+ * Prepares the selection (sub)tree for evaluation.
+ *
+ * \param[in,out] sel Root of the selection subtree to prepare.
+ *
+ * It also allocates memory for the \p sel->v.u.g or \p sel->v.u.p
+ * structure if required.
+ */
+static void
+init_item_evaloutput(t_selelem *sel)
+{
+    /* Process children. */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        t_selelem *child;
+
+        child = sel->child;
+        while (child)
+        {
+            init_item_evaloutput(child);
+            child = child->next;
+        }
+    }
+
+    if (sel->type == SEL_SUBEXPR && sel->refcount == 2)
+    {
+        sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+        if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+        {
+            _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
+        }
+    }
+    else if (sel->type == SEL_SUBEXPR
+             && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
+    {
+        sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
+        sel->cdata->evaluate = sel->evaluate;
+        sel->child->mempool = NULL;
+        sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+        if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+        {
+            _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
+        }
+    }
+    else if (sel->type == SEL_SUBEXPRREF && sel->child->refcount == 2)
+    {
+        if (sel->v.u.ptr)
+        {
+            _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
+            _gmx_selelem_free_values(sel->child->child);
+            sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+            sel->child->child->flags |= (sel->flags & SEL_ALLOCDATA);
+            _gmx_selvalue_setstore(&sel->child->child->v, sel->v.u.ptr);
+        }
+        else if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+        {
+            _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
+        }
+        sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+    }
+
+    /* Make sure that the group/position structure is allocated. */
+    if (!sel->v.u.ptr && (sel->flags & SEL_ALLOCVAL))
+    {
+        if (sel->v.type == GROUP_VALUE || sel->v.type == POS_VALUE)
+        {
+            _gmx_selvalue_reserve(&sel->v, 1);
+            sel->v.nr = 1;
+        }
+    }
+}
+
 
 /********************************************************************
- * COMPILER DATA INITIALIZATION PASS
+ * COMPILER DATA INITIALIZATION
  ********************************************************************/
 
 /*! \brief
@@ -873,23 +1209,34 @@ init_item_compilerdata(t_selelem *sel)
     sel->cdata->evaluate = sel->evaluate;
 
     /* Initialize the flags */
-    sel->cdata->bMethodParam = FALSE;
-    sel->cdata->bStatic      = !(sel->flags & SEL_DYNAMIC);
-    sel->cdata->bStaticEval  = TRUE;
-    sel->cdata->bEvalMax     = (sel->type == SEL_SUBEXPR ? TRUE : FALSE);
-    /* Set the method parameter flag for non-atom-valued parameters */
+    sel->cdata->flags = SEL_CDATA_STATICEVAL;
+    if (!(sel->flags & SEL_DYNAMIC))
+    {
+        sel->cdata->flags |= SEL_CDATA_STATIC;
+    }
+    if (sel->type == SEL_SUBEXPR)
+    {
+        sel->cdata->flags |= SEL_CDATA_EVALMAX;
+    }
+    /* Set the full evaluation flag for subexpressions that require it;
+     * the subexpression has already been initialized, so we can simply
+     * access its compilation flags.*/
     if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
     {
         child = sel->child;
         while (child)
         {
-            if (!(child->flags & SEL_ATOMVAL))
+            if (!(child->flags & SEL_ATOMVAL) && child->child)
             {
-                child->child->cdata->bMethodParam = TRUE;
+                child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
             }
             child = child->next;
         }
     }
+    else if (sel->type == SEL_ROOT && sel->child->type == SEL_SUBEXPRREF)
+    {
+        sel->child->child->cdata->flags |= SEL_CDATA_FULLEVAL;
+    }
 
     /* Initialize children */
     if (sel->type != SEL_SUBEXPRREF)
@@ -912,10 +1259,13 @@ init_item_compilerdata(t_selelem *sel)
         child = sel->child;
         while (child)
         {
-            child->cdata->bEvalMax = bEvalMax;
-            if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT)
+            if (bEvalMax)
+            {
+                child->cdata->flags |= SEL_CDATA_EVALMAX;
+            }
+            else if (child->type == SEL_BOOLEAN && child->u.boolt == BOOL_NOT)
             {
-                child->child->cdata->bEvalMax = !bEvalMax;
+                child->child->cdata->flags |= SEL_CDATA_EVALMAX;
             }
             child = child->next;
         }
@@ -926,32 +1276,10 @@ init_item_compilerdata(t_selelem *sel)
         child = sel->child;
         while (child)
         {
-            child->cdata->bEvalMax = TRUE;
+            child->cdata->flags |= SEL_CDATA_EVALMAX;
             child = child->next;
         }
     }
-
-    /* Initialize the minimum and maximum evaluation groups */
-    sel->cdata->bMinMaxAlloc = FALSE;
-    if (sel->type != SEL_ROOT && sel->v.type != NO_VALUE)
-    {
-        if (sel->type == SEL_SUBEXPR)
-        {
-            sel->cdata->gmin = sel->child->cdata->gmin;
-            sel->cdata->gmax = sel->child->cdata->gmax;
-        }
-        else if (sel->v.type == GROUP_VALUE && sel->cdata->bStatic)
-        {
-            sel->cdata->gmin = sel->v.u.g;
-            sel->cdata->gmax = sel->v.u.g;
-        }
-        else
-        {
-            sel->cdata->bMinMaxAlloc = TRUE;
-            snew(sel->cdata->gmin, 1);
-            snew(sel->cdata->gmax, 1);
-        }
-    }
 }
 
 /*! \brief
@@ -970,15 +1298,16 @@ init_item_staticeval(t_selelem *sel)
 {
     t_selelem   *child;
 
-    /* Non-atom-valued method parameters should always have bStaticEval,
+    /* Subexpressions with full evaluation should always have bStaticEval,
      * so don't do anything if a reference to them is encountered. */
-    if (sel->type == SEL_SUBEXPRREF && sel->child->cdata->bMethodParam)
+    if (sel->type == SEL_SUBEXPRREF
+        && (sel->child->cdata->flags & SEL_CDATA_FULLEVAL))
     {
         return;
     }
 
     /* Propagate the bStaticEval flag to children if it is not set */
-    if (!sel->cdata->bStaticEval)
+    if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
     {
         child = sel->child;
         while (child)
@@ -986,9 +1315,9 @@ init_item_staticeval(t_selelem *sel)
             if ((sel->type != SEL_EXPRESSION && sel->type != SEL_MODIFIER)
                 || (child->flags & SEL_ATOMVAL))
             {
-                if (child->cdata->bStaticEval)
+                if (child->cdata->flags & SEL_CDATA_STATICEVAL)
                 {
-                    child->cdata->bStaticEval = FALSE;
+                    child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
                     init_item_staticeval(child);
                 }
             }
@@ -1012,7 +1341,7 @@ init_item_staticeval(t_selelem *sel)
             }
             while (child)
             {
-                child->cdata->bStaticEval = FALSE;
+                child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
                 child = child->next;
             }
         }
@@ -1027,9 +1356,135 @@ init_item_staticeval(t_selelem *sel)
     }
 }
 
+/*! \brief
+ * Initializes compiler flags for subexpressions.
+ *
+ * \param sel Root of the selection subtree to process.
+ */
+static void
+init_item_subexpr_flags(t_selelem *sel)
+{
+    if (sel->type == SEL_SUBEXPR)
+    {
+        if (sel->refcount == 2)
+        {
+            sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
+        }
+        else if (!(sel->cdata->flags & SEL_CDATA_FULLEVAL))
+        {
+            sel->cdata->flags |= SEL_CDATA_COMMONSUBEXPR;
+        }
+    }
+    else if (sel->type == SEL_SUBEXPRREF && sel->child->refcount == 2)
+    {
+        sel->cdata->flags |= SEL_CDATA_SIMPLESUBEXPR;
+    }
+
+    /* Process children, but only follow subexpression references if the
+     * common subexpression flag needs to be propagated. */
+    if (sel->type != SEL_SUBEXPRREF
+        || ((sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
+            && sel->child->refcount > 2))
+    {
+        t_selelem *child = sel->child;
+
+        while (child)
+        {
+            if (!(child->cdata->flags & SEL_CDATA_COMMONSUBEXPR))
+            {
+                if (sel->type != SEL_EXPRESSION || (child->flags & SEL_ATOMVAL))
+                {
+                    child->cdata->flags |=
+                        (sel->cdata->flags & SEL_CDATA_COMMONSUBEXPR);
+                }
+                init_item_subexpr_flags(child);
+            }
+            child = child->next;
+        }
+    }
+}
+
+/*! \brief
+ * Initializes the gmin and gmax fields of the compiler data structure.
+ *
+ * \param sel Root of the selection subtree to process.
+ */
+static void
+init_item_minmax_groups(t_selelem *sel)
+{
+    /* Process children. */
+    if (sel->type != SEL_SUBEXPRREF)
+    {
+        t_selelem *child;
+
+        child = sel->child;
+        while (child)
+        {
+            init_item_minmax_groups(child);
+            child = child->next;
+        }
+    }
+
+    /* Initialize the minimum and maximum evaluation groups. */
+    if (sel->type != SEL_ROOT && sel->v.type != NO_VALUE)
+    {
+        if (sel->v.type == GROUP_VALUE
+            && (sel->cdata->flags & SEL_CDATA_STATIC))
+        {
+            sel->cdata->gmin = sel->v.u.g;
+            sel->cdata->gmax = sel->v.u.g;
+        }
+        else if (sel->type == SEL_SUBEXPR
+                 && ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+                     || (sel->cdata->flags & SEL_CDATA_FULLEVAL)))
+        {
+            sel->cdata->gmin = sel->child->cdata->gmin;
+            sel->cdata->gmax = sel->child->cdata->gmax;
+        }
+        else
+        {
+            sel->cdata->flags |= SEL_CDATA_MINMAXALLOC;
+            snew(sel->cdata->gmin, 1);
+            snew(sel->cdata->gmax, 1);
+        }
+    }
+}
+
 
 /********************************************************************
- * STATIC ANALYSIS COMPILER PASS
+ * EVALUATION GROUP INITIALIZATION
+ ********************************************************************/
+
+/*! \brief
+ * Initializes evaluation groups for root items.
+ *
+ * \param[in,out] sc   Selection collection data.
+ *
+ * The evaluation group of each \ref SEL_ROOT element corresponding to a
+ * selection in \p sc is set to \p gall.  The same is done for \ref SEL_ROOT
+ * elements corresponding to subexpressions that need full evaluation.
+ */
+static void
+initialize_evalgrps(gmx_ana_selcollection_t *sc)
+{
+    t_selelem   *root;
+
+    root = sc->root;
+    while (root)
+    {
+        if (root->child->type != SEL_SUBEXPR
+            || (root->child->cdata->flags & SEL_CDATA_FULLEVAL))
+        {
+            gmx_ana_index_set(&root->u.cgrp, sc->gall.isize, sc->gall.index,
+                              root->u.cgrp.name, 0);
+        }
+        root = root->next;
+    }
+}
+
+
+/********************************************************************
+ * STATIC ANALYSIS
  ********************************************************************/
 
 /*! \brief
@@ -1048,16 +1503,64 @@ mark_subexpr_dynamic(t_selelem *sel, bool bDynamic)
 {
     t_selelem *child;
 
-    sel->cdata->bStatic = (!bDynamic && !(sel->flags & SEL_DYNAMIC));
+    if (!bDynamic && !(sel->flags & SEL_DYNAMIC))
+    {
+        sel->cdata->flags |= SEL_CDATA_STATIC;
+    }
+    else
+    {
+        sel->cdata->flags &= ~SEL_CDATA_STATIC;
+    }
     child = sel->child;
     while (child)
     {
         if (sel->type != SEL_EXPRESSION || child->type != SEL_SUBEXPRREF
             || (child->u.param->flags & SPAR_ATOMVAL))
         {
-            mark_subexpr_dynamic(child, bDynamic);
+            mark_subexpr_dynamic(child, bDynamic);
+        }
+        child = child->next;
+    }
+}
+
+/*! \brief
+ * Frees memory for subexpressions that are no longer needed.
+ *
+ * \param     sel      Selection subtree to check.
+ *
+ * Checks whether the subtree rooted at \p sel refers to any \ref SEL_SUBEXPR
+ * elements that are not referred to by anything else except their own root
+ * element. If such elements are found, all memory allocated for them is freed
+ * except the actual element. The element is left because otherwise a dangling
+ * pointer would be left at the root element, which is not traversed by this
+ * function. Later compilation passes remove the stub elements.
+ */
+static void
+release_subexpr_memory(t_selelem *sel)
+{
+    if (sel->type == SEL_SUBEXPR)
+    {
+        if (sel->refcount == 2)
+        {
+            release_subexpr_memory(sel->child);
+            sel->name = NULL;
+            _gmx_selelem_free_chain(sel->child);
+            _gmx_selelem_free_values(sel);
+            _gmx_selelem_free_exprdata(sel);
+            _gmx_selelem_free_compiler_data(sel);
+            sel->child = NULL;
+        }
+    }
+    else
+    {
+        t_selelem *child;
+
+        child = sel->child;
+        while (child)
+        {
+            release_subexpr_memory(child);
+            child = child->next;
         }
-        child = child->next;
     }
 }
 
@@ -1073,6 +1576,37 @@ mark_subexpr_dynamic(t_selelem *sel, bool bDynamic)
 static void
 make_static(t_selelem *sel)
 {
+    /* If this is a subexpression reference and the data is stored in the
+     * child, we transfer data ownership before doing anything else. */
+    if (sel->type == SEL_SUBEXPRREF
+        && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
+    {
+        if (sel->child->child->flags & SEL_ALLOCDATA)
+        {
+            sel->flags |= SEL_ALLOCDATA;
+            sel->child->child->flags &= ~SEL_ALLOCDATA;
+        }
+        if (sel->child->child->flags & SEL_ALLOCVAL)
+        {
+            sel->flags |= SEL_ALLOCVAL;
+            sel->v.nalloc = sel->child->child->v.nalloc;
+            sel->child->child->flags &= ~SEL_ALLOCVAL;
+            sel->child->child->v.nalloc = -1;
+        }
+    }
+    /* When we reach here for parameter elements, the value is already
+     * stored in the parent element, so make sure that it is not freed
+     * through this element. */
+    if (sel->type == SEL_SUBEXPRREF && sel->u.param)
+    {
+        sel->u.param->val.nalloc = sel->v.nalloc;
+        sel->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+        sel->v.nalloc = -1;
+    }
+    /* Free the children. */
+    release_subexpr_memory(sel);
+    _gmx_selelem_free_chain(sel->child);
+    sel->child           = NULL;
     /* Free the expression data as it is no longer needed */
     _gmx_selelem_free_exprdata(sel);
     /* Make the item static */
@@ -1080,13 +1614,8 @@ make_static(t_selelem *sel)
     sel->type            = SEL_CONST;
     sel->evaluate        = NULL;
     sel->cdata->evaluate = NULL;
-    /* Free the children */
-    _gmx_selelem_free_chain(sel->child);
-    sel->child           = NULL;
     /* Set the group value.
-     * None of the elements for which this function may be called uses
-     * the cgrp group, so we can simply overwrite the contents without
-     * worrying about memory leaks. */
+     * free_exprdata above frees the cgrp group, so we can just override it. */
     if (sel->v.type == GROUP_VALUE)
     {
         gmx_ana_index_set(&sel->u.cgrp, sel->v.u.g->isize, sel->v.u.g->index, NULL, 0);
@@ -1094,7 +1623,7 @@ make_static(t_selelem *sel)
 }
 
 /*! \brief
- * Evaluates a constant expression during analyze_static() and analyze_static2().
+ * Evaluates a constant expression during analyze_static().
  *
  * \param[in]     data Evaluation data.
  * \param[in,out] sel Selection to process.
@@ -1190,18 +1719,6 @@ init_method(t_selelem *sel, t_topology *top, int isize)
         && (bAtomVal || !(sel->flags & SEL_METHODINIT)))
     {
         sel->flags |= SEL_METHODINIT;
-        /* The allocation flags are cleared first to not to free anything if
-         * initialization fails. */
-        child = sel->child;
-        if (sel->type == SEL_MODIFIER && sel->v.type != NO_VALUE)
-        {
-            child = child->next;
-        }
-        while (child)
-        {
-            child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
-            child = child->next;
-        }
         rc = sel->u.expr.method->init(top, sel->u.expr.method->nparams,
                 sel->u.expr.method->param, sel->u.expr.mdata);
         if (rc != 0)
@@ -1219,6 +1736,10 @@ init_method(t_selelem *sel, t_topology *top, int isize)
             {
                 return rc;
             }
+            if (sel->v.type != POS_VALUE && sel->v.type != GROUP_VALUE)
+            {
+                alloc_selection_data(sel, isize, TRUE);
+            }
         }
         else
         {
@@ -1274,11 +1795,11 @@ evaluate_boolean_static_part(gmx_sel_evaluate_t *data, t_selelem *sel,
 
     /* Find the last static subexpression */
     child = sel->child;
-    while (child->next && child->next->cdata->bStatic)
+    while (child->next && (child->next->cdata->flags & SEL_CDATA_STATIC))
     {
         child = child->next;
     }
-    if (!child->cdata->bStatic)
+    if (!(child->cdata->flags & SEL_CDATA_STATIC))
     {
         return 0;
     }
@@ -1303,7 +1824,9 @@ evaluate_boolean_static_part(gmx_sel_evaluate_t *data, t_selelem *sel,
         _gmx_selvalue_reserve(&child->v, 1);
         gmx_ana_index_copy(child->v.u.g, sel->v.u.g, TRUE);
         init_item_compilerdata(child);
-        child->cdata->bStaticEval = sel->cdata->bStaticEval;
+        init_item_minmax_groups(child);
+        child->cdata->flags &= ~SEL_CDATA_STATICEVAL;
+        child->cdata->flags |= sel->cdata->flags & SEL_CDATA_STATICEVAL;
         child->next = next;
         sel->child = child;
     }
@@ -1324,7 +1847,8 @@ evaluate_boolean_static_part(gmx_sel_evaluate_t *data, t_selelem *sel,
      * time copying the group. */
     child->evaluate = NULL;
     if (sel->u.boolt == BOOL_NOT
-        || (sel->cdata->bStaticEval && sel->u.boolt == BOOL_OR))
+        || ((sel->cdata->flags & SEL_CDATA_STATICEVAL)
+            && sel->u.boolt == BOOL_OR))
     {
         child->cdata->evaluate = NULL;
     }
@@ -1397,7 +1921,7 @@ evaluate_boolean_minmax_grps(t_selelem *sel, gmx_ana_index_t *g,
                 child = child->next;
             }
             /* Update the static part if other expressions limit it */
-            if (sel->child->cdata->bStatic
+            if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
                 && sel->child->v.u.g->isize > gmax->isize)
             {
                 gmx_ana_index_copy(sel->child->v.u.g, gmax, FALSE);
@@ -1426,7 +1950,7 @@ evaluate_boolean_minmax_grps(t_selelem *sel, gmx_ana_index_t *g,
             }
             /* Update the static part if other expressions have static parts
              * that are not included. */
-            if (sel->child->cdata->bStatic
+            if ((sel->child->cdata->flags & SEL_CDATA_STATIC)
                 && sel->child->v.u.g->isize < gmin->isize)
             {
                 gmx_ana_index_reserve(sel->child->v.u.g, gmin->isize);
@@ -1462,26 +1986,25 @@ evaluate_boolean_minmax_grps(t_selelem *sel, gmx_ana_index_t *g,
  * expressions have been evaluated.
  * The above is exactly true only for elements other than subexpressions:
  * another pass is required for subexpressions that are referred to more than
- * once to evaluate the static parts.
- * This second pass is performed by analyze_static2().
- *
- * \see analyze_static2()
+ * once and whose evaluation group is not known in advance.
  */
 static int
 analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
 {
     t_selelem       *child, *next;
-    gmx_ana_index_t  gmin, gmax;
-    bool             bDelayAlloc;
+    bool             bDoMinMax;
     int              rc;
 
-    gmx_ana_index_clear(&gmin);
-    gmx_ana_index_clear(&gmax);
-    bDelayAlloc = FALSE;
-
     if (sel->type != SEL_ROOT && g)
     {
-        bDelayAlloc = !alloc_selection_data(sel, g->isize, FALSE);
+        alloc_selection_data(sel, g->isize, FALSE);
+    }
+
+    bDoMinMax = (sel->cdata->flags & SEL_CDATA_MINMAXALLOC);
+    if (sel->type != SEL_SUBEXPR && bDoMinMax)
+    {
+        gmx_ana_index_deinit(sel->cdata->gmin);
+        gmx_ana_index_deinit(sel->cdata->gmax);
     }
 
     /* TODO: This switch is awfully long... */
@@ -1507,7 +2030,7 @@ analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
             if (!(sel->flags & SEL_DYNAMIC))
             {
                 rc = sel->cdata->evaluate(data, sel, g);
-                if (rc == 0 && sel->cdata->bStatic)
+                if (rc == 0 && (sel->cdata->flags & SEL_CDATA_STATIC))
                 {
                     make_static(sel);
                 }
@@ -1521,7 +2044,10 @@ analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
                 {
                     rc = sel->cdata->evaluate(data, sel, g);
                 }
-                gmx_ana_index_copy(&gmax, g, TRUE);
+                if (bDoMinMax)
+                {
+                    gmx_ana_index_copy(sel->cdata->gmax, g, TRUE);
+                }
             }
             break;
 
@@ -1529,7 +2055,7 @@ analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
             if (!(sel->flags & SEL_DYNAMIC))
             {
                 rc = sel->cdata->evaluate(data, sel, g);
-                if (rc == 0 && sel->cdata->bStatic)
+                if (rc == 0 && (sel->cdata->flags & SEL_CDATA_STATIC))
                 {
                     make_static(sel);
                 }
@@ -1561,7 +2087,27 @@ analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
                 }
 
                 /* Evaluate minimal and maximal selections */
-                evaluate_boolean_minmax_grps(sel, g, &gmin, &gmax);
+                evaluate_boolean_minmax_grps(sel, g, sel->cdata->gmin,
+                                             sel->cdata->gmax);
+            }
+            break;
+
+        case SEL_ARITHMETIC:
+            rc = sel->cdata->evaluate(data, sel, g);
+            if (rc != 0)
+            {
+                return rc;
+            }
+            if (!(sel->flags & SEL_DYNAMIC))
+            {
+                if (sel->cdata->flags & SEL_CDATA_STATIC)
+                {
+                    make_static(sel);
+                }
+            }
+            else if (bDoMinMax)
+            {
+                gmx_ana_index_copy(sel->cdata->gmax, g, TRUE);
             }
             break;
 
@@ -1570,28 +2116,19 @@ analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
             break;
 
         case SEL_SUBEXPR:
-            if (sel->u.cgrp.isize == 0)
+            if (sel->cdata->flags & (SEL_CDATA_SIMPLESUBEXPR | SEL_CDATA_FULLEVAL))
+            {
+                rc = sel->cdata->evaluate(data, sel, g);
+                _gmx_selvalue_setstore(&sel->v, sel->child->v.u.ptr);
+            }
+            else if (sel->u.cgrp.isize == 0)
             {
                 gmx_ana_index_reserve(&sel->u.cgrp, g->isize);
-                if (bDelayAlloc)
-                {
-                    /* We need to evaluate the child before we can allocate the
-                     * memory. */
-                    rc = sel->child->evaluate(data, sel->child, g);
-                    if (rc != 0)
-                    {
-                        return rc;
-                    }
-                    alloc_selection_data(sel, g->isize, TRUE);
-                    /* Do not evaluate the child again */
-                    sel->child->evaluate = NULL;
-                    rc = sel->cdata->evaluate(data, sel, g);
-                    sel->child->evaluate = &analyze_static;
-                }
-                else
+                rc = sel->cdata->evaluate(data, sel, g);
+                if (bDoMinMax)
                 {
-                    alloc_selection_data(sel->child, g->isize, FALSE);
-                    rc = sel->cdata->evaluate(data, sel, g);
+                    gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, TRUE);
+                    gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, TRUE);
                 }
             }
             else
@@ -1601,75 +2138,69 @@ analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
                 {
                     isize += sel->u.cgrp.isize;
                     gmx_ana_index_reserve(&sel->u.cgrp, isize);
-                    if (sel->v.type == GROUP_VALUE || (sel->flags & SEL_ATOMVAL))
-                    {
-                        alloc_selection_data(sel->child, isize, FALSE);
-                        alloc_selection_data(sel,        isize, FALSE);
-                    }
-                    rc = sel->cdata->evaluate(data, sel, g);
+                    alloc_selection_data(sel, isize, FALSE);
                 }
-                else
+                rc = sel->cdata->evaluate(data, sel, g);
+                if (isize > 0 && bDoMinMax)
                 {
-                    rc = sel->cdata->evaluate(data, sel, g);
+                    gmx_ana_index_reserve(sel->cdata->gmin,
+                                          sel->cdata->gmin->isize
+                                          + sel->child->cdata->gmin->isize);
+                    gmx_ana_index_reserve(sel->cdata->gmax,
+                                          sel->cdata->gmax->isize
+                                          + sel->child->cdata->gmax->isize);
+                    gmx_ana_index_merge(sel->cdata->gmin, sel->cdata->gmin,
+                                        sel->child->cdata->gmin);
+                    gmx_ana_index_merge(sel->cdata->gmax, sel->cdata->gmax,
+                                        sel->child->cdata->gmax);
                 }
             }
             break;
 
         case SEL_SUBEXPRREF:
-            /* Evaluate the subexpression if it is not yet evaluated.
-             * Can happen when a variable is passed as a parameter or as
-             * a selection. */
-            if (sel->child->u.cgrp.isize == 0)
-            {
-                rc = sel->child->evaluate(data, sel->child, g ? g : data->gall);
-                if (rc != 0)
-                {
-                    return rc;
-                }
-                /* Prevent another evaluation of the child. */
-                sel->child->evaluate = NULL;
-                alloc_selection_data(sel, sel->child->cdata->gmax->isize, TRUE);
-            }
-            if (!g)
+            if (!g && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
             {
+                /* The subexpression should have been evaluated if g is NULL
+                 * (i.e., this is a method parameter or a direct value of a
+                 * selection). */
                 alloc_selection_data(sel, sel->child->cdata->gmax->isize, TRUE);
             }
-            /* TODO: This is not general enough if/when position references
-             * can be evaluated more than once (that is, if there are position
-             * methods that do not have SMETH_SINGLEVAL or SMETH_VARNUMVAL). */
-            if (sel->v.type == POS_VALUE && !(sel->flags & SEL_OUTINIT))
-            {
-                gmx_ana_pos_copy(sel->v.u.p, sel->child->child->v.u.p, TRUE);
-                sel->flags |= SEL_OUTINIT;
-            }
             rc = sel->cdata->evaluate(data, sel, g);
-            sel->child->evaluate = &analyze_static;
             if (rc != 0)
             {
                 return rc;
             }
+            if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+                && (sel->child->child->flags & SEL_ALLOCVAL))
+            {
+                _gmx_selvalue_setstore(&sel->v, sel->child->child->v.u.ptr);
+            }
             /* Store the parameter value if required */
             store_param_val(sel);
             if (!(sel->flags & SEL_DYNAMIC))
             {
-                if (sel->cdata->bStatic)
+                if (sel->cdata->flags & SEL_CDATA_STATIC)
                 {
                     make_static(sel);
                 }
             }
-            else
+            else if (bDoMinMax)
             {
-                if (sel->child->refcount <= 2 || !g)
+                if ((sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR) || !g)
                 {
-                    gmx_ana_index_copy(&gmin, sel->child->cdata->gmin, TRUE);
-                    gmx_ana_index_copy(&gmax, sel->child->cdata->gmax, TRUE);
+                    gmx_ana_index_copy(sel->cdata->gmin, sel->child->cdata->gmin, TRUE);
+                    gmx_ana_index_copy(sel->cdata->gmax, sel->child->cdata->gmax, TRUE);
                 }
                 else
                 {
-                    gmx_ana_index_reserve(&gmin, min(g->isize, sel->child->cdata->gmin->isize));
-                    gmx_ana_index_reserve(&gmax, min(g->isize, sel->child->cdata->gmax->isize));
-                    gmx_ana_index_intersection(&gmin, sel->child->cdata->gmin, g);
-                    gmx_ana_index_intersection(&gmax, sel->child->cdata->gmax, g);
+                    gmx_ana_index_reserve(sel->cdata->gmin,
+                                          min(g->isize, sel->child->cdata->gmin->isize));
+                    gmx_ana_index_reserve(sel->cdata->gmax,
+                                          min(g->isize, sel->child->cdata->gmax->isize));
+                    gmx_ana_index_intersection(sel->cdata->gmin,
+                                               sel->child->cdata->gmin, g);
+                    gmx_ana_index_intersection(sel->cdata->gmax,
+                                               sel->child->cdata->gmax, g);
                 }
             }
             break;
@@ -1681,115 +2212,24 @@ analyze_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
     }
 
     /* Update the minimal and maximal evaluation groups */
-    if (sel->cdata->bMinMaxAlloc)
-    {
-        gmx_ana_index_reserve(sel->cdata->gmin, sel->cdata->gmin->isize + gmin.isize);
-        gmx_ana_index_reserve(sel->cdata->gmax, sel->cdata->gmax->isize + gmax.isize);
-        gmx_ana_index_merge(sel->cdata->gmin, sel->cdata->gmin, &gmin);
-        gmx_ana_index_merge(sel->cdata->gmax, sel->cdata->gmax, &gmax);
-    }
-    /* Replace the result of the evaluation */
-    /* This is not necessary for subexpressions or for boolean negations
-     * because the evaluation function already has done it properly. */
-    if (sel->v.type == GROUP_VALUE && (sel->flags & SEL_DYNAMIC)
-        && sel->type != SEL_SUBEXPR
-        && !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
-    {
-        if (sel->cdata->bEvalMax)
-        {
-            gmx_ana_index_copy(sel->v.u.g, &gmax, FALSE);
-        }
-        else
-        {
-            gmx_ana_index_copy(sel->v.u.g, &gmin, FALSE);
-        }
-    }
-    gmx_ana_index_deinit(&gmin);
-    gmx_ana_index_deinit(&gmax);
-
-    /* Make sure that enough data storage has been allocated */
-    /* TODO: Constant expressions could be handled here more intelligently */
-    if (sel->type != SEL_ROOT && sel->cdata->bStaticEval)
-    {
-        alloc_selection_data(sel, sel->cdata->gmax->isize, TRUE);
-        /* Make sure that the new value pointer is stored if required */
-        store_param_val(sel);
-    }
-
-    return 0;
-}
-
-/*! \brief
- * Evaluates the static parts of \p sel and analyzes the structure.
- * 
- * \param[in]     data Evaluation data.
- * \param[in,out] sel  Selection currently being evaluated.
- * \param[in]     g   Group for which \p sel should be evaluated.
- * \returns       0 on success, a non-zero error code on error.
- *
- * This function is a simpler version of analyze_static() that is used
- * during a second evaluation round, and can thus use information calculated
- * by analyze_static().
- * It is also used as the replacement for the \c t_selelem::evaluate
- * function pointer.
- * It is used to evaluate the static parts of subexpressions that could not
- * be evaluated during the analyze_static() pass.
- *
- * \see analyze_static()
- */
-static int
-analyze_static2(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
-{
-    int rc;
-
-    rc = 0;
-    switch (sel->type)
-    {
-        case SEL_CONST:
-            rc = process_const(data, sel, g);
-            break;
-
-        case SEL_EXPRESSION:
-        case SEL_BOOLEAN:
-        case SEL_SUBEXPRREF:
-            if (sel->cdata->bStatic)
-            {
-                rc = sel->cdata->evaluate(data, sel, g);
-                if (rc == 0)
-                {
-                    make_static(sel);
-                }
-            }
-            else if (sel->type == SEL_BOOLEAN)
-            {
-                rc = evaluate_boolean_static_part(data, sel, g);
-                if (rc == 0)
-                {
-                    rc = sel->cdata->evaluate(data, sel, g);
-                }
-            }
-            break;
-
-        case SEL_ROOT:     /* Roots should not be present here */
-        case SEL_MODIFIER: /* Modifiers should not be present here */
-        case SEL_SUBEXPR:
-            rc = sel->cdata->evaluate(data, sel, g);
-            break;
-    }
-    /* Exit if there was some problem */
-    if (rc != 0)
+    if (bDoMinMax)
     {
-        return rc;
+        gmx_ana_index_squeeze(sel->cdata->gmin);
+        gmx_ana_index_squeeze(sel->cdata->gmax);
+        sfree(sel->cdata->gmin->name);
+        sfree(sel->cdata->gmax->name);
+        sel->cdata->gmin->name = NULL;
+        sel->cdata->gmax->name = NULL;
     }
 
     /* Replace the result of the evaluation */
     /* This is not necessary for subexpressions or for boolean negations
      * because the evaluation function already has done it properly. */
-    if (sel->v.type == GROUP_VALUE && !sel->cdata->bStatic
+    if (sel->v.type == GROUP_VALUE && (sel->flags & SEL_DYNAMIC)
         && sel->type != SEL_SUBEXPR
         && !(sel->type == SEL_BOOLEAN && sel->u.boolt == BOOL_NOT))
     {
-        if (sel->cdata->bEvalMax)
+        if (sel->cdata->flags & SEL_CDATA_EVALMAX)
         {
             gmx_ana_index_copy(sel->v.u.g, sel->cdata->gmax, FALSE);
         }
@@ -1804,51 +2244,38 @@ analyze_static2(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
 
 
 /********************************************************************
- * ROOT ITEM INITIALIZATION COMPILER PASS
+ * EVALUATION GROUP INITIALIZATION
  ********************************************************************/
 
 /*! \brief
- * Initializes a \ref SEL_ROOT element.
+ * Initializes the evaluation group for a \ref SEL_ROOT element.
  *
  * \param     root Root element to initialize.
- * \returns Pointer to the selection element that should replace \p root.
- *   Can be \p root itself or NULL if the selection should be removed.
+ * \param[in] gall Group of all atoms.
  *
  * Checks whether it is necessary to evaluate anything through the root
  * element, and either clears the evaluation function or initializes the
  * evaluation group.
- *
- * If the function returns NULL, the memory allocated for \p root is 
- * automatically freed.
  */
-static t_selelem *
-init_root_item(t_selelem *root)
+static void
+init_root_item(t_selelem *root, gmx_ana_index_t *gall)
 {
     t_selelem   *expr;
     char        *name;
 
-    /* Process subexpressions */
-    if (root->child->type == SEL_SUBEXPR)
+    expr = root->child;
+    /* Subexpressions with non-static evaluation group should not be
+     * evaluated by the root, and neither should be single-reference
+     * subexpressions that don't evaluate for all atoms. */
+    if (expr->type == SEL_SUBEXPR
+        && (!(root->child->cdata->flags & SEL_CDATA_STATICEVAL)
+            || ((root->child->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+                && !(root->child->cdata->flags & SEL_CDATA_FULLEVAL))))
     {
-        if (root->child->refcount == 1)
-        {
-            /* Free subexpressions that are no longer used */
-            _gmx_selelem_free(root);
-            return NULL;
-        }
-        else if (root->child->v.type == POS_VALUE)
-        {
-            /* Position values only need to be evaluated once, by the root */
-        }
-        else if (!root->child->cdata->bStaticEval)
+        root->evaluate = NULL;
+        if (root->cdata)
         {
-            /* Subexpressions with non-static evaluation group should not be
-             * evaluated by the root. */
-            root->evaluate = NULL;
-            if (root->cdata)
-            {
-                root->cdata->evaluate = NULL;
-            }
+            root->cdata->evaluate = NULL;
         }
     }
 
@@ -1856,22 +2283,50 @@ init_root_item(t_selelem *root)
     name = root->u.cgrp.name;
     if (root->evaluate)
     {
-        expr = root->child;
-        if (expr->type == SEL_SUBEXPR)
+        /* Non-atom-valued non-group expressions don't care about the group, so
+         * don't allocate any memory for it. */
+        if ((expr->flags & SEL_VARNUMVAL)
+            || ((expr->flags & SEL_SINGLEVAL) && expr->v.type != GROUP_VALUE))
         {
-            gmx_ana_index_copy(&root->u.cgrp, expr->cdata->gmax, TRUE);
+            gmx_ana_index_set(&root->u.cgrp, -1, NULL, NULL, 0);
+        }
+        else if (expr->cdata->gmax->isize == gall->isize)
+        {
+            /* Save some memory by only referring to the global group. */
+            gmx_ana_index_set(&root->u.cgrp, gall->isize, gall->index, NULL, 0);
         }
         else
         {
-            /* expr should evaluate the positions for a selection */
-            if (expr->v.u.p->g)
+            gmx_ana_index_copy(&root->u.cgrp, expr->cdata->gmax, TRUE);
+        }
+        /* For selections, store the maximum group for
+         * gmx_ana_selcollection_evaluate_fin() as the value of the root
+         * element (unused otherwise). */
+        if (expr->type != SEL_SUBEXPR && expr->v.u.p->g)
+        {
+            t_selelem *child = expr;
+
+            /* TODO: This code is copied from parsetree.c; it would be better
+             * to have this hardcoded only in one place. */
+            while (child->type == SEL_MODIFIER)
+            {
+                child = child->child;
+                if (child->type == SEL_SUBEXPRREF)
+                {
+                    child = child->child->child;
+                }
+            }
+            if (child->type == SEL_SUBEXPRREF)
+            {
+                child = child->child->child;
+            }
+            if (child->child->flags & SEL_DYNAMIC)
             {
                 _gmx_selelem_set_vtype(root, GROUP_VALUE);
                 root->flags  |= (SEL_ALLOCVAL | SEL_ALLOCDATA);
                 _gmx_selvalue_reserve(&root->v, 1);
                 gmx_ana_index_copy(root->v.u.g, expr->v.u.p->g, TRUE);
             }
-            gmx_ana_index_set(&root->u.cgrp, -1, NULL, NULL, 0);
         }
     }
     else
@@ -1879,53 +2334,11 @@ init_root_item(t_selelem *root)
         gmx_ana_index_clear(&root->u.cgrp);
     }
     root->u.cgrp.name = name;
-    return root;
-}
-
-/*! \brief
- * Initializes the evaluation groups for \ref SEL_ROOT items.
- *
- * \param   root First selection in the whole selection chain.
- * \returns The new first element for the chain.
- *
- * The function also removes static subexpressions that are no longer used.
- */
-static t_selelem *
-process_roots(t_selelem *root)
-{
-    t_selelem *item;
-    t_selelem *next;
-
-    do
-    {
-        next = root->next;
-        root = init_root_item(root);
-        if (!root)
-        {
-            root = next;
-        }
-    }
-    while (root == next);
-    item = root;
-    while (item && item->next)
-    {
-        next = item->next->next;
-        item->next = init_root_item(item->next);
-        if (!item->next)
-        {
-            item->next = next;
-        }
-        else
-        {
-            item = item->next;
-        }
-    }
-    return root;
 }
 
 
 /********************************************************************
- * SUBEXPRESSION OPTIMIZATION PASS
+ * FINAL SUBEXPRESSION OPTIMIZATION
  ********************************************************************/
 
 /*! \brief
@@ -1937,51 +2350,79 @@ process_roots(t_selelem *root)
  * referenced once.
  */
 static void
-optimize_item_subexpressions(t_selelem *sel)
+postprocess_item_subexpressions(t_selelem *sel)
 {
-    t_selelem *child;
-
-    /* Call recursively for all children unless the children have already been processed */
+    /* Process children. */
     if (sel->type != SEL_SUBEXPRREF)
     {
+        t_selelem *child;
+
         child = sel->child;
         while (child)
         {
-            optimize_item_subexpressions(child);
+            postprocess_item_subexpressions(child);
             child = child->next;
         }
     }
 
-    /* Optimize the evaluation of subexpressions that are used only once */
-    if (sel->type == SEL_SUBEXPRREF && sel->cdata->bStaticEval && sel->child->refcount == 2)
+    /* Replace the evaluation function of statically evaluated subexpressions
+     * for which the static group was not known in advance. */
+    if (sel->type == SEL_SUBEXPR && sel->refcount > 2
+        && (sel->cdata->flags & SEL_CDATA_STATICEVAL)
+        && !(sel->cdata->flags & SEL_CDATA_FULLEVAL))
     {
-        /* The evaluation functions are not always needed, and they do some
-         * extra work, but it should be neglible compared to other factors
-         * in the evaluation, so set them always for simplicity. */
-        sel->evaluate = &_gmx_sel_evaluate_subexprref_pass;
+        char *name;
+
+        /* We need to free memory allocated for the group, because it is no
+         * longer needed (and would be lost on next call to the evaluation
+         * function). But we need to preserve the name. */
+        name = sel->u.cgrp.name;
+        gmx_ana_index_deinit(&sel->u.cgrp);
+        sel->u.cgrp.name = name;
+
+        sel->evaluate = &_gmx_sel_evaluate_subexpr_staticeval;
         if (sel->cdata)
         {
             sel->cdata->evaluate = sel->evaluate;
         }
-        /* Replace the value of the child */
         _gmx_selelem_free_values(sel->child);
-        sel->child->flags            &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+        sel->child->mempool = NULL;
         _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
-        sel->child->evaluate = &_gmx_sel_evaluate_subexpr_pass;
-        if (sel->child->cdata)
+        sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+    }
+
+    /* Adjust memory allocation flags for subexpressions that are used only
+     * once.  This is not strictly necessary, but we do it to have the memory
+     * managed consistently for all types of subexpressions. */
+    if (sel->type == SEL_SUBEXPRREF
+        && (sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR))
+    {
+        if (sel->child->child->flags & SEL_ALLOCVAL)
         {
-            sel->child->cdata->evaluate = sel->child->evaluate;
+            sel->flags |= SEL_ALLOCVAL;
+            sel->flags |= (sel->child->child->flags & SEL_ALLOCDATA);
+            sel->v.nalloc = sel->child->child->v.nalloc;
+            sel->child->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+            sel->child->child->v.nalloc = -1;
         }
-        /* Replace the value of the grandchild */
-        _gmx_selelem_free_values(sel->child->child);
-        sel->child->child->flags     &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
-        _gmx_selvalue_setstore(&sel->child->child->v, sel->v.u.ptr);
+    }
+
+    /* Do the same for subexpressions that are evaluated at once for all atoms. */
+    if (sel->type == SEL_SUBEXPR
+        && !(sel->cdata->flags & SEL_CDATA_SIMPLESUBEXPR)
+        && (sel->cdata->flags & SEL_CDATA_FULLEVAL))
+    {
+        sel->flags |= SEL_ALLOCVAL;
+        sel->flags |= (sel->child->flags & SEL_ALLOCDATA);
+        sel->v.nalloc = sel->child->v.nalloc;
+        sel->child->flags &= ~(SEL_ALLOCVAL | SEL_ALLOCDATA);
+        sel->child->v.nalloc = -1;
     }
 }
 
 
 /********************************************************************
- * COM CALCULATION COMPILER PASS
+ * COM CALCULATION INITIALIZATION
  ********************************************************************/
 
 /*! \brief
@@ -2018,7 +2459,7 @@ init_item_comg(t_selelem *sel, gmx_ana_poscalc_coll_t *pcc,
             /* Create a default calculation if one does not yet exist */
             int cflags;
             cflags = 0;
-            if (!sel->cdata->bStaticEval)
+            if (!(sel->cdata->flags & SEL_CDATA_STATICEVAL))
             {
                 cflags |= POS_DYNAMIC;
             }
@@ -2060,7 +2501,7 @@ init_item_comg(t_selelem *sel, gmx_ana_poscalc_coll_t *pcc,
 
 
 /********************************************************************
- * FREE COMPILER DATA PASS
+ * COMPILER DATA FREEING
  ********************************************************************/
 
 /*! \brief
@@ -2092,23 +2533,21 @@ free_item_compilerdata(t_selelem *sel)
 
 
 /********************************************************************
- * INFORMATION UPDATE
+ * MASS AND CHARGE CALCULATION
  ********************************************************************/
 
 /*! \brief
- * Updates the information about the selection.
+ * Initializes total masses and charges for selections.
  *
  * \param[in]     top   Topology information.
  * \param[in]     ngrps Number of elements in the \p sel array.
  * \param[in,out] sel   Array of selections to update.
  * \param[in]     bMaskOnly TRUE if the positions will always be calculated
  *   for all atoms, i.e., the masses/charges do not change.
- *
- * Initializes total masses and charges.
  */
 static void
-update_info(t_topology *top, int ngrps, gmx_ana_selection_t *sel[],
-            bool bMaskOnly)
+calculate_mass_charge(t_topology *top, int ngrps, gmx_ana_selection_t *sel[],
+                      bool bMaskOnly)
 {
     int   g, b, i;
 
@@ -2157,6 +2596,17 @@ update_info(t_topology *top, int ngrps, gmx_ana_selection_t *sel[],
  * MAIN COMPILATION FUNCTION
  ********************************************************************/
 
+/*!
+ * \param[in,out] sc     Selection collection to debug.
+ * \param[in]     bDebug If TRUE, later call to gmx_ana_selcollection_compile()
+ *     will print out intermediate selection trees.
+ */
+void
+gmx_ana_selcollection_set_compile_debug(gmx_ana_selcollection_t *sc, bool bDebug)
+{
+    sc->bDebugCompile = bDebug;
+}
+
 /*!
  * \param[in,out] sc Selection collection to be compiled.
  * \returns       0 on successful compilation, a non-zero error code on error.
@@ -2179,7 +2629,13 @@ gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc)
     int          flags;
     int          rc;
 
-    _gmx_sel_evaluate_init(&evaldata, &sc->gall, sc->top, NULL, NULL);
+    rc = _gmx_sel_mempool_create(&sc->mempool);
+    if (rc != 0)
+    {
+        return rc;
+    }
+    _gmx_sel_evaluate_init(&evaldata, sc->mempool, &sc->gall,
+                           sc->top, NULL, NULL);
 
     /* Clear the symbol table because it is not possible to parse anything
      * after compilation, and variable references in the symbol table can
@@ -2187,8 +2643,10 @@ gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc)
      */
     _gmx_selcollection_clear_symtab(sc);
 
+    /* Remove any unused variables. */
+    sc->root = remove_unused_subexpressions(sc->root);
     /* Extract subexpressions into separate roots */
-    sc->root = extract_subexpressions(sc->root, &sc->gall);
+    sc->root = extract_subexpressions(sc->root);
 
     /* Initialize the evaluation callbacks and process the tree structure
      * to conform to the expectations of the callback functions. */
@@ -2196,29 +2654,58 @@ gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc)
     item = sc->root;
     while (item)
     {
-        /* Process boolean expressions */
+        /* Process boolean and arithmetic expressions. */
         optimize_boolean_expressions(item);
         reorder_boolean_static_children(item);
-        /* Initialize evaluation */
-        if (!init_item_evaluation(item))
+        if (!optimize_arithmetic_expressions(item))
         {
             /* FIXME: Clean up the collection */
             return -1;
         }
+        /* Initialize evaluation function. */
+        if (!init_item_evalfunc(item))
+        {
+            /* FIXME: Clean up the collection */
+            return -1;
+        }
+        setup_memory_pooling(item, sc->mempool);
         /* Initialize the compiler data */
         init_item_compilerdata(item);
         init_item_staticeval(item);
         item = item->next;
     }
+    /* Initialize subexpression flags and evaluation output.
+     * Requires compiler flags for the full tree. */
+    item = sc->root;
+    while (item)
+    {
+        init_item_subexpr_flags(item);
+        init_item_evaloutput(item);
+        item = item->next;
+    }
+    /* Initialize minimum/maximum index groups.
+     * Requires evaluation output for the full tree. */
+    item = sc->root;
+    while (item)
+    {
+        init_item_minmax_groups(item);
+        item = item->next;
+    }
     /* Initialize the evaluation index groups */
     initialize_evalgrps(sc);
 
+    if (sc->bDebugCompile)
+    {
+        fprintf(stderr, "\nTree after initial compiler processing:\n");
+        gmx_ana_selcollection_print_tree(stderr, sc, FALSE);
+    }
+
     /* Evaluate all static parts of the selection and analyze the tree
      * to allocate enough memory to store the value of each dynamic subtree. */
     item = sc->root;
     while (item)
     {
-        if (item->child->type == SEL_SUBEXPR && item->child->refcount > 2)
+        if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
         {
             mark_subexpr_dynamic(item->child, TRUE);
         }
@@ -2232,25 +2719,42 @@ gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc)
         item = item->next;
     }
 
+    /* At this point, static subexpressions no longer have references to them,
+     * so they can be removed. */
+    sc->root = remove_unused_subexpressions(sc->root);
+
+    if (sc->bDebugCompile)
+    {
+        fprintf(stderr, "\nTree after first analysis pass:\n");
+        gmx_ana_selcollection_print_tree(stderr, sc, FALSE);
+    }
+
     /* Do a second pass to evaluate static parts of common subexpressions */
-    /* Note that the refcount check skips constant subexpressions completely
-     * since they were already evaluated by analyze_static(). */
     item = sc->root;
     while (item)
     {
-        if (item->child->type == SEL_SUBEXPR && item->child->refcount > 2)
+        if (item->child->cdata->flags & SEL_CDATA_COMMONSUBEXPR)
         {
+            bool bMinMax = item->child->cdata->flags & SEL_CDATA_MINMAXALLOC;
+
             mark_subexpr_dynamic(item->child, FALSE);
             item->child->u.cgrp.isize = 0;
-            /* We won't clear item->child->child->v.u.g here, because it may
+            /* We won't clear item->child->v.u.g here, because it may
              * be static, and hence actually point to item->child->cdata->gmax,
              * which is used below. We could also check whether this is the
              * case and only clear the group otherwise, but because the value
              * is actually overwritten immediately in the evaluate call, we
              * won't, because similar problems may arise if gmax handling ever
-             * changes and the check were not updated. */
-            set_evaluation_function(item, &analyze_static2);
+             * changes and the check were not updated.
+             * For the same reason, we clear the min/max flag so that the
+             * evaluation group doesn't get messed up. */
+            set_evaluation_function(item, &analyze_static);
+            item->child->cdata->flags &= ~SEL_CDATA_MINMAXALLOC;
             rc = item->evaluate(&evaldata, item->child, item->child->cdata->gmax);
+            if (bMinMax)
+            {
+                item->child->cdata->flags |= SEL_CDATA_MINMAXALLOC;
+            }
             if (rc != 0)
             {
                 /* FIXME: Clean up the collection */
@@ -2260,11 +2764,19 @@ gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc)
         item = item->next;
     }
 
-    /* Initialize evaluation groups and remove unused subexpressions. */
-    sc->root = process_roots(sc->root);
+    /* We need a yet another pass of subexpression removal to remove static
+     * subexpressions referred to by common dynamic subexpressions. */
+    sc->root = remove_unused_subexpressions(sc->root);
 
-    /* Initialize position calculations for methods, perform some final
-     * optimization and free the memory allocated for the compilation. */
+    if (sc->bDebugCompile)
+    {
+        fprintf(stderr, "\nTree after second analysis pass:\n");
+        gmx_ana_selcollection_print_tree(stderr, sc, FALSE);
+    }
+
+    /* Initialize evaluation groups, position calculations for methods, perform
+     * some final optimization, and free the memory allocated for the
+     * compilation. */
     /* By default, use whole residues/molecules. */
     flags = POS_COMPLWHOLE;
     rc = gmx_ana_poscalc_type_from_enum(sc->rpost, &post, &flags);
@@ -2277,7 +2789,8 @@ gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc)
     item = sc->root;
     while (item)
     {
-        optimize_item_subexpressions(item);
+        init_root_item(item, &sc->gall);
+        postprocess_item_subexpressions(item);
         rc = init_item_comg(item, sc->pcc, post, flags);
         if (rc != 0)
         {
@@ -2288,8 +2801,15 @@ gmx_ana_selcollection_compile(gmx_ana_selcollection_t *sc)
         item = item->next;
     }
 
-    /* Finish up by updating some information */
-    update_info(sc->top, sc->nr, sc->sel, sc->bMaskOnly);
+    /* Allocate memory for the evaluation memory pool. */
+    rc = _gmx_sel_mempool_reserve(sc->mempool, 0);
+    if (rc != 0)
+    {
+        return rc;
+    }
+
+    /* Finish up by calculating total masses and charges. */
+    calculate_mass_charge(sc->top, sc->nr, sc->sel, sc->bMaskOnly);
 
     return 0;
 }
index e447d42fd0fe4b7e1a82cfa6b03f02bce89bac80..06a4d8b7062b13aa2af56492cedaf1714a092530 100644 (file)
 #include <selmethod.h>
 
 #include "evaluate.h"
+#include "mempool.h"
 #include "selcollection.h"
 #include "selelem.h"
 
+/*!
+ * \param[in] fp       File handle to receive the output.
+ * \param[in] evalfunc Function pointer to print.
+ */
+void
+_gmx_sel_print_evalfunc_name(FILE *fp, sel_evalfunc evalfunc)
+{
+    if (!evalfunc)
+        fprintf(fp, "none");
+    else if (evalfunc == &_gmx_sel_evaluate_root)
+        fprintf(fp, "root");
+    else if (evalfunc == &_gmx_sel_evaluate_static)
+        fprintf(fp, "static");
+    else if (evalfunc == &_gmx_sel_evaluate_subexpr_simple)
+        fprintf(fp, "subexpr_simple");
+    else if (evalfunc == &_gmx_sel_evaluate_subexpr_staticeval)
+        fprintf(fp, "subexpr_staticeval");
+    else if (evalfunc == &_gmx_sel_evaluate_subexpr)
+        fprintf(fp, "subexpr");
+    else if (evalfunc == &_gmx_sel_evaluate_subexprref_simple)
+        fprintf(fp, "ref_simple");
+    else if (evalfunc == &_gmx_sel_evaluate_subexprref)
+        fprintf(fp, "ref");
+    else if (evalfunc == &_gmx_sel_evaluate_method)
+        fprintf(fp, "method");
+    else if (evalfunc == &_gmx_sel_evaluate_modifier)
+        fprintf(fp, "mod");
+    else if (evalfunc == &_gmx_sel_evaluate_not)
+        fprintf(fp, "not");
+    else if (evalfunc == &_gmx_sel_evaluate_and)
+        fprintf(fp, "and");
+    else if (evalfunc == &_gmx_sel_evaluate_or)
+        fprintf(fp, "or");
+    else if (evalfunc == &_gmx_sel_evaluate_arithmetic)
+        fprintf(fp, "arithmetic");
+    else
+        fprintf(fp, "%p", (void*)(evalfunc));
+}
+
 /*!
  * \param[out] data Evaluation data structure to initialize.
+ * \param[in]  mp   Memory pool for intermediate evaluation values.
  * \param[in]  gall Index group with all the atoms.
  * \param[in]  top  Topology structure for evaluation.
  * \param[in]  fr   New frame for evaluation.
  * \param[in]  pbc  New PBC information for evaluation.
  */
 void
-_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data, gmx_ana_index_t *gall,
+_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data,
+                       gmx_sel_mempool_t *mp, gmx_ana_index_t *gall,
                        t_topology *top, t_trxframe *fr, t_pbc *pbc)
 {
+    data->mp   = mp;
     data->gall = gall;
     data->top  = top;
     data->fr   = fr;
@@ -133,7 +176,7 @@ gmx_ana_selcollection_evaluate(gmx_ana_selcollection_t *sc,
     int                 g, i;
     int                 rc;
 
-    _gmx_sel_evaluate_init(&data, &sc->gall, sc->top, fr, pbc);
+    _gmx_sel_evaluate_init(&data, sc->mempool, &sc->gall, sc->top, fr, pbc);
     init_frame_eval(sc->root);
     sel = sc->root;
     while (sel)
@@ -150,7 +193,7 @@ gmx_ana_selcollection_evaluate(gmx_ana_selcollection_t *sc,
              * _gmx_sel_evaluate_subexpr(). */
             if (sel->child->v.type == GROUP_VALUE)
             {
-                sel->child->child->v.u.g->isize = 0;
+                sel->child->v.u.g->isize = 0;
             }
         }
         if (sel->evaluate)
@@ -199,7 +242,7 @@ gmx_ana_selcollection_evaluate_fin(gmx_ana_selcollection_t *sc, int nframes)
     for (g = 0; g < sc->nr; ++g)
     {
         sel = sc->sel[g]->selelem;
-        if (sc->sel[g]->g)
+        if (sc->sel[g]->bDynamic)
         {
             gmx_ana_index_copy(sc->sel[g]->g, sel->v.u.g, FALSE);
             sc->sel[g]->g->name = NULL;
@@ -215,6 +258,37 @@ gmx_ana_selcollection_evaluate_fin(gmx_ana_selcollection_t *sc, int nframes)
     return 0;
 }
 
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel  Selection element being evaluated.
+ * \param[in] g    Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * Evaluates each child of \p sel in \p g.
+ */
+int
+_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data, t_selelem *sel,
+                           gmx_ana_index_t *g)
+{
+    t_selelem  *child;
+    int         rc;
+
+    child = sel->child;
+    while (child)
+    {
+        if (child->evaluate)
+        {
+            rc = child->evaluate(data, child, g);
+            if (rc != 0)
+            {
+                return rc;
+            }
+        }
+        child = child->next;
+    }
+    return 0;
+}
+
 /*!
  * \param[in] data Data for the current frame.
  * \param[in] sel Selection element being evaluated.
@@ -276,15 +350,15 @@ _gmx_sel_evaluate_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index
  * \returns   0 on success, a non-zero error code on error.
  *
  * Evaluates the child element (there should be exactly one) in \p g.
- * The number of values is copied from the child to \p sel->v.nr, but
- * otherwise the value of \p sel is not touched.
+ * The compiler has taken care that the child actually stores the evaluated
+ * value in the value pointer of this element.
  *
  * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPR
  * elements that are used only once, and hence do not need full subexpression
  * handling.
  */
 int
-_gmx_sel_evaluate_subexpr_pass(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
 {
     int        rc;
 
@@ -300,6 +374,40 @@ _gmx_sel_evaluate_subexpr_pass(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana
     return 0;
 }
 
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel  Selection element being evaluated.
+ * \param[in] g    Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ *
+ * If this is the first call for this frame, evaluates the child element
+ * there should be exactly one in \p g.
+ * The compiler has taken care that the child actually stores the evaluated
+ * value in the value pointer of this element.
+ * Assumes that \p g is persistent for the duration of the whole evaluation.
+ *
+ * This function is used as \c t_selelem::evaluate for \ref SEL_SUBEXPR
+ * elements that have a static evaluation group, and hence do not need full
+ * subexpression handling.
+ */
+int
+_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+{
+    if (sel->u.cgrp.isize == 0)
+    {
+        int  rc;
+
+        rc = sel->child->evaluate(data, sel->child, g);
+        if (rc != 0)
+        {
+            return rc;
+        }
+        sel->v.nr = sel->child->v.nr;
+        gmx_ana_index_set(&sel->u.cgrp, g->isize, g->index, sel->u.cgrp.name, 0);
+    }
+    return 0;
+}
+
 /*!
  * \param[in]  data  Data for the current frame.
  * \param[in]  sel   Selection element being evaluated.
@@ -316,6 +424,9 @@ _gmx_sel_evaluate_subexpr_pass(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana
  * The call to gmx_ana_index_difference() can take quite a lot of unnecessary
  * time if the subexpression is evaluated either several times for the same
  * group or for completely distinct groups.
+ * However, in the majority of cases, these situations occur when
+ * _gmx_sel_evaluate_subexpr_staticeval() can be used, so this should not be a
+ * major problem.
  */
 int
 _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
@@ -326,15 +437,14 @@ _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_inde
     if (sel->u.cgrp.isize == 0)
     {
         char *name;
-        /* We need to check for the presence because the compiler may clear
-         * it temporarily. */
-        if (sel->child->evaluate)
+        void *old_ptr    = sel->child->v.u.ptr;
+        int   old_nalloc = sel->child->v.nalloc;
+        _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
+        rc = sel->child->evaluate(data, sel->child, g);
+        _gmx_selvalue_setstore_alloc(&sel->child->v, old_ptr, old_nalloc);
+        if (rc != 0)
         {
-            rc = sel->child->evaluate(data, sel->child, g);
-            if (rc != 0)
-            {
-                return rc;
-            }
+            return rc;
         }
         /* We need to keep the name for the cgrp across the copy to avoid
          * problems if g has a name set. */
@@ -345,33 +455,24 @@ _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_inde
     }
     else
     {
-        if (sel->v.type == GROUP_VALUE)
+        /* We allocate some extra memory here to avoid some computation. */
+        rc = _gmx_sel_mempool_alloc_group(data->mp, &gmiss, g->isize);
+        if (rc != 0)
         {
-            gmx_ana_index_set(&gmiss, 0, sel->child->v.u.g->index + sel->child->v.u.g->isize, NULL, 0);
+            return rc;
         }
-        else
+        gmx_ana_index_difference(&gmiss, g, &sel->u.cgrp);
+        if (gmiss.isize == 0)
         {
-            gmx_ana_index_set(&gmiss, 0, sel->u.cgrp.index + sel->u.cgrp.isize, NULL, 0);
+            _gmx_sel_mempool_free_group(data->mp, &gmiss);
         }
-        gmx_ana_index_difference(&gmiss, g, &sel->u.cgrp);
     }
     if (gmiss.isize > 0)
     {
-        /* We use the value of sel to store the old value of the child before
-         * evaluating the missing values. */
-        if (sel->v.type == GROUP_VALUE)
-        {
-            atom_id *tmp             = sel->child->v.u.g->index;
-            sel->child->v.u.g->index = sel->v.u.g->index;
-            sel->v.u.g->index        = tmp;
-            sel->v.u.g->isize        = sel->child->v.u.g->isize;
-            sel->child->v.u.g->isize = 0;
-        }
-        else
+        rc = _gmx_selelem_mempool_reserve(sel->child, gmiss.isize);
+        if (rc != 0)
         {
-            void *tmp           = sel->child->v.u.ptr;
-            sel->child->v.u.ptr = sel->v.u.ptr;
-            sel->v.u.ptr        = tmp;
+            return rc;
         }
         /* Evaluate the missing values for the child */
         rc = sel->child->evaluate(data, sel->child, &gmiss);
@@ -382,8 +483,7 @@ _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_inde
         /* Merge the missing values to the existing ones. */
         if (sel->v.type == GROUP_VALUE)
         {
-            gmx_ana_index_merge(sel->child->v.u.g, sel->child->v.u.g, sel->v.u.g);
-            gmx_ana_index_merge(&sel->u.cgrp, &sel->u.cgrp, &gmiss);
+            gmx_ana_index_merge(sel->v.u.g, sel->child->v.u.g, sel->v.u.g);
         }
         else
         {
@@ -400,11 +500,11 @@ _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_inde
                     {
                         if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
                         {
-                            sel->child->v.u.i[k] = sel->child->v.u.i[j--];
+                            sel->v.u.i[k] = sel->v.u.i[j--];
                         }
                         else
                         {
-                            sel->child->v.u.i[k] = sel->v.u.i[i--];
+                            sel->v.u.i[k] = sel->child->v.u.i[i--];
                         }
                     }
                     break;
@@ -414,11 +514,11 @@ _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_inde
                     {
                         if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
                         {
-                            sel->child->v.u.r[k] = sel->child->v.u.r[j--];
+                            sel->v.u.r[k] = sel->v.u.r[j--];
                         }
                         else
                         {
-                            sel->child->v.u.r[k] = sel->v.u.r[i--];
+                            sel->v.u.r[k] = sel->child->v.u.r[i--];
                         }
                     }
                     break;
@@ -428,11 +528,11 @@ _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_inde
                     {
                         if (i < 0 || (j >= 0 && sel->u.cgrp.index[i] < gmiss.index[j]))
                         {
-                            sel->child->v.u.s[k] = sel->child->v.u.s[j--];
+                            sel->v.u.s[k] = sel->v.u.s[j--];
                         }
                         else
                         {
-                            sel->child->v.u.s[k] = sel->v.u.s[i--];
+                            sel->v.u.s[k] = sel->child->v.u.s[i--];
                         }
                     }
                     break;
@@ -447,10 +547,10 @@ _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_inde
                     gmx_bug("internal error");
                     return -1;
             }
-            /* TODO: With some additional storage, we could do a merge here */
-            sel->u.cgrp.isize += gmiss.isize;
-            gmx_ana_index_sort(&sel->u.cgrp);
         }
+        gmx_ana_index_merge(&sel->u.cgrp, &sel->u.cgrp, &gmiss);
+        _gmx_selelem_mempool_release(sel->child);
+        _gmx_sel_mempool_free_group(data->mp, &gmiss);
     }
     return 0;
 }
@@ -461,15 +561,30 @@ _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_inde
  * \param[in] g   Group for which \p sel should be evaluated.
  * \returns   0 for success.
  *
+ * Sets the value pointers of the child and its child to point to the same
+ * memory as the value pointer of this element to avoid copying, and then
+ * evaluates evaluates the child.
+ *
  * This function is used as \c t_selelem:evaluate for \ref SEL_SUBEXPRREF
- * elements for which the actual value is evaluated directly by the
- * subexpression, but for which the number of values needs to be passed
- * forward.
+ * elements for which the \ref SEL_SUBEXPR does not have other references.
  */
 int
-_gmx_sel_evaluate_subexprref_pass(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
+_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g)
 {
-    sel->v.nr = sel->child->child->v.nr;
+    if (g)
+    {
+        int rc;
+
+        _gmx_selvalue_setstore(&sel->child->v, sel->v.u.ptr);
+        _gmx_selvalue_setstore_alloc(&sel->child->child->v, sel->v.u.ptr,
+                                     sel->child->child->v.nalloc);
+        rc = sel->child->evaluate(data, sel->child, g);
+        if (rc != 0)
+        {
+            return rc;
+        }
+    }
+    sel->v.nr = sel->child->v.nr;
     if (sel->u.param)
     {
         sel->u.param->val.nr = sel->v.nr;
@@ -503,9 +618,7 @@ _gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_i
     t_selelem *expr;
     int        i, j;
 
-    /* We need to check for the presence because the compiler may clear
-     * it temporarily. */
-    if (g && sel->child->evaluate)
+    if (g)
     {
         int rc;
 
@@ -515,7 +628,7 @@ _gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_i
             return rc;
         }
     }
-    expr = sel->child->child;
+    expr = sel->child;
     switch (sel->v.type)
     {
         case INT_VALUE:
@@ -783,12 +896,17 @@ _gmx_sel_evaluate_not(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t
 {
     int rc;
 
-    rc = sel->child->evaluate(data, sel->child, g);
+    rc = _gmx_selelem_mempool_reserve(sel->child, g->isize);
+    if (rc == 0)
+    {
+        rc = sel->child->evaluate(data, sel->child, g);
+    }
     if (rc != 0)
     {
         return rc;
     }
     gmx_ana_index_difference(sel->v.u.g, g, sel->child->v.u.g);
+    _gmx_selelem_mempool_release(sel->child);
     return 0;
 }
 
@@ -829,21 +947,31 @@ _gmx_sel_evaluate_and(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t
     {
         child = child->next;
     }
-    rc = child->evaluate(data, child, g);
+    rc = _gmx_selelem_mempool_reserve(child, g->isize);
+    if (rc == 0)
+    {
+        rc = child->evaluate(data, child, g);
+    }
     if (rc != 0)
     {
         return rc;
     }
     gmx_ana_index_copy(sel->v.u.g, child->v.u.g, FALSE);
+    _gmx_selelem_mempool_release(child);
     child = child->next;
     while (child && sel->v.u.g->isize > 0)
     {
-        rc = child->evaluate(data, child, sel->v.u.g);
+        rc = _gmx_selelem_mempool_reserve(child, sel->v.u.g->isize);
+        if (rc == 0)
+        {
+            rc = child->evaluate(data, child, sel->v.u.g);
+        }
         if (rc != 0)
         {
             return rc;
         }
         gmx_ana_index_intersection(sel->v.u.g, sel->v.u.g, child->v.u.g);
+        _gmx_selelem_mempool_release(child);
         child = child->next;
     }
     return 0;
@@ -885,23 +1013,37 @@ _gmx_sel_evaluate_or(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *
     child = sel->child;
     if (child->evaluate)
     {
-        rc = child->evaluate(data, child, g);
+        rc = _gmx_selelem_mempool_reserve(child, g->isize);
+        if (rc == 0)
+        {
+            rc = child->evaluate(data, child, g);
+        }
         if (rc != 0)
         {
             return rc;
         }
+        gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
+        _gmx_selelem_mempool_release(child);
+    }
+    else
+    {
+        gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
     }
-    gmx_ana_index_partition(sel->v.u.g, &tmp, g, child->v.u.g);
     child = child->next;
     while (child && tmp.isize > 0)
     {
         tmp.name = NULL;
-        rc = child->evaluate(data, child, &tmp);
+        rc = _gmx_selelem_mempool_reserve(child, tmp.isize);
+        if (rc == 0)
+        {
+            rc = child->evaluate(data, child, &tmp);
+        }
         if (rc != 0)
         {
             return rc;
         }
         gmx_ana_index_partition(&tmp, &tmp2, &tmp, child->v.u.g);
+        _gmx_selelem_mempool_release(child);
         sel->v.u.g->isize += tmp.isize;
         tmp.isize = tmp2.isize;
         tmp.index = tmp2.index;
@@ -910,3 +1052,82 @@ _gmx_sel_evaluate_or(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *
     gmx_ana_index_sort(sel->v.u.g);
     return 0;
 }
+
+
+/********************************************************************
+ * ARITHMETIC EVALUATION
+ ********************************************************************/
+
+/*!
+ * \param[in] data Data for the current frame.
+ * \param[in] sel  Selection element being evaluated.
+ * \param[in] g    Group for which \p sel should be evaluated.
+ * \returns   0 on success, a non-zero error code on error.
+ */
+int
+_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data, t_selelem *sel,
+                             gmx_ana_index_t *g)
+{
+    t_selelem  *left, *right;
+    int         n, i, i1, i2;
+    real        lval, rval=0., val=0.;
+    int         rc;
+
+    left  = sel->child;
+    right = left->next;
+
+    if (left->mempool)
+    {
+        _gmx_selvalue_setstore(&left->v, sel->v.u.ptr);
+        rc = _gmx_selelem_mempool_reserve(right, g->isize);
+        if (rc != 0)
+        {
+            return rc;
+        }
+    }
+    else if (right->mempool)
+    {
+        _gmx_selvalue_setstore(&right->v, sel->v.u.ptr);
+    }
+    rc = _gmx_sel_evaluate_children(data, sel, g);
+
+    n = (sel->flags & SEL_SINGLEVAL) ? 1 : g->isize;
+    sel->v.nr = n;
+    for (i = i1 = i2 = 0; i < n; ++i)
+    {
+        lval = left->v.u.r[i1];
+        if (sel->u.arith.type != ARITH_NEG)
+        {
+            rval = right->v.u.r[i2];
+        }
+        switch (sel->u.arith.type)
+        {
+            case ARITH_PLUS:    val = lval + rval;     break;
+            case ARITH_MINUS:   val = lval - rval;     break;
+            case ARITH_NEG:     val = -lval;           break;
+            case ARITH_MULT:    val = lval * rval;     break;
+            case ARITH_DIV:     val = lval / rval;     break;
+            case ARITH_EXP:     val = pow(lval, rval); break;
+        }
+        sel->v.u.r[i] = val;
+        if (!(left->flags & SEL_SINGLEVAL))
+        {
+            ++i1;
+        }
+        if (sel->u.arith.type != ARITH_NEG && !(right->flags & SEL_SINGLEVAL))
+        {
+            ++i2;
+        }
+    }
+
+    if (left->mempool)
+    {
+        _gmx_selvalue_setstore(&left->v, NULL);
+        _gmx_selelem_mempool_release(right);
+    }
+    else if (right->mempool)
+    {
+        _gmx_selvalue_setstore(&right->v, NULL);
+    }
+    return 0;
+}
index 9eb4a6e9de06f21ad78ab1b7df145606e68c79cb..99c15c71698cc8caacfb5ba1b5ea61d3edc01179 100644 (file)
 
 #include "selelem.h"
 
+struct gmx_sel_mempool_t;
+
 /*! \internal \brief
  * Data structure for passing information required during evaluation.
  */
 typedef struct gmx_sel_evaluate_t
 {
+    /** Memory pool for intermediate values. */
+    struct gmx_sel_mempool_t *mp;
     /** Index group that contains all the atoms. */
     gmx_ana_index_t         *gall;
     /** Topology information. */
@@ -68,8 +72,12 @@ typedef struct gmx_sel_evaluate_t
 /*@{*/
 /** Initializes an evaluation data structure. */
 void
-_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data, gmx_ana_index_t *gall,
+_gmx_sel_evaluate_init(gmx_sel_evaluate_t *data,
+                       struct gmx_sel_mempool_t *mp, gmx_ana_index_t *gall,
                        t_topology *top, t_trxframe *fr, t_pbc *pbc);
+/** Evaluates the children of a general selection element. */
+int
+_gmx_sel_evaluate_children(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
 /** Evaluates the children of a \ref SEL_EXPRESSION element. */
 int
 _gmx_sel_evaluate_method_params(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
@@ -84,20 +92,26 @@ _gmx_sel_evaluate_root(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t
 /** Evaluates a static group selection element. */
 int
 _gmx_sel_evaluate_static(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates an arithmetic expression element. */
+int
+_gmx_sel_evaluate_arithmetic(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
 /*@}*/
 
 /*! \name Subexpression evaluation functions
  */
 /*@{*/
-/** Evaluates a subexpression, only handling the number of values. */
+/** Evaluates a subexpression when there is only one reference. */
+int
+_gmx_sel_evaluate_subexpr_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+/** Evaluates a subexpression when the evaluation group is static. */
 int
-_gmx_sel_evaluate_subexpr_pass(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_subexpr_staticeval(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
 /** Evaluates a subexpression. */
 int
 _gmx_sel_evaluate_subexpr(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
-/** Evaluates a subexpression reference, only handling the number of values. */
+/** Evaluates a subexpression reference when there are no other references. */
 int
-_gmx_sel_evaluate_subexprref_pass(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
+_gmx_sel_evaluate_subexprref_simple(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
 /** Evaluates a subexpression reference. */
 int
 _gmx_sel_evaluate_subexprref(gmx_sel_evaluate_t *data, t_selelem *sel, gmx_ana_index_t *g);
index 46ea17ecc36acefea76371758001d970c5a6f782..f28f2aaf5b20e759cd86a577b441d0262d329a19 100644 (file)
@@ -37,7 +37,9 @@
 #ifndef SELECTION_KEYWORDS_H
 #define SELECTION_KEYWORDS_H
 
+struct gmx_ana_selmethod_t;
 struct t_selelem;
+struct t_selexpr_param;
 
 /** Selection method data for comparison expression evaluation. */
 extern struct gmx_ana_selmethod_t sm_compare;
@@ -62,4 +64,15 @@ _gmx_selelem_set_kwpos_type(struct t_selelem *sel, const char *type);
 void
 _gmx_selelem_set_kwpos_flags(struct t_selelem *sel, int flags);
 
+/** Does custom processing for parameters of the \c same selection method. */
+int
+_gmx_selelem_custom_init_same(struct gmx_ana_selmethod_t **method,
+                              struct t_selexpr_param *params, void *scanner);
+
+/** Initializes a selection element for evaluating a keyword in a given group. */
+int
+_gmx_sel_init_keyword_evaluator(struct t_selelem **sel,
+                                struct gmx_ana_selmethod_t *method,
+                                struct t_selexpr_param *param, void *scanner);
+
 #endif
diff --git a/src/gmxlib/selection/mempool.c b/src/gmxlib/selection/mempool.c
new file mode 100644 (file)
index 0000000..32d8aa0
--- /dev/null
@@ -0,0 +1,210 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Memory pooling for selection evaluation.
+ *
+ * \todo
+ * Document these functions.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <gmx_fatal.h>
+#include <smalloc.h>
+
+#include <indexutil.h>
+
+#include "mempool.h"
+
+#define ALIGN_STEP 8
+
+typedef struct gmx_sel_mempool_block_t
+{
+    void                       *ptr;
+    size_t                      size;
+} gmx_sel_mempool_block_t;
+
+struct gmx_sel_mempool_t
+{
+    size_t                      currsize;
+    size_t                      freesize;
+    char                       *buffer;
+    char                       *freeptr;
+    int                         nblocks;
+    gmx_sel_mempool_block_t    *blockstack;
+    int                         blockstack_nalloc;
+    size_t                      maxsize;
+};
+
+int
+_gmx_sel_mempool_create(gmx_sel_mempool_t **mpp)
+{
+    gmx_sel_mempool_t *mp;
+
+    snew(mp, 1);
+    mp->currsize          = 0;
+    mp->freesize          = 0;
+    mp->buffer            = NULL;
+    mp->freeptr           = NULL;
+    mp->nblocks           = 0;
+    mp->blockstack        = NULL;
+    mp->blockstack_nalloc = 0;
+    mp->maxsize           = 0;
+    *mpp = mp;
+    return 0;
+}
+
+void
+_gmx_sel_mempool_destroy(gmx_sel_mempool_t *mp)
+{
+    if (!mp->buffer)
+    {
+        int  i;
+
+        for (i = 0; i < mp->nblocks; ++i)
+        {
+            sfree(mp->blockstack[i].ptr);
+        }
+    }
+    sfree(mp->buffer);
+    sfree(mp->blockstack);
+    sfree(mp);
+}
+
+int
+_gmx_sel_mempool_alloc(gmx_sel_mempool_t *mp, void **ptrp, size_t size)
+{
+    void   *ptr = NULL;
+    size_t  size_walign;
+
+    *ptrp = NULL;
+    size_walign = ((size + ALIGN_STEP - 1) / ALIGN_STEP) * ALIGN_STEP;
+    if (mp->buffer)
+    {
+        if (mp->freesize < size)
+        {
+            gmx_bug("out of memory pool memory");
+            return ENOMEM;
+        }
+        ptr = mp->freeptr;
+        mp->freeptr  += size_walign;
+        mp->freesize -= size_walign;
+        mp->currsize += size_walign;
+    }
+    else
+    {
+        ptr = malloc(size);
+        if (!ptr)
+        {
+            gmx_mem("out of memory");
+            return ENOMEM;
+        }
+        mp->currsize += size_walign;
+        if (mp->currsize > mp->maxsize)
+        {
+            mp->maxsize = mp->currsize;
+        }
+    }
+
+    if (mp->nblocks >= mp->blockstack_nalloc)
+    {
+        mp->blockstack_nalloc = mp->nblocks + 10;
+        srenew(mp->blockstack, mp->blockstack_nalloc);
+    }
+    mp->blockstack[mp->nblocks].ptr  = ptr;
+    mp->blockstack[mp->nblocks].size = size_walign;
+    mp->nblocks++;
+
+    *ptrp = ptr;
+    return 0;
+}
+
+void
+_gmx_sel_mempool_free(gmx_sel_mempool_t *mp, void *ptr)
+{
+    int size;
+
+    if (ptr == NULL)
+    {
+        return;
+    }
+    assert(mp->nblocks > 0 && mp->blockstack[mp->nblocks - 1].ptr == ptr);
+    mp->nblocks--;
+    size = mp->blockstack[mp->nblocks].size;
+    mp->currsize -= size;
+    if (mp->buffer)
+    {
+        mp->freeptr = (char *)ptr;
+        mp->freesize += size;
+    }
+    else
+    {
+        sfree(ptr);
+    }
+}
+
+int
+_gmx_sel_mempool_reserve(gmx_sel_mempool_t *mp, size_t size)
+{
+    assert(mp->nblocks == 0 && !mp->buffer);
+    if (size == 0)
+    {
+        size = mp->maxsize;
+    }
+    mp->buffer = (char *)malloc(size);
+    if (!mp->buffer)
+    {
+        gmx_mem("out of memory");
+        return ENOMEM;
+    }
+    mp->freesize = size;
+    mp->freeptr  = mp->buffer;
+    return 0;
+}
+
+int
+_gmx_sel_mempool_alloc_group(gmx_sel_mempool_t *mp, gmx_ana_index_t *g,
+                             int isize)
+{
+    return _gmx_sel_mempool_alloc(mp, (void **)&g->index,
+                                  sizeof(*g->index)*isize);
+}
+
+void
+_gmx_sel_mempool_free_group(gmx_sel_mempool_t *mp, gmx_ana_index_t *g)
+{
+    _gmx_sel_mempool_free(mp, g->index);
+    g->index = NULL;
+}
diff --git a/src/gmxlib/selection/mempool.h b/src/gmxlib/selection/mempool.h
new file mode 100644 (file)
index 0000000..ca6abba
--- /dev/null
@@ -0,0 +1,69 @@
+/*
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2009, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ */
+/*! \internal \file
+ * \brief Declarations for memory pooling functions.
+ *
+ * This is an implementation header: there should be no need to use it outside
+ * this directory.
+ */
+#ifndef GMX_SELECTION_MEMPOOL_H
+#define GMX_SELECTION_MEMPOOL_H
+
+struct gmx_ana_index_t;
+
+typedef struct gmx_sel_mempool_t gmx_sel_mempool_t;
+
+/** Create an empty memory pool. */
+int
+_gmx_sel_mempool_create(gmx_sel_mempool_t **mpp);
+/** Destroy a memory pool. */
+void
+_gmx_sel_mempool_destroy(gmx_sel_mempool_t *mp);
+
+/** Allocate memory from a memory pool. */
+int
+_gmx_sel_mempool_alloc(gmx_sel_mempool_t *mp, void **ptrp, size_t size);
+/** Release memory allocated from a memory pool. */
+void
+_gmx_sel_mempool_free(gmx_sel_mempool_t *mp, void *ptr);
+/** Set the size of a memory pool. */
+int
+_gmx_sel_mempool_reserve(gmx_sel_mempool_t *mp, size_t size);
+
+/** Convenience function for allocating an index group from a memory pool. */
+int
+_gmx_sel_mempool_alloc_group(gmx_sel_mempool_t *mp, struct gmx_ana_index_t *g,
+                             int isize);
+/** Convenience function for freeing an index group from a memory pool. */
+void
+_gmx_sel_mempool_free_group(gmx_sel_mempool_t *mp, struct gmx_ana_index_t *g);
+
+#endif
index 9c40f0434eee7094b6308c99e2aea9e4b68643a4..e46863a1b526c731134470d189f45ba7cccfdcb8 100644 (file)
@@ -179,6 +179,44 @@ convert_values(t_selexpr_value *values, e_selvalue_t type, void *scanner)
     return rc;
 }
 
+/*! \brief
+ * Adds a child element for a parameter, keeping the parameter order.
+ *
+ * \param[in,out] root  Root element to which the child is added.
+ * \param[in]     child Child to add.
+ * \param[in]     param Parameter for which this child is a value.
+ *
+ * Puts \p child in the child list of \p root such that the list remains
+ * in the same order as the corresponding parameters.
+ */
+static void
+place_child(t_selelem *root, t_selelem *child, gmx_ana_selparam_t *param)
+{
+    gmx_ana_selparam_t *ps;
+    int                 n;
+
+    ps = root->u.expr.method->param;
+    n  = param - ps;
+    /* Put the child element in the correct place */
+    if (!root->child || n < root->child->u.param - ps)
+    {
+        child->next = root->child;
+        root->child = child;
+    }
+    else
+    {
+        t_selelem *prev;
+
+        prev = root->child;
+        while (prev->next && prev->next->u.param - ps >= n)
+        {
+            prev = prev->next;
+        }
+        child->next = prev->next;
+        prev->next  = child;
+    }
+}
+
 /*! \brief
  * Comparison function for sorting integer ranges.
  * 
@@ -419,13 +457,15 @@ parse_values_range(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param)
  * \param[in] nval   Number of values in \p values.
  * \param[in] values Pointer to the list of values.
  * \param     param  Parameter to parse.
+ * \param     root   Selection element to which child expressions are added.
  * \returns   TRUE if the values were parsed successfully, FALSE otherwise.
  *
  * For integer ranges, the sequence of numbers from the first to second value
  * is stored, each as a separate value.
  */
 static bool
-parse_values_varnum(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param)
+parse_values_varnum(int nval, t_selexpr_value *values,
+                    gmx_ana_selparam_t *param, t_selelem *root)
 {
     t_selexpr_value    *value;
     int                 i, j;
@@ -519,6 +559,26 @@ parse_values_varnum(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param
         *param->nvalptr = param->val.nr;
     }
     param->nvalptr = NULL;
+    /* Create a dummy child element to store the string values.
+     * This element is responsible for freeing the values, but carries no
+     * other function. */
+    if (param->val.type == STR_VALUE)
+    {
+        t_selelem *child;
+
+        child = _gmx_selelem_create(SEL_CONST);
+        _gmx_selelem_set_vtype(child, STR_VALUE);
+        child->name = param->name;
+        child->flags &= ~SEL_ALLOCVAL;
+        child->flags |= SEL_FLAGSSET | SEL_VARNUMVAL | SEL_ALLOCDATA;
+        child->v.nr = param->val.nr;
+        _gmx_selvalue_setstore(&child->v, param->val.u.s);
+        /* Because the child is not group-valued, the u union is not used
+         * for anything, so we can abuse it by storing the parameter value
+         * as place_child() expects, but this is really ugly... */
+        child->u.param = param;
+        place_child(root, child, param);
+    }
 
     return TRUE;
 }
@@ -539,8 +599,6 @@ parse_values_varnum(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param
 static t_selelem *
 add_child(t_selelem *root, gmx_ana_selparam_t *param, t_selelem *expr)
 {
-    gmx_ana_selparam_t *ps;
-    int                 n;
     t_selelem          *child;
     int                 rc;
 
@@ -549,8 +607,6 @@ add_child(t_selelem *root, gmx_ana_selparam_t *param, t_selelem *expr)
         gmx_bug("unsupported root element for selection parameter parser");
         return NULL;
     }
-    ps = root->u.expr.method->param;
-    n  = param - ps;
     /* Create a subexpression reference element if necessary */
     if (expr->type == SEL_SUBEXPRREF)
     {
@@ -591,23 +647,7 @@ add_child(t_selelem *root, gmx_ana_selparam_t *param, t_selelem *expr)
         param->flags &= ~SPAR_DYNAMIC;
     }
     /* Put the child element in the correct place */
-    if (!root->child || n < root->child->u.param - ps)
-    {
-        child->next = root->child;
-        root->child = child;
-    }
-    else
-    {
-        t_selelem *prev;
-
-        prev = root->child;
-        while (prev->next && prev->next->u.param - ps >= n)
-        {
-            prev = prev->next;
-        }
-        child->next = prev->next;
-        prev->next  = child;
-    }
+    place_child(root, child, param);
     return child;
 
 on_error:
@@ -671,6 +711,7 @@ parse_values_varnum_expr(int nval, t_selexpr_value *values,
         return FALSE;
     }
 
+    child->flags   |= SEL_ALLOCVAL;
     param->val.nr   = -1;
     *param->nvalptr = param->val.nr;
     /* Rest of the initialization is done during compilation in
@@ -711,6 +752,7 @@ set_expr_value_store(t_selelem *sel, gmx_ana_selparam_t *param, int i)
             gmx_bug("internal error");
             return FALSE;
     }
+    sel->v.nr = 1;
     sel->v.nalloc = -1;
     return TRUE;
 }
@@ -753,6 +795,7 @@ parse_values_std(int nval, t_selexpr_value *values, gmx_ana_selparam_t *param,
             {
                 return FALSE;
             }
+            child->flags |= SEL_ALLOCVAL;
             if (child->v.type != GROUP_VALUE && (child->flags & SEL_ATOMVAL))
             {
                 /* Rest of the initialization is done during compilation in
@@ -1025,6 +1068,9 @@ convert_const_values(t_selexpr_value *values)
                 case REAL_VALUE:
                     val->u.r.r1 = val->u.r.r2 = expr->v.u.r[0];
                     break;
+                case STR_VALUE:
+                    val->u.s = expr->v.u.s[0];
+                    break;
                 case POS_VALUE:
                     copy_rvec(expr->v.u.p->x[0], val->u.x);
                     break;
@@ -1166,7 +1212,7 @@ _gmx_sel_parse_params(t_selexpr_param *pparams, int nparam, gmx_ana_selparam_t *
             }
             else
             {
-                rc = parse_values_varnum(pparam->nval, pparam->value, oparam);
+                rc = parse_values_varnum(pparam->nval, pparam->value, oparam, root);
             }
         }
         else if (oparam->flags & SPAR_ENUMVAL)
index e8ed8802165e95fb89f10f0c6eb9a7a034d9f80a..948bd084c9ed24336f138a9e014bd0199ad32f08 100644 (file)
      XOR = 285,
      OR = 286,
      AND = 287,
-     NOT = 288
+     NOT = 288,
+     UNARY_NEG = 289
    };
 #endif
 /* Tokens.  */
 #define OR 286
 #define AND 287
 #define NOT 288
+#define UNARY_NEG 289
 
 
 
@@ -205,8 +207,8 @@ typedef union YYSTYPE
     struct t_selexpr_value     *val;
     struct t_selexpr_param     *param;
 }
-/* Line 193 of yacc.c.  */
-#line 210 "parser.c"
+/* Line 187 of yacc.c.  */
+#line 212 "parser.c"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
@@ -219,7 +221,7 @@ typedef union YYSTYPE
 
 
 /* Line 216 of yacc.c.  */
-#line 223 "parser.c"
+#line 225 "parser.c"
 
 #ifdef short
 # undef short
@@ -269,7 +271,7 @@ typedef short int yytype_int16;
 #define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
 
 #ifndef YY_
-# if defined YYENABLE_NLS && YYENABLE_NLS
+# if YYENABLE_NLS
 #  if ENABLE_NLS
 #   include <libintl.h> /* INFRINGES ON USER NAME SPACE */
 #   define YY_(msgid) dgettext ("bison-runtime", msgid)
@@ -434,20 +436,20 @@ union yyalloc
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  2
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   252
+#define YYLAST   329
 
 /* YYNTOKENS -- Number of terminals.  */
-#define YYNTOKENS  38
+#define YYNTOKENS  44
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  19
+#define YYNNTS  20
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  68
+#define YYNRULES  76
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  110
+#define YYNSTATES  125
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
-#define YYMAXUTOK   288
+#define YYMAXUTOK   289
 
 #define YYTRANSLATE(YYX)                                               \
   ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
@@ -459,12 +461,12 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-      35,    36,     2,     2,    37,     2,     2,     2,     2,     2,
-       2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
-       2,    34,     2,     2,     2,     2,     2,     2,     2,     2,
+      41,    42,    36,    34,    43,    35,     2,    37,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,    40,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
+       2,     2,     2,     2,    39,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
        2,     2,     2,     2,     2,     2,     2,     2,     2,     2,
@@ -483,7 +485,7 @@ static const yytype_uint8 yytranslate[] =
        2,     2,     2,     2,     2,     2,     1,     2,     3,     4,
        5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
       15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    27,    28,    29,    30,    31,    32,    33
+      25,    26,    27,    28,    29,    30,    31,    32,    33,    38
 };
 
 #if YYDEBUG
@@ -495,46 +497,51 @@ static const yytype_uint8 yyprhs[] =
       20,    22,    25,    29,    33,    37,    39,    41,    44,    47,
       49,    51,    55,    59,    61,    63,    65,    67,    70,    74,
       78,    82,    86,    89,    92,    94,    96,    99,   103,   107,
-     111,   113,   115,   118,   122,   126,   134,   138,   141,   145,
-     147,   149,   151,   153,   156,   157,   160,   163,   164,   166,
-     168,   171,   175,   177,   179,   181,   185,   189,   193
+     111,   113,   115,   118,   122,   126,   130,   134,   138,   141,
+     145,   149,   151,   154,   162,   166,   169,   173,   175,   177,
+     179,   181,   184,   185,   188,   191,   192,   194,   196,   199,
+     203,   205,   207,   209,   211,   215,   219
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
 static const yytype_int8 yyrhs[] =
 {
-      39,     0,    -1,    -1,    39,    40,    -1,    41,    10,    -1,
-       1,    10,    -1,    -1,    42,    -1,     6,    -1,    46,    -1,
-      44,    -1,    46,    44,    -1,     9,    34,    47,    -1,     9,
-      34,    49,    -1,     9,    34,    50,    -1,     4,    -1,    43,
-      -1,     4,     5,    -1,    43,     5,    -1,    50,    -1,    47,
-      -1,    35,    44,    36,    -1,    44,    23,    51,    -1,     6,
-      -1,     7,    -1,     8,    -1,     9,    -1,    33,    47,    -1,
-      47,    32,    47,    -1,    47,    31,    47,    -1,    35,    47,
-      36,    -1,    49,    28,    49,    -1,    11,    46,    -1,    11,
-       6,    -1,    24,    -1,    18,    -1,    48,    19,    -1,    48,
-      17,    55,    -1,    48,    16,    55,    -1,    48,    21,    51,
-      -1,     6,    -1,     7,    -1,    48,    16,    -1,    48,    20,
-      51,    -1,    35,    49,    36,    -1,    35,    45,    37,    45,
-      37,    45,    36,    -1,    35,    50,    36,    -1,    22,    51,
-      -1,    18,    27,    47,    -1,    14,    -1,    13,    -1,    15,
-      -1,    52,    -1,    52,    26,    -1,    -1,    52,    53,    -1,
-      25,    54,    -1,    -1,    55,    -1,    56,    -1,    55,    56,
-      -1,    55,    37,    56,    -1,    47,    -1,    50,    -1,    49,
+      45,     0,    -1,    -1,    45,    46,    -1,    47,    10,    -1,
+       1,    10,    -1,    -1,    48,    -1,     6,    -1,    52,    -1,
+      50,    -1,    52,    50,    -1,     9,    40,    53,    -1,     9,
+      40,    55,    -1,     9,    40,    57,    -1,     4,    -1,    49,
+      -1,     4,     5,    -1,    49,     5,    -1,    57,    -1,    53,
+      -1,    41,    50,    42,    -1,    50,    23,    58,    -1,     6,
+      -1,     7,    -1,     8,    -1,     9,    -1,    33,    53,    -1,
+      53,    32,    53,    -1,    53,    31,    53,    -1,    41,    53,
+      42,    -1,    55,    28,    55,    -1,    11,    52,    -1,    11,
+       6,    -1,    24,    -1,    18,    -1,    54,    19,    -1,    54,
+      17,    62,    -1,    54,    16,    62,    -1,    54,    21,    58,
+      -1,     6,    -1,     7,    -1,    54,    16,    -1,    54,    20,
+      58,    -1,    55,    34,    55,    -1,    55,    35,    55,    -1,
+      55,    36,    55,    -1,    55,    37,    55,    -1,    35,    55,
+      -1,    55,    39,    55,    -1,    41,    55,    42,    -1,    52,
+      -1,    54,    17,    -1,    41,    51,    43,    51,    43,    51,
+      42,    -1,    41,    57,    42,    -1,    22,    58,    -1,    18,
+      27,    53,    -1,    14,    -1,    13,    -1,    15,    -1,    59,
+      -1,    59,    26,    -1,    -1,    59,    60,    -1,    25,    61,
+      -1,    -1,    62,    -1,    63,    -1,    62,    63,    -1,    62,
+      43,    63,    -1,    53,    -1,    57,    -1,    55,    -1,    56,
       -1,     6,    12,     6,    -1,     6,    12,     7,    -1,     7,
-      12,    45,    -1,    46,    -1
+      12,    51,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
 static const yytype_uint16 yyrline[] =
 {
-       0,   166,   166,   167,   176,   177,   197,   201,   202,   211,
-     221,   223,   225,   227,   229,   235,   236,   239,   240,   244,
-     245,   250,   251,   262,   263,   266,   267,   275,   281,   287,
-     299,   303,   311,   317,   325,   326,   330,   335,   340,   348,
-     360,   367,   377,   382,   390,   398,   403,   407,   415,   426,
-     430,   434,   443,   445,   450,   451,   456,   463,   464,   468,
-     469,   471,   475,   477,   479,   481,   486,   491,   496
+       0,   173,   173,   174,   183,   184,   204,   208,   209,   218,
+     228,   230,   232,   234,   236,   242,   243,   246,   247,   251,
+     252,   257,   258,   269,   270,   273,   274,   282,   288,   294,
+     306,   310,   318,   324,   332,   333,   337,   342,   347,   355,
+     367,   374,   384,   389,   397,   399,   401,   403,   405,   407,
+     409,   416,   423,   435,   440,   444,   452,   463,   467,   471,
+     480,   482,   487,   488,   493,   500,   501,   505,   506,   508,
+     512,   514,   516,   518,   520,   525,   530
 };
 #endif
 
@@ -549,11 +556,12 @@ static const char *const yytname[] =
   "KEYWORD_STR", "KEYWORD_POS", "KEYWORD_GROUP", "METHOD_NUMERIC",
   "METHOD_GROUP", "METHOD_POS", "MODIFIER", "EMPTY_POSMOD", "PARAM",
   "END_OF_METHOD", "OF", "CMP_OP", "PARAM_REDUCT", "XOR", "OR", "AND",
-  "NOT", "'='", "'('", "')'", "','", "$accept", "commands", "command",
-  "cmd_plain", "help_request", "help_topic", "selection", "number",
-  "string", "sel_expr", "pos_mod", "num_expr", "pos_expr", "method_params",
-  "method_param_list", "method_param", "value_list", "value_list_nonempty",
-  "value_item", 0
+  "NOT", "'+'", "'-'", "'*'", "'/'", "UNARY_NEG", "'^'", "'='", "'('",
+  "')'", "','", "$accept", "commands", "command", "cmd_plain",
+  "help_request", "help_topic", "selection", "number", "string",
+  "sel_expr", "pos_mod", "num_expr", "str_expr", "pos_expr",
+  "method_params", "method_param_list", "method_param", "value_list",
+  "value_list_nonempty", "value_item", 0
 };
 #endif
 
@@ -565,20 +573,22 @@ static const yytype_uint16 yytoknum[] =
        0,   256,   257,   258,   259,   260,   261,   262,   263,   264,
      265,   266,   267,   268,   269,   270,   271,   272,   273,   274,
      275,   276,   277,   278,   279,   280,   281,   282,   283,   284,
-     285,   286,   287,   288,    61,    40,    41,    44
+     285,   286,   287,   288,    43,    45,    42,    47,   289,    94,
+      61,    40,    41,    44
 };
 # endif
 
 /* YYR1[YYN] -- Symbol number of symbol that rule YYN derives.  */
 static const yytype_uint8 yyr1[] =
 {
-       0,    38,    39,    39,    40,    40,    41,    41,    41,    41,
-      41,    41,    41,    41,    41,    42,    42,    43,    43,    44,
-      44,    44,    44,    45,    45,    46,    46,    47,    47,    47,
-      47,    47,    47,    47,    48,    48,    47,    47,    47,    47,
-      49,    49,    49,    49,    49,    50,    50,    50,    50,    47,
-      49,    50,    51,    51,    52,    52,    53,    54,    54,    55,
-      55,    55,    56,    56,    56,    56,    56,    56,    56
+       0,    44,    45,    45,    46,    46,    47,    47,    47,    47,
+      47,    47,    47,    47,    47,    48,    48,    49,    49,    50,
+      50,    50,    50,    51,    51,    52,    52,    53,    53,    53,
+      53,    53,    53,    53,    54,    54,    53,    53,    53,    53,
+      55,    55,    55,    55,    55,    55,    55,    55,    55,    55,
+      55,    56,    56,    57,    57,    57,    57,    53,    55,    57,
+      58,    58,    59,    59,    60,    61,    61,    62,    62,    62,
+      63,    63,    63,    63,    63,    63,    63
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -588,9 +598,10 @@ static const yytype_uint8 yyr2[] =
        1,     2,     3,     3,     3,     1,     1,     2,     2,     1,
        1,     3,     3,     1,     1,     1,     1,     2,     3,     3,
        3,     3,     2,     2,     1,     1,     2,     3,     3,     3,
-       1,     1,     2,     3,     3,     7,     3,     2,     3,     1,
-       1,     1,     1,     2,     0,     2,     2,     0,     1,     1,
-       2,     3,     1,     1,     1,     3,     3,     3,     1
+       1,     1,     2,     3,     3,     3,     3,     3,     2,     3,
+       3,     1,     2,     7,     3,     2,     3,     1,     1,     1,
+       1,     2,     0,     2,     2,     0,     1,     1,     2,     3,
+       1,     1,     1,     1,     3,     3,     3
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -598,131 +609,151 @@ static const yytype_uint8 yyr2[] =
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       2,     0,     1,     0,    15,     8,    41,    25,    26,     0,
-      50,    49,    51,    35,    54,    34,     0,     0,     3,     0,
-       7,    16,    10,     9,    20,     0,     0,    19,     5,    17,
-       0,    33,    26,    32,     0,    47,    52,    40,    35,     0,
-      27,    40,    41,     0,     0,    20,     0,    19,     4,    18,
-      54,    11,     0,     0,    42,     0,    36,    54,    54,     0,
-       0,    12,    13,    14,    48,    57,    53,    55,     0,    21,
-       0,    30,    44,    46,    22,    29,    28,    40,    41,    68,
-      62,    64,    63,    38,    59,    37,    43,    39,     0,     0,
-      31,     0,    56,    58,    23,    24,     0,     0,     0,     0,
-      60,     0,    42,     0,    65,    66,    67,    61,     0,    45
+       2,     0,     1,     0,    15,    40,    41,    25,    26,     0,
+      58,    57,    59,    35,    62,    34,     0,     0,     0,     3,
+       0,     7,    16,    10,     9,    20,     0,     0,    19,     5,
+      17,     0,    33,    26,    32,     0,    55,    60,    40,    35,
+       0,    27,     0,     0,    48,    40,    41,     0,     0,    20,
+       0,    19,     4,    18,    62,    11,     0,     0,    42,     0,
+      36,    62,    62,     0,     0,     0,     0,     0,     0,     0,
+      12,    13,    14,    56,    65,    61,    63,     0,     0,    42,
+      21,     0,    30,    50,    54,    22,    29,    28,    40,    41,
+      51,    70,     0,    72,    73,    71,    38,    67,    37,    43,
+      39,    31,    44,    45,    46,    47,    49,     0,    64,    66,
+      23,    24,     0,     0,     0,    52,     0,    68,     0,    74,
+      75,    76,    69,     0,    53
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int8 yydefgoto[] =
 {
-      -1,     1,    18,    19,    20,    21,    22,    44,    79,    80,
-      25,    81,    82,    35,    36,    67,    92,    83,    84
+      -1,     1,    19,    20,    21,    22,    23,    48,    90,    91,
+      26,    93,    94,    95,    36,    37,    76,   108,    98,    97
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -74
+#define YYPACT_NINF -87
 static const yytype_int16 yypact[] =
 {
-     -74,    64,   -74,    13,     4,    14,   -74,   -74,    16,    40,
-     -74,   -74,   -74,    33,   -74,   -74,   207,   133,   -74,    47,
-     -74,    58,    46,   156,    -4,    96,    48,   -74,   -74,   -74,
-     170,   -74,   -74,   -74,   207,   -74,    30,   -74,   -74,   207,
-     -74,    52,    53,   -15,    54,    49,   -23,    56,   -74,   -74,
-     -74,    46,   207,   207,   119,   119,   -74,   -74,   -74,   217,
-     193,    -4,    48,   -74,    -4,   119,   -74,   -74,    49,   -74,
-      60,   -74,   -74,   -74,   -74,   -74,   -74,    91,    92,   -74,
-      -4,   -74,   -74,    87,   -74,    87,   -74,   -74,   217,    -9,
-     -74,    56,   -74,    87,   -74,   -74,    69,    77,    60,   119,
-     -74,    71,   -74,    60,   -74,   -74,   -74,   -74,    72,   -74
+     -87,   124,   -87,    -1,     6,     8,   -87,   -87,    12,    56,
+     -87,   -87,   -87,    17,   -87,   -87,   278,   288,   200,   -87,
+      53,   -87,    75,    66,   225,     0,   133,    84,   -87,   -87,
+     -87,   239,   -87,   -87,   -87,   278,   -87,    57,   -87,   -87,
+     278,   -87,   288,   -14,    55,    54,    58,   -16,    63,   -18,
+      68,    69,   -87,   -87,   -87,    66,   278,   278,   186,   186,
+     -87,   -87,   -87,   288,   288,   288,   288,   288,   288,   264,
+       0,    84,   -87,     0,   186,   -87,   -87,   -18,    51,   -87,
+     -87,   102,   -87,   -87,   -87,   -87,    83,   -87,   110,   114,
+     -87,     0,   164,    19,   -87,   -87,   155,   -87,   155,   -87,
+     -87,    19,    38,    38,    55,    55,    55,    69,   -87,   155,
+     -87,   -87,    93,   107,   102,   186,   186,   -87,   102,   -87,
+     -87,   -87,   -87,    85,   -87
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int8 yypgoto[] =
 {
-     -74,   -74,   -74,   -74,   -74,   -74,    24,   -64,    36,     1,
-     -58,    -1,     2,   -14,   -74,   -74,   -74,   -51,   -73
+     -87,   -87,   -87,   -87,   -87,   -87,    15,   -78,    28,    60,
+     -17,     3,   -87,     4,   -46,   -87,   -87,   -87,   -57,   -86
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -41
+#define YYTABLE_NINF -25
 static const yytype_int8 yytable[] =
 {
-      26,    89,    24,    27,    85,    59,    96,   102,    50,    29,
-     100,    57,   100,    72,    93,    26,    46,    40,    45,    47,
-     100,    69,    26,    28,    24,    27,   107,    52,    53,    62,
-      89,    61,    63,    26,   106,    64,    74,    23,    46,   108,
-      68,    43,   -40,    86,    87,    33,    31,    51,     7,    32,
-      30,    26,    26,    75,    76,    65,    66,    48,    90,    46,
-      34,    68,    91,    49,     2,     3,    94,    95,     4,    50,
-       5,     6,     7,     8,    -6,     9,    59,    10,    11,    12,
-      52,    53,    13,   104,   105,    71,    14,   101,    15,   -23,
-     -24,    70,    73,    77,    78,     7,    32,    16,     9,    17,
-      10,    11,    12,    97,    98,    13,   103,    72,   109,    14,
-       0,    15,    54,    55,     0,    56,    57,    58,     0,     0,
-      16,     0,    60,     0,    99,    77,    78,     7,    32,     0,
-       9,     0,    10,    11,    12,     0,     0,    13,     0,    41,
-      42,    14,     0,    15,     9,     0,    10,    11,    12,     0,
-       0,    13,    16,     0,    60,    14,     0,    15,     0,     0,
-       0,     0,    37,     6,     0,     0,    16,     9,    17,    10,
-      11,    12,     0,     0,    13,     0,    37,     6,    14,     0,
+      43,    96,    79,   112,    27,    28,    61,    54,    85,    29,
+     117,    30,   117,    56,    57,    99,   100,   109,    -8,    27,
+      44,    50,    51,   117,    82,    43,    80,    27,    28,    24,
+     122,    56,    57,    47,    71,    72,   121,    34,    27,    55,
+     123,    92,    92,    50,    35,    78,    43,    43,    43,    43,
+      43,    43,    31,    64,    65,    66,    67,    92,    68,    27,
+      27,    25,    32,    52,     7,    33,   101,   102,   103,   104,
+     105,   106,    50,   107,    66,    67,    41,    68,    49,    92,
+      53,    92,    74,    75,    25,    64,    65,    66,    67,    54,
+      68,    70,    92,    83,    68,    73,    63,   -23,    92,    92,
+      77,   -24,    64,    65,    66,    67,    81,    68,   110,   111,
+      83,    84,    63,   119,   120,    57,    86,    87,    64,    65,
+      66,    67,   113,    68,     2,     3,   114,   124,     4,    77,
+       5,     6,     7,     8,    -6,     9,   118,    10,    11,    12,
+       0,     0,    13,     0,     0,     0,    14,     0,    15,    58,
+      59,     0,    60,    61,    62,     0,     0,    16,     0,    17,
+       0,    88,    89,     7,    33,    18,     9,     0,    10,    11,
+      12,     0,     0,    13,     0,     0,     0,    14,     0,    15,
+      58,   115,     0,    60,    61,    62,     0,     0,    16,     0,
+      17,     0,    88,    89,     7,    33,    69,     9,   116,    10,
+      11,    12,     0,     0,    13,     0,    45,    46,    14,     0,
       15,     9,     0,    10,    11,    12,     0,     0,    13,    16,
-       0,    17,    14,     0,    15,     0,     0,     0,     0,    41,
-      42,     0,     0,    16,     9,    60,    10,    11,    12,     0,
-       0,    13,     0,    37,     6,    14,     0,    15,     9,     0,
-      10,    11,     0,    37,     6,    38,    16,     0,    60,     0,
-      10,    15,     0,     0,     0,    38,     0,     0,     0,     0,
-      16,    15,    39,     0,     0,     0,     0,     0,     0,     0,
-       0,     0,    88
+       0,    17,    14,     0,    15,     0,     0,    69,     0,     0,
+       0,    38,     6,    16,     0,    17,     9,     0,    10,    11,
+      12,    18,     0,    13,     0,    38,     6,    14,     0,    15,
+       9,     0,    10,    11,    12,     0,     0,    13,    16,     0,
+      17,    14,     0,    15,     0,     0,    18,     0,     0,     0,
+      45,    46,    16,     0,    17,     9,     0,    10,    11,    12,
+      69,     0,    13,     0,    38,     6,    14,     0,    15,     9,
+       0,    10,    11,     0,    38,     6,    39,    16,     0,    17,
+       0,    10,    15,     0,     0,    69,    39,     0,     0,     0,
+       0,    16,    15,    17,     0,     0,     0,     0,     0,    40,
+       0,     0,     0,    17,     0,     0,     0,     0,     0,    42
 };
 
 static const yytype_int8 yycheck[] =
 {
-       1,    59,     1,     1,    55,    28,    70,    16,    23,     5,
-      83,    20,    85,    36,    65,    16,    17,    16,    17,    17,
-      93,    36,    23,    10,    23,    23,    99,    31,    32,    30,
-      88,    30,    30,    34,    98,    34,    50,     1,    39,   103,
-      39,    17,    28,    57,    58,     9,     6,    23,     8,     9,
-      34,    52,    53,    52,    53,    25,    26,    10,    59,    60,
-      27,    60,    60,     5,     0,     1,     6,     7,     4,    23,
-       6,     7,     8,     9,    10,    11,    28,    13,    14,    15,
-      31,    32,    18,     6,     7,    36,    22,    88,    24,    37,
-      37,    37,    36,     6,     7,     8,     9,    33,    11,    35,
-      13,    14,    15,    12,    12,    18,    37,    36,    36,    22,
-      -1,    24,    16,    17,    -1,    19,    20,    21,    -1,    -1,
-      33,    -1,    35,    -1,    37,     6,     7,     8,     9,    -1,
-      11,    -1,    13,    14,    15,    -1,    -1,    18,    -1,     6,
-       7,    22,    -1,    24,    11,    -1,    13,    14,    15,    -1,
-      -1,    18,    33,    -1,    35,    22,    -1,    24,    -1,    -1,
-      -1,    -1,     6,     7,    -1,    -1,    33,    11,    35,    13,
+      17,    58,    16,    81,     1,     1,    20,    23,    54,    10,
+      96,     5,    98,    31,    32,    61,    62,    74,    10,    16,
+      17,    18,    18,   109,    42,    42,    42,    24,    24,     1,
+     116,    31,    32,    18,    31,    31,   114,     9,    35,    24,
+     118,    58,    59,    40,    27,    42,    63,    64,    65,    66,
+      67,    68,    40,    34,    35,    36,    37,    74,    39,    56,
+      57,     1,     6,    10,     8,     9,    63,    64,    65,    66,
+      67,    68,    69,    69,    36,    37,    16,    39,    18,    96,
+       5,    98,    25,    26,    24,    34,    35,    36,    37,    23,
+      39,    31,   109,    42,    39,    35,    28,    43,   115,   116,
+      40,    43,    34,    35,    36,    37,    43,    39,     6,     7,
+      42,    42,    28,     6,     7,    32,    56,    57,    34,    35,
+      36,    37,    12,    39,     0,     1,    12,    42,     4,    69,
+       6,     7,     8,     9,    10,    11,    43,    13,    14,    15,
+      -1,    -1,    18,    -1,    -1,    -1,    22,    -1,    24,    16,
+      17,    -1,    19,    20,    21,    -1,    -1,    33,    -1,    35,
+      -1,     6,     7,     8,     9,    41,    11,    -1,    13,    14,
+      15,    -1,    -1,    18,    -1,    -1,    -1,    22,    -1,    24,
+      16,    17,    -1,    19,    20,    21,    -1,    -1,    33,    -1,
+      35,    -1,     6,     7,     8,     9,    41,    11,    43,    13,
       14,    15,    -1,    -1,    18,    -1,     6,     7,    22,    -1,
       24,    11,    -1,    13,    14,    15,    -1,    -1,    18,    33,
-      -1,    35,    22,    -1,    24,    -1,    -1,    -1,    -1,     6,
-       7,    -1,    -1,    33,    11,    35,    13,    14,    15,    -1,
-      -1,    18,    -1,     6,     7,    22,    -1,    24,    11,    -1,
-      13,    14,    -1,     6,     7,    18,    33,    -1,    35,    -1,
-      13,    24,    -1,    -1,    -1,    18,    -1,    -1,    -1,    -1,
-      33,    24,    35,    -1,    -1,    -1,    -1,    -1,    -1,    -1,
-      -1,    -1,    35
+      -1,    35,    22,    -1,    24,    -1,    -1,    41,    -1,    -1,
+      -1,     6,     7,    33,    -1,    35,    11,    -1,    13,    14,
+      15,    41,    -1,    18,    -1,     6,     7,    22,    -1,    24,
+      11,    -1,    13,    14,    15,    -1,    -1,    18,    33,    -1,
+      35,    22,    -1,    24,    -1,    -1,    41,    -1,    -1,    -1,
+       6,     7,    33,    -1,    35,    11,    -1,    13,    14,    15,
+      41,    -1,    18,    -1,     6,     7,    22,    -1,    24,    11,
+      -1,    13,    14,    -1,     6,     7,    18,    33,    -1,    35,
+      -1,    13,    24,    -1,    -1,    41,    18,    -1,    -1,    -1,
+      -1,    33,    24,    35,    -1,    -1,    -1,    -1,    -1,    41,
+      -1,    -1,    -1,    35,    -1,    -1,    -1,    -1,    -1,    41
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
    symbol of state STATE-NUM.  */
 static const yytype_uint8 yystos[] =
 {
-       0,    39,     0,     1,     4,     6,     7,     8,     9,    11,
-      13,    14,    15,    18,    22,    24,    33,    35,    40,    41,
-      42,    43,    44,    46,    47,    48,    49,    50,    10,     5,
-      34,     6,     9,    46,    27,    51,    52,     6,    18,    35,
-      47,     6,     7,    44,    45,    47,    49,    50,    10,     5,
-      23,    44,    31,    32,    16,    17,    19,    20,    21,    28,
-      35,    47,    49,    50,    47,    25,    26,    53,    47,    36,
-      37,    36,    36,    36,    51,    47,    47,     6,     7,    46,
-      47,    49,    50,    55,    56,    55,    51,    51,    35,    48,
-      49,    50,    54,    55,     6,     7,    45,    12,    12,    37,
-      56,    49,    16,    37,     6,     7,    45,    56,    45,    36
+       0,    45,     0,     1,     4,     6,     7,     8,     9,    11,
+      13,    14,    15,    18,    22,    24,    33,    35,    41,    46,
+      47,    48,    49,    50,    52,    53,    54,    55,    57,    10,
+       5,    40,     6,     9,    52,    27,    58,    59,     6,    18,
+      41,    53,    41,    54,    55,     6,     7,    50,    51,    53,
+      55,    57,    10,     5,    23,    50,    31,    32,    16,    17,
+      19,    20,    21,    28,    34,    35,    36,    37,    39,    41,
+      53,    55,    57,    53,    25,    26,    60,    53,    55,    16,
+      42,    43,    42,    42,    42,    58,    53,    53,     6,     7,
+      52,    53,    54,    55,    56,    57,    62,    63,    62,    58,
+      58,    55,    55,    55,    55,    55,    55,    57,    61,    62,
+       6,     7,    51,    12,    12,    17,    43,    63,    43,     6,
+       7,    51,    63,    51,    42
 };
 
 #define yyerrok                (yyerrstatus = 0)
@@ -796,7 +827,7 @@ while (YYID (0))
    we won't break user code: when these are the locations we know.  */
 
 #ifndef YY_LOCATION_PRINT
-# if defined YYLTYPE_IS_TRIVIAL && YYLTYPE_IS_TRIVIAL
+# if YYLTYPE_IS_TRIVIAL
 #  define YY_LOCATION_PRINT(File, Loc)                 \
      fprintf (File, "%d.%d-%d.%d",                     \
              (Loc).first_line, (Loc).first_column,     \
@@ -1237,89 +1268,99 @@ yydestruct (yymsg, yytype, yyvaluep, scanner)
   switch (yytype)
     {
       case 5: /* "HELP_TOPIC" */
-#line 146 "parser.y"
+#line 153 "parser.y"
        { free((yyvaluep->str));                     };
-#line 1243 "parser.c"
+#line 1274 "parser.c"
        break;
       case 8: /* "STR" */
-#line 146 "parser.y"
+#line 153 "parser.y"
        { free((yyvaluep->str));                     };
-#line 1248 "parser.c"
+#line 1279 "parser.c"
        break;
       case 9: /* "IDENTIFIER" */
-#line 146 "parser.y"
+#line 153 "parser.y"
        { free((yyvaluep->str));                     };
-#line 1253 "parser.c"
+#line 1284 "parser.c"
        break;
       case 25: /* "PARAM" */
-#line 147 "parser.y"
+#line 154 "parser.y"
        { if((yyvaluep->str)) free((yyvaluep->str));              };
-#line 1258 "parser.c"
+#line 1289 "parser.c"
+       break;
+      case 28: /* "CMP_OP" */
+#line 153 "parser.y"
+       { free((yyvaluep->str));                     };
+#line 1294 "parser.c"
        break;
-      case 40: /* "command" */
-#line 148 "parser.y"
+      case 46: /* "command" */
+#line 155 "parser.y"
        { if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
-#line 1263 "parser.c"
+#line 1299 "parser.c"
        break;
-      case 41: /* "cmd_plain" */
-#line 148 "parser.y"
+      case 47: /* "cmd_plain" */
+#line 155 "parser.y"
        { if((yyvaluep->sel)) _gmx_selelem_free((yyvaluep->sel)); };
-#line 1268 "parser.c"
+#line 1304 "parser.c"
        break;
-      case 44: /* "selection" */
-#line 149 "parser.y"
+      case 50: /* "selection" */
+#line 156 "parser.y"
        { _gmx_selelem_free_chain((yyvaluep->sel));  };
-#line 1273 "parser.c"
+#line 1309 "parser.c"
        break;
-      case 46: /* "string" */
-#line 146 "parser.y"
+      case 52: /* "string" */
+#line 153 "parser.y"
        { free((yyvaluep->str));                     };
-#line 1278 "parser.c"
+#line 1314 "parser.c"
        break;
-      case 47: /* "sel_expr" */
-#line 150 "parser.y"
+      case 53: /* "sel_expr" */
+#line 157 "parser.y"
        { _gmx_selelem_free((yyvaluep->sel));        };
-#line 1283 "parser.c"
+#line 1319 "parser.c"
        break;
-      case 49: /* "num_expr" */
-#line 150 "parser.y"
+      case 55: /* "num_expr" */
+#line 157 "parser.y"
        { _gmx_selelem_free((yyvaluep->sel));        };
-#line 1288 "parser.c"
+#line 1324 "parser.c"
        break;
-      case 50: /* "pos_expr" */
-#line 150 "parser.y"
+      case 56: /* "str_expr" */
+#line 157 "parser.y"
        { _gmx_selelem_free((yyvaluep->sel));        };
-#line 1293 "parser.c"
+#line 1329 "parser.c"
        break;
-      case 51: /* "method_params" */
-#line 151 "parser.y"
+      case 57: /* "pos_expr" */
+#line 157 "parser.y"
+       { _gmx_selelem_free((yyvaluep->sel));        };
+#line 1334 "parser.c"
+       break;
+      case 58: /* "method_params" */
+#line 158 "parser.y"
        { _gmx_selexpr_free_params((yyvaluep->param)); };
-#line 1298 "parser.c"
+#line 1339 "parser.c"
        break;
-      case 52: /* "method_param_list" */
-#line 151 "parser.y"
+      case 59: /* "method_param_list" */
+#line 158 "parser.y"
        { _gmx_selexpr_free_params((yyvaluep->param)); };
-#line 1303 "parser.c"
+#line 1344 "parser.c"
        break;
-      case 53: /* "method_param" */
-#line 151 "parser.y"
+      case 60: /* "method_param" */
+#line 158 "parser.y"
        { _gmx_selexpr_free_params((yyvaluep->param)); };
-#line 1308 "parser.c"
+#line 1349 "parser.c"
        break;
-      case 54: /* "value_list" */
-#line 152 "parser.y"
+      case 61: /* "value_list" */
+#line 159 "parser.y"
        { _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1313 "parser.c"
+#line 1354 "parser.c"
        break;
-      case 55: /* "value_list_nonempty" */
-#line 152 "parser.y"
+      case 62: /* "value_list_nonempty" */
+#line 159 "parser.y"
        { _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1318 "parser.c"
+#line 1359 "parser.c"
        break;
-      case 56: /* "value_item" */
-#line 152 "parser.y"
+      case 63: /* "value_item" */
+#line 159 "parser.y"
        { _gmx_selexpr_free_values((yyvaluep->val)); };
-#line 1323 "parser.c"
+#line 1364 "parser.c"
        break;
 
       default:
@@ -1628,12 +1669,12 @@ yyreduce:
   switch (yyn)
     {
         case 2:
-#line 166 "parser.y"
+#line 173 "parser.y"
     { (yyval.sel) = NULL ;}
     break;
 
   case 3:
-#line 168 "parser.y"
+#line 175 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_append_selection((yyvsp[(2) - (2)].sel), (yyvsp[(1) - (2)].sel), scanner);
                  if (_gmx_sel_parser_should_finish(scanner))
@@ -1642,12 +1683,12 @@ yyreduce:
     break;
 
   case 4:
-#line 176 "parser.y"
+#line 183 "parser.y"
     { (yyval.sel) = (yyvsp[(1) - (2)].sel); ;}
     break;
 
   case 5:
-#line 178 "parser.y"
+#line 185 "parser.y"
     {
                  (yyval.sel) = NULL;
                  _gmx_selparser_error("invalid selection '%s'",
@@ -1666,7 +1707,7 @@ yyreduce:
     break;
 
   case 6:
-#line 197 "parser.y"
+#line 204 "parser.y"
     {
                  (yyval.sel) = NULL;
                  _gmx_sel_handle_empty_cmd(scanner);
@@ -1674,12 +1715,12 @@ yyreduce:
     break;
 
   case 7:
-#line 201 "parser.y"
+#line 208 "parser.y"
     { (yyval.sel) = NULL; ;}
     break;
 
   case 8:
-#line 203 "parser.y"
+#line 210 "parser.y"
     {
                  t_selelem *s, *p;
                  s = _gmx_sel_init_group_by_id((yyvsp[(1) - (1)].i), scanner);
@@ -1691,7 +1732,7 @@ yyreduce:
     break;
 
   case 9:
-#line 212 "parser.y"
+#line 219 "parser.y"
     {
                  t_selelem *s, *p;
                  s = _gmx_sel_init_group_by_name((yyvsp[(1) - (1)].str), scanner);
@@ -1704,52 +1745,52 @@ yyreduce:
     break;
 
   case 10:
-#line 222 "parser.y"
+#line 229 "parser.y"
     { (yyval.sel) = _gmx_sel_init_selection(NULL, (yyvsp[(1) - (1)].sel), scanner); ;}
     break;
 
   case 11:
-#line 224 "parser.y"
+#line 231 "parser.y"
     { (yyval.sel) = _gmx_sel_init_selection((yyvsp[(1) - (2)].str), (yyvsp[(2) - (2)].sel), scanner);   ;}
     break;
 
   case 12:
-#line 226 "parser.y"
+#line 233 "parser.y"
     { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  ;}
     break;
 
   case 13:
-#line 228 "parser.y"
+#line 235 "parser.y"
     { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  ;}
     break;
 
   case 14:
-#line 230 "parser.y"
+#line 237 "parser.y"
     { (yyval.sel) = _gmx_sel_assign_variable((yyvsp[(1) - (3)].str), (yyvsp[(3) - (3)].sel), scanner);  ;}
     break;
 
   case 15:
-#line 235 "parser.y"
+#line 242 "parser.y"
     { _gmx_sel_handle_help_cmd(NULL, scanner); ;}
     break;
 
   case 17:
-#line 239 "parser.y"
+#line 246 "parser.y"
     { _gmx_sel_handle_help_cmd((yyvsp[(2) - (2)].str), scanner); ;}
     break;
 
   case 18:
-#line 240 "parser.y"
+#line 247 "parser.y"
     { _gmx_sel_handle_help_cmd((yyvsp[(2) - (2)].str), scanner); ;}
     break;
 
   case 19:
-#line 244 "parser.y"
+#line 251 "parser.y"
     { (yyval.sel) = (yyvsp[(1) - (1)].sel); ;}
     break;
 
   case 20:
-#line 246 "parser.y"
+#line 253 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_position((yyvsp[(1) - (1)].sel), NULL, scanner);
                  if ((yyval.sel) == NULL) YYERROR;
@@ -1757,12 +1798,12 @@ yyreduce:
     break;
 
   case 21:
-#line 250 "parser.y"
+#line 257 "parser.y"
     { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
     break;
 
   case 22:
-#line 252 "parser.y"
+#line 259 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_modifier((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].sel), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
@@ -1770,27 +1811,27 @@ yyreduce:
     break;
 
   case 23:
-#line 262 "parser.y"
+#line 269 "parser.y"
     { (yyval.r) = (yyvsp[(1) - (1)].i); ;}
     break;
 
   case 24:
-#line 263 "parser.y"
+#line 270 "parser.y"
     { (yyval.r) = (yyvsp[(1) - (1)].r); ;}
     break;
 
   case 25:
-#line 266 "parser.y"
+#line 273 "parser.y"
     { (yyval.str) = (yyvsp[(1) - (1)].str); ;}
     break;
 
   case 26:
-#line 267 "parser.y"
+#line 274 "parser.y"
     { (yyval.str) = (yyvsp[(1) - (1)].str); ;}
     break;
 
   case 27:
-#line 276 "parser.y"
+#line 283 "parser.y"
     {
                  (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
                  (yyval.sel)->u.boolt = BOOL_NOT;
@@ -1799,7 +1840,7 @@ yyreduce:
     break;
 
   case 28:
-#line 282 "parser.y"
+#line 289 "parser.y"
     {
                  (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
                  (yyval.sel)->u.boolt = BOOL_AND;
@@ -1808,7 +1849,7 @@ yyreduce:
     break;
 
   case 29:
-#line 288 "parser.y"
+#line 295 "parser.y"
     {
                  (yyval.sel) = _gmx_selelem_create(SEL_BOOLEAN);
                  (yyval.sel)->u.boolt = BOOL_OR;
@@ -1817,12 +1858,12 @@ yyreduce:
     break;
 
   case 30:
-#line 299 "parser.y"
+#line 306 "parser.y"
     { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
     break;
 
   case 31:
-#line 304 "parser.y"
+#line 311 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_comparison((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), (yyvsp[(2) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
@@ -1830,7 +1871,7 @@ yyreduce:
     break;
 
   case 32:
-#line 312 "parser.y"
+#line 319 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_group_by_name((yyvsp[(2) - (2)].str), scanner);
                  free((yyvsp[(2) - (2)].str));
@@ -1839,7 +1880,7 @@ yyreduce:
     break;
 
   case 33:
-#line 318 "parser.y"
+#line 325 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_group_by_id((yyvsp[(2) - (2)].i), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
@@ -1847,17 +1888,17 @@ yyreduce:
     break;
 
   case 34:
-#line 325 "parser.y"
+#line 332 "parser.y"
     { (yyval.str) = NULL; ;}
     break;
 
   case 35:
-#line 326 "parser.y"
+#line 333 "parser.y"
     { (yyval.str) = (yyvsp[(1) - (1)].str);   ;}
     break;
 
   case 36:
-#line 331 "parser.y"
+#line 338 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
@@ -1865,7 +1906,7 @@ yyreduce:
     break;
 
   case 37:
-#line 336 "parser.y"
+#line 343 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
@@ -1873,7 +1914,7 @@ yyreduce:
     break;
 
   case 38:
-#line 341 "parser.y"
+#line 348 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (3)].meth), process_value_list((yyvsp[(3) - (3)].val), NULL), (yyvsp[(1) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
@@ -1881,7 +1922,7 @@ yyreduce:
     break;
 
   case 39:
-#line 349 "parser.y"
+#line 356 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
@@ -1889,7 +1930,7 @@ yyreduce:
     break;
 
   case 40:
-#line 361 "parser.y"
+#line 368 "parser.y"
     {
                  (yyval.sel) = _gmx_selelem_create(SEL_CONST);
                  _gmx_selelem_set_vtype((yyval.sel), INT_VALUE);
@@ -1899,7 +1940,7 @@ yyreduce:
     break;
 
   case 41:
-#line 368 "parser.y"
+#line 375 "parser.y"
     {
                  (yyval.sel) = _gmx_selelem_create(SEL_CONST);
                  _gmx_selelem_set_vtype((yyval.sel), REAL_VALUE);
@@ -1909,7 +1950,7 @@ yyreduce:
     break;
 
   case 42:
-#line 378 "parser.y"
+#line 385 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
@@ -1917,7 +1958,7 @@ yyreduce:
     break;
 
   case 43:
-#line 383 "parser.y"
+#line 390 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_method((yyvsp[(2) - (3)].meth), (yyvsp[(3) - (3)].param), (yyvsp[(1) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
@@ -1925,154 +1966,199 @@ yyreduce:
     break;
 
   case 44:
-#line 390 "parser.y"
-    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+#line 398 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '+', scanner); ;}
     break;
 
   case 45:
-#line 399 "parser.y"
-    { (yyval.sel) = _gmx_sel_init_const_position((yyvsp[(2) - (7)].r), (yyvsp[(4) - (7)].r), (yyvsp[(6) - (7)].r)); ;}
+#line 400 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '-', scanner); ;}
     break;
 
   case 46:
-#line 403 "parser.y"
-    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+#line 402 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '*', scanner); ;}
     break;
 
   case 47:
+#line 404 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '/', scanner); ;}
+    break;
+
+  case 48:
+#line 406 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(2) - (2)].sel), NULL, '-', scanner); ;}
+    break;
+
+  case 49:
 #line 408 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_arithmetic((yyvsp[(1) - (3)].sel), (yyvsp[(3) - (3)].sel), '^', scanner); ;}
+    break;
+
+  case 50:
+#line 409 "parser.y"
+    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+    break;
+
+  case 51:
+#line 417 "parser.y"
+    {
+                 (yyval.sel) = _gmx_selelem_create(SEL_CONST);
+                 _gmx_selelem_set_vtype((yyval.sel), STR_VALUE);
+                 _gmx_selvalue_reserve(&(yyval.sel)->v, 1);
+                 (yyval.sel)->v.u.s[0] = (yyvsp[(1) - (1)].str);
+             ;}
+    break;
+
+  case 52:
+#line 424 "parser.y"
+    {
+                 (yyval.sel) = _gmx_sel_init_keyword((yyvsp[(2) - (2)].meth), NULL, (yyvsp[(1) - (2)].str), scanner);
+                 if ((yyval.sel) == NULL) YYERROR;
+             ;}
+    break;
+
+  case 53:
+#line 436 "parser.y"
+    { (yyval.sel) = _gmx_sel_init_const_position((yyvsp[(2) - (7)].r), (yyvsp[(4) - (7)].r), (yyvsp[(6) - (7)].r)); ;}
+    break;
+
+  case 54:
+#line 440 "parser.y"
+    { (yyval.sel) = (yyvsp[(2) - (3)].sel); ;}
+    break;
+
+  case 55:
+#line 445 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_method((yyvsp[(1) - (2)].meth), (yyvsp[(2) - (2)].param), NULL, scanner);
                  if ((yyval.sel) == NULL) YYERROR;
              ;}
     break;
 
-  case 48:
-#line 416 "parser.y"
+  case 56:
+#line 453 "parser.y"
     {
                  (yyval.sel) = _gmx_sel_init_position((yyvsp[(3) - (3)].sel), (yyvsp[(1) - (3)].str), scanner);
                  if ((yyval.sel) == NULL) YYERROR;
              ;}
     break;
 
-  case 49:
-#line 427 "parser.y"
+  case 57:
+#line 464 "parser.y"
     { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
     break;
 
-  case 50:
-#line 431 "parser.y"
+  case 58:
+#line 468 "parser.y"
     { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
     break;
 
-  case 51:
-#line 435 "parser.y"
+  case 59:
+#line 472 "parser.y"
     { (yyval.sel) = _gmx_sel_init_variable_ref((yyvsp[(1) - (1)].sel)); ;}
     break;
 
-  case 52:
-#line 444 "parser.y"
+  case 60:
+#line 481 "parser.y"
     { (yyval.param) = process_param_list((yyvsp[(1) - (1)].param)); ;}
     break;
 
-  case 53:
-#line 446 "parser.y"
+  case 61:
+#line 483 "parser.y"
     { (yyval.param) = process_param_list((yyvsp[(1) - (2)].param)); ;}
     break;
 
-  case 54:
-#line 450 "parser.y"
+  case 62:
+#line 487 "parser.y"
     { (yyval.param) = NULL;              ;}
     break;
 
-  case 55:
-#line 452 "parser.y"
+  case 63:
+#line 489 "parser.y"
     { (yyvsp[(2) - (2)].param)->next = (yyvsp[(1) - (2)].param); (yyval.param) = (yyvsp[(2) - (2)].param); ;}
     break;
 
-  case 56:
-#line 457 "parser.y"
+  case 64:
+#line 494 "parser.y"
     {
                  (yyval.param) = _gmx_selexpr_create_param((yyvsp[(1) - (2)].str));
                  (yyval.param)->value = process_value_list((yyvsp[(2) - (2)].val), &(yyval.param)->nval);
              ;}
     break;
 
-  case 57:
-#line 463 "parser.y"
+  case 65:
+#line 500 "parser.y"
     { (yyval.val) = NULL; ;}
     break;
 
-  case 58:
-#line 464 "parser.y"
+  case 66:
+#line 501 "parser.y"
     { (yyval.val) = (yyvsp[(1) - (1)].val);   ;}
     break;
 
-  case 59:
-#line 468 "parser.y"
+  case 67:
+#line 505 "parser.y"
     { (yyval.val) = (yyvsp[(1) - (1)].val); ;}
     break;
 
-  case 60:
-#line 470 "parser.y"
+  case 68:
+#line 507 "parser.y"
     { (yyvsp[(2) - (2)].val)->next = (yyvsp[(1) - (2)].val); (yyval.val) = (yyvsp[(2) - (2)].val); ;}
     break;
 
-  case 61:
-#line 472 "parser.y"
+  case 69:
+#line 509 "parser.y"
     { (yyvsp[(3) - (3)].val)->next = (yyvsp[(1) - (3)].val); (yyval.val) = (yyvsp[(3) - (3)].val); ;}
     break;
 
-  case 62:
-#line 476 "parser.y"
+  case 70:
+#line 513 "parser.y"
     { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
     break;
 
-  case 63:
-#line 478 "parser.y"
+  case 71:
+#line 515 "parser.y"
     { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
     break;
 
-  case 64:
-#line 480 "parser.y"
+  case 72:
+#line 517 "parser.y"
     { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
     break;
 
-  case 65:
-#line 482 "parser.y"
+  case 73:
+#line 519 "parser.y"
+    { (yyval.val) = _gmx_selexpr_create_value_expr((yyvsp[(1) - (1)].sel)); ;}
+    break;
+
+  case 74:
+#line 521 "parser.y"
     {
                  (yyval.val) = _gmx_selexpr_create_value(INT_VALUE);
                  (yyval.val)->u.i.i1 = (yyvsp[(1) - (3)].i); (yyval.val)->u.i.i2 = (yyvsp[(3) - (3)].i);
              ;}
     break;
 
-  case 66:
-#line 487 "parser.y"
+  case 75:
+#line 526 "parser.y"
     {
                  (yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
                  (yyval.val)->u.r.r1 = (yyvsp[(1) - (3)].i); (yyval.val)->u.r.r2 = (yyvsp[(3) - (3)].r);
              ;}
     break;
 
-  case 67:
-#line 492 "parser.y"
+  case 76:
+#line 531 "parser.y"
     {
                  (yyval.val) = _gmx_selexpr_create_value(REAL_VALUE);
                  (yyval.val)->u.r.r1 = (yyvsp[(1) - (3)].r); (yyval.val)->u.r.r2 = (yyvsp[(3) - (3)].r);
              ;}
     break;
 
-  case 68:
-#line 497 "parser.y"
-    {
-                 (yyval.val) = _gmx_selexpr_create_value(STR_VALUE);
-                 (yyval.val)->u.s = (yyvsp[(1) - (1)].str);
-             ;}
-    break;
-
 
 /* Line 1267 of yacc.c.  */
-#line 2076 "parser.c"
+#line 2162 "parser.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2286,7 +2372,7 @@ yyreturn:
 }
 
 
-#line 503 "parser.y"
+#line 537 "parser.y"
 
 
 static t_selexpr_value *
index f2b1f1b832909708892c80b19fd9897fc0f1c3e5..088158bd72fd40369d7a2b874d7348dba2db6c7e 100644 (file)
@@ -69,7 +69,8 @@
      XOR = 285,
      OR = 286,
      AND = 287,
-     NOT = 288
+     NOT = 288,
+     UNARY_NEG = 289
    };
 #endif
 /* Tokens.  */
 #define OR 286
 #define AND 287
 #define NOT 288
+#define UNARY_NEG 289
 
 
 
@@ -122,8 +124,8 @@ typedef union YYSTYPE
     struct t_selexpr_value     *val;
     struct t_selexpr_param     *param;
 }
-/* Line 1529 of yacc.c.  */
-#line 127 "parser.h"
+/* Line 1489 of yacc.c.  */
+#line 129 "parser.h"
        YYSTYPE;
 # define yystype YYSTYPE /* obsolescent; will be withdrawn */
 # define YYSTYPE_IS_DECLARED 1
index 81b92d1b803e2773028f6343314c7e449b316867..4bd09f2a2afca4d914b7bb1f822e6e2d2392adc3 100644 (file)
@@ -123,9 +123,15 @@ yyerror(yyscan_t, char const *s);
 %nonassoc <str> CMP_OP
 /* A dummy token that determines the precedence of parameter reduction */
 %nonassoc       PARAM_REDUCT
-/* Operator tokens */
-%left           AND OR XOR
+/* Boolean operator tokens */
+%left           OR XOR
+%left           AND
 %left           NOT
+/* Arithmetic operator tokens */
+%left           '+' '-'
+%left           '*' '/'
+%right          UNARY_NEG   /* Dummy token for unary negation precedence */
+%right          '^'
 
 /* Simple non-terminals */
 %type <r>     number
@@ -137,21 +143,22 @@ yyerror(yyscan_t, char const *s);
 %type <sel>   selection
 %type <sel>   sel_expr
 %type <sel>   num_expr
+%type <sel>   str_expr
 %type <sel>   pos_expr
 
 /* Parameter/value non-terminals */
 %type <param> method_params method_param_list method_param
 %type <val>   value_list value_list_nonempty value_item
 
-%destructor { free($$);                     } HELP_TOPIC STR IDENTIFIER string
+%destructor { free($$);                     } HELP_TOPIC STR IDENTIFIER CMP_OP string
 %destructor { if($$) free($$);              } PARAM
 %destructor { if($$) _gmx_selelem_free($$); } command cmd_plain
 %destructor { _gmx_selelem_free_chain($$);  } selection
-%destructor { _gmx_selelem_free($$);        } sel_expr num_expr pos_expr
+%destructor { _gmx_selelem_free($$);        } sel_expr num_expr str_expr pos_expr
 %destructor { _gmx_selexpr_free_params($$); } method_params method_param_list method_param
 %destructor { _gmx_selexpr_free_values($$); } value_list value_list_nonempty value_item
 
-%expect 72
+%expect 91
 %debug
 %pure-parser
 
@@ -386,8 +393,38 @@ num_expr:    pos_mod KEYWORD_NUMERIC
              }
 ;
 
-/* Grouping of numeric expressions */
-num_expr:    '(' num_expr ')'   { $$ = $2; }
+/* Arithmetic evaluation and grouping */
+num_expr:    num_expr '+' num_expr
+             { $$ = _gmx_sel_init_arithmetic($1, $3, '+', scanner); }
+           | num_expr '-' num_expr
+             { $$ = _gmx_sel_init_arithmetic($1, $3, '-', scanner); }
+           | num_expr '*' num_expr
+             { $$ = _gmx_sel_init_arithmetic($1, $3, '*', scanner); }
+           | num_expr '/' num_expr
+             { $$ = _gmx_sel_init_arithmetic($1, $3, '/', scanner); }
+           | '-' num_expr %prec UNARY_NEG
+             { $$ = _gmx_sel_init_arithmetic($2, NULL, '-', scanner); }
+           | num_expr '^' num_expr
+             { $$ = _gmx_sel_init_arithmetic($1, $3, '^', scanner); }
+           | '(' num_expr ')'   { $$ = $2; }
+;
+
+/********************************************************************
+ * STRING EXPRESSIONS
+ ********************************************************************/
+
+str_expr:    string
+             {
+                 $$ = _gmx_selelem_create(SEL_CONST);
+                 _gmx_selelem_set_vtype($$, STR_VALUE);
+                 _gmx_selvalue_reserve(&$$->v, 1);
+                 $$->v.u.s[0] = $1;
+             }
+           | pos_mod KEYWORD_STR
+             {
+                 $$ = _gmx_sel_init_keyword($2, NULL, $1, scanner);
+                 if ($$ == NULL) YYERROR;
+             }
 ;
 
 /********************************************************************
@@ -478,6 +515,8 @@ value_item:  sel_expr            %prec PARAM_REDUCT
              { $$ = _gmx_selexpr_create_value_expr($1); }
            | num_expr            %prec PARAM_REDUCT
              { $$ = _gmx_selexpr_create_value_expr($1); }
+           | str_expr            %prec PARAM_REDUCT
+             { $$ = _gmx_selexpr_create_value_expr($1); }
            | TOK_INT TO TOK_INT
              {
                  $$ = _gmx_selexpr_create_value(INT_VALUE);
@@ -493,11 +532,6 @@ value_item:  sel_expr            %prec PARAM_REDUCT
                  $$ = _gmx_selexpr_create_value(REAL_VALUE);
                  $$->u.r.r1 = $1; $$->u.r.r2 = $3;
              }
-           | string
-             {
-                 $$ = _gmx_selexpr_create_value(STR_VALUE);
-                 $$->u.s = $1;
-             }
 ;
 
 %%
index daae031d77cfe18f31bb5f0b0f09982d7e4848b9..7cf7f07122f1de1589eeff54aad2c3f326013d1b 100644 (file)
  * which are in the order given in the input.
  * The children always have \ref GROUP_VALUE, but different element types
  * are possible.
+ *
+ *
+ * \subsection selparser_tree_arith Arithmetic elements
+ *
+ * One \ref SEL_ARITHMETIC element is created for each arithmetic operation in
+ * the input, and the tree structure represents the evaluation order.
+ * The \c t_selelem::optype type gives the name of the operation.
+ * Each element has exactly two children (one for unary negation elements),
+ * which are in the order given in the input.
  */
 #ifdef HAVE_CONFIG_H
 #include <config.h>
@@ -360,7 +369,8 @@ _gmx_selelem_update_flags(t_selelem *sel)
 {
     t_selelem          *child;
     int                 rc;
-    bool                bUseChildType;
+    bool                bUseChildType=FALSE;
+    bool                bOnlySingleChildren;
 
     /* Return if the flags have already been set */
     if (sel->flags & SEL_FLAGSSET)
@@ -395,6 +405,11 @@ _gmx_selelem_update_flags(t_selelem *sel)
             bUseChildType = FALSE;
             break;
 
+        case SEL_ARITHMETIC:
+            sel->flags |= SEL_ATOMVAL;
+            bUseChildType = FALSE;
+            break;
+
         case SEL_MODIFIER:
             if (sel->v.type != NO_VALUE)
             {
@@ -407,11 +422,14 @@ _gmx_selelem_update_flags(t_selelem *sel)
             bUseChildType = FALSE;
             break;
 
-        default:
+        case SEL_BOOLEAN:
+        case SEL_SUBEXPR:
+        case SEL_SUBEXPRREF:
             bUseChildType = TRUE;
             break;
     }
     /* Loop through children to propagate their flags upwards */
+    bOnlySingleChildren = TRUE;
     child = sel->child;
     while (child)
     {
@@ -434,33 +452,40 @@ _gmx_selelem_update_flags(t_selelem *sel)
             }
             sel->flags |= (child->flags & SEL_VALTYPEMASK);
         }
+        if (!(child->flags & SEL_SINGLEVAL))
+        {
+            bOnlySingleChildren = FALSE;
+        }
 
         child = child->next;
     }
-    /* Mark that the flags are set */
-    sel->flags |= SEL_FLAGSSET;
+    /* For arithmetic expressions consisting only of single values,
+     * the result is also a single value. */
+    if (sel->type == SEL_ARITHMETIC && bOnlySingleChildren)
+    {
+        sel->flags = (sel->flags & ~SEL_VALTYPEMASK) | SEL_SINGLEVAL;
+    }
     /* For root elements, the type should be propagated here, after the
      * children have been updated. */
     if (sel->type == SEL_ROOT)
     {
         sel->flags |= (sel->child->flags & SEL_VALTYPEMASK);
     }
+    /* Mark that the flags are set */
+    sel->flags |= SEL_FLAGSSET;
     return 0;
 }
 
-/*! \brief
- * Initializes the method parameter data of \ref SEL_EXPRESSION and
- * \ref SEL_MODIFIER elements.
- *
- * \param[in]     sc     Selection collection.
+/*!
  * \param[in,out] sel    Selection element to initialize.
+ * \param[in]     scanner Scanner data structure.
  *
  * A deep copy of the parameters is made to allow several
  * expressions with the same method to coexist peacefully.
  * Calls sel_datafunc() if one is specified for the method.
  */
-static void
-init_method_params(gmx_ana_selcollection_t *sc, t_selelem *sel)
+void
+_gmx_selelem_init_method_params(t_selelem *sel, yyscan_t scanner)
 {
     int                 nparams;
     gmx_ana_selparam_t *orgparam;
@@ -507,6 +532,8 @@ init_method_params(gmx_ana_selcollection_t *sc, t_selelem *sel)
     }
     if (sel->u.expr.method->set_poscoll)
     {
+        gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
+
         sel->u.expr.method->set_poscoll(sc->pcc, mdata);
     }
     /* Store the values */
@@ -514,19 +541,17 @@ init_method_params(gmx_ana_selcollection_t *sc, t_selelem *sel)
     sel->u.expr.mdata         = mdata;
 }
 
-/*! \brief
- * Initializes the method for a \ref SEL_EXPRESSION selection element.
- *
- * \param[in]     sc     Selection collection.
+/*!
  * \param[in,out] sel    Selection element to initialize.
  * \param[in]     method Selection method to set.
+ * \param[in]     scanner Scanner data structure.
  *
  * Makes a copy of \p method and stores it in \p sel->u.expr.method,
- * and calls init_method_params();
+ * and calls _gmx_selelem_init_method_params();
  */
-static void
-set_method(gmx_ana_selcollection_t *sc, t_selelem *sel,
-           gmx_ana_selmethod_t *method)
+void
+_gmx_selelem_set_method(t_selelem *sel, gmx_ana_selmethod_t *method,
+                        yyscan_t scanner)
 {
     int      i;
 
@@ -534,7 +559,7 @@ set_method(gmx_ana_selcollection_t *sc, t_selelem *sel,
     sel->name   = method->name;
     snew(sel->u.expr.method, 1);
     memcpy(sel->u.expr.method, method, sizeof(gmx_ana_selmethod_t));
-    init_method_params(sc, sel);
+    _gmx_selelem_init_method_params(sel, scanner);
 }
 
 /*! \brief
@@ -571,6 +596,42 @@ set_refpos_type(gmx_ana_poscalc_coll_t *pcc, t_selelem *sel, const char *rpost)
     return rc;
 }
 
+/*!
+ * \param[in]  left    Selection element for the left hand side.
+ * \param[in]  right   Selection element for the right hand side.
+ * \param[in]  op      String representation of the operator.
+ * \param[in]  scanner Scanner data structure.
+ * \returns    The created selection element.
+ *
+ * This function handles the creation of a \c t_selelem object for
+ * arithmetic expressions.
+ */
+t_selelem *
+_gmx_sel_init_arithmetic(t_selelem *left, t_selelem *right, char op,
+                         yyscan_t scanner)
+{
+    t_selelem         *sel;
+    char               buf[2];
+
+    buf[0] = op;
+    buf[1] = 0;
+    sel = _gmx_selelem_create(SEL_ARITHMETIC);
+    sel->v.type        = REAL_VALUE;
+    switch(op)
+    {
+        case '+': sel->u.arith.type = ARITH_PLUS; break;
+        case '-': sel->u.arith.type = (right ? ARITH_MINUS : ARITH_NEG); break;
+        case '*': sel->u.arith.type = ARITH_MULT; break;
+        case '/': sel->u.arith.type = ARITH_DIV;  break;
+        case '^': sel->u.arith.type = ARITH_EXP;  break;
+    }
+    sel->u.arith.opstr = strdup(buf);
+    sel->name          = sel->u.arith.opstr;
+    sel->child         = left;
+    sel->child->next   = right;
+    return sel;
+}
+
 /*!
  * \param[in]  left   Selection element for the left hand side.
  * \param[in]  right  Selection element for the right hand side.
@@ -585,14 +646,13 @@ t_selelem *
 _gmx_sel_init_comparison(t_selelem *left, t_selelem *right, char *cmpop,
                          yyscan_t scanner)
 {
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
     t_selelem         *sel;
     t_selexpr_param   *params, *param;
     const char        *name;
     int                rc;
 
     sel = _gmx_selelem_create(SEL_EXPRESSION);
-    set_method(sc, sel, &sm_compare);
+    _gmx_selelem_set_method(sel, &sm_compare, scanner);
     /* Create the parameter for the left expression */
     name               = left->v.type == INT_VALUE ? "int1" : "real1";
     params = param     = _gmx_selexpr_create_param(strdup(name));
@@ -650,7 +710,7 @@ _gmx_sel_init_keyword(gmx_ana_selmethod_t *method, t_selexpr_value *args,
 
     root = _gmx_selelem_create(SEL_EXPRESSION);
     child = root;
-    set_method(sc, child, method);
+    _gmx_selelem_set_method(child, method, scanner);
 
     /* Initialize the evaluation of keyword matching if values are provided */
     if (args)
@@ -676,7 +736,7 @@ _gmx_sel_init_keyword(gmx_ana_selmethod_t *method, t_selexpr_value *args,
         }
         /* Initialize the selection element */
         root = _gmx_selelem_create(SEL_EXPRESSION);
-        set_method(sc, root, kwmethod);
+        _gmx_selelem_set_method(root, kwmethod, scanner);
         params = param = _gmx_selexpr_create_param(NULL);
         param->nval    = 1;
         param->value   = _gmx_selexpr_create_value_expr(child);
@@ -714,6 +774,11 @@ on_error:
  *
  * This function handles the creation of a \c t_selelem object for
  * selection methods that take parameters.
+ *
+ * Part of the behavior of the \c same selection keyword is hardcoded into
+ * this function (or rather, into _gmx_selelem_custom_init_same()) to allow the
+ * use of any keyword in \c "same KEYWORD as" without requiring special
+ * handling somewhere else (or sacrificing the simple syntax).
  */
 t_selelem *
 _gmx_sel_init_method(gmx_ana_selmethod_t *method, t_selexpr_param *params,
@@ -724,8 +789,15 @@ _gmx_sel_init_method(gmx_ana_selmethod_t *method, t_selexpr_param *params,
     int              rc;
 
     _gmx_sel_finish_method(scanner);
+    /* The "same" keyword needs some custom massaging of the parameters. */
+    rc = _gmx_selelem_custom_init_same(&method, params, scanner);
+    if (rc != 0)
+    {
+        _gmx_selexpr_free_params(params);
+        return NULL;
+    }
     root = _gmx_selelem_create(SEL_EXPRESSION);
-    set_method(sc, root, method);
+    _gmx_selelem_set_method(root, method, scanner);
     /* Process the parameters */
     if (!_gmx_sel_parse_params(params, root->u.expr.method->nparams,
                                root->u.expr.method->param, root, scanner))
@@ -757,7 +829,6 @@ t_selelem *
 _gmx_sel_init_modifier(gmx_ana_selmethod_t *method, t_selexpr_param *params,
                        t_selelem *sel, yyscan_t scanner)
 {
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
     t_selelem         *root;
     t_selelem         *mod;
     t_selexpr_param   *vparam;
@@ -765,7 +836,7 @@ _gmx_sel_init_modifier(gmx_ana_selmethod_t *method, t_selexpr_param *params,
 
     _gmx_sel_finish_method(scanner);
     mod = _gmx_selelem_create(SEL_MODIFIER);
-    set_method(sc, mod, method);
+    _gmx_selelem_set_method(mod, method, scanner);
     if (method->type == NO_VALUE)
     {
         t_selelem *child;
@@ -814,12 +885,11 @@ _gmx_sel_init_modifier(gmx_ana_selmethod_t *method, t_selexpr_param *params,
 t_selelem *
 _gmx_sel_init_position(t_selelem *expr, const char *type, yyscan_t scanner)
 {
-    gmx_ana_selcollection_t *sc = _gmx_sel_lexer_selcollection(scanner);
     t_selelem       *root;
     t_selexpr_param *params;
 
     root = _gmx_selelem_create(SEL_EXPRESSION);
-    set_method(sc, root, &sm_keyword_pos);
+    _gmx_selelem_set_method(root, &sm_keyword_pos, scanner);
     _gmx_selelem_set_kwpos_type(root, type);
     /* Create the parameters for the parameter parser. */
     params        = _gmx_selexpr_create_param(NULL);
index 66a4c570a9475528fc7fe678fc5d9242e955ced6..060fbc34817836a89d3819794605aba346c1d1b5 100644 (file)
@@ -129,6 +129,19 @@ _gmx_selexpr_free_params(t_selexpr_param *param);
 int
 _gmx_selelem_update_flags(struct t_selelem *sel);
 
+/** Initializes the method parameter data of \ref SEL_EXPRESSION and
+ * \ref SEL_MODIFIER elements. */
+void
+_gmx_selelem_init_method_params(struct t_selelem *sel, void *scanner);
+/** Initializes the method for a \ref SEL_EXPRESSION selection element. */
+void
+_gmx_selelem_set_method(struct t_selelem *sel,
+                        struct gmx_ana_selmethod_t *method, void *scanner);
+
+/** Creates a \c t_selelem for arithmetic expression evaluation. */
+struct t_selelem *
+_gmx_sel_init_arithmetic(struct t_selelem *left, struct t_selelem *right,
+                         char op, void *scanner);
 /** Creates a \c t_selelem for comparsion expression evaluation. */
 struct t_selelem *
 _gmx_sel_init_comparison(struct t_selelem *left, struct t_selelem *right,
index 1e6bb449a453b6f96d10fe07c2eec909449b2da3..00edefef9e3dbcdce30b0c6b654c27047c386f2d 100644 (file)
@@ -86,6 +86,8 @@ struct gmx_ana_selcollection_t
     bool                        bVelocities;
     /** TRUE if forces should be evaluated for output positions. */
     bool                        bForces;
+    /** TRUE if debugging output should be printed during compilation. */
+    bool                        bDebugCompile;
 
     /** Root of the selection element tree. */
     struct t_selelem           *root;
@@ -104,6 +106,8 @@ struct gmx_ana_selcollection_t
     struct gmx_ana_index_t         gall;
     /** Position calculation collection used for selection position evaluation. */
     struct gmx_ana_poscalc_coll_t *pcc;
+    /** Memory pool used for selection evaluation. */
+    struct gmx_sel_mempool_t      *mempool;
     /** Parser symbol table. */
     struct gmx_sel_symtab_t     *symtab;
 };
index 08393d4f88ebf122dec1a62d0e556088f6e5fe8e..100afdfd907a959b7225a704a5c86862d57f1fd8 100644 (file)
@@ -50,6 +50,7 @@
 #include <selection.h>
 #include <selmethod.h>
 
+#include "mempool.h"
 #include "selcollection.h"
 #include "selelem.h"
 #include "symrec.h"
@@ -72,6 +73,7 @@ gmx_ana_selcollection_create(gmx_ana_selcollection_t **scp,
     sc->bMaskOnly = FALSE;
     sc->bVelocities = FALSE;
     sc->bForces   = FALSE;
+    sc->bDebugCompile = FALSE;
     sc->root      = NULL;
     sc->nr        = 0;
     sc->sel       = NULL;
@@ -80,6 +82,7 @@ gmx_ana_selcollection_create(gmx_ana_selcollection_t **scp,
     sc->top       = NULL;
     gmx_ana_index_clear(&sc->gall);
     sc->pcc       = pcc;
+    sc->mempool   = NULL;
     _gmx_sel_symtab_create(&sc->symtab);
     *scp = sc;
     return 0;
@@ -110,6 +113,10 @@ gmx_ana_selcollection_free(gmx_ana_selcollection_t *sc)
     }
     sfree(sc->varstrs);
     gmx_ana_index_deinit(&sc->gall);
+    if (sc->mempool)
+    {
+        _gmx_sel_mempool_destroy(sc->mempool);
+    }
     _gmx_selcollection_clear_symtab(sc);
     sfree(sc);
 }
index b88a86d3677d352d3a6f47e2ded1e8d6826be3c9..8f8e30d88a2cd4e973d2294fb9e2a702ced06ee6 100644 (file)
@@ -43,8 +43,8 @@
 #include <position.h>
 #include <selmethod.h>
 
-#include "evaluate.h"
 #include "keywords.h"
+#include "mempool.h"
 #include "selelem.h"
 
 /*!
@@ -63,6 +63,7 @@ _gmx_selelem_type_str(t_selelem *sel)
         case SEL_CONST:      return "CONST";
         case SEL_EXPRESSION: return "EXPR";
         case SEL_BOOLEAN:    return "BOOL";
+        case SEL_ARITHMETIC: return "ARITH";
         case SEL_ROOT:       return "ROOT";
         case SEL_SUBEXPR:    return "SUBEXPR";
         case SEL_SUBEXPRREF: return "REF";
@@ -139,6 +140,7 @@ _gmx_selelem_create(e_selelem_t type)
     }
     _gmx_selvalue_clear(&sel->v);
     sel->evaluate   = NULL;
+    sel->mempool    = NULL;
     sel->child      = NULL;
     sel->next       = NULL;
     sel->refcount   = 1;
@@ -178,6 +180,80 @@ _gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype)
     return 0;
 }
 
+/*!
+ * \param[in,out] sel   Selection element to reserve.
+ * \param[in]     count Number of values to reserve memory for.
+ * \returns       0 on success or if no memory pool, non-zero on error.
+ *
+ * Reserves memory for the values of \p sel from the \p sel->mempool
+ * memory pool. If no memory pool is set, nothing is done.
+ */
+int
+_gmx_selelem_mempool_reserve(t_selelem *sel, int count)
+{
+    int rc = 0;
+
+    if (!sel->mempool)
+    {
+        return 0;
+    }
+    switch (sel->v.type)
+    {
+        case INT_VALUE:
+            rc = _gmx_sel_mempool_alloc(sel->mempool, (void **)&sel->v.u.i,
+                                        sizeof(*sel->v.u.i)*count);
+            break;
+
+        case REAL_VALUE:
+            rc = _gmx_sel_mempool_alloc(sel->mempool, (void **)&sel->v.u.r,
+                                        sizeof(*sel->v.u.r)*count);
+            break;
+
+        case GROUP_VALUE:
+            rc = _gmx_sel_mempool_alloc_group(sel->mempool, sel->v.u.g, count);
+            break;
+
+        default:
+            gmx_incons("mem pooling not implemented for requested type");
+            return -1;
+    }
+    return rc;
+}
+
+/*!
+ * \param[in,out] sel   Selection element to release.
+ *
+ * Releases the memory allocated for the values of \p sel from the
+ * \p sel->mempool memory pool. If no memory pool is set, nothing is done.
+ */
+void
+_gmx_selelem_mempool_release(t_selelem *sel)
+{
+    if (!sel->mempool)
+    {
+        return;
+    }
+    switch (sel->v.type)
+    {
+        case INT_VALUE:
+        case REAL_VALUE:
+            _gmx_sel_mempool_free(sel->mempool, sel->v.u.ptr);
+            _gmx_selvalue_setstore(&sel->v, NULL);
+            break;
+
+        case GROUP_VALUE:
+            if (sel->v.u.g)
+            {
+                _gmx_sel_mempool_free_group(sel->mempool, sel->v.u.g);
+            }
+            break;
+
+        default:
+            gmx_incons("mem pooling not implemented for requested type");
+            break;
+    }
+}
+
 /*!
  * \param[in] sel Selection to free.
  */
@@ -186,6 +262,7 @@ _gmx_selelem_free_values(t_selelem *sel)
 {
     int   i, n;
 
+    _gmx_selelem_mempool_release(sel);
     if ((sel->flags & SEL_ALLOCDATA) && sel->v.u.ptr)
     {
         /* The number of position/group structures is constant, so the
@@ -227,78 +304,89 @@ _gmx_selelem_free_values(t_selelem *sel)
         sfree(sel->v.u.ptr);
     }
     _gmx_selvalue_setstore(&sel->v, NULL);
+    if (sel->type == SEL_SUBEXPRREF && sel->u.param)
+    {
+        sel->u.param->val.u.ptr = NULL;
+    }
 }
 
 /*!
- * \param[in] sel Selection to free.
+ * \param[in] method Method to free.
+ * \param[in] mdata  Method data to free.
  */
 void
-_gmx_selelem_free_exprdata(t_selelem *sel)
+_gmx_selelem_free_method(gmx_ana_selmethod_t *method, void *mdata)
 {
-    int i;
+    sel_freefunc free_func = NULL;
 
-    if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
+    /* Save the pointer to the free function. */
+    if (method && method->free)
     {
-        /* Free method data */
-        if (sel->u.expr.mdata)
-        {
-            if (sel->u.expr.method && sel->u.expr.method->free)
-            {
-                sel->u.expr.method->free(sel->u.expr.mdata);
-            }
-            sfree(sel->u.expr.mdata);
-            sel->u.expr.mdata = NULL;
-        }
-        /* Free the method itself */
-        if (sel->u.expr.method)
+        free_func = method->free;
+    }
+
+    /* Free the method itself.
+     * Has to be done before freeing the method data, because parameter
+     * values are typically stored in the method data, and here we may
+     * access them. */
+    if (method)
+    {
+        int  i, j;
+
+        /* Free the memory allocated for the parameters that are not managed
+         * by the selection method itself. */
+        for (i = 0; i < method->nparams; ++i)
         {
-            /* If the method has not yet been initialized, we must free the
-             * memory allocated for parameter values here. */
-            if (!(sel->flags & SEL_METHODINIT))
+            gmx_ana_selparam_t *param = &method->param[i];
+
+            if (param->val.u.ptr)
             {
-                for (i = 0; i < sel->u.expr.method->nparams; ++i)
+                if (param->val.type == GROUP_VALUE)
                 {
-                    gmx_ana_selparam_t *param = &sel->u.expr.method->param[i];
-
-                    if ((param->flags & (SPAR_VARNUM | SPAR_ATOMVAL))
-                        && param->val.type != GROUP_VALUE
-                        && param->val.type != POS_VALUE)
+                    for (j = 0; j < param->val.nr; ++j)
                     {
-                        /* We don't need to check for enum values here, because
-                         * SPAR_ENUMVAL cannot be combined with the flags
-                         * required above. If it ever will be, this results
-                         * in a double free within this function, which should
-                         * be relatively easy to debug.
-                         */
-                        if (param->val.type == STR_VALUE)
-                        {
-                            int j;
-
-                            for (j = 0; j < param->val.nr; ++j)
-                            {
-                                sfree(param->val.u.s[j]);
-                            }
-                        }
-                        sfree(param->val.u.ptr);
+                        gmx_ana_index_deinit(&param->val.u.g[j]);
+                    }
+                }
+                else if (param->val.type == POS_VALUE)
+                {
+                    for (j = 0; j < param->val.nr; ++j)
+                    {
+                        gmx_ana_pos_deinit(&param->val.u.p[j]);
                     }
                 }
-            }
-            /* And even if it is, the arrays allocated for enum values need
-             * to be freed. */
-            for (i = 0; i < sel->u.expr.method->nparams; ++i)
-            {
-                gmx_ana_selparam_t *param = &sel->u.expr.method->param[i];
 
-                if (param->flags & SPAR_ENUMVAL)
+                if (param->val.nalloc > 0)
                 {
                     sfree(param->val.u.ptr);
                 }
-
             }
-            sfree(sel->u.expr.method->param);
-            sfree(sel->u.expr.method);
-            sel->u.expr.method = NULL;
         }
+        sfree(method->param);
+        sfree(method);
+    }
+    /* Free method data. */
+    if (mdata)
+    {
+        if (free_func)
+        {
+            free_func(mdata);
+        }
+        sfree(mdata);
+    }
+}
+
+/*!
+ * \param[in] sel Selection to free.
+ */
+void
+_gmx_selelem_free_exprdata(t_selelem *sel)
+{
+    if (sel->type == SEL_EXPRESSION || sel->type == SEL_MODIFIER)
+    {
+        _gmx_selelem_free_method(sel->u.expr.method, sel->u.expr.mdata);
+        sel->u.expr.mdata = NULL;
+        sel->u.expr.method = NULL;
         /* Free position data */
         if (sel->u.expr.pos)
         {
@@ -312,6 +400,16 @@ _gmx_selelem_free_exprdata(t_selelem *sel)
             sel->u.expr.pc = NULL;
         }
     }
+    if (sel->type == SEL_ARITHMETIC)
+    {
+        sfree(sel->u.arith.opstr);
+        sel->u.arith.opstr = NULL;
+    }
+    if (sel->type == SEL_SUBEXPR || sel->type == SEL_ROOT
+        || (sel->type == SEL_CONST && sel->v.type == GROUP_VALUE))
+    {
+        gmx_ana_index_deinit(&sel->u.cgrp);
+    }
 }
 
 /*!
@@ -324,8 +422,6 @@ _gmx_selelem_free_exprdata(t_selelem *sel)
 void
 _gmx_selelem_free(t_selelem *sel)
 {
-    t_selelem *child, *prev;
-    
     /* Decrement the reference counter and do nothing if references remain */
     sel->refcount--;
     if (sel->refcount > 0)
@@ -333,25 +429,16 @@ _gmx_selelem_free(t_selelem *sel)
         return;
     }
 
-    /* Free the children */
-    child = sel->child;
-    while (child)
-    {
-        prev = child;
-        child = child->next;
-        _gmx_selelem_free(prev);
-    }
+    /* Free the children.
+     * Must be done before freeing other data, because the children may hold
+     * references to data in this element. */
+    _gmx_selelem_free_chain(sel->child);
 
     /* Free value storage */
     _gmx_selelem_free_values(sel);
 
     /* Free other storage */
     _gmx_selelem_free_exprdata(sel);
-    if (sel->type == SEL_SUBEXPR || sel->type == SEL_ROOT
-        || (sel->type == SEL_CONST && sel->v.type == GROUP_VALUE))
-    {
-        gmx_ana_index_deinit(&sel->u.cgrp);
-    }
 
     /* Free temporary compiler data if present */
     _gmx_selelem_free_compiler_data(sel);
@@ -379,44 +466,6 @@ _gmx_selelem_free_chain(t_selelem *first)
     }
 }
 
-/*! \brief
- * Writes out a human-readable name for the evaluation function.
- *
- * \param[in] fp  File handle to receive the output.
- * \param[in] sel Selection element for which the evaluation function is printed.
- */
-static void
-print_evaluation_func(FILE *fp, t_selelem *sel)
-{
-    fprintf(fp, " eval=");
-    if (!sel->evaluate)
-        fprintf(fp, "none");
-    else if (sel->evaluate == &_gmx_sel_evaluate_root)
-        fprintf(fp, "root");
-    else if (sel->evaluate == &_gmx_sel_evaluate_static)
-        fprintf(fp, "static");
-    else if (sel->evaluate == &_gmx_sel_evaluate_subexpr_pass)
-        fprintf(fp, "subexpr_pass");
-    else if (sel->evaluate == &_gmx_sel_evaluate_subexpr)
-        fprintf(fp, "subexpr");
-    else if (sel->evaluate == &_gmx_sel_evaluate_subexprref_pass)
-        fprintf(fp, "ref_pass");
-    else if (sel->evaluate == &_gmx_sel_evaluate_subexprref)
-        fprintf(fp, "ref");
-    else if (sel->evaluate == &_gmx_sel_evaluate_method)
-        fprintf(fp, "method");
-    else if (sel->evaluate == &_gmx_sel_evaluate_modifier)
-        fprintf(fp, "mod");
-    else if (sel->evaluate == &_gmx_sel_evaluate_not)
-        fprintf(fp, "not");
-    else if (sel->evaluate == &_gmx_sel_evaluate_and)
-        fprintf(fp, "and");
-    else if (sel->evaluate == &_gmx_sel_evaluate_or)
-        fprintf(fp, "or");
-    else
-        fprintf(fp, "%p", (void*)(sel->evaluate));
-}
-
 /*!
  * \param[in] fp      File handle to receive the output.
  * \param[in] sel     Root of the selection subtree to print.
@@ -461,6 +510,10 @@ _gmx_selelem_print_tree(FILE *fp, t_selelem *sel, bool bValues, int level)
     {
         fprintf(fp, "0");
     }
+    if (sel->mempool)
+    {
+        fprintf(fp, "P");
+    }
     if (sel->type == SEL_CONST)
     {
         if (sel->v.type == INT_VALUE)
@@ -490,7 +543,8 @@ _gmx_selelem_print_tree(FILE *fp, t_selelem *sel, bool bValues, int level)
     }
     if (sel->evaluate)
     {
-        print_evaluation_func(fp, sel);
+        fprintf(fp, " eval=");
+        _gmx_sel_print_evalfunc_name(fp, sel->evaluate);
     }
     if (sel->refcount > 1)
     {
@@ -509,7 +563,11 @@ _gmx_selelem_print_tree(FILE *fp, t_selelem *sel, bool bValues, int level)
         {
             g = &sel->u.cgrp;
         }
-        if (g->isize > 0)
+        if (g->isize < 0)
+        {
+            fprintf(fp, "%*c group: (null)\n", level*2+1, ' ');
+        }
+        else if (g->isize > 0)
         {
             fprintf(fp, "%*c group:", level*2+1, ' ');
             if (g->isize <= 20)
@@ -535,6 +593,11 @@ _gmx_selelem_print_tree(FILE *fp, t_selelem *sel, bool bValues, int level)
         }
     }
 
+    if (sel->cdata)
+    {
+        _gmx_selelem_print_compiler_info(fp, sel, level);
+    }
+
     if (bValues && sel->type != SEL_CONST && sel->type != SEL_ROOT && sel->v.u.ptr)
     {
         fprintf(fp, "%*c value: ", level*2+1, ' ');
index b3c43939314d716dc77cb71024ffffa2f07b2fc7..71c7ba9b36eccb8e16a5ee214086d5a514258466 100644 (file)
@@ -51,6 +51,7 @@ struct gmx_ana_selparam_t;
 struct gmx_ana_selmethod_t;
 
 struct gmx_sel_evaluate_t;
+struct gmx_sel_mempool_t;
 struct t_selelem;
 
 /********************************************************************/
@@ -67,6 +68,8 @@ typedef enum
     SEL_EXPRESSION,
     /** Boolean expression. */
     SEL_BOOLEAN,
+    /** Arithmetic expression. */
+    SEL_ARITHMETIC,
     /** Root node of the evaluation tree. */
     SEL_ROOT,
     /** Subexpression that may be referenced several times. */
@@ -86,6 +89,17 @@ typedef enum
     BOOL_XOR            /**< Xor (not implemented). */
 } e_boolean_t;
 
+/** Defines the arithmetic operation of \c t_selelem objects with type \ref SEL_ARITHMETIC. */
+typedef enum
+{
+    ARITH_PLUS,         /**< + */
+    ARITH_MINUS,        /**< - */
+    ARITH_NEG,          /**< Unary - */
+    ARITH_MULT,         /**< * */
+    ARITH_DIV,          /**< / */
+    ARITH_EXP           /**< ^ (to power) */
+} e_arithmetic_t;
+
 /** Returns a string representation of the type of a \c t_selelem. */
 extern const char *
 _gmx_selelem_type_str(struct t_selelem *sel);
@@ -146,6 +160,13 @@ _gmx_sel_value_type_str(gmx_ana_selvalue_t *val);
  * a selection.
  *
  * Even if the flag is set, \p v.u.ptr can be NULL during initialization.
+ *
+ * \todo
+ * This flag overlaps with the function of \p v.nalloc field, and could
+ * probably be removed, making memory management simpler. Currently, the
+ * \p v.nalloc field is not kept up-to-date in all cases when this flag
+ * is changed and is used in places where this flag is not, so this would
+ * require a careful investigation of the selection code.
  */
 #define SEL_ALLOCVAL    (1<<8)
 /*! \brief
@@ -258,9 +279,18 @@ typedef struct t_selelem
         }                               expr;
         /** Operation type for \ref SEL_BOOLEAN elements. */
         e_boolean_t                     boolt;
+        /** Operation type for \ref SEL_ARITHMETIC elements. */
+        struct {
+            /** Operation type. */
+            e_arithmetic_t              type;
+            /** String representation. */
+            char                       *opstr;
+        }                               arith;
         /** Associated selection parameter for \ref SEL_SUBEXPRREF elements. */
         struct gmx_ana_selparam_t      *param;
     }                                   u;
+    /** Memory pool to use for values, or NULL if standard memory handling. */
+    struct gmx_sel_mempool_t           *mempool;
     /** Internal data for the selection compiler. */
     struct t_compiler_data             *cdata;
     
@@ -278,12 +308,23 @@ typedef struct t_selelem
     int                                  refcount;
 } t_selelem;
 
+/* In evaluate.c */
+/** Writes out a human-readable name for an evaluation function. */
+extern void
+_gmx_sel_print_evalfunc_name(FILE *fp, sel_evalfunc evalfunc);
+
 /** Allocates memory and performs some common initialization for a \c t_selelem. */
 extern t_selelem *
 _gmx_selelem_create(e_selelem_t type);
 /** Sets the value type of a \c t_selelem. */
 extern int
 _gmx_selelem_set_vtype(t_selelem *sel, e_selvalue_t vtype);
+/** Reserves memory for value of a \c t_selelem from a memory pool. */
+extern int
+_gmx_selelem_mempool_reserve(t_selelem *sel, int count);
+/** Releases memory pool used for value of a \c t_selelem. */
+extern void
+_gmx_selelem_mempool_release(t_selelem *sel);
 /** Frees the memory allocated for a \c t_selelem structure and all its children. */
 extern void
 _gmx_selelem_free(t_selelem *sel);
@@ -294,7 +335,10 @@ _gmx_selelem_free_chain(t_selelem *first);
 /** Frees the memory allocated for the \c t_selelem::d union. */
 extern void
 _gmx_selelem_free_values(t_selelem *sel);
-/** Frees the memory allocated for the \c t_selelem::u.expr field. */
+/** Frees the memory allocated for a selection method. */
+extern void
+_gmx_selelem_free_method(struct gmx_ana_selmethod_t *method, void *mdata);
+/** Frees the memory allocated for the \c t_selelem::u field. */
 extern void
 _gmx_selelem_free_exprdata(t_selelem *sel);
 /* In compiler.c */
@@ -305,6 +349,10 @@ _gmx_selelem_free_compiler_data(t_selelem *sel);
 /** Prints a human-readable version of a selection element subtree. */
 extern void
 _gmx_selelem_print_tree(FILE *fp, t_selelem *root, bool bValues, int level);
+/* In compile.c */
+/** Prints a human-readable version of the internal compiler data structure. */
+extern void
+_gmx_selelem_print_compiler_info(FILE *fp, t_selelem *sel, int level);
 
 /** Returns TRUE if the selection element subtree requires topology information for evaluation. */
 extern bool
index 74e77e8d185c6cc1b34180624e53d496e90bbdbc..561eae76c4976c9835ecf5773ff676da8404f4ce 100644 (file)
@@ -57,6 +57,16 @@ static const char *help_common[] = {
     "described under \"syntax\". Available keywords can be found under",
     "\"keywords\", and concrete examples under \"examples\".",
     "Other subtopics give more details on certain aspects.",
+    "\"help all\" prints the help for all subtopics.",
+};
+
+static const char *help_arithmetic[] = {
+    "ARITHMETIC EXPRESSIONS IN SELECTIONS[PAR]",
+
+    "Basic arithmetic evaluation is supported for numeric expressions.",
+    "Supported operations are addition, subtraction, negation, multiplication,",
+    "division, and exponentiation (using ^).",
+    "Result of a division by zero or other illegal operations is undefined.",
 };
 
 static const char *help_cmdline[] = {
@@ -167,13 +177,11 @@ static const char *help_keywords[] = {
 static const char *help_limits[] = {
     "SELECTION LIMITATIONS[PAR]",
 
-    "Arithmetic expressions are not implemented.[PAR]",
-
     "Some analysis programs may require a special structure for the input",
     "selections (e.g., [TT]g_angle[tt] requires the index group to be made",
     "of groups of three or four atoms).",
     "For such programs, it is up to the user to provide a proper selection",
-    "expression that always returns such positions.[PAR]",
+    "expression that always returns such positions.",
 };
 
 static const char *help_positions[] = {
@@ -283,14 +291,15 @@ static const char *help_syntax[] = {
 };
 
 static const t_selection_help_item helpitems[] = {
-    {NULL,          asize(help_common),    help_common},
-    {"cmdline",     asize(help_cmdline),   help_cmdline},
-    {"evaluation",  asize(help_eval),      help_eval},
-    {"examples",    asize(help_examples),  help_examples},
-    {"keywords",    asize(help_keywords),  help_keywords},
-    {"limitations", asize(help_limits),    help_limits},
-    {"positions",   asize(help_positions), help_positions},
-    {"syntax",      asize(help_syntax),    help_syntax},
+    {NULL,          asize(help_common),     help_common},
+    {"cmdline",     asize(help_cmdline),    help_cmdline},
+    {"syntax",      asize(help_syntax),     help_syntax},
+    {"positions",   asize(help_positions),  help_positions},
+    {"arithmetic",  asize(help_arithmetic), help_arithmetic},
+    {"keywords",    asize(help_keywords),   help_keywords},
+    {"evaluation",  asize(help_eval),       help_eval},
+    {"limitations", asize(help_limits),     help_limits},
+    {"examples",    asize(help_examples),   help_examples},
 };
 
 /*! \brief
@@ -325,7 +334,14 @@ print_keyword_list(struct gmx_ana_selcollection_t *sc, e_selvalue_t type,
             }
             else
             {
-                fprintf(stderr, "%s\n", method->name);
+                const char *symname = _gmx_sel_sym_name(symbol);
+
+                fprintf(stderr, "%s", symname);
+                if (strcmp(symname, method->name) != 0)
+                {
+                    fprintf(stderr, " (synonym for %s)", method->name);
+                }
+                fprintf(stderr, "\n");
             }
         }
         symbol = _gmx_sel_next_symbol(symbol, SYMBOL_METHOD);
@@ -342,14 +358,27 @@ print_keyword_list(struct gmx_ana_selcollection_t *sc, e_selvalue_t type,
 void
 _gmx_sel_print_help(struct gmx_ana_selcollection_t *sc, const char *topic)
 {
-    const t_selection_help_item *item = 0;
-    int  i;
+    const t_selection_help_item *item = NULL;
+    size_t i;
 
     /* Find the item for the topic */
     if (!topic)
     {
         item = &helpitems[0];
     }
+    else if (strcmp(topic, "all") == 0)
+    {
+        for (i = 0; i < asize(helpitems); ++i)
+        {
+            item = &helpitems[i];
+            _gmx_sel_print_help(sc, item->topic);
+            if (i != asize(helpitems) - 1)
+            {
+                fprintf(stderr, "\n\n");
+            }
+        }
+        return;
+    }
     else
     {
         for (i = 1; i < asize(helpitems); ++i)
@@ -357,6 +386,7 @@ _gmx_sel_print_help(struct gmx_ana_selcollection_t *sc, const char *topic)
             if (strncmp(helpitems[i].topic, topic, strlen(topic)) == 0)
             {
                 item = &helpitems[i];
+                break;
             }
         }
     }
@@ -388,10 +418,20 @@ _gmx_sel_print_help(struct gmx_ana_selcollection_t *sc, const char *topic)
     /* Special handling of certain pages */
     if (!topic)
     {
+        int len = 0;
+
         /* Print the subtopics on the main page */
         fprintf(stderr, "\nAvailable subtopics:\n");
         for (i = 1; i < asize(helpitems); ++i)
         {
+            int len1 = strlen(helpitems[i].topic) + 2;
+
+            len += len1;
+            if (len > 79)
+            {
+                fprintf(stderr, "\n");
+                len = len1;
+            }
             fprintf(stderr, "  %s", helpitems[i].topic);
         }
         fprintf(stderr, "\n");
index 8d185f109dd2396b4fa838415e1620d7954bc5b3..14482957b594eb580c7d045fc54f3608a5f38896 100644 (file)
@@ -73,7 +73,8 @@ extern gmx_ana_selmethod_t sm_all;
 extern gmx_ana_selmethod_t sm_none;
 extern gmx_ana_selmethod_t sm_atomnr;
 extern gmx_ana_selmethod_t sm_resnr;
-extern gmx_ana_selmethod_t sm_resind;
+extern gmx_ana_selmethod_t sm_resindex;
+extern gmx_ana_selmethod_t sm_molindex;
 extern gmx_ana_selmethod_t sm_atomname;
 extern gmx_ana_selmethod_t sm_atomtype;
 extern gmx_ana_selmethod_t sm_resname;
@@ -102,39 +103,59 @@ extern gmx_ana_selmethod_t sm_plus;
 /* From sm_permute.c */
 extern gmx_ana_selmethod_t sm_permute;
 
+/*! \brief
+ * Helper structure for defining selection methods.
+ */
+typedef struct {
+    /*! \brief
+     * Name to register the method under.
+     *
+     * If NULL, use the actual name of the method.
+     * This field is used for defining synonyms.
+     */
+    const char            *name;
+    /** Method data structure to register. */
+    gmx_ana_selmethod_t   *method;
+} t_register_method;
+
 /** Array of selection methods defined in the library. */
-static gmx_ana_selmethod_t *const smtable_def[] = {
-    &sm_cog,
-    &sm_com,
+static const t_register_method smtable_def[] = {
+    {NULL,         &sm_cog},
+    {NULL,         &sm_com},
 
-    &sm_all,
-    &sm_none,
-    &sm_atomnr,
-    &sm_resnr,
-    &sm_resind,
-    &sm_atomname,
-    &sm_atomtype,
-    &sm_resname,
-    &sm_insertcode,
-    &sm_chain,
-    &sm_mass,
-    &sm_charge,
-    &sm_altloc,
-    &sm_occupancy,
-    &sm_betafactor,
-    &sm_x,
-    &sm_y,
-    &sm_z,
+    {NULL,         &sm_all},
+    {NULL,         &sm_none},
+    {NULL,         &sm_atomnr},
+    {NULL,         &sm_resnr},
+    {"resid",      &sm_resnr},
+    {NULL,         &sm_resindex},
+    {"residue",    &sm_resindex},
+    {NULL,         &sm_molindex},
+    {"mol",        &sm_molindex},
+    {"molecule",   &sm_molindex},
+    {NULL,         &sm_atomname},
+    {NULL,         &sm_atomtype},
+    {NULL,         &sm_resname},
+    {NULL,         &sm_insertcode},
+    {NULL,         &sm_chain},
+    {NULL,         &sm_mass},
+    {NULL,         &sm_charge},
+    {NULL,         &sm_altloc},
+    {NULL,         &sm_occupancy},
+    {NULL,         &sm_betafactor},
+    {NULL,         &sm_x},
+    {NULL,         &sm_y},
+    {NULL,         &sm_z},
 
-    &sm_distance,
-    &sm_mindistance,
-    &sm_within,
-    &sm_insolidangle,
-    &sm_same,
+    {NULL,         &sm_distance},
+    {NULL,         &sm_mindistance},
+    {NULL,         &sm_within},
+    {NULL,         &sm_insolidangle},
+    {NULL,         &sm_same},
 
-    &sm_merge,
-    &sm_plus,
-    &sm_permute,
+    {NULL,         &sm_merge},
+    {NULL,         &sm_plus},
+    {NULL,         &sm_permute},
 };
 
 /*! \brief
@@ -397,7 +418,6 @@ check_callbacks(FILE *fp, gmx_ana_selmethod_t *method)
 {
     bool         bOk = TRUE;
     bool         bNeedInit;
-    bool         bNeedFree;
     int          i;
 
     /* Make some checks on init_data and free */
@@ -419,10 +439,6 @@ check_callbacks(FILE *fp, gmx_ana_selmethod_t *method)
     /* Warn of dynamic callbacks in static methods */
     if (!(method->flags & SMETH_MODIFIER))
     {
-        if (method->init_frame && !(method->flags & SMETH_DYNAMIC))
-        {
-            report_error(fp, method->name, "warning: init_frame not used because the method is static");
-        }
         if (method->pupdate && !(method->flags & SMETH_DYNAMIC))
         {
             report_error(fp, method->name, "warning: pupdate not used because the method is static");
@@ -438,19 +454,12 @@ check_callbacks(FILE *fp, gmx_ana_selmethod_t *method)
     /* Loop through the parameters to determine if initialization callbacks
      * are needed. */
     bNeedInit = FALSE;
-    bNeedFree = FALSE;
     for (i = 0; i < method->nparams; ++i)
     {
-        if (method->param[i].val.type == POS_VALUE
-            || method->param[i].val.type == GROUP_VALUE)
-        {
-            bNeedFree = TRUE;
-        }
         if (method->param[i].val.type != POS_VALUE
             && (method->param[i].flags & (SPAR_VARNUM | SPAR_ATOMVAL)))
         {
             bNeedInit = TRUE;
-            bNeedFree = TRUE;
         }
     }
     /* Check that the callbacks required by the parameters are present */
@@ -459,11 +468,6 @@ check_callbacks(FILE *fp, gmx_ana_selmethod_t *method)
         report_error(fp, method->name, "error: init should be provided");
         bOk = FALSE;
     }
-    if (bNeedFree && !method->free)
-    {
-        report_error(fp, method->name, "error: free should be provided");
-        bOk = FALSE;
-    }
     return bOk;
 }
 
@@ -655,7 +659,16 @@ gmx_ana_selmethod_register_defaults(struct gmx_ana_selcollection_t *sc)
     bOk = TRUE;
     for (i = 0; i < asize(smtable_def); ++i)
     {
-        rc = gmx_ana_selmethod_register(sc, smtable_def[i]->name, smtable_def[i]);
+        gmx_ana_selmethod_t *method = smtable_def[i].method;
+
+        if (smtable_def[i].name == NULL)
+        {
+            rc = gmx_ana_selmethod_register(sc, method->name, method);
+        }
+        else
+        {
+            rc = gmx_ana_selmethod_register(sc, smtable_def[i].name, method);
+        }
         if (rc != 0)
         {
             bOk = FALSE;
index dfd796ae1a9a1ee893c3d5110164a27b0809dfa1..eb98b6d371b179262c2ba11600dc2030f66cfb77 100644 (file)
@@ -52,7 +52,7 @@ typedef enum
     CMP_GTR,            /**< '>' */
     CMP_GEQ,            /**< '>=' */
     CMP_EQUAL,          /**< '==' */
-    CMP_NEQ,            /**< '!=' */
+    CMP_NEQ             /**< '!=' */
 } e_comparison_t;
 
 /** The operand has a single value. */
@@ -61,6 +61,10 @@ typedef enum
 #define CMP_DYNAMICVAL 2
 /** The value is real. */
 #define CMP_REALVAL    4
+/** The integer array is allocated. */
+#define CMP_ALLOCINT   16
+/** The real array is allocated. */
+#define CMP_ALLOCREAL  32
 
 /*! \internal \brief
  * Data structure for comparison expression operand values.
@@ -325,7 +329,7 @@ convert_int_real(int n, t_compare_value *val)
     /* Free the previous value if one is present. */
     sfree(val->r);
     val->r      = rv;
-    val->flags |= CMP_REALVAL;
+    val->flags |= CMP_REALVAL | CMP_ALLOCREAL;
 }
 
 /* \brief
@@ -379,6 +383,7 @@ convert_real_int(int n, t_compare_value *val, e_comparison_t cmpt, bool bRight)
     sfree(val->i);
     val->i      = iv;
     val->flags &= ~CMP_REALVAL;
+    val->flags |= CMP_ALLOCINT;
     return 0;
 }
 
@@ -470,10 +475,22 @@ free_data_compare(void *data)
     t_methoddata_compare *d = (t_methoddata_compare *)data;
 
     sfree(d->cmpop);
-    sfree(d->left.i);
-    sfree(d->left.r);
-    sfree(d->right.i);
-    sfree(d->right.r);
+    if (d->left.flags & CMP_ALLOCINT)
+    {
+        sfree(d->left.i);
+    }
+    if (d->left.flags & CMP_ALLOCREAL)
+    {
+        sfree(d->left.r);
+    }
+    if (d->right.flags & CMP_ALLOCINT)
+    {
+        sfree(d->right.i);
+    }
+    if (d->right.flags & CMP_ALLOCREAL)
+    {
+        sfree(d->right.r);
+    }
 }
 
 /*!
index 0a669539fa2cef80b5a5b041d8a1e1772675bc4b..0846650e716e99e8543d59babc8b38451c04d46d 100644 (file)
@@ -230,7 +230,6 @@ free_data_common(void *data)
 {
     t_methoddata_distance *d = (t_methoddata_distance *)data;
 
-    gmx_ana_pos_deinit(&d->p);
     gmx_ana_nbsearch_free(d->nb);
 }
 
index 55ac6334e92dcd62928939a2407c4010c1db7a90..bc5ab8e6115d61c85f446dea9bb77ab992924e12 100644 (file)
@@ -388,8 +388,6 @@ free_data_insolidangle(void *data)
     t_methoddata_insolidangle *d = (t_methoddata_insolidangle *)data;
     int                        i;
 
-    gmx_ana_pos_deinit(&d->center);
-    gmx_ana_pos_deinit(&d->span);
     if (d->tbin)
     {
         for (i = 0; i < d->ntbins; ++i)
index 67c799b7f02e9f4560608357a1847c6c319a8bb9..109027d7185f20d8168cc3c84af004add7ce67f1 100644 (file)
 #define USE_REGEX
 #endif
 
+#include <gmx_fatal.h>
 #include <macros.h>
 #include <smalloc.h>
 #include <string2.h>
 
 #include <selmethod.h>
 
+#include "keywords.h"
+#include "parsetree.h"
+#include "selelem.h"
+
 /** Allocates data for integer keyword evaluation. */
 static void *
 init_data_kwint(int npar, gmx_ana_selparam_t *param);
@@ -66,12 +71,6 @@ init_kwreal(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
 /** Initializes data for string keyword evaluation. */
 static int
 init_kwstr(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/** Frees the memory allocated for integer keyword evaluation. */
-static void
-free_data_kwint(void *data);
-/** Frees the memory allocated for real keyword evaluation. */
-static void
-free_data_kwreal(void *data);
 /** Frees the memory allocated for string keyword evaluation. */
 static void
 free_data_kwstr(void *data);
@@ -179,7 +178,7 @@ gmx_ana_selmethod_t sm_keyword_int = {
      NULL,
     &init_kwint,
      NULL,
-    &free_data_kwint,
+     NULL,
      NULL,
     &evaluate_keyword_int,
      NULL,
@@ -194,7 +193,7 @@ gmx_ana_selmethod_t sm_keyword_real = {
      NULL,
     &init_kwreal,
      NULL,
-    &free_data_kwreal,
+     NULL,
      NULL,
     &evaluate_keyword_real,
      NULL,
@@ -216,6 +215,41 @@ gmx_ana_selmethod_t sm_keyword_str = {
     {NULL, 0, NULL},
 };
 
+/** Initializes keyword evaluation for an arbitrary group. */
+static int
+init_kweval(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Initializes output for keyword evaluation in an arbitrary group. */
+static int
+init_output_kweval(t_topology *top, gmx_ana_selvalue_t *out, void *data);
+/** Frees the data allocated for keyword evaluation in an arbitrary group. */
+static void
+free_data_kweval(void *data);
+/** Initializes frame evaluation for keyword evaluation in an arbitrary group. */
+static int
+init_frame_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
+/** Evaluates keywords in an arbitrary group. */
+static int
+evaluate_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+
+/*! \internal \brief
+ * Data structure for keyword evaluation in arbitrary groups.
+ */
+typedef struct
+{
+    /** Wrapped keyword method for evaluating the values. */
+    gmx_ana_selmethod_t  *kwmethod;
+    /** Method data for \p kwmethod. */
+    void                 *kwmdata;
+    /** Group in which \p kwmethod should be evaluated. */
+    gmx_ana_index_t       g;
+} t_methoddata_kweval;
+
+/** Parameters for keyword evaluation in an arbitrary group. */
+static gmx_ana_selparam_t smparams_kweval[] = {
+    {NULL,   {GROUP_VALUE, 1, {NULL}}, NULL, SPAR_DYNAMIC},
+};
+
 
 /********************************************************************
  * INTEGER KEYWORD EVALUATION
@@ -255,20 +289,6 @@ init_kwint(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
     return 0;
 }
 
-/*!
- * \param data Data to free (should point to a \ref t_methoddata_kwint).
- *
- * Frees the memory allocated for t_methoddata_kwint::r.
- */
-static void
-free_data_kwint(void *data)
-{
-    t_methoddata_kwint *d = (t_methoddata_kwint *)data;
-
-    sfree(d->v);
-    sfree(d->r);
-}
-
 /*!
  * See sel_updatefunc() for description of the parameters.
  * \p data should point to a \c t_methoddata_kwint.
@@ -360,20 +380,6 @@ init_kwreal(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
     return 0;
 }
 
-/*!
- * \param data Data to free (should point to a \ref t_methoddata_kwreal).
- *
- * Frees the memory allocated for t_methoddata_kwreal::r.
- */
-static void
-free_data_kwreal(void *data)
-{
-    t_methoddata_kwreal *d = (t_methoddata_kwreal *)data;
-
-    sfree(d->v);
-    sfree(d->r);
-}
-
 /*!
  * See sel_updatefunc() for description of the parameters.
  * \p data should point to a \c t_methoddata_kwreal.
@@ -495,10 +501,6 @@ init_kwstr(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
                 fprintf(stderr, "WARNING: error in regular expression,\n"
                                 "         will match '%s' as a simple string\n", s);
             }
-            else
-            {
-                sfree(s);
-            }
             sfree(buf);
 #else
             bRegExp = FALSE;
@@ -512,7 +514,6 @@ init_kwstr(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
         }
         d->m[i].bRegExp = bRegExp;
     }
-    sfree(param[1].val.u.s);
     return 0;
 }
 
@@ -527,7 +528,6 @@ free_data_kwstr(void *data)
     t_methoddata_kwstr *d = (t_methoddata_kwstr *)data;
     int                 i;
 
-    sfree(d->v);
     for (i = 0; i < d->n; ++i)
     {
         if (d->m[i].bRegExp)
@@ -538,10 +538,6 @@ free_data_kwstr(void *data)
             regfree(&d->m[i].u.r);
 #endif
         }
-        else
-        {
-            sfree(d->m[i].u.s);
-        }
     }
     sfree(d->m);
 }
@@ -595,3 +591,154 @@ evaluate_keyword_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
     }
     return 0;
 }
+
+
+/********************************************************************
+ * KEYWORD EVALUATION FOR ARBITRARY GROUPS
+ ********************************************************************/
+
+/*!
+ * \param[in] top   Not used.
+ * \param[in] npar  Not used.
+ * \param[in] param Not used.
+ * \param[in] data  Should point to \ref t_methoddata_kweval.
+ * \returns   0 on success, a non-zero error code on return.
+ *
+ * Calls the initialization method of the wrapped keyword.
+ */
+static int
+init_kweval(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+    return d->kwmethod->init(top, 0, NULL, d->kwmdata);
+}
+
+/*!
+ * \param[in]     top   Not used.
+ * \param[in,out] out   Pointer to output data structure.
+ * \param[in,out] data  Should point to \c t_methoddata_kweval.
+ * \returns       0 for success.
+ */
+static int
+init_output_kweval(t_topology *top, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+    out->nr = d->g.isize;
+    return 0;
+}
+
+/*!
+ * \param data Data to free (should point to a \c t_methoddata_kweval).
+ *
+ * Frees the memory allocated for all the members of \c t_methoddata_kweval.
+ */
+static void
+free_data_kweval(void *data)
+{
+    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+    _gmx_selelem_free_method(d->kwmethod, d->kwmdata);
+}
+
+/*!
+ * \param[in]  top  Topology.
+ * \param[in]  fr   Current frame.
+ * \param[in]  pbc  PBC structure.
+ * \param      data Should point to a \ref t_methoddata_kweval.
+ * \returns    0 on success, a non-zero error code on error.
+ *
+ * Creates a lookup structure that enables fast queries of whether a point
+ * is within the solid angle or not.
+ */
+static int
+init_frame_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
+{
+    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+    return d->kwmethod->init_frame(top, fr, pbc, d->kwmdata);
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_kweval.
+ *
+ * Calls the evaluation function of the wrapped keyword with the given
+ * parameters, with the exception of using \c t_methoddata_kweval::g for the
+ * evaluation group.
+ */
+static int
+evaluate_kweval(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_kweval *d = (t_methoddata_kweval *)data;
+
+    return d->kwmethod->update(top, fr, pbc, &d->g, out, d->kwmdata);
+}
+
+/*!
+ * \param[out]  selp    Pointer to receive a pointer to the created selection
+ *      element (set to NULL on error).
+ * \param[in]   method  Keyword selection method to evaluate.
+ * \param[in]   param   Parameter that gives the group to evaluate \p method in.
+ * \param[in]   scanner Scanner data structure.
+ * \returns     0 on success, non-zero error code on error.
+ *
+ * Creates a \ref SEL_EXPRESSION selection element (pointer put in \c *selp)
+ * that evaluates the keyword method given by \p method in the group given by
+ * \p param.
+ */
+int
+_gmx_sel_init_keyword_evaluator(t_selelem **selp, gmx_ana_selmethod_t *method,
+                                t_selexpr_param *param, void *scanner)
+{
+    t_selelem            *sel;
+    t_methoddata_kweval  *data;
+
+    if ((method->flags & (SMETH_SINGLEVAL | SMETH_VARNUMVAL))
+        || method->outinit || method->pupdate)
+    {
+        _gmx_selexpr_free_params(param);
+        gmx_incons("unsupported keyword method for arbitrary group evaluation");
+        return -1;
+    }
+
+    *selp = NULL;
+    sel = _gmx_selelem_create(SEL_EXPRESSION);
+    _gmx_selelem_set_method(sel, method, scanner);
+
+    snew(data, 1);
+    data->kwmethod = sel->u.expr.method;
+    data->kwmdata  = sel->u.expr.mdata;
+    gmx_ana_index_clear(&data->g);
+
+    snew(sel->u.expr.method, 1);
+    memcpy(sel->u.expr.method, data->kwmethod, sizeof(gmx_ana_selmethod_t));
+    sel->u.expr.method->flags       |= SMETH_VARNUMVAL;
+    sel->u.expr.method->init_data    = NULL;
+    sel->u.expr.method->set_poscoll  = NULL;
+    sel->u.expr.method->init         = method->init ? &init_kweval : NULL;
+    sel->u.expr.method->outinit      = &init_output_kweval;
+    sel->u.expr.method->free         = &free_data_kweval;
+    sel->u.expr.method->init_frame   = method->init_frame ? &init_frame_kweval : NULL;
+    sel->u.expr.method->update       = &evaluate_kweval;
+    sel->u.expr.method->pupdate      = NULL;
+    sel->u.expr.method->nparams      = asize(smparams_kweval);
+    sel->u.expr.method->param        = smparams_kweval;
+    _gmx_selelem_init_method_params(sel, scanner);
+    sel->u.expr.mdata = data;
+
+    sel->u.expr.method->param[0].val.u.g = &data->g;
+
+    sfree(param->name);
+    param->name = NULL;
+    if (!_gmx_sel_parse_params(param, sel->u.expr.method->nparams,
+                               sel->u.expr.method->param, sel, scanner))
+    {
+        _gmx_selelem_free(sel);
+        return -1;
+    }
+    *selp = sel;
+    return 0;
+}
index e3ac61275930116e1d4ce4f4a3bca39946e4cea8..34d2b0d740891a6199611247ac9d95addb99fe02 100644 (file)
@@ -299,8 +299,6 @@ free_data_merge(void *data)
 {
     t_methoddata_merge *d = (t_methoddata_merge *)data;
 
-    gmx_ana_pos_deinit(&d->p1);
-    gmx_ana_pos_deinit(&d->p2);
     gmx_ana_index_deinit(&d->g);
 }
 
index 16ec41edf594902148d59135098dd806c9ed9340..a318912eb2cf77685ae4de4d177544127eb1a328 100644 (file)
@@ -216,9 +216,7 @@ free_data_permute(void *data)
 {
     t_methoddata_permute *d = (t_methoddata_permute *)data;
 
-    gmx_ana_pos_deinit(&d->p);
     gmx_ana_index_deinit(&d->g);
-    sfree(d->perm);
     sfree(d->rperm);
 }
 
index 2ba8f5615487be1b40310a75ee5dc9d333ece096..a58d1854cfbec52c4c176ceef626bac3ee261a5e 100644 (file)
@@ -352,7 +352,6 @@ free_data_pos(void *data)
     t_methoddata_pos *d = (t_methoddata_pos *)data;
 
     sfree(d->type);
-    gmx_ana_index_deinit(&d->g);
     gmx_ana_poscalc_free(d->pc);
 }
 
index 2b07c63dcef7a228a1a53af3c0c5a84461c7ace4..f7b881394d304a70c6172b61486efce3711b65a3 100644 (file)
 #include <config.h>
 #endif
 
+#include <stdlib.h>
+
 #include <macros.h>
 #include <smalloc.h>
+#include <string2.h>
 
-#include <indexutil.h>
 #include <selmethod.h>
 
+#include "keywords.h"
+#include "parsetree.h"
+#include "selelem.h"
+
 /*! \internal \brief
  * Data structure for the \p same selection method.
  *
- * All angle values are in the units of radians.
+ * To avoid duplicate initialization code, the same data structure is used
+ * for matching both integer and string keywords; hence the unions.
  */
 typedef struct
 {
-    /*! \brief Input group. */
-    gmx_ana_index_t       g;
+    /** Value for each atom to match. */
+    union
+    {
+        int                 *i;
+        char               **s;
+        void                *ptr;
+    }                        val;
+    /*! \brief
+     * Number of values in the \p as array.
+     *
+     * For string values, this is actually the number of values in the
+     * \p as_s_sorted array.
+     */
+    int                      nas;
+    /** Values to match against. */
+    union
+    {
+        int                 *i;
+        char               **s;
+        void                *ptr;
+    }                        as;
+    /*! \brief
+     * Separate array for sorted \p as.s array.
+     *
+     * The array of strings returned as the output value of a parameter should
+     * not be messed with to avoid memory corruption (the pointers in the array
+     * may be reused for several evaluations), so we keep our own copy for
+     * modifications.
+     */
+    char                   **as_s_sorted;
+    /** Whether simple matching can be used. */
+    bool                     bSorted;
 } t_methoddata_same;
 
-/*! \brief Allocates data for the \p same selection method. */
+/** Allocates data for the \p same selection method. */
 static void *
 init_data_same(int npar, gmx_ana_selparam_t *param);
-/*! \brief Initializes the \p same selection method. */
+/** Initializes the \p same selection method. */
 static int
 init_same(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
-/*! \brief Frees the data allocated for the \p same selection method. */
+/** Frees the data allocated for the \p same selection method. */
 static void
 free_data_same(void *data);
-/*! \brief Initializes the evaluation of the \p same selection method for a frame. */
+/** Initializes the evaluation of the \p same selection method for a frame. */
+static int
+init_frame_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
+/** Evaluates the \p same selection method. */
 static int
-init_frame_same(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
-/*! \brief Evaluates the \p same selection method. */
+evaluate_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Initializes the evaluation of the \p same selection method for a frame. */
 static int
-evaluate_same(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+init_frame_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data);
+/** Evaluates the \p same selection method. */
+static int
+evaluate_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                 gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
 
-/*! \brief Enum array for the \p same selection method. */
-static char *same_enum[] = { NULL, "residue", NULL };
+/** Parameters for the \p same selection method. */
+static gmx_ana_selparam_t smparams_same_int[] = {
+    {NULL, {INT_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_ATOMVAL},
+    {"as", {INT_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+};
 
-/*! \brief Parameters for the \p same selection method. */
-static gmx_ana_selparam_t smparams_same[] = {
-    {NULL, {STR_VALUE,   1, {same_enum}}, NULL, SPAR_ENUMVAL},
-    {"as", {GROUP_VALUE, 1, {NULL}},      NULL, SPAR_DYNAMIC},
+/** Parameters for the \p same selection method. */
+static gmx_ana_selparam_t smparams_same_str[] = {
+    {NULL, {STR_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_ATOMVAL},
+    {"as", {STR_VALUE, -1, {NULL}}, NULL, SPAR_DYNAMIC | SPAR_VARNUM},
+};
+
+/** Help text for the \p same selection method. */
+static const char *help_same[] = {
+    "EXTENDING SELECTIONS[PAR]",
+
+    "[TT]same KEYWORD as ATOM_EXPR[tt][PAR]",
+
+    "The keyword [TT]same[tt] can be used to select all atoms for which",
+    "the given [TT]KEYWORD[tt] matches any of the atoms in [TT]ATOM_EXPR[tt].",
+    "Keywords that evaluate to integer or string values are supported.",
 };
 
 /*! \internal \brief Selection method data for the \p same method. */
 gmx_ana_selmethod_t sm_same = {
-    "same", GROUP_VALUE, SMETH_REQTOP,
-    asize(smparams_same), smparams_same,
+    "same", GROUP_VALUE, 0,
+    asize(smparams_same_int), smparams_same_int,
     &init_data_same,
     NULL,
-    NULL,
+    &init_same,
     NULL,
     &free_data_same,
+    &init_frame_same_int,
+    &evaluate_same_int,
+    NULL,
+    {"same KEYWORD as ATOM_EXPR", asize(help_same), help_same},
+};
+
+/*! \brief
+ * Selection method data for the \p same method.
+ *
+ * This selection method is used for matching string keywords. The parser
+ * never sees this method; _gmx_selelem_custom_init_same() replaces sm_same
+ * with this method in cases where it is required.
+ */
+static gmx_ana_selmethod_t sm_same_str = {
+    "same", GROUP_VALUE, SMETH_SINGLEVAL,
+    asize(smparams_same_str), smparams_same_str,
+    &init_data_same,
+    NULL,
+    &init_same,
     NULL,
-    &evaluate_same,
+    &free_data_same,
+    &init_frame_same_str,
+    &evaluate_same_str,
     NULL,
-    {"same residue as ATOM_EXPR", 0, NULL},
+    {"same KEYWORD as ATOM_EXPR", asize(help_same), help_same},
 };
 
 /*!
@@ -105,11 +184,101 @@ init_data_same(int npar, gmx_ana_selparam_t *param)
     t_methoddata_same *data;
 
     snew(data, 1);
-    gmx_ana_index_clear(&data->g);
-    param[1].val.u.g = &data->g;
+    data->as_s_sorted = NULL;
+    param[1].nvalptr = &data->nas;
     return data;
 }
 
+/*!
+ * \param[in,out] method  The method to initialize.
+ * \param[in,out] params  Pointer to the first parameter.
+ * \param[in]     scanner Scanner data structure.
+ * \returns       0 on success, a non-zero error code on error.
+ *
+ * If \p *method is not a \c same method, this function returns zero
+ * immediately.
+ */
+int
+_gmx_selelem_custom_init_same(gmx_ana_selmethod_t **method,
+                              t_selexpr_param *params,
+                              void *scanner)
+{
+    gmx_ana_selmethod_t *kwmethod;
+    t_selelem           *kwelem;
+    t_selexpr_param     *param;
+    char                *pname;
+    int                  rc;
+
+    /* Do nothing if this is not a same method. */
+    if (!*method || (*method)->name != sm_same.name)
+    {
+        return 0;
+    }
+
+    if (params->nval != 1 || !params->value->bExpr
+        || params->value->u.expr->type != SEL_EXPRESSION)
+    {
+        _gmx_selparser_error("error: 'same' should be followed by a single keyword");
+        return -1;
+    }
+    kwmethod = params->value->u.expr->u.expr.method;
+
+    if (kwmethod->type == STR_VALUE)
+    {
+        *method = &sm_same_str;
+    }
+
+    /* We do custom processing with the second parameter, so remove it from
+     * the params list, but save the name for later. */
+    param        = params->next;
+    params->next = NULL;
+    pname        = param->name;
+    param->name  = NULL;
+    /* Create a second keyword evaluation element for the keyword given as
+     * the first parameter, evaluating the keyword in the group given by the
+     * second parameter. */
+    rc = _gmx_sel_init_keyword_evaluator(&kwelem, kwmethod, param, scanner);
+    if (rc != 0)
+    {
+        sfree(pname);
+        return rc;
+    }
+    /* Replace the second parameter with one with a value from \p kwelem. */
+    param        = _gmx_selexpr_create_param(pname);
+    param->nval  = 1;
+    param->value = _gmx_selexpr_create_value_expr(kwelem);
+    params->next = param;
+    return 0;
+}
+
+/*!
+ * \param   top   Not used.
+ * \param   npar  Not used (should be 2).
+ * \param   param Initialized method parameters (should point to a copy of
+ *      \ref smparams_same).
+ * \param   data  Pointer to \ref t_methoddata_same to initialize.
+ * \returns 0 on success, -1 on failure.
+ */
+static int
+init_same(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    t_methoddata_same *d = (t_methoddata_same *)data;
+
+    d->val.ptr = param[0].val.u.ptr;
+    d->as.ptr  = param[1].val.u.ptr;
+    if (param[1].val.type == STR_VALUE)
+    {
+        snew(d->as_s_sorted, d->nas);
+    }
+    if (!(param[0].flags & SPAR_ATOMVAL))
+    {
+        fprintf(stderr, "ERROR: the same selection keyword combined with a "
+                        "non-keyword does not make sense\n");
+        return -1;
+    }
+    return 0;
+}
+
 /*!
  * \param data Data to free (should point to a \ref t_methoddata_same).
  */
@@ -118,40 +287,243 @@ free_data_same(void *data)
 {
     t_methoddata_same *d = (t_methoddata_same *)data;
 
-    gmx_ana_index_deinit(&d->g);
+    sfree(d->as_s_sorted);
+}
+
+/*! \brief
+ * Helper function for comparison of two integers.
+ */
+static int
+cmp_int(const void *a, const void *b)
+{
+    if (*(int *)a < *(int *)b)
+    {
+        return -1;
+    }
+    if (*(int *)a > *(int *)b)
+    {
+        return 1;
+    }
+    return 0;
+}
+
+/*!
+ * \param[in]  top  Not used.
+ * \param[in]  fr   Current frame.
+ * \param[in]  pbc  PBC structure.
+ * \param      data Should point to a \ref t_methoddata_same.
+ * \returns    0 on success, a non-zero error code on error.
+ *
+ * Sorts the \c data->as.i array and removes identical values for faster and
+ * simpler lookup.
+ */
+static int
+init_frame_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
+{
+    t_methoddata_same *d = (t_methoddata_same *)data;
+    int                i, j;
+
+    /* Collapse adjacent values, and check whether the array is sorted. */
+    d->bSorted = TRUE;
+    for (i = 1, j = 0; i < d->nas; ++i)
+    {
+        if (d->as.i[i] != d->as.i[j])
+        {
+            if (d->as.i[i] < d->as.i[j])
+            {
+                d->bSorted = FALSE;
+            }
+            ++j;
+            d->as.i[j] = d->as.i[i];
+        }
+    }
+    d->nas = j + 1;
+
+    if (!d->bSorted)
+    {
+        qsort(d->as.i, d->nas, sizeof(d->as.i[0]), &cmp_int);
+        /* More identical values may become adjacent after sorting. */
+        for (i = 1, j = 0; i < d->nas; ++i)
+        {
+            if (d->as.i[i] != d->as.i[j])
+            {
+                ++j;
+                d->as.i[j] = d->as.i[i];
+            }
+        }
+        d->nas = j + 1;
+    }
+    return 0;
 }
 
 /*!
  * See sel_updatefunc() for description of the parameters.
  * \p data should point to a \c t_methoddata_same.
  *
- * Calculates which atoms in \p g are in the same residues as the atoms in
- * \c t_methoddata_same::g.
+ * Calculates which values in \c data->val.i can be found in \c data->as.i
+ * (assumed sorted), and writes the corresponding atoms to output.
+ * If \c data->val is sorted, uses a linear scan of both arrays, otherwise a
+ * binary search of \c data->as is performed for each block of values in
+ * \c data->val.
  */
 static int
-evaluate_same(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-              gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+evaluate_same_int(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
 {
     t_methoddata_same *d = (t_methoddata_same *)data;
-    int                    i, j, resind;
+    int                    i, j;
 
     out->u.g->isize = 0;
     i = j = 0;
-    while (i < d->g.isize)
+    while (j < g->isize)
+    {
+        if (d->bSorted)
+        {
+            /* If we are sorted, we can do a simple linear scan. */
+            while (i < d->nas && d->as.i[i] < d->val.i[j]) ++i;
+        }
+        else
+        {
+            /* If not, we must do a binary search of all the values. */
+            int i1, i2;
+
+            i1 = 0;
+            i2 = d->nas;
+            while (i2 - i1 > 1)
+            {
+                int itry = (i1 + i2) / 2;
+                if (d->as.i[itry] <= d->val.i[j])
+                {
+                    i1 = itry;
+                }
+                else
+                {
+                    i2 = itry;
+                }
+            }
+            i = (d->as.i[i1] == d->val.i[j] ? i1 : d->nas);
+        }
+        /* Check whether the value was found in the as list. */
+        if (i == d->nas || d->as.i[i] != d->val.i[j])
+        {
+            /* If not, skip all atoms with the same value. */
+            int tmpval = d->val.i[j];
+            ++j;
+            while (j < g->isize && d->val.i[j] == tmpval) ++j;
+        }
+        else
+        {
+            /* Copy all the atoms with this value to the output. */
+            while (j < g->isize && d->val.i[j] == d->as.i[i])
+            {
+                out->u.g->index[out->u.g->isize++] = g->index[j];
+                ++j;
+            }
+        }
+        if (j < g->isize && d->val.i[j] < d->val.i[j - 1])
+        {
+            d->bSorted = FALSE;
+        }
+    }
+    return 0;
+}
+
+/*! \brief
+ * Helper function for comparison of two strings.
+ */
+static int
+cmp_str(const void *a, const void *b)
+{
+    return strcmp(*(char **)a, *(char **)b);
+}
+
+/*!
+ * \param[in]  top  Not used.
+ * \param[in]  fr   Current frame.
+ * \param[in]  pbc  PBC structure.
+ * \param      data Should point to a \ref t_methoddata_same.
+ * \returns    0 on success, a non-zero error code on error.
+ *
+ * Sorts the \c data->as.s array and removes identical values for faster and
+ * simpler lookup.
+ */
+static int
+init_frame_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc, void *data)
+{
+    t_methoddata_same *d = (t_methoddata_same *)data;
+    int                i, j;
+
+    /* Collapse adjacent values.
+     * For strings, it's unlikely that the values would be sorted originally,
+     * so set bSorted always to FALSE. */
+    d->bSorted = FALSE;
+    d->as_s_sorted[0] = d->as.s[0];
+    for (i = 1, j = 0; i < d->nas; ++i)
     {
-        resind = top->atoms.atom[d->g.index[i]].resind;
-        /* Find the first atom in the current residue */
-        while (top->atoms.atom[g->index[j]].resind < resind) ++j;
-        /* Copy all the atoms in the residue to the output */
-        while (j < g->isize && top->atoms.atom[g->index[j]].resind == resind)
+        if (strcmp(d->as.s[i], d->as_s_sorted[j]) != 0)
         {
-            out->u.g->index[out->u.g->isize++] = g->index[j];
             ++j;
+            d->as_s_sorted[j] = d->as.s[i];
         }
-        /* Skip the rest of the atoms in the residue */
-        ++i;
-        while (i < d->g.isize && top->atoms.atom[d->g.index[i]].resind == resind) ++i;
     }
+    d->nas = j + 1;
+
+    qsort(d->as_s_sorted, d->nas, sizeof(d->as_s_sorted[0]), &cmp_str);
+    /* More identical values may become adjacent after sorting. */
+    for (i = 1, j = 0; i < d->nas; ++i)
+    {
+        if (strcmp(d->as_s_sorted[i], d->as_s_sorted[j]) != 0)
+        {
+            ++j;
+            d->as_s_sorted[j] = d->as_s_sorted[i];
+        }
+    }
+    d->nas = j + 1;
     return 0;
 }
 
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data should point to a \c t_methoddata_same.
+ *
+ * Calculates which strings in \c data->val.s can be found in \c data->as.s
+ * (assumed sorted), and writes the corresponding atoms to output.
+ * A binary search of \c data->as is performed for each block of values in
+ * \c data->val.
+ */
+static int
+evaluate_same_str(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    t_methoddata_same *d = (t_methoddata_same *)data;
+    int                    i, j;
+
+    out->u.g->isize = 0;
+    j = 0;
+    while (j < g->isize)
+    {
+        /* Do a binary search of the strings. */
+        void *ptr;
+        ptr = bsearch(&d->val.s[j], d->as_s_sorted, d->nas,
+                      sizeof(d->as_s_sorted[0]), &cmp_str);
+        /* Check whether the value was found in the as list. */
+        if (ptr == NULL)
+        {
+            /* If not, skip all atoms with the same value. */
+            const char *tmpval = d->val.s[j];
+            ++j;
+            while (j < g->isize && strcmp(d->val.s[j], tmpval) == 0) ++j;
+        }
+        else
+        {
+            const char *tmpval = d->val.s[j];
+            /* Copy all the atoms with this value to the output. */
+            while (j < g->isize && strcmp(d->val.s[j], tmpval) == 0)
+            {
+                out->u.g->index[out->u.g->isize++] = g->index[j];
+                ++j;
+            }
+        }
+    }
+    return 0;
+}
index f74efc4c78d6494f645a0aaa0bc39dd17055d8f8..155cb84aefac00ff1a7d4922d961b15dd1484279 100644 (file)
@@ -54,10 +54,17 @@ evaluate_atomnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
 static int
 evaluate_resnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
-/** Evaluates the \p resind selection keyword. */
+/** Evaluates the \p resindex selection keyword. */
 static int
-evaluate_resind(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
+/** Checks whether molecule information is present in the topology. */
+static int
+check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data);
+/** Evaluates the \p molindex selection keyword. */
+static int
+evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data);
 /** Evaluates the \p name selection keyword. */
 static int
 evaluate_atomname(t_topology *top, t_trxframe *fr, t_pbc *pbc,
@@ -174,9 +181,9 @@ gmx_ana_selmethod_t sm_resnr = {
     NULL,
 };
 
-/** \internal Selection method data for \p resind selection keyword. */
-gmx_ana_selmethod_t sm_resind = {
-    "resind", INT_VALUE, SMETH_REQTOP,
+/** \internal Selection method data for \p resindex selection keyword. */
+gmx_ana_selmethod_t sm_resindex = {
+    "resindex", INT_VALUE, SMETH_REQTOP,
     0, NULL,
     NULL,
     NULL,
@@ -184,7 +191,21 @@ gmx_ana_selmethod_t sm_resind = {
     NULL,
     NULL,
     NULL,
-    &evaluate_resind,
+    &evaluate_resindex,
+    NULL,
+};
+
+/** \internal Selection method data for \p molindex selection keyword. */
+gmx_ana_selmethod_t sm_molindex = {
+    "molindex", INT_VALUE, SMETH_REQTOP,
+    0, NULL,
+    NULL,
+    NULL,
+    &check_molecules,
+    NULL,
+    NULL,
+    NULL,
+    &evaluate_molindex,
     NULL,
 };
 
@@ -447,8 +468,8 @@ evaluate_resnr(t_topology *top, t_trxframe *fr, t_pbc *pbc,
  * Returns the residue indices for each atom in \p out->u.i.
  */
 static int
-evaluate_resind(t_topology *top, t_trxframe *fr, t_pbc *pbc,
-                gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+evaluate_resindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
 {
     int  i;
 
@@ -460,6 +481,50 @@ evaluate_resind(t_topology *top, t_trxframe *fr, t_pbc *pbc,
     return 0;
 }
 
+/*!
+ * \param[in] top  Topology structure.
+ * \param     npar Not used.
+ * \param     param Not used.
+ * \param     data Not used.
+ * \returns   0 if molecule info is present in the topology, -1 otherwise.
+ *
+ * If molecule information is not found, also prints an error message.
+ */
+static int
+check_molecules(t_topology *top, int npar, gmx_ana_selparam_t *param, void *data)
+{
+    bool bOk;
+
+    bOk = (top != NULL && top->mols.nr > 0);
+    if (!bOk)
+    {
+        fprintf(stderr, "Molecule information not available in topology!\n");
+        return -1;
+    }
+    return 0;
+}
+
+/*!
+ * See sel_updatefunc() for description of the parameters.
+ * \p data is not used.
+ *
+ * Returns the molecule indices for each atom in \p out->u.i.
+ */
+static int
+evaluate_molindex(t_topology *top, t_trxframe *fr, t_pbc *pbc,
+                  gmx_ana_index_t *g, gmx_ana_selvalue_t *out, void *data)
+{
+    int  i, j;
+
+    out->nr = g->isize;
+    for (i = j = 0; i < g->isize; ++i)
+    {
+        while (top->mols.index[j + 1] <= g->index[i]) ++j;
+        out->u.i[i] = j + 1;
+    }
+    return 0;
+}
+
 /*!
  * See sel_updatefunc() for description of the parameters.
  * \p data is not used.
index 8284169b96bbf2b8e6fb02a78a052b6c4c5b8c3c..465b9fd441a3a869338c3e116703f02e016ff05f 100644 (file)
@@ -46,7 +46,7 @@ typedef enum
     SYMBOL_RESERVED,    /**< The symbol is a reserved keyword. */
     SYMBOL_VARIABLE,    /**< The symbol is a variable. */
     SYMBOL_METHOD,      /**< The symbol is a selection method. */
-    SYMBOL_POS,         /**< The symbol is a position keyword. */
+    SYMBOL_POS          /**< The symbol is a position keyword. */
 } e_symbol_t;
 
 /** Symbol table for the selection parser. */
index 877b0cce0af8cbf9244c82bd5f72d4b023a05169..f5c15b53573301f3acaec947060a165570797106 100644 (file)
@@ -161,11 +161,14 @@ gmx_test_selection(int argc, char *argv[])
 
     bool                bMaskOnly  = FALSE;
     bool                bFrameTree = FALSE;
+    bool                bDebugCompile = FALSE;
     int                 nref       = 0;
     int                 nmaxind    = 20;
     t_pargs             pa[] = {
         {"-mask",   FALSE, etBOOL, {&bMaskOnly},
          "Test position mask functionality"},
+        {"-compdebug", FALSE, etBOOL, {&bDebugCompile},
+         "Print intermediate trees during compilation"},
         {"-frtree", FALSE, etBOOL, {&bFrameTree},
          "Print the whole evaluation tree for each frame"},
         {"-nref",   FALSE, etINT,  {&nref},
@@ -199,6 +202,7 @@ gmx_test_selection(int argc, char *argv[])
         gmx_ana_add_flags(trj, ANA_USE_POSMASK);
         gmx_ana_selcollection_set_outpostype(d.sc, NULL, TRUE);
     }
+    gmx_ana_selcollection_set_compile_debug(d.sc, bDebugCompile);
     gmx_ana_set_nrefgrps(trj, nref);
     gmx_ana_init_selections(trj);
     gmx_ana_get_ngrps(trj, &ngrps);
@@ -214,6 +218,7 @@ gmx_test_selection(int argc, char *argv[])
     print_selections(ngrps, sel, d.nmaxind);
 
     gmx_ana_traj_free(trj);
+    done_filenms(NFILE, fnm);
 
     return 0;
 }
diff --git a/src/gmxlib/sfactor.c b/src/gmxlib/sfactor.c
new file mode 100644 (file)
index 0000000..5d955d5
--- /dev/null
@@ -0,0 +1,674 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * GROningen Mixture of Alchemy and Childrens' Stories
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <ctype.h>
+#include "sysstuff.h"
+#include "smalloc.h"
+#include "string2.h"
+#include "futil.h"
+#include "maths.h"
+#include "gmx_fatal.h"
+#include "vec.h"
+#include "macros.h"
+#include "index.h"
+#include "strdb.h"
+#include "copyrite.h"
+#include "tpxio.h"
+#include "typedefs.h"
+#include "statutil.h"
+#include "oenv.h"
+#include "gmxfio.h"
+#include "xvgr.h"
+#include "matio.h"
+#include "gmx_ana.h"
+#include "names.h"
+#include "sfactor.h"
+
+
+typedef struct gmx_structurefactors {
+    int nratoms;
+    int *p;        /* proton number */
+    int *n;        /* neutron number */
+    /* Parameters for the Cromer Mann fit */
+    real **a;    /* parameter a */
+    real **b;    /* parameter b */
+    real *c;       /* parameter c */
+    char **atomnm;  /* atomname */
+
+} gmx_structurefactors;
+
+typedef struct reduced_atom{
+    rvec x;
+    int  t;
+} reduced_atom;
+
+
+typedef struct structure_factor
+{
+  int     n_angles;
+  int     n_groups;
+  double  lambda;
+  double  energy;
+  double  momentum;
+  double  ref_k;
+  double  **F;
+  int     nSteps;
+  int     total_n_atoms;
+} structure_factor;
+
+
+extern int * create_indexed_atom_type (reduced_atom_t * atm, int size)
+{
+/*
+ * create an index of the atom types found in a  group
+ * i.e.: for water index_atp[0]=type_number_of_O and
+ *                 index_atp[1]=type_number_of_H
+ *
+ * the last element is set to 0
+ */
+    int *index_atp, i, i_tmp, j;
+
+    reduced_atom *att=(reduced_atom *)atm;
+
+    snew (index_atp, 1);
+    i_tmp = 1;
+    index_atp[0] = att[0].t;
+    for (i = 1; i < size; i++) {
+       for (j = 0; j < i_tmp; j++)
+           if (att[i].t == index_atp[j])
+               break;
+       if (j == i_tmp) {       /* i.e. no indexed atom type is  == to atm[i].t */
+           i_tmp++;
+           srenew (index_atp, i_tmp * sizeof (int));
+           index_atp[i_tmp - 1] = att[i].t;
+       }
+    }
+    i_tmp++;
+    srenew (index_atp, i_tmp * sizeof (int));
+    index_atp[i_tmp - 1] = 0;
+    return index_atp;
+}
+
+
+
+extern t_complex *** rc_tensor_allocation(int x, int y, int z)
+{
+  t_complex ***t;
+  int i,j;
+
+  snew(t,x);
+  t = (t_complex ***)calloc(x,sizeof(t_complex**));
+  if(!t) exit(fprintf(stderr,"\nallocation error"));
+  t[0] = (t_complex **)calloc(x*y,sizeof(t_complex*));
+  if(!t[0]) exit(fprintf(stderr,"\nallocation error"));
+  t[0][0] = (t_complex *)calloc(x*y*z,sizeof(t_complex));
+  if(!t[0][0]) exit(fprintf(stderr,"\nallocation error"));
+
+  for( j = 1 ; j < y ; j++)
+    t[0][j] = t[0][j-1] + z;
+  for( i = 1 ; i < x ; i++) {
+    t[i] = t[i-1] + y;
+    t[i][0] = t[i-1][0] + y*z;
+    for( j = 1 ; j < y ; j++)
+      t[i][j] = t[i][j-1] + z;
+  }
+  return t;
+}
+
+
+extern void compute_structure_factor (structure_factor_t * sft, matrix box,
+                              reduced_atom_t * red, int isize, real start_q,
+                              real end_q, int group,real **sf_table)
+{
+    structure_factor *sf=(structure_factor *)sft;
+    reduced_atom *redt=(reduced_atom *)red;
+
+    t_complex ***tmpSF;
+    rvec k_factor;
+    real kdotx, asf, kx, ky, kz, krr;
+    int kr, maxkx, maxky, maxkz, i, j, k, p, *counter;
+
+
+    k_factor[XX] = 2 * M_PI / box[XX][XX];
+    k_factor[YY] = 2 * M_PI / box[YY][YY];
+    k_factor[ZZ] = 2 * M_PI / box[ZZ][ZZ];
+
+    maxkx = (int) (end_q / k_factor[XX] + 0.5);
+    maxky = (int) (end_q / k_factor[YY] + 0.5);
+    maxkz = (int) (end_q / k_factor[ZZ] + 0.5);
+
+    snew (counter, sf->n_angles);
+
+    tmpSF = rc_tensor_allocation(maxkx,maxky,maxkz);
+/*
+ * The big loop...
+ * compute real and imaginary part of the structure factor for every
+ * (kx,ky,kz))
+ */
+    fprintf(stderr,"\n");
+    for (i = 0; i < maxkx; i++) {
+       fprintf (stderr,"\rdone %3.1f%%     ", (double)(100.0*(i+1))/maxkx);
+       kx = i * k_factor[XX];
+       for (j = 0; j < maxky; j++) {
+           ky = j * k_factor[YY];
+           for (k = 0; k < maxkz; k++)
+               if (i != 0 || j != 0 || k != 0) {
+                   kz = k * k_factor[ZZ];
+                   krr = sqrt (sqr (kx) + sqr (ky) + sqr (kz));
+                   if (krr >= start_q && krr <= end_q) {
+                       kr = (int) (krr/sf->ref_k + 0.5);
+                       if (kr < sf->n_angles) {
+                           counter[kr]++;  /* will be used for the copmutation
+                                              of the average*/
+                           for (p = 0; p < isize; p++) {
+                               asf = sf_table[redt[p].t][kr];
+
+                               kdotx = kx * redt[p].x[XX] +
+                                   ky * redt[p].x[YY] + kz * redt[p].x[ZZ];
+
+                               tmpSF[i][j][k].re += cos (kdotx) * asf;
+                               tmpSF[i][j][k].im += sin (kdotx) * asf;
+                           }
+                       }
+                   }
+               }
+       }
+    }                          /* end loop on i */
+/*
+ *  compute the square modulus of the structure factor, averaging on the surface
+ *  kx*kx + ky*ky + kz*kz = krr*krr
+ *  note that this is correct only for a (on the macroscopic scale)
+ *  isotropic system.
+ */
+    for (i = 0; i < maxkx; i++) {
+       kx = i * k_factor[XX]; for (j = 0; j < maxky; j++) {
+           ky = j * k_factor[YY]; for (k = 0; k < maxkz; k++) {
+               kz = k * k_factor[ZZ]; krr = sqrt (sqr (kx) + sqr (ky)
+               + sqr (kz)); if (krr >= start_q && krr <= end_q) {
+                   kr = (int) (krr / sf->ref_k + 0.5);
+                       if (kr < sf->n_angles && counter[kr] != 0)
+                               sf->F[group][kr] +=
+                           (sqr (tmpSF[i][j][k].re) +
+                            sqr (tmpSF[i][j][k].im))/ counter[kr];
+               }
+           }
+       }
+    } sfree (counter); free(tmpSF[0][0]); free(tmpSF[0]); free(tmpSF);
+}
+
+
+extern gmx_structurefactors_t *gmx_structurefactors_init(const char *datfn) {
+    
+       /* Read the database for the structure factor of the different atoms */
+
+    FILE *fp;
+    char line[STRLEN];
+    gmx_structurefactors *gsf;
+    double a1,a2,a3,a4,b1,b2,b3,b4,c;
+    int n,p;
+    int i;
+    int nralloc=10;
+    int line_no;
+    char atomn[32];
+    fp=libopen(datfn);
+    line_no = 0;
+
+    snew(gsf,1);
+
+    snew(gsf->atomnm,nralloc);
+    snew(gsf->a,nralloc);
+    snew(gsf->b,nralloc);
+    snew(gsf->c,nralloc);
+    snew(gsf->n,nralloc);
+    snew(gsf->p,nralloc);
+    gsf->nratoms=line_no;
+    while(get_a_line(fp,line,STRLEN)) {
+        i=line_no;
+        if (sscanf(line,"%s %d %d %lf %lf %lf %lf %lf %lf %lf %lf %lf",
+                   atomn,&p,&n,&a1,&a2,&a3,&a4,&b1,&b2,&b3,&b4,&c) == 12) {
+            gsf->atomnm[i]=strdup(atomn);
+            gsf->n[i]=n;
+            gsf->p[i]=p;
+            snew(gsf->a[i],4);
+            snew(gsf->b[i],4);
+            gsf->a[i][0]=a1;
+            gsf->a[i][1]=a2;
+            gsf->a[i][2]=a3;
+            gsf->a[i][3]=a4;
+            gsf->b[i][0]=b1;
+            gsf->b[i][1]=b2;
+            gsf->b[i][2]=b3;
+            gsf->b[i][3]=b4;
+            gsf->c[i]=c;
+            line_no++;            
+            gsf->nratoms=line_no;
+            if (line_no==nralloc){
+               nralloc+=10;
+                srenew(gsf->atomnm,nralloc);
+                srenew(gsf->a,nralloc);
+                srenew(gsf->b,nralloc);
+                srenew(gsf->c,nralloc);
+                srenew(gsf->n,nralloc);
+                srenew(gsf->p,nralloc);
+            }
+        }
+        else 
+            fprintf(stderr,"WARNING: Error in file %s at line %d ignored\n",
+                    datfn,line_no);
+    }
+
+    srenew(gsf->atomnm,gsf->nratoms);
+    srenew(gsf->a,gsf->nratoms);
+    srenew(gsf->b,gsf->nratoms);
+    srenew(gsf->c,gsf->nratoms);
+    srenew(gsf->n,gsf->nratoms);
+    srenew(gsf->p,gsf->nratoms);
+
+    fclose(fp);
+
+    return (gmx_structurefactors_t *) gsf;
+
+}
+
+
+extern void rearrange_atoms (reduced_atom_t * positions, t_trxframe *fr, atom_id * index,
+                     int isize, t_topology * top, bool flag,gmx_structurefactors_t *gsf)
+/* given the group's index, return the (continuous) array of atoms */
+{
+  int i;
+
+  reduced_atom *pos=(reduced_atom *)positions;
+
+  if (flag)
+    for (i = 0; i < isize; i++)
+      pos[i].t =
+       return_atom_type (*(top->atoms.atomname[index[i]]),gsf);
+  for (i = 0; i < isize; i++)
+    copy_rvec (fr->x[index[i]], pos[i].x);
+
+   positions=(reduced_atom_t *)pos;
+}
+
+
+extern int return_atom_type (const char *name,gmx_structurefactors_t *gsf)
+{
+  typedef struct {
+    const char *name;
+    int  nh;
+  } t_united_h;
+  t_united_h uh[] = {
+    { "CH1", 1 }, { "CH2", 2 }, { "CH3", 3 },
+    { "CS1", 1 }, { "CS2", 2 }, { "CS3", 3 },
+    { "CP1", 1 }, { "CP2", 2 }, { "CP3", 3 }
+  };
+  int i,cnt=0;
+  int *tndx;
+  int nrc;
+  int fndx=0;
+  int NCMT;
+
+  gmx_structurefactors *gsft=(gmx_structurefactors *)gsf;
+
+  NCMT=gsft->nratoms;
+
+  snew(tndx,NCMT);
+
+  for(i=0; (i<asize(uh)); i++)
+    if (strcmp(name,uh[i].name) == 0)
+      return NCMT-1+uh[i].nh;
+
+  for(i=0; (i<NCMT); i++){
+    if (strncmp (name, gsft->atomnm[i],strlen(gsft->atomnm[i])) == 0){
+      tndx[cnt]=i;
+      cnt++;
+    }
+  }
+
+  if (cnt==0)
+  gmx_fatal(FARGS,"\nError: atom (%s) not in list (%d types checked)!\n",
+           name,i);
+  else{
+         nrc=0;
+         for(i=0;i<cnt;i++){
+                 if(strlen(gsft->atomnm[tndx[i]])>(size_t)nrc){
+                         nrc=strlen(gsft->atomnm[tndx[i]]);
+                     fndx=tndx[i];
+                 }
+         }
+     
+         return fndx;
+  }
+
+  return 0;
+}
+
+extern int gmx_structurefactors_get_sf(gmx_structurefactors_t *gsf, int elem, real a[4], real b[4], real *c){
+
+       int success;
+       int i;
+    gmx_structurefactors *gsft=(gmx_structurefactors *)gsf;
+       success=0;
+
+       for(i=0;i<4;i++){
+            a[i]=gsft->a[elem][i];
+            b[i]=gsft->b[elem][i];
+            *c=gsft->c[elem];
+        }
+
+        success+=1;
+       return success;
+}
+
+int atp_size (int *index_atp)
+{
+    int i = 0;
+
+    while (index_atp[i])
+       i++;
+    return i;
+}
+
+
+extern int do_scattering_intensity (const char* fnTPS, const char* fnNDX,
+                             const char* fnXVG, const char *fnTRX,
+                             const char* fnDAT,
+                             real start_q,real end_q,
+                             real energy,int ng,const output_env_t oenv)
+{
+    int i,*isize,flags = TRX_READ_X,**index_atp;
+    t_trxstatus *status;
+    char **grpname,title[STRLEN];
+    atom_id **index;
+    t_topology top;
+    int ePBC;
+    t_trxframe fr;
+    reduced_atom_t **red;
+    structure_factor *sf;
+    rvec *xtop;
+    real **sf_table;
+    int nsftable;
+    matrix box;
+    double r_tmp;
+
+    gmx_structurefactors_t *gmx_sf;
+    real *a,*b,c;
+    int success;
+
+    snew(a,4);
+    snew(b,4);
+
+
+    gmx_sf=gmx_structurefactors_init(fnDAT);
+
+    success=gmx_structurefactors_get_sf(gmx_sf,0, a, b, &c);
+
+    snew (sf, 1);
+    sf->energy = energy;
+
+    /* Read the topology informations */
+    read_tps_conf (fnTPS, title, &top, &ePBC, &xtop, NULL, box, TRUE);
+    sfree (xtop);
+
+    /* groups stuff... */
+    snew (isize, ng);
+    snew (index, ng);
+    snew (grpname, ng);
+
+    fprintf (stderr, "\nSelect %d group%s\n", ng,
+            ng == 1 ? "" : "s");
+    if (fnTPS)
+       get_index (&top.atoms, fnNDX, ng, isize, index, grpname);
+    else
+       rd_index (fnNDX, ng, isize, index, grpname);
+
+    /* The first time we read data is a little special */
+    read_first_frame (oenv,&status, fnTRX, &fr, flags);
+
+    sf->total_n_atoms = fr.natoms;
+
+    snew (red, ng);
+    snew (index_atp, ng);
+
+    r_tmp = max (box[XX][XX], box[YY][YY]);
+    r_tmp = (double) max (box[ZZ][ZZ], r_tmp);
+
+    sf->ref_k = (2.0 * M_PI) / (r_tmp);
+    /* ref_k will be the reference momentum unit */
+    sf->n_angles = (int) (end_q / sf->ref_k + 0.5);
+
+    snew (sf->F, ng);
+    for (i = 0; i < ng; i++)
+       snew (sf->F[i], sf->n_angles);
+    for (i = 0; i < ng; i++) {
+       snew (red[i], isize[i]);
+       rearrange_atoms (red[i], &fr, index[i], isize[i], &top, TRUE,gmx_sf);
+       index_atp[i] = create_indexed_atom_type (red[i], isize[i]);
+    }
+
+    sf_table = compute_scattering_factor_table (gmx_sf,(structure_factor_t *)sf,&nsftable);
+
+
+    /* This is the main loop over frames */
+
+    do {
+       sf->nSteps++;
+       for (i = 0; i < ng; i++) {
+           rearrange_atoms (red[i], &fr, index[i], isize[i], &top,FALSE,gmx_sf);
+
+           compute_structure_factor ((structure_factor_t *)sf, box, red[i], isize[i],
+                                     start_q, end_q, i, sf_table);
+       }
+    }
+
+    while (read_next_frame (oenv,status, &fr));
+
+    save_data ((structure_factor_t *)sf, fnXVG, ng, start_q, end_q,oenv);
+
+
+    sfree(a);
+    sfree(b);
+
+    gmx_structurefactors_done(gmx_sf);
+
+    return 0;
+}
+
+
+extern void save_data (structure_factor_t *sft, const char *file, int ngrps,
+                real start_q, real end_q, const output_env_t oenv)
+{
+
+    FILE *fp;
+    int i, g = 0;
+    double *tmp, polarization_factor, A;
+
+    structure_factor *sf=(structure_factor *)sft;
+    
+    fp = xvgropen (file, "Scattering Intensity", "q (1/nm)",
+                  "Intensity (a.u.)",oenv);
+
+    snew (tmp, ngrps);
+
+    for (g = 0; g < ngrps; g++)
+       for (i = 0; i < sf->n_angles; i++) {
+            
+/*
+ *          theta is half the angle between incoming and scattered vectors.
+ *
+ *          polar. fact. = 0.5*(1+cos^2(2*theta)) = 1 - 0.5 * sin^2(2*theta)
+ *
+ *          sin(theta) = q/(2k) := A  ->  sin^2(theta) = 4*A^2 (1-A^2) ->
+ *          -> 0.5*(1+cos^2(2*theta)) = 1 - 2 A^2 (1-A^2)
+ */
+           A = (double) (i * sf->ref_k) / (2.0 * sf->momentum);
+           polarization_factor = 1 - 2.0 * sqr (A) * (1 - sqr (A));
+           sf->F[g][i] *= polarization_factor;
+       }
+    for (i = 0; i < sf->n_angles; i++) {
+       if (i * sf->ref_k >= start_q && i * sf->ref_k <= end_q) {
+           fprintf (fp, "%10.5f  ", i * sf->ref_k);
+           for (g = 0; g < ngrps; g++)
+               fprintf (fp, "  %10.5f ", (sf->F[g][i]) /( sf->total_n_atoms*
+                                                         sf->nSteps));
+           fprintf (fp, "\n");
+       }
+    }
+
+    ffclose (fp);
+}
+
+
+extern double CMSF (gmx_structurefactors_t *gsf,int type,int nh,double lambda, double sin_theta)
+/*
+ * return Cromer-Mann fit for the atomic scattering factor:
+ * sin_theta is the sine of half the angle between incoming and scattered
+ * vectors. See g_sq.h for a short description of CM fit.
+ */
+{
+  int i,success;
+  double tmp = 0.0, k2;
+  real *a,*b;
+  real c;
+
+  snew(a,4);
+  snew(b,4);
+
+ /*
+  *
+  * f0[k] = c + [SUM a_i*EXP(-b_i*(k^2)) ]
+  *             i=1,4
+  */
+
+  /*
+   *  united atoms case
+   *  CH2 / CH3 groups
+   */
+  if (nh > 0) {
+    tmp = (CMSF (gsf,return_atom_type ("C",gsf),0,lambda, sin_theta) +
+          nh*CMSF (gsf,return_atom_type ("H",gsf),0,lambda, sin_theta));
+  }
+  /* all atom case */
+  else {
+    k2 = (sqr (sin_theta) / sqr (10.0 * lambda));
+    success=gmx_structurefactors_get_sf(gsf,type,a,b,&c);
+    tmp = c;
+    for (i = 0; (i < 4); i++)
+      tmp += a[i] * exp (-b[i] * k2);
+  }
+  return tmp;
+}
+
+
+
+extern real **gmx_structurefactors_table(gmx_structurefactors_t *gsf,real momentum, real ref_k, real lambda, int n_angles){
+
+       int NCMT;
+       int nsftable;
+       int i,j;
+       double q,sin_theta;
+    real **sf_table;
+    gmx_structurefactors *gsft=(gmx_structurefactors *)gsf;
+
+    NCMT=gsft->nratoms;
+       nsftable = NCMT+3;
+
+    snew (sf_table,nsftable);
+    for (i = 0; (i < nsftable); i++) {
+       snew (sf_table[i], n_angles);
+       for (j = 0; j < n_angles; j++) {
+               q = ((double) j * ref_k);
+               /* theta is half the angle between incoming
+                          and scattered wavevectors. */
+               sin_theta = q / (2.0 * momentum);
+               if (i < NCMT){
+                    sf_table[i][j] = CMSF (gsf,i,0,lambda, sin_theta);
+                }
+                else
+                       sf_table[i][j] = CMSF (gsf,i,i-NCMT+1,lambda, sin_theta);
+       }
+    }
+    return sf_table;
+}
+
+extern void gmx_structurefactors_done(gmx_structurefactors_t *gsf){
+
+       int i;
+       gmx_structurefactors *sf;
+       sf=(gmx_structurefactors *) gsf;
+
+       for(i=0;i<sf->nratoms;i++){
+        sfree(sf->a[i]);
+               sfree(sf->b[i]);
+               sfree(sf->atomnm[i]);
+       }
+
+       sfree(sf->a);
+       sfree(sf->b);
+       sfree(sf->atomnm);
+       sfree(sf->p);
+       sfree(sf->n);
+       sfree(sf->c);
+
+       sfree(sf);
+
+}
+
+extern real **compute_scattering_factor_table (gmx_structurefactors_t *gsf,structure_factor_t *sft,int *nsftable)
+{
+/*
+ *  this function build up a table of scattering factors for every atom
+ *  type and for every scattering angle.
+ */
+   
+    double hc=1239.842;
+    real ** sf_table;
+
+    structure_factor *sf=(structure_factor *)sft;
+
+
+    /* \hbar \omega \lambda = hc = 1239.842 eV * nm */
+    sf->momentum = ((double) (2. * 1000.0 * M_PI * sf->energy) / hc);
+    sf->lambda = hc / (1000.0 * sf->energy);
+    fprintf (stderr, "\nwavelenght = %f nm\n", sf->lambda);
+
+    sf_table=gmx_structurefactors_table(gsf,sf->momentum,sf->ref_k,sf->lambda,sf->n_angles);
+
+    return sf_table;
+}
+
+
index c9adcd62b8a18b840f320c16bd35fc87f9534e4a..da0dd88053b7b3add666551470c21632bc172371 100644 (file)
 #include "pppm.h"
 #include "gmxfio.h"
 
+#include "thread_mpi.h"
+
 #define p2(x) ((x)*(x))
 #define p3(x) ((x)*(x)*(x)) 
 #define p4(x) ((x)*(x)*(x)*(x)) 
 
 static real A,A_3,B,B_4,C,c1,c2,c3,c4,c5,c6,One_4pi,FourPi_V,Vol,N0;
+#ifdef GMX_THREADS
+static tMPI_Thread_mutex_t shift_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
+#endif
+
 
 void set_shift_consts(FILE *log,real r1,real rc,rvec box,t_forcerec *fr)
 {
+#ifdef GMX_THREADS
+  /* at the very least we shouldn't allow multiple threads to set these 
+     simulataneously */
+  tMPI_Thread_mutex_lock(&shift_mutex);
+#endif
   /* A, B and C are recalculated in tables.c */
   if (r1 < rc) {
     A   = (2*r1-5*rc)/(p3(rc)*p2(rc-r1));
@@ -100,6 +111,9 @@ void set_shift_consts(FILE *log,real r1,real rc,rvec box,t_forcerec *fr)
   }
     
   One_4pi = 1.0/(4.0*M_PI);
+#ifdef GMX_THREADS
+  tMPI_Thread_mutex_unlock(&shift_mutex);
+#endif
 }
 
 real gk(real k,real rc,real r1)
index 733c9ddc42001d91c1e3e3ca8be6135adf8660a6..b3a628f35bc7742d7129eaed596055ebfd18ba8a 100644 (file)
 #include "gmx_fatal.h"
 #include "sighandler.h"
 
-/* The following two variables and the signal_handler function
- * are used from md.c and pme.c as well 
- *
- * Do not fear these global variables: they represent inherently process-global
- * information that needs to be shared across threads 
- */
-
 
-/* we got a signal to stop in the next step: */
-volatile sig_atomic_t bGotStopNextStepSignal=FALSE;
-/* we got a signal to stop in the next neighbour search step: */
-volatile sig_atomic_t bGotStopNextNSStepSignal=FALSE;
+const char *gmx_stop_cond_name[] =
+{
+    "None",
+    "Stop at the next neighbor search step",
+    "Stop at the next step",
+    "Abort"
+};
 
-/* our names for the handled signals. These must match the number given
-   in signal_handler. */
-const char *signal_name[] =
+/* these do not neccesarily match the stop condition, but are 
+   referred to in the signal handler. */
+const char *gmx_signal_name[] =
 {
-    "TERM",
+    "None",
     "INT",
-    "second INT"
+    "TERM",
+    "second INT/TERM",
+    "remote INT/TERM",
+    "remote second INT/TERM",
+    "USR1",
+    "Abort"
 };
 
-/* the last signal received, according to the numbering
-   we use in signal_name */
-volatile sig_atomic_t last_signal_number_recvd=-1;
+static volatile sig_atomic_t stop_condition=gmx_stop_cond_none;
+static volatile sig_atomic_t last_signal_name=0;
 
-RETSIGTYPE signal_handler(int n)
+static volatile sig_atomic_t usr_condition=0;
+
+static RETSIGTYPE signal_handler(int n)
 {
     switch (n) {
-        case SIGTERM:
-            bGotStopNextStepSignal = TRUE;
-            last_signal_number_recvd = 0;
-            break;
 /* windows doesn't do SIGINT correctly according to ANSI (yes, signals are in 
    ANSI C89, and windows spawns a thread specifically to run the INT signal 
    handler), but that doesn't matter for a simple signal handler like this. */
+        case SIGTERM:
         case SIGINT:
-            if (!bGotStopNextNSStepSignal)
-            {
-                bGotStopNextNSStepSignal = TRUE;
-                last_signal_number_recvd = 1;
-            }            else if (!bGotStopNextStepSignal)
-            {
-                bGotStopNextStepSignal = TRUE;
-                last_signal_number_recvd = 2;
-            }
-            else
+            /* we explicitly set things up to allow this: */
+            stop_condition++;
+            if (n==SIGINT)
+                last_signal_name=1;
+            if (n==SIGTERM)
+                last_signal_name=2;
+            if (stop_condition == gmx_stop_cond_next)
+                last_signal_name=3;
+            if (stop_condition >= gmx_stop_cond_abort)
                 abort();
             break;
+#ifdef HAVE_SIGUSR1
+        case SIGUSR1:
+            usr_condition=1;
+            break;
+#endif
+        default:
+            break;
     }
 }
 
@@ -111,8 +116,49 @@ void signal_handler_install(void)
         }
         signal(SIGINT,signal_handler);
     }
+#ifdef HAVE_SIGUSR1
+    if (getenv("GMX_NO_USR1") == NULL)
+    {
+        if (debug)
+        {
+            fprintf(debug,"Installing signal handler for SIGUSR1\n");
+        }
+        signal(SIGUSR1,signal_handler);
+    }
+#endif
+}
+
+gmx_stop_cond_t gmx_get_stop_condition(void)
+{
+    return (gmx_stop_cond_t)stop_condition;
+}
+
+void gmx_set_stop_condition(gmx_stop_cond_t recvd_stop_cond)
+{
+    if (recvd_stop_cond > stop_condition)
+    {
+        stop_condition=recvd_stop_cond;
+        if (stop_condition == gmx_stop_cond_next_ns)
+            last_signal_name=4;
+        if (stop_condition == gmx_stop_cond_next)
+            last_signal_name=5;
+    }
+}
 
+const char *gmx_get_signal_name(void)
+{
+    return gmx_signal_name[last_signal_name];
 }
 
+bool gmx_got_usr_signal(void)
+{
+#ifdef HAVE_SIGUSR1
+    bool ret=(bool)usr_condition;
+    usr_condition=0;
+    return ret;
+#else
+    return FALSE;
+#endif
+}
 
 
index 75c68076b6f751866e7f52cb4032f6b20dbcbca3..a5f3f792129b657f16dc1fe58c668f3d2d168cfd 100644 (file)
@@ -178,7 +178,9 @@ void *save_realloc(const char *name,const char *file,int line,void *ptr,
   
   p=NULL;
   if (size==0)
-    p=NULL;
+    {
+      save_free(name, file, line, ptr);
+    }
   else
     {
 #ifdef PRINT_ALLOC_KB
@@ -201,10 +203,10 @@ void *save_realloc(const char *name,const char *file,int line,void *ptr,
                  "Not enough memory. Failed to realloc %"gmx_large_int_fmt
                  " bytes for %s, %s=%x\n(called from file %s, line %d)",
                  (gmx_large_int_t)size,name,name,ptr,file,line);
-    }
 #ifdef DEBUG
-  log_action(1,name,file,line,1,size,p);
+      log_action(1,name,file,line,1,size,p);
 #endif
+    }
   return p;
 }
 
@@ -250,3 +252,109 @@ size_t memavail(void)
   }
   return size;
 }
+
+/* If we don't have useful routines for allocating aligned memory,
+ * then we have to use the old-style GROMACS approach bitwise-ANDing
+ * pointers to ensure alignment. We store the pointer to the originally
+ * allocated region in the space before the returned pointer */
+
+/* we create a positive define for the absence of an system-provided memalign */
+#if (!defined HAVE_POSIX_MEMALIGN && !defined HAVE_MEMALIGN && \
+     !defined HAVE__ALIGNED_MALLOC)
+#define GMX_OWN_MEMALIGN
+#endif
+
+
+/* Pointers allocated with this routine should only be freed
+ * with save_free_aligned, however this will only matter
+ * on systems that lack posix_memalign() and memalign() when 
+ * freeing memory that needed to be adjusted to achieve
+ * the necessary alignment. */
+void *save_calloc_aligned(const char *name,const char *file,int line,
+                          unsigned nelem,size_t elsize,size_t alignment)
+{
+    void **aligned=NULL;
+    void *malloced=NULL;
+    bool allocate_fail;
+
+    if (alignment == 0)
+    {
+        gmx_fatal(errno,__FILE__,__LINE__,
+                  "Cannot allocate aligned memory with alignment of zero!\n(called from file %s, line %d)",file,line);
+    }
+
+    
+    if (nelem ==0 || elsize == 0)
+    {
+        aligned  = NULL;
+    }
+    else
+    {
+#ifdef PRINT_ALLOC_KB
+        if (nelem*elsize >= PRINT_ALLOC_KB*1024)
+        {
+            printf("Allocating %.1f MB for %s\n",
+                   nelem*elsize/(PRINT_ALLOC_KB*1024.0),name);
+        }
+#endif
+
+        allocate_fail = FALSE; /* stop compiler warnings */
+#ifdef HAVE_POSIX_MEMALIGN
+        allocate_fail = (0!=posix_memalign(&malloced, alignment, nelem*elsize));
+#elif defined HAVE_MEMALIGN
+        allocate_fail = ((malloced=memalign(alignment, nelem*elsize)) == NULL);
+#elif defined HAVE__ALIGNED_MALLOC
+        allocate_fail = ((malloced=_aligned_malloc(nelem*elsize, alignment)) 
+                         == NULL);
+#else
+        allocate_fail = ((malloced = malloc(nelem*elsize+alignment+
+                                            sizeof(void*)))==NULL);
+#endif
+        if (allocate_fail)
+        {
+            gmx_fatal(errno,__FILE__,__LINE__,
+                      "Not enough memory. Failed to allocate %u aligned elements of size %u for %s\n(called from file %s, line %d)",nelem,elsize,name,file,line);
+        }
+        /* we start with the original pointer */
+        aligned=(void**)malloced;
+  
+#ifdef GMX_OWN_MEMALIGN
+       /* Make the aligned pointer, and save the underlying pointer that
+        * we're allowed to free(). */
+
+        /* we first make space to store that underlying pointer: */
+        aligned = aligned + 1; 
+        /* then we apply a bit mask */
+       aligned = (void *) (((size_t) aligned + alignment - 1) & 
+                            (~((size_t) (alignment-1))));
+        /* and we store the original pointer in the area just before the 
+           pointer we're going to return */
+        aligned[-1] = malloced;
+#endif
+       memset(aligned, 0,(size_t) (nelem * elsize));
+    }
+    return (void*)aligned;
+}
+
+/* This routine can NOT be called with any pointer */
+void save_free_aligned(const char *name,const char *file,int line,void *ptr)
+{
+    int i, j;
+    void *free=ptr;
+
+    if (NULL != ptr)
+    {
+#ifdef GMX_OWN_MEMALIGN 
+        /* we get the pointer from just before the memaligned pointer */
+        free= ((void**)ptr)[-1];
+#endif
+
+#ifndef HAVE__ALIGNED_MALLOC
+        /* (Now) we're allowed to use a normal free() on this pointer. */
+        save_free(name,file,line,free);
+#else
+        _aligned_free(free);
+#endif
+    }
+}
+
index d52305ff9f551fd8a6bc09645595d8d3a9e05037..68712285554e48717df58bf597276d9b39b7b14c 100644 (file)
@@ -426,9 +426,10 @@ static void split_blocks(FILE *fp,t_inputrec *ir, int nnodes,
   
   natoms = cgs->index[cgs->nr];
        
-  if (debug) {
+  if (NULL != debug) {
     pr_block(debug,0,"cgs",cgs,TRUE);
     pr_blocka(debug,0,"sblock",sblock,TRUE);
+    fflush(debug);
   }
 
   cgsnum = make_invblock(cgs,natoms+1);        
index 0f3b408e1998ca66c183e5dee85f1c3cdc5ef63f..eb723bed61e13c1f96c3338abbd16fc9f5e2b7b1 100644 (file)
@@ -503,12 +503,12 @@ int gmx_stats_remove_outliers(gmx_stats_t gstats,double level)
     return estatsOK;
 }
 
-int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int nbins,
-                             int normalized,real **x,real **y)
+int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int *nb,
+                             int ehisto,int normalized,real **x,real **y)
 {
     gmx_stats *stats = (gmx_stats *) gstats;
-    int    i,ok,index;
-    double maxy,miny,dy;
+    int    i,ok,index=0,nbins=*nb,*nindex;
+    double minx,maxx,maxy,miny,delta,dd,minh;
   
     if (((binwidth <= 0) && (nbins <= 0)) ||
         ((binwidth > 0) && (nbins > 0)))
@@ -519,49 +519,76 @@ int gmx_stats_make_histogram(gmx_stats_t gstats,real binwidth,int nbins,
     {
         return estatsNO_POINTS;
     }
+    minx = maxx = stats->x[0];
     miny = maxy = stats->y[0];
     for(i=1; (i<stats->np); i++) 
     {
         miny = (stats->y[i] < miny) ? stats->y[i] : miny;
         maxy = (stats->y[i] > maxy) ? stats->y[i] : maxy;
+        minx = (stats->x[i] < minx) ? stats->x[i] : minx;
+        maxx = (stats->x[i] > maxx) ? stats->x[i] : maxx;
     }
+    if (ehisto == ehistoX)
+    {
+        delta = maxx-minx;
+        minh = minx;
+    }
+    else if (ehisto == ehistoY)
+    {
+        delta = maxy-miny;
+        minh = miny;
+    }
+    else
+        return estatsINVALID_INPUT;
+        
     if (binwidth == 0)
     {
-        binwidth = (maxy-miny)/nbins;
+        binwidth = (delta)/nbins;
     }
     else
     {
-        nbins = gmx_nint((maxy-miny)/binwidth + 0.5);
+        nbins = gmx_nint((delta)/binwidth + 0.5);
     }
     snew(*x,nbins);
+    snew(nindex,nbins);
     for(i=0; (i<nbins); i++) 
     {
-        (*x)[i] = miny + binwidth*(i+0.5);
+        (*x)[i] = minh + binwidth*(i+0.5);
     }
     if (normalized == 0)
     {
-        dy = 1;
+        dd = 1;
     }
     else
     {
-        dy = 1.0/(binwidth*stats->np);
+        dd = 1.0/(binwidth*stats->np);
     }
     
     snew(*y,nbins);
     for(i=0; (i<stats->np); i++) 
     {
-        index = (stats->y[i]-miny)/binwidth;
-               
-               if(index<0)
+        if (ehisto == ehistoY)
+            index = (stats->y[i]-miny)/binwidth;
+               else if (ehisto == ehistoX)
+            index = (stats->x[i]-minx)/binwidth;
+               if (index<0)
                {
                        index = 0;
                }
-               if(index>nbins-1)
+               if (index>nbins-1)
                {
                        index = nbins-1;
                }
-        (*y)[index] += dy;
-    }
+        (*y)[index] += dd;
+        nindex[index]++;
+    }
+    if (*nb == 0)
+        *nb = nbins;
+    for(i=0; (i<nbins); i++)
+        if (nindex[i] > 0)
+            (*y)[i] /= nindex[i];
+            
+    sfree(nindex);
     
     return estatsOK;
 }
index f58d53b390d37902f6b6f6e4d5a1ea8414a79280..aeed4ebcc2a48de42d103c6783477c831f70fd41 100644 (file)
@@ -108,8 +108,9 @@ const char *ShortProgram(void)
 #endif
     if ((pr=strrchr(ret,'/')) != NULL)
         ret=pr+1;
-    /*else
-        ret=ret;*/
+    /* Strip away the libtool prefix if it's still there. */
+    if(strlen(ret) > 3 && !strncmp(ret, "lt-", 3))
+        ret = ret + 3;
     return ret;
 }
 
@@ -430,13 +431,7 @@ static FILE *man_file(const output_env_t oenv,const char *mantp)
 {
     FILE   *fp;
     char   buf[256];
-    const char *pr;
-    const char *program_name=output_env_get_program_name(oenv);
-    
-    if ( (pr=strrchr(program_name,'/')) == NULL)
-        pr=program_name;
-    else 
-        pr+=1;
+    const char *pr = output_env_get_short_program_name(oenv);
     
     if (strcmp(mantp,"ascii") != 0)
         sprintf(buf,"%s.%s",pr,mantp);
@@ -815,6 +810,8 @@ void parse_common_args(int *argc,char *argv[],unsigned long Flags,
         setTimeValue(TDELTA,opt2parg_real("-dt",npall,all_pa));
     
     /* clear memory */
+    for (i = 0; i < npall; ++i)
+        sfree((void *)all_pa[i].desc);
     sfree(all_pa);
     
     if (!FF(PCA_NOEXIT_ON_ARGS)) {
index 34c31275dd6ab5b27e77b069ed3d3e6c4649c044..9b03172d4d779c030c703d31f40ed1c7a2b9f756 100644 (file)
@@ -184,13 +184,13 @@ int get_file(const char *db,char ***strings)
 {
   FILE *in;
   char **ptr=NULL;
-  char buf[256];
+  char buf[STRLEN];
   int  i,nstr,maxi;
 
   in=libopen(db);
   
   i=maxi=0;
-  while (fgets2(buf,255,in)) {
+  while (fgets2(buf,STRLEN-1,in)) {
     if (i>=maxi) {
       maxi+=50;
       srenew(ptr,maxi);
index 0c60560c2d70c885f00d06369c0dfba833bdb838..0f05d74cc8e4a93ef6dfd8a1986e5a626e60a38d 100644 (file)
@@ -364,7 +364,8 @@ gmx_wcmatch(const char *pattern, const char *str)
         }
         ++pattern;
     }
-    return 0;
+    /* When the pattern runs out, we have a match if the string has ended. */
+    return (*str == 0) ? 0 : GMX_NO_WCMATCH;
 }
 
 char *wrap_lines(const char *buf,int line_width, int indent,bool bIndentFirst)
index e5e35f43e3d082766a9216506fdcf79e2cdf79ef..dcc8a06f7653f007c3f779b4b6e788787e922f02 100644 (file)
@@ -4,7 +4,7 @@
 add_library(thread_mpi STATIC threads.c tmpi_init.c errhandler.c 
             type.c group.c comm.c topology.c p2p.c collective.c 
             once.c list.c reduce_fast.c profile.c event.c barrier.c
-            hwinfo.c)
+            lock.c hwinfo.c)
 
 # make it link to the threads library (-lpthreads, for example)
 target_link_libraries(thread_mpi ${THREAD_LIB})
@@ -14,6 +14,9 @@ target_link_libraries(thread_mpi ${THREAD_LIB})
 #add_definitions(-DHAVE_TMPI_CONFIG_H)
 #include_directories( . )
 
+# this configure file only works here. If you include the source
+# files into your project, insert the contest of the tmpi_config.h.cmakein
+# into your config.h.cmakein file
 configure_file(tmpi_config.h.cmakein  ${CMAKE_CURRENT_BINARY_DIR}/tmpi_config.h)
 include_directories(${CMAKE_CURRENT_BINARY_DIR})
 add_definitions(-DHAVE_TMPI_CONFIG_H)
index a3e6a94972794d6c7c80080723366bdbf1fe354c..66e0fa54f060a5529095260124d300817933aac9 100644 (file)
@@ -16,7 +16,7 @@ libthread_mpi_la_SOURCES = group.c       barrier.c      list.c  \
                           once.c        tmpi_init.c    comm.c \
                           profile.c     errhandler.c   topology.c \
                           event.c       type.c         reduce_fast.c \
-                          hwinfo.c
+                          hwinfo.c      lock.c
 
 CLEANFILES     = *.la *~ \\\#*
 
index 9036328d6eb2f448ce3146cca0656c10b8ca3351..6f752435b5c3e94f282f9b2b5daf209271afb35d 100644 (file)
@@ -57,7 +57,7 @@ files.
 
 
 
-void tMPI_Spinlock_barrier_init(tMPI_Spinlock_barrier_t *barrier, int count)
+void tMPI_Barrier_init(tMPI_Barrier_t *barrier, int count)
 {
     barrier->threshold = count;
     barrier->cycle     = 0;
@@ -66,7 +66,7 @@ void tMPI_Spinlock_barrier_init(tMPI_Spinlock_barrier_t *barrier, int count)
 }
 
 
-int tMPI_Spinlock_barrier_wait(tMPI_Spinlock_barrier_t *barrier)
+int tMPI_Barrier_wait(tMPI_Barrier_t *barrier)
 {
     int    cycle;
     int    status;
index 5d736b34af3a35f03df23ad66a43780c4ea8c533..6a0e04b29f392126818d14dadfc68b25dd7fe538 100644 (file)
@@ -586,7 +586,7 @@ int tMPI_Barrier(tMPI_Comm comm)
         tMPI_Profile_wait_start(cur);
 #endif
 
-        tMPI_Spinlock_barrier_wait( &(comm->barrier) );
+        tMPI_Barrier_wait( &(comm->barrier) );
 #if defined(TMPI_PROFILE) 
         tMPI_Profile_wait_stop(cur, TMPIWAIT_Barrier);
 #endif
index f407d52368d82476d99e36059a48719c4ff2026a..17f71de2ec8de01368ff34c61c4c073b4f55866c 100644 (file)
@@ -95,6 +95,59 @@ int tMPI_Comm_rank(tMPI_Comm comm, int *rank)
     return tMPI_Group_rank(&(comm->grp), rank);
 }
 
+
+int tMPI_Comm_compare(tMPI_Comm comm1, tMPI_Comm comm2, int *result)
+{
+    int i,j;
+#ifdef TMPI_TRACE
+    tMPI_Trace_print("tMPI_Comm_compare(%p, %p, %p)", comm1, comm2, result);
+#endif
+    if (comm1 == comm2)
+    {
+        *result=TMPI_IDENT;
+        return TMPI_SUCCESS;
+    }
+
+    if ( (!comm1) || (!comm2) )
+    {
+        *result=TMPI_UNEQUAL;
+        return TMPI_SUCCESS;
+    }
+
+    if (comm1->grp.N != comm2->grp.N)
+    {
+        *result=TMPI_UNEQUAL;
+        return TMPI_SUCCESS;
+    }
+
+    *result=TMPI_CONGRUENT;
+    /* we assume that there are two identical comm members within a comm */
+    for(i=0;i<comm1->grp.N;i++)
+    {
+        if (comm1->grp.peers[i] != comm2->grp.peers[i])
+        {
+            bool found=FALSE;
+
+            *result=TMPI_SIMILAR;
+            for(j=0;j<comm2->grp.N;j++)
+            {
+                if (comm1->grp.peers[i] == comm2->grp.peers[j])
+                {
+                    found=TRUE;
+                    break;
+                }
+            }
+            if (!found)
+            {
+                *result=TMPI_UNEQUAL;
+                return TMPI_SUCCESS;
+            }
+        }
+    }
+    return TMPI_SUCCESS;
+}
+
+
 tMPI_Comm tMPI_Comm_alloc(tMPI_Comm parent, int N)
 {
     struct tmpi_comm_ *ret;
@@ -117,7 +170,7 @@ tMPI_Comm tMPI_Comm_alloc(tMPI_Comm parent, int N)
 
 
     /* initialize the main barrier */
-    tMPI_Spinlock_barrier_init(&(ret->barrier), N);
+    tMPI_Barrier_init(&(ret->barrier), N);
 
 #if 0
     {
@@ -130,13 +183,13 @@ tMPI_Comm tMPI_Comm_alloc(tMPI_Comm parent, int N)
         } 
 
         ret->Nreduce_barriers=Nbarriers;
-        ret->reduce_barrier=(tMPI_Spinlock_barrier_t*)
-                  tMPI_Malloc(sizeof(tMPI_Spinlock_barrier_t)*(Nbarriers+1));
+        ret->reduce_barrier=(tMPI_Barrier_t*)
+                  tMPI_Malloc(sizeof(tMPI_Barrier_t)*(Nbarriers+1));
         ret->N_reduce_barrier=(int*)tMPI_Malloc(sizeof(int)*(Nbarriers+1));
         Nred=N;
         for(i=0;i<Nbarriers;i++)
         {
-            tMPI_Spinlock_barrier_init( &(ret->reduce_barrier[i]), Nred);
+            tMPI_Barrier_init( &(ret->reduce_barrier[i]), Nred);
             ret->N_reduce_barrier[i]=Nred;
             /* Nred is now Nred/2 + a rest term because solitary 
                process at the end of the list must still be accounter for */
@@ -159,8 +212,8 @@ tMPI_Comm tMPI_Comm_alloc(tMPI_Comm parent, int N)
 
         ret->N_reduce_iter=Niter;
         /* allocate the list */
-        ret->reduce_barrier=(tMPI_Spinlock_barrier_t**)
-                  tMPI_Malloc(sizeof(tMPI_Spinlock_barrier_t*)*(Niter+1));
+        ret->reduce_barrier=(tMPI_Barrier_t**)
+                  tMPI_Malloc(sizeof(tMPI_Barrier_t*)*(Niter+1));
         ret->N_reduce=(int*)tMPI_Malloc(sizeof(int)*(Niter+1));
 
         /* we re-set Nred to N */
@@ -172,11 +225,11 @@ tMPI_Comm tMPI_Comm_alloc(tMPI_Comm parent, int N)
             Nred = Nred/2 + Nred%2;
             ret->N_reduce[i] = Nred;
             /* allocate the sub-list */
-            ret->reduce_barrier[i]=(tMPI_Spinlock_barrier_t*)
-                      tMPI_Malloc(sizeof(tMPI_Spinlock_barrier_t)*(Nred));
+            ret->reduce_barrier[i]=(tMPI_Barrier_t*)
+                      tMPI_Malloc(sizeof(tMPI_Barrier_t)*(Nred));
             for(j=0;j<Nred;j++)
             {
-                tMPI_Spinlock_barrier_init(&(ret->reduce_barrier[i][j]),2);
+                tMPI_Barrier_init(&(ret->reduce_barrier[i][j]),2);
             }
         }
     }
index 236474e204be543f117571b63d05eae0f464db1e..321328a9593a71805e6ee778bffe8415f77d4a61 100644 (file)
@@ -63,9 +63,7 @@ files.
 #include "thread_mpi/collective.h"
 #include "thread_mpi/barrier.h"
 #include "thread_mpi/hwinfo.h"
-#include "wait.h"
-#include "barrier.h"
-#include "event.h"
+#include "thread_mpi/lock.h"
 #ifdef TMPI_PROFILE
 #include "profile.h"
 #endif
@@ -556,7 +554,7 @@ struct tmpi_comm_
     struct tmpi_group_ grp; /* the communicator group */
 
     /* the barrier for tMPI_Barrier() */
-    tMPI_Spinlock_barrier_t barrier;
+    tMPI_Barrier_t barrier;
 
 
     /* List of barriers for reduce operations.
@@ -565,7 +563,7 @@ struct tmpi_comm_
        reduce_barrier[2] contains a list of N/8 barriers for N/4 threads
        and so on. (until N/x reaches 1)
        This is to facilitate tree-based algorithms for tMPI_Reduce, etc.  */
-    tMPI_Spinlock_barrier_t **reduce_barrier;
+    tMPI_Barrier_t **reduce_barrier;
     int *N_reduce; /* the number of barriers in each iteration */
     int N_reduce_iter; /* the number of iterations */
 
similarity index 70%
rename from src/gmxlib/thread_mpi/barrier.h
rename to src/gmxlib/thread_mpi/lock.c
index b369f92d65e76fc993fe52eee834511104264fc1..275cbf7ad5eca048a29703209b83b660f5a7b35b 100644 (file)
@@ -35,13 +35,55 @@ be called official thread_mpi. Details are found in the README & COPYING
 files.
 */
 
+#ifdef HAVE_TMPI_CONFIG_H
+#include "tmpi_config.h"
+#endif
 
-struct tMPI_Spinlock_barrier
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "impl.h"
+
+
+
+void tMPI_Lock_init(tMPI_Lock_t *lock)
+{
+    tMPI_Spinlock_init(&(lock->lock));
+    TMPI_YIELD_WAIT_DATA_INIT(lock);
+}
+
+
+void tMPI_Lock_lock(tMPI_Lock_t *lock)
 {
-    tMPI_Atomic_t     count;     /*!< Number of threads remaining     */
-    int               threshold; /*!< Total number of threads         */
-    volatile int      cycle;     /*!< Current cycle (alternating 0/1) */
-    TMPI_YIELD_WAIT_DATA
-};
+    while(!tMPI_Spinlock_trylock(&(lock->lock)))
+    {
+        TMPI_YIELD_WAIT(lock);
+    }
+}
 
 
+void tMPI_Lock_unlock(tMPI_Lock_t *lock)
+{
+    tMPI_Spinlock_unlock(&(lock->lock));
+}
+
+int tMPI_Lock_trylock(tMPI_Lock_t *lock)
+{
+    return tMPI_Spinlock_trylock(&(lock->lock));
+}
+
+int tMPI_Lock_islocked(const tMPI_Lock_t *lock)
+{
+    return tMPI_Spinlock_islocked(&(lock->lock));
+}
index af964d0f757a2f435c0d0317fad99d716c58ae75..1a4ce3109afa5917e8f8617175a0dbeb0da311c2 100644 (file)
@@ -121,7 +121,7 @@ void tMPI_Send_env_list_init(struct send_envelope_list *evl, int N)
 #endif
     evl->Nalloc=N;
 
-    evl->alloc_head=(struct envelope*)tMPI_Malloc(sizeof(struct envelope)*N );
+    evl->alloc_head=(struct envelope*)tMPI_Malloc(sizeof(struct envelope)*N);
     for(i=0;i<N;i++) 
     { 
         evl->alloc_head[i].next=(i<(N-1)) ? &(evl->alloc_head[i+1]) : NULL;
index a93950e95b14925acc72046f5ea6cba8ff8ba33d..19b6bc27032d0d5685c9250aee312326e8679147 100644 (file)
@@ -68,6 +68,8 @@ files.
 #include <stdarg.h>
 #endif
 
+int tMPI_Profile_started=0;
+
 
 /* this must match the tmpi_functions enum: */
 const char *tmpi_function_names[] = 
@@ -144,6 +146,7 @@ void tMPI_Profile_init(struct tmpi_profile *prof)
     prof->buffered_coll_xfers=0;
     prof->total_p2p_xfers=0;
     prof->total_coll_xfers=0;
+    tMPI_Profile_started=1;
 }
 
 
@@ -160,6 +163,7 @@ void tMPI_Profile_stop(struct tmpi_profile *prof)
 #ifdef TMPI_CYCLE_COUNT
     prof->global_stop=tmpi_cycles_read();
 #endif
+    tMPI_Profile_started=0;
 }
 
 /* output functions */
index d18eeec1c17e67f79bd5a7db52e472121ba5fa5b..ef78544858d30b3f860d2bac7119444aa6bd52d0 100644 (file)
@@ -123,6 +123,8 @@ struct tmpi_profile
 #endif
 };
 
+extern int tMPI_Profile_started;
+
 /* initialize the profile counter */
 void tMPI_Profile_init(struct tmpi_profile *prof);
 
index 164a5d61dd02fae208ce99b7df988e9a182b663b..a1abe5ede338496c40c53a73512b5edc1311112e 100644 (file)
@@ -110,7 +110,7 @@ int tMPI_Reduce_fast(void* sendbuf, void* recvbuf, int count,
 #ifdef TMPI_DEBUG
         printf("%d: iteration %d: myrank_rtr=%d, stepping=%d\n", 
                myrank, iteration, myrank_rtr, stepping);
-        fflush(0);
+        fflush(stdout);
 #endif
         /* check if I'm the reducing thread in this iteration's pair: */
         if (myrank_rtr%stepping == 0)
@@ -125,7 +125,7 @@ int tMPI_Reduce_fast(void* sendbuf, void* recvbuf, int count,
 #ifdef TMPI_DEBUG
                 printf("%d: waiting to reduce with %d, iteration=%d\n", 
                        myrank, nbr, iteration);
-                fflush(0);
+                fflush(stdout);
 #endif
 
 #if defined(TMPI_PROFILE) && defined(TMPI_CYCLE_COUNT)
@@ -140,7 +140,7 @@ int tMPI_Reduce_fast(void* sendbuf, void* recvbuf, int count,
 #ifdef TMPI_DEBUG
                 printf("%d: reducing with %d, iteration=%d\n", 
                        myrank, nbr, iteration);
-                fflush(0);
+                fflush(stdout);
 #endif
                 /* we reduce with our neighbour*/
                 if (iteration==0)
@@ -175,7 +175,7 @@ int tMPI_Reduce_fast(void* sendbuf, void* recvbuf, int count,
             {
 #ifdef TMPI_DEBUG
             printf("%d: not waiting copying buffer\n", myrank);
-            fflush(0);
+            fflush(stdout);
 #endif
                 /* we still need to put things in the right buffer for the next
                    iteration. We need to check for overlapping buffers
@@ -197,7 +197,7 @@ int tMPI_Reduce_fast(void* sendbuf, void* recvbuf, int count,
 #ifdef TMPI_DEBUG
             printf("%d: signalled %d, now waiting: iteration=%d\n", 
                    nbr, myrank,  iteration);
-            fflush(0);
+            fflush(stdout);
 #endif
  
             /* And wait for an incoming event from out neighbour */
@@ -216,7 +216,7 @@ int tMPI_Reduce_fast(void* sendbuf, void* recvbuf, int count,
 
 #ifdef TMPI_DEBUG
         printf("%d: iteration over, iteration=%d\n", myrank,  iteration);
-        fflush(0);
+        fflush(stdout);
 #endif
 
         Nred = Nred/2 + Nred%2;
@@ -298,7 +298,7 @@ int tMPI_Allreduce(void* sendbuf, void* recvbuf, int count,
 #if defined(TMPI_PROFILE) 
     tMPI_Profile_wait_start(cur);
 #endif
-    tMPI_Spinlock_barrier_wait( &(comm->barrier));
+    tMPI_Barrier_wait( &(comm->barrier));
 #if defined(TMPI_PROFILE) && defined(TMPI_CYCLE_COUNT)
     tMPI_Profile_wait_stop(cur, TMPIWAIT_Reduce);
 #endif
@@ -320,7 +320,7 @@ int tMPI_Allreduce(void* sendbuf, void* recvbuf, int count,
 #if defined(TMPI_PROFILE) && defined(TMPI_CYCLE_COUNT)
     tMPI_Profile_wait_start(cur);
 #endif
-    tMPI_Spinlock_barrier_wait( &(comm->barrier));
+    tMPI_Barrier_wait( &(comm->barrier));
 #if defined(TMPI_PROFILE)
     tMPI_Profile_wait_stop(cur, TMPIWAIT_Reduce);
     tMPI_Profile_count_stop(cur, TMPIFN_Allreduce);
index 78766a0d14f69acc5691420745c96d5c391ded07..f36cdaa55b2f720409b9735cee9536086439f085 100644 (file)
@@ -55,7 +55,7 @@ files.
 
 
 /* the number of envelopes to allocate per thread-to-thread path */
-#define N_EV_ALLOC 8
+#define N_EV_ALLOC 16
 
 /* the normal maximum number of threads for pre-defined arrays
    (if the actual number of threads is bigger than this, it'll
diff --git a/src/gmxlib/thread_mpi/tmpi_impl.h b/src/gmxlib/thread_mpi/tmpi_impl.h
deleted file mode 100644 (file)
index b206ebb..0000000
+++ /dev/null
@@ -1,762 +0,0 @@
-/*
-This source code file is part of thread_mpi.  
-Written by Sander Pronk, Erik Lindahl, and possibly others. 
-
-Copyright (c) 2009, Sander Pronk, Erik Lindahl.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-1) Redistributions of source code must retain the above copyright
-   notice, this list of conditions and the following disclaimer.
-2) Redistributions in binary form must reproduce the above copyright
-   notice, this list of conditions and the following disclaimer in the
-   documentation and/or other materials provided with the distribution.
-3) Neither the name of the copyright holders nor the
-   names of its contributors may be used to endorse or promote products
-   derived from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY US ''AS IS'' AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL WE BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-If you want to redistribute modifications, please consider that
-scientific software is very special. Version control is crucial -
-bugs must be traceable. We will be happy to consider code for
-inclusion in the official distribution, but derived work should not
-be called official thread_mpi. Details are found in the README & COPYING
-files.
-*/
-
-
-
-#include "settings.h"
-
-
-/* BASIC DEFINITIONS */
-
-
-#ifndef __cplusplus
-typedef int bool;
-#define TRUE 1
-#define FALSE 0
-#else
-#ifndef TRUE
-#define TRUE true
-#endif
-#ifndef FALSE
-#define FALSE false
-#endif
-#endif
-
-
-
-
-
-#ifdef USE_COLLECTIVE_COPY_BUFFER
-/* PRE-ALLOCATED COMMUNICATION BUFFERS */
-
-/* Buffer structure. Every thread structure has several of these ready to
-   be used when the data transmission is small enough for double copying to 
-   occur (i.e. the size of the transmission is less than N*MAX_COPY_BUFFER_SIZE,
-   where N is the number of receiving threads).
-
-   These buffers come in two sizes: one pre-allocated to MAX_COPY_BUFFER_SIZE
-   (for point-to-point transmissions, and one pre-allocated to 
-   Nthreads*MAX_COPY_BUFFE_SIZE). */
-struct copy_buffer
-{
-    void *buf; /* the actual buffer */
-    struct copy_buffer *next; /* pointer to next free buffer in buffer_list */
-    size_t size; /* allocated size of buffer */
-};
-
-/* a list of copy_buffers of a specific size. */
-struct copy_buffer_list
-{
-    struct copy_buffer *cb; /* pointer to the first copy_buffer */
-    size_t size; /* allocated size of buffers in this list */
-    struct copy_buffer *cb_alloc; /* list as allocated */
-    int Nbufs; /* number of allocated buffers */
-};
-#endif
-
-
-
-
-
-
-
-
-
-
-
-
-
-/* POINT-TO-POINT COMMUNICATION DATA STRUCTURES */
-
-/* the message envelopes (as described in the MPI standard). 
-   These fully describes the message, and make each message unique (enough).
-
-   Transmitting data works by having the sender put a pointer to an envelope 
-   onto the receiver's new envelope list corresponding to the originating 
-   thread. 
-   The sender then waits until the receiver finishes the transmission, while
-   matching all incoming new envelopes against its own list of receive 
-   envelopes.
-
-   The receiver either directly matches its receiving envelope against
-   all previously un-matched sending envelopes, or, if no suitable envelope
-   is found, it puts the receive envelope on a receive list. 
-   Once waiting for completion, the receiver matches against all incoming 
-   new envelopes.  */
-
-/* the state of an individual point-to-point transmission */
-enum envelope_state
-{
-    env_unmatched       = 0, /* the envelope has not had a match yet */
-    env_copying         = 1, /* busy copying (only used for send_envelope 
-                                by receiver if using_cpbuf is true,
-                                but cb was still NULL).  */
-    env_cb_available    = 2, /* the copy buffer is available. Set by
-                                the sender on a send_buffer. */
-    env_finished        = 3  /* the transmission has finished */
-};
-
-
-/* the send envelope. Held in tmpi_thread->evs[src_thread]  */
-struct send_envelope
-{
-    int tag; /* the tag */
-    tMPI_Comm comm; /* this is a structure shared across threads, so we
-                      can test easily whether two threads are talking
-                      about the same comm. */
-
-    struct tmpi_thread *src, *dest; /* these are pretty obvious */
-
-    void *buf; /* buffer to be sent  */
-    size_t bufsize; /* the size of the data to be transmitted */
-    tMPI_Datatype datatype; /* the data type */
-
-    bool nonblock; /* whether the receiver is non-blocking */
-
-    /* state, values from enum_envelope_state .  
-       (there's a few busy-waits relying on this flag). 
-       status=env_unmatched  is the initial state.*/
-    tMPI_Atomic_t state;
-
-    /* the error condition */
-    int error;
-
-    /* the message status */
-    tMPI_Status *status;
-    /* prev and next envelopes in the linked list  */
-    struct send_envelope *prev,*next;
-#ifdef USE_SEND_RECV_COPY_BUFFER
-    bool using_cb; /* whether a copy buffer is (going to be) used */
-    void* cb;/* the allocated copy buffer pointer */
-#endif
-    /* the list I'm in */
-    struct send_envelope_list *list;
-};
-
-/* the receive envelope. Held in tmpi_thread->evl  */
-struct recv_envelope
-{
-    int tag; /* the tag */
-    /* transmission type flags */
-
-
-    tMPI_Comm comm; /* this is a structure shared across threads, so we
-                      can test easily whether two threads are talking
-                      about the same comm. */
-
-    struct tmpi_thread *src, *dest; /* these are pretty obvious */
-
-    void *buf; /* buffer to be sent  */
-    size_t bufsize; /* the size of the data to be transmitted, or the
-                       size of the actually transmitted data after Xfer. */
-    tMPI_Datatype datatype; /* the data type */
-
-    bool nonblock; /* whether the receiver is non-blocking */
-
-     /* state, values from enum_envelope_state .  
-        (there's a few busy-waits relying on this flag). 
-        status=env_unmatched  is the initial state.*/
-    tMPI_Atomic_t state;
-
-    /* the error condition */
-    int error;
-
-    /* prev and next envelopes in the linked list  */
-    struct recv_envelope *prev,*next;
-    /* the list I'm in */
-    struct recv_envelope_list *list;
-};
-
-
-/* singly linked lists of free send & receive envelopes belonging to a
-   thread. */
-struct free_envelope_list 
-{
-    struct recv_envelope *head_recv; /* the first element in the 
-                                             linked list */
-    struct recv_envelope *recv_alloc_head;  /* the allocated recv list */
-};
-
-/* collection of send envelopes to a specific thread */
-struct send_envelope_list
-{
-    struct send_envelope *head_free; /* singly linked list with free send
-                                        envelopes. A single-thread LIFO.*/
-#ifdef TMPI_LOCK_FREE_LISTS
-    tMPI_Atomic_ptr_t head_new; /* singly linked list with the new send 
-                                  envelopes (i.e. those that are put there by 
-                                  the sending thread, but not yet checked by 
-                                  the receiving thread). This is a lock-free 
-                                  shared detachable list.*/
-    tMPI_Atomic_ptr_t head_rts; /* singly linked list with free send
-                                   envelopes returned by the other thread. 
-                                   This is a lock-free shared LIFO.*/
-#else
-    struct send_envelope *head_new; /* singly linked list with the new 
-                                       send envelopes (i.e. those that 
-                                       are put there by the sending 
-                                       thread, but not yet checked by 
-                                       the receiving thread). */
-    struct send_envelope *head_rts; /* singly linked list with free 
-                                       send envelopes */
-    tMPI_Spinlock_t lock_new; /* this locks head_new */
-    tMPI_Spinlock_t lock_rts; /* this locks head_rts */
-#endif
-    struct send_envelope *head_old; /* the old send envelopes, in a circular 
-                                       doubly linked list. These have been 
-                                       checked by the receiving thread against 
-                                       the existing recv_envelope_list. */
-
-    struct send_envelope *alloc_head;  /* the allocated send list */
-    size_t Nalloc; /* number of allocted sends */
-};
-
-struct recv_envelope_list
-{
-    struct recv_envelope *head; /* first envelope in this list */
-    struct recv_envelope dummy; /* the dummy element for the list */
-};
-
-
-/* the request object for asynchronious operations. */
-struct tmpi_req_
-{
-    bool recv; /* whether it's a receive request. */
-    bool finished; /* whether it's finished */
-
-    struct send_envelope *evs; /* the envelope */
-    struct recv_envelope *evr; /* the envelope */
-
-    struct tmpi_status_ st;
-
-    struct tmpi_req_ *next,*prev; /* next,prev request in linked list */
-};
-
-/* pre-allocated  request object list */
-struct req_list
-{
-    struct tmpi_req_ *head; /* pre-allocated singly linked list of requests. 
-                               (i.e. reqs->prev is undefined). */
-    struct tmpi_req_ *alloc_head; /* the allocated block */
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/* MULTICAST COMMUNICATION DATA STRUCTURES */
-
-/* these are data structures meant for keeping track of multicast operations
-   (tMPI_Bcast, tMPI_Gather, etc.). Because these operations are all collective
-   across the comm, and are always blocking, the protocol can be much simpler
-   than that for point-to-point communication through tMPI_Send/Recv, etc. */
-
-/* unique tags for multicast & collective operations */
-#define TMPI_BCAST_TAG      1
-#define TMPI_GATHER_TAG     2
-#define TMPI_GATHERV_TAG    3
-#define TMPI_SCATTER_TAG    4
-#define TMPI_SCATTERV_TAG   5
-#define TMPI_REDUCE_TAG     6
-#define TMPI_ALLTOALL_TAG   7
-#define TMPI_ALLTOALLV_TAG  8
-
-
-/* thread-specific part of the coll_env */
-struct coll_env_thread
-{
-    tMPI_Atomic_t current_sync; /* sync counter value for the current
-                                   communication */
-    tMPI_Atomic_t n_remaining;  /* remaining threads count for each thread */
-
-    int tag; /* collective communication type */
-    tMPI_Datatype datatype; /* datatype */
-
-    void **buf; /* array of send/recv buffer values */
-    size_t *bufsize; /* array of number of bytes to send/recv */
-
-#ifdef USE_COLLECTIVE_COPY_BUFFER
-    bool using_cb; /* whether a copy buffer is (going to be) used */
-    tMPI_Atomic_t buf_readcount; /* Number of threads reading from buf
-                                    while using_cpbuf is true, but cpbuf 
-                                    is still NULL.  */
-    tMPI_Atomic_ptr_t *cpbuf; /* copy_buffer pointers. */
-    struct copy_buffer *cb; /* the copy buffer cpbuf points to */
-#endif
-#ifdef TMPI_NO_BUSY_WAIT_COLLECTIVE
-    tMPI_Thread_mutex_t wait_mutex; /* mutex associated with waiting */
-    tMPI_Thread_cond_t send_cond; /* condition associated with the sending */
-    tMPI_Thread_cond_t recv_cond; /* condition associated with the receiving */
-#endif
-
-    bool *read_data; /* whether we read data from a specific thread. */
-};
-
-/* Collective communications once sync. These run in parallel with
-   the collection of coll_env_threads*/
-struct coll_env_coll
-{
-    /* collective sync data */
-    tMPI_Atomic_t current_sync; /* sync counter value for the current
-                                   communication */
-    tMPI_Atomic_t n_remaining;  /* remaining threads count */
-
-    void *res; /* result data for once calls. */
-};
-
-/* the collective communication envelope. There's a few of these per 
-   comm, and each one stands for one collective communication call.  */
-struct coll_env
-{
-    struct coll_env_thread *met; /* thread-specific collective envelope data.*/
-
-    struct coll_env_coll coll;
-    int N;
-};
-
-/* multicast synchronization data structure. There's one of these for 
-   each thread in each tMPI_Comm structure */
-struct coll_sync
-{
-    int synct; /* sync counter for coll_env_thread.  */
-    int syncs; /* sync counter for coll_env_coll.  */
-};
-
-
-
-
-
-
-
-
-
-
-/* GLOBALLY AVAILABLE DATA STRUCTURES */
-#ifdef TMPI_PROFILE
-#include "profile.h"
-#endif
-
-/* information about a running thread. This structure is put in a 
-   globally available array; the envelope exchange, etc. are all done through
-   the elements of this array.*/
-struct tmpi_thread
-{
-    tMPI_Thread_t thread_id;
-
-    /* the receive envelopes posted for other threads to check */
-    struct recv_envelope_list evr;
-    /* the send envelopes posted by other threadas */
-    struct send_envelope_list *evs;
-
-
-#ifndef TMPI_NO_BUSY_WAIT_SEND_RECV
-    /* send envelope change indicator/count */
-    tMPI_Atomic_t evs_new_incoming;
-#else
-    /* lock+signal for signaling newly available send envelopes to this thread, 
-       or finished send envelopes from this thread. */
-    tMPI_Thread_mutex_t ev_check_lock;
-    tMPI_Thread_cond_t ev_check_cond;
-    /* send envelope change count */
-    int evs_new_incoming;
-    /* the number of send envelopes from this thread that have been 
-       xmitted by other threads */
-    int ev_received;
-#endif
-
-    struct req_list rql;  /* list of pre-allocated requests */
-
-    struct free_envelope_list envelopes; /* free envelopes */
-#ifdef USE_COLLECTIVE_COPY_BUFFER
-    /* copy buffer list for multicast communications */
-    struct copy_buffer_list cbl_multi; 
-#endif
-
-    tMPI_Comm self_comm; /* comms for MPI_COMM_SELF */
-
-#ifdef TMPI_PROFILE
-    struct tmpi_profile profile;
-#endif
-
-    void (*start_fn)(void*); /* The start function (or NULL, if main() is to be
-                                called) */
-    void *start_arg; /* the argument to the start function, if it's not main()*/
-
-    /* we copy these for each thread (this is not required by the 
-       MPI standard, but it's convenient). Note that we copy, because
-       some programs (like Gromacs) like to manipulate these. */    
-    int argc;
-    char **argv;
-};
-
-
-/* the error handler  */
-struct tmpi_errhandler_
-{
-    int err;
-    tMPI_Errhandler_fn fn;
-};
-
-/* standard error handler functions */
-void tmpi_errors_are_fatal_fn(tMPI_Comm *comm, int *err);
-void tmpi_errors_return_fn(tMPI_Comm *comm, int *err);
-
-
-/* global MPI information */
-struct tmpi_global
-{
-    /* list of pointers to all user-defined types */
-    struct tmpi_datatype_ **usertypes;
-    int N_usertypes;
-    int Nalloc_usertypes;
-
-    /* spinlock/mutex for manipulating tmpi_user_types */
-    tMPI_Spinlock_t  datatype_lock;
-};
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/* COMMUNICATOR DATA STRUCTURES */
-
-
-
-struct tmpi_group_
-{
-    int N; /* the number of threads */
-    struct tmpi_thread **peers; /* the list of peers to communicate with */
-#if 0
-    int Nrefs; /* the number of references to this structure */
-#endif
-};
-
-
-/* the communicator objects are globally shared. */
-struct tmpi_comm_
-{
-    struct tmpi_group_ grp; /* the communicator group */
-
-    /* list of barrier_t's. 
-       multicast_barrier[0] contains a barrier for N threads 
-       (N=the number of threads in the communicator)
-       multicast_barrier[1] contains a barrier for N/2 threads
-       multicast_barrier[2] contains a barrier for N/4 threads
-       multicast_barrier[3] contains a barrier for N/8 threads
-       and so on. (until N/x reaches 1)
-       This is to facilitate tree-based algorithms for tMPI_Reduce, etc.  */
-#ifndef TMPI_NO_BUSY_WAIT_BARRIER
-    tMPI_Spinlock_barrier_t *multicast_barrier;   
-#else
-    tMPI_Thread_barrier_t *multicast_barrier;   
-#endif
-    int *N_multicast_barrier;
-    int Nbarriers;
-
-    struct coll_env *cev; /* list of multicast envelope objecs */
-    struct coll_sync *csync; /* list of multicast sync objecs */
-
-    /* lists of globally shared send/receive buffers for tMPI_Reduce, etc. */
-    volatile void **sendbuf, **recvbuf; 
-    
-    /* mutex for communication object creation. Traditional mutexes are 
-       better here because communicator creation should not be done in 
-       time-critical sections of code.   */ 
-    tMPI_Thread_mutex_t comm_create_lock;
-    tMPI_Thread_cond_t comm_create_prep; 
-    tMPI_Thread_cond_t comm_create_finish;
-
-    tMPI_Comm *new_comm; /* newly created communicators */
-    struct tmpi_split *split;
-
-    /* the topologies (only cartesian topology is currently implemented */
-    struct cart_topol *cart;
-    /*struct tmpi_graph_topol_ *graph;*/
-
-    tMPI_Errhandler erh;
-
-    /* links of a global list of all comms that starts at TMPI_COMM_WORLD */
-    struct tmpi_comm_ *next,*prev;
-};
-
-
-/* specific for tMPI_Split: */
-struct tmpi_split
-{ 
-    volatile int Ncol_init;
-    volatile int Ncol_destroy;
-    volatile bool can_finish;
-    volatile int *colors;
-    volatile int *keys;
-};
-
-/* cartesian topology */
-struct cart_topol
-{
-    int ndims; /* number of dimensions */
-    int *dims; /* procs per coordinate */
-    int *periods; /* whether the grid is periodic, per dimension */
-};
-
-#if 0
-/* graph topology */
-struct tmpi_graph_topol_
-{
-};
-#endif
-
-
-
-
-
-
-
-/* tMPI_Reduce Op functions */
-typedef void (*tMPI_Op_fn)(void*, void*, void*, int);
-
-
-struct tmpi_datatype_component
-{
-    struct tmpi_datatype_ *type;
-    unsigned int count;
-};
-
-/* we don't support datatypes with holes (yet)  */
-struct tmpi_datatype_
-{
-    size_t size; /* full extent of type. */   
-    tMPI_Op_fn *op_functions; /* array of op functions for this datatype */
-    int N_comp; /* number of components */
-    struct tmpi_datatype_component *comps; /* the components */
-    bool committed; /* whether the data type is committed */
-};
-/* just as a shorthand:  */
-typedef struct tmpi_datatype_ tmpi_dt;
-
-
-
-#if 0
-#ifdef TMPI_PROFILE
-/* bookkeeping structure for a single call */
-struct tmpi_profile_call_
-{
-    int Ncalls;
-    int Nbuffered; 
-}
-
-/* bookkeeping structure for profiling */
-struct tmpi_profile_
-{
-    struct tmpi_profile_call_ tMPI_Send;
-}; 
-#endif
-#endif
-
-
-
-
-
-/* global variables */
-
-/* the threads themselves (tmpi_comm only contains lists of pointers to this
-         structure */
-extern struct tmpi_thread *threads;
-extern int Nthreads;
-
-/* thread info */
-extern tMPI_Thread_key_t id_key; /* the key to get the thread id */
-
-/* misc. global information about MPI */
-extern struct tmpi_global *tmpi_global;
-
-
-
-
-
-#ifdef TMPI_TRACE
-void tMPI_Trace_print(const char *fmt, ...);
-#endif
-
-/* error-checking malloc/realloc: */
-void *tMPI_Malloc(size_t size);
-void *tMPI_Realloc(void *p, size_t size);
-
-
-/* get the current thread structure pointer */
-#define tMPI_Get_current() ((struct tmpi_thread*) \
-                            tMPI_Thread_getspecific(id_key))
-
-/* get the number of this thread */
-/*#define tMPI_This_threadnr() (tMPI_Get_current() - threads)*/
-
-/* get the number of a specific thread. We convert to the resulting size_t to
-   int, which is unlikely to cause problems in the foreseeable future. */
-#define tMPI_Threadnr(th) (int)(th - threads)
-
-/* get thread associated with rank  */
-#define tMPI_Get_thread(comm, rank) (comm->grp.peers[rank])
-
-
-#if 0
-/* get the current thread structure pointer */
-struct tmpi_thread *tMPI_Get_current(void);
-/* get the thread belonging to comm with rank rank */
-struct tmpi_thread *tMPI_Get_thread(tMPI_Comm comm, int rank);
-
-#endif
-
-/* handle an error, returning the errorcode */
-int tMPI_Error(tMPI_Comm comm, int tmpi_errno);
-
-
-
-/* check whether we're the main thread */
-bool tMPI_Is_master(void);
-/* check whether the current process is in a group */
-bool tMPI_In_group(tMPI_Group group);
-
-/* find the rank of a thread in a comm */
-int tMPI_Comm_seek_rank(tMPI_Comm comm, struct tmpi_thread *th);
-/* find the size of a comm */
-int tMPI_Comm_N(tMPI_Comm comm);
-
-/* allocate a comm object, making space for N threads */
-tMPI_Comm tMPI_Comm_alloc(tMPI_Comm parent, int N);
-/* de-allocate a comm object */
-void tMPI_Comm_destroy(tMPI_Comm comm);
-/* allocate a group object */
-tMPI_Group tMPI_Group_alloc(void);
-
-
-#ifdef USE_COLLECTIVE_COPY_BUFFER
-/* initialize a copy_buffer_list */
-void tMPI_Copy_buffer_list_init(struct copy_buffer_list *cbl, int Nbufs, 
-                                size_t size);
-/* initialize a copy_buffer_list */
-void tMPI_Copy_buffer_list_destroy(struct copy_buffer_list *cbl);
-/* get a copy buffer from a list */
-struct copy_buffer *tMPI_Copy_buffer_list_get(struct copy_buffer_list *cbl);
-/* return a copy buffer to a list */
-void tMPI_Copy_buffer_list_return(struct copy_buffer_list *cbl, 
-                                  struct copy_buffer *cb);
-/* initialize a copy buffer */
-void tMPI_Copy_buffer_init(struct copy_buffer *cb, size_t size);
-void tMPI_Copy_buffer_destroy(struct copy_buffer *cb);
-#endif
-
-
-
-
-
-/* initialize a free envelope list with N envelopes */
-void tMPI_Free_env_list_init(struct free_envelope_list *evl, int N);
-/* destroy a free envelope list */
-void tMPI_Free_env_list_destroy(struct free_envelope_list *evl);
-
-
-/* initialize a send envelope list */
-void tMPI_Send_env_list_init(struct send_envelope_list *evl, int N);
-/* destroy a send envelope list */
-void tMPI_Send_env_list_destroy(struct send_envelope_list *evl);
-
-
-
-
-
-
-/* initialize a recv envelope list */
-void tMPI_Recv_env_list_init(struct recv_envelope_list *evl);
-/* destroy a recv envelope list */
-void tMPI_Recv_env_list_destroy(struct recv_envelope_list *evl);
-
-
-
-
-/* initialize request list */
-void tMPI_Req_list_init(struct req_list *rl, int N_reqs);
-/* destroy request list */
-void tMPI_Req_list_destroy(struct req_list *rl);
-
-
-
-
-/* multicast functions */
-/* initialize a coll env structure */
-void tMPI_Coll_env_init(struct coll_env *mev, int N);
-/* destroy a coll env structure */
-void tMPI_Coll_env_destroy(struct coll_env *mev);
-
-/* initialize a coll sync structure */
-void tMPI_Coll_sync_init(struct coll_sync *msc);
-/* destroy a coll sync structure */
-void tMPI_Coll_sync_destroy(struct coll_sync *msc);
-
-
-
-
-/* and we need this prototype */
-int main(int argc, char **argv);
-
-
-
-
-
-
index c934b1e2af304402d22f41205a52c32ef6c0a71b..d19805df5f5c87a0c8854d061ed6242c2054ca09 100644 (file)
@@ -100,8 +100,9 @@ struct tmpi_global *tmpi_global=NULL;
 
 
 /* start N threads with argc, argv (used by tMPI_Init)*/
-static void tMPI_Start_threads(int N, int *argc, char ***argv,
-                               void (*start_fn)(void*), void *start_arg);
+static void tMPI_Start_threads(bool main_returns, int N, int *argc, 
+                               char ***argv, void (*start_fn)(void*), 
+                               void *start_arg);
 /* starter function for threads; takes a void pointer to a
       struct tmpi_starter_, which calls main() if tmpi_start_.fn == NULL */
 static void* tMPI_Thread_starter(void *arg);
@@ -139,6 +140,7 @@ void tMPI_Trace_print(const char *fmt, ...)
 void *tMPI_Malloc(size_t size)
 {
     void *ret=(void*)malloc(size);
+
     if (!ret)
     {
         tMPI_Error(TMPI_COMM_WORLD, TMPI_ERR_MALLOC);
@@ -249,11 +251,14 @@ int tMPI_Get_N(int *argc, char ***argv, const char *optname, int *nthreads)
 
 static void tMPI_Thread_init(struct tmpi_thread *th)
 {
-    int N_envelopes=(Nthreads+1)*(Nthreads+1)*N_EV_ALLOC;  
-    int N_send_envelopes=(Nthreads+1)*N_EV_ALLOC;  
-    int N_reqs=(Nthreads+1)*(Nthreads+1)*N_EV_ALLOC;  
+    int N_envelopes=(Nthreads+1)*N_EV_ALLOC;  
+    int N_send_envelopes=N_EV_ALLOC;  
+    int N_reqs=(Nthreads+1)*N_EV_ALLOC;  
     int i;
 
+    /* we set our thread id, as a thread-specific piece of global data. */
+    tMPI_Thread_setspecific(id_key, th);
+
     /* allocate comm.self */
     th->self_comm=tMPI_Comm_alloc(TMPI_COMM_WORLD, 1);
     th->self_comm->grp.peers[0]=th;
@@ -347,8 +352,6 @@ static void tMPI_Global_destroy(struct tmpi_global *g)
 static void* tMPI_Thread_starter(void *arg)
 {
     struct tmpi_thread *th=(struct tmpi_thread*)arg;
-    /* we set our thread id, as a thread-specific piece of global data. */
-    tMPI_Thread_setspecific(id_key, arg);
 
 #ifdef TMPI_TRACE
     tMPI_Trace_print("Created thread nr. %d", (int)(th-threads));
@@ -372,7 +375,7 @@ static void* tMPI_Thread_starter(void *arg)
 }
 
 
-void tMPI_Start_threads(int N, int *argc, char ***argv, 
+void tMPI_Start_threads(bool main_returns, int N, int *argc, char ***argv, 
                         void (*start_fn)(void*), void *start_arg)
 {
 #ifdef TMPI_TRACE
@@ -400,7 +403,6 @@ void tMPI_Start_threads(int N, int *argc, char ***argv,
         {
             tMPI_Error(TMPI_COMM_WORLD, TMPI_ERR_INIT);
         }
-        /*printf("thread keys created\n"); fflush(NULL);*/
         for(i=0;i<N;i++)
         {
             TMPI_COMM_WORLD->grp.peers[i]=&(threads[i]);
@@ -438,9 +440,12 @@ void tMPI_Start_threads(int N, int *argc, char ***argv,
                 tMPI_Error(TMPI_COMM_WORLD, TMPI_ERR_INIT);
             }
         }
-        /* the main thread now also runs start_fn */
-        /*threads[0].thread_id=NULL; we can't count on this being a pointer*/
-        tMPI_Thread_starter((void*)&(threads[0]));
+        /* the main thread now also runs start_fn if we don't want
+           it to return */
+        if (!main_returns)
+            tMPI_Thread_starter((void*)&(threads[0]));
+        else
+            tMPI_Thread_init(&(threads[0]));
     }
 }
 
@@ -456,7 +461,7 @@ int tMPI_Init(int *argc, char ***argv)
     {
         int N=0;
         tMPI_Get_N(argc, argv, "-nt", &N);
-        tMPI_Start_threads(N, argc, argv, NULL, NULL);
+        tMPI_Start_threads(FALSE, N, argc, argv, NULL, NULL);
     }
     else
     {
@@ -467,7 +472,8 @@ int tMPI_Init(int *argc, char ***argv)
     return TMPI_SUCCESS;
 }
 
-int tMPI_Init_fn(int N, void (*start_function)(void*), void *arg)
+int tMPI_Init_fn(int main_thread_returns, int N, 
+                 void (*start_function)(void*), void *arg)
 {
 #ifdef TMPI_TRACE
     tMPI_Trace_print("tMPI_Init_fn(%d, %p, %p)", N, start_function, arg);
@@ -480,7 +486,7 @@ int tMPI_Init_fn(int N, void (*start_function)(void*), void *arg)
 
     if (TMPI_COMM_WORLD==0 && N>=1) /* we're the main process */
     {
-        tMPI_Start_threads(N, 0, 0, start_function, arg);
+        tMPI_Start_threads(main_thread_returns, N, 0, 0, start_function, arg);
     }
     return TMPI_SUCCESS;
 }
@@ -596,7 +602,7 @@ int tMPI_Abort(tMPI_Comm comm, int errorcode)
     if (comm==TMPI_COMM_WORLD)
         fprintf(stderr, " on TMPI_COMM_WORLD");
     fprintf(stderr,"\n");
-    fflush(0);
+    fflush(stdout);
 
     abort();
 #else
index bfe28fe4f0faa280ad3c5b6d10073d7b38fe2ee0..abed1450e437c762f100c23c0af7507c9d8a93b0 100644 (file)
@@ -273,7 +273,7 @@ static void tMPI_Cart_init(tMPI_Comm *comm_cart, int ndims, int *dims,
        every thread that is part of the new communicator */
     if (*comm_cart)
     {
-        tMPI_Spinlock_barrier_wait( &( (*comm_cart)->barrier) );
+        tMPI_Barrier_wait( &( (*comm_cart)->barrier) );
     }
 }
 
index 8c5af936dce7de070cbcc1b8fb5cdfd61c1e8988..241e64e3bcbff687acb5076464ac1eb1149539aa 100644 (file)
@@ -407,7 +407,8 @@ int tMPI_Thread_setspecific(tMPI_Thread_key_t key, void *value)
     return ret==0;
 }
 
-
+#if 0
+/* use once Vista is minimum required version */
 static BOOL CALLBACK InitHandleWrapperFunction(PINIT_ONCE InitOnce,
                                                PVOID Parameter,
                                                PVOID *lpContext)
@@ -422,12 +423,13 @@ static BOOL CALLBACK InitHandleWrapperFunction(PINIT_ONCE InitOnce,
 CRITICAL_SECTION tMPI_Once_cs;
 tMPI_Spinlock_t tMPI_Once_cs_lock=TMPI_SPINLOCK_INITIALIZER;
 volatile int tMPI_Once_init=0;
-
+#endif
 
 int tMPI_Thread_once(tMPI_Thread_once_t *once_control, 
                      void (*init_routine)(void))
 {
 #if 0
+    /* use once Vista is minimum required version */
     BOOL bStatus;
     bStatus = InitOnceExecuteOnce(once_control, InitHandleWrapperFunction, 
                                   init_routine, NULL);
index 2fe3e89e270c5af3ac8cad0f91f0c091224c445a..8aecd7aaa599c9e9232f89195e6f7e55e7834866 100644 (file)
@@ -182,6 +182,11 @@ void gmx_sort_ilist_fe(t_idef *idef,const real *qA,const real *qB)
     t_iatom *iabuf;
     int  iabuf_nalloc;
 
+    if (qB == NULL)
+    {
+        qB = qA;
+    }
+
     iabuf_nalloc = 0;
     iabuf        = NULL;
     
index 8d7b94dc194a9e23dd0dc1892f9ff872b3d12a11..c6e46cd7c2e191ac32bfcbcb5452c85888964396 100644 (file)
@@ -165,125 +165,129 @@ static const t_ftupd ftupd[] = {
 /* Needed for backward compatibility */
 #define MAXNODES 256
 
-void _do_section(int fp,int key,bool bRead,const char *src,int line)
+static void _do_section(t_fileio *fio,int key,bool bRead,const char *src,
+                        int line)
 {
   char buf[STRLEN];
   bool bDbg;
 
-  if (gmx_fio_getftp(fp) == efTPA) {
+  if (gmx_fio_getftp(fio) == efTPA) {
     if (!bRead) {
-      do_string(itemstr[key]);
-      bDbg       = gmx_fio_getdebug(fp);
-      gmx_fio_setdebug(fp,FALSE);
-      do_string(comment_str[key]);
-      gmx_fio_setdebug(fp,bDbg);
+      gmx_fio_write_string(fio,itemstr[key]);
+      bDbg       = gmx_fio_getdebug(fio);
+      gmx_fio_setdebug(fio,FALSE);
+      gmx_fio_write_string(fio,comment_str[key]);
+      gmx_fio_setdebug(fio,bDbg);
     }
     else {
-      if (gmx_fio_getdebug(fp))
+      if (gmx_fio_getdebug(fio))
        fprintf(stderr,"Looking for section %s (%s, %d)",
                itemstr[key],src,line);
       
       do {
-       do_string(buf);
+       gmx_fio_do_string(fio,buf);
       } while ((strcasecmp(buf,itemstr[key]) != 0));
       
       if (strcasecmp(buf,itemstr[key]) != 0) 
        gmx_fatal(FARGS,"\nCould not find section heading %s",itemstr[key]);
-      else if (gmx_fio_getdebug(fp))
+      else if (gmx_fio_getdebug(fio))
        fprintf(stderr," and found it\n");
     }
   }
 }
 
-#define do_section(key,bRead) _do_section(fp,key,bRead,__FILE__,__LINE__)
+#define do_section(fio,key,bRead) _do_section(fio,key,bRead,__FILE__,__LINE__)
 
 /**************************************************************
  *
  * Now the higer level routines that do io of the structures and arrays
  *
  **************************************************************/
-static void do_pullgrp(t_pullgrp *pgrp,bool bRead, int file_version)
+static void do_pullgrp(t_fileio *fio, t_pullgrp *pgrp, bool bRead, 
+                       int file_version)
 {
   bool bDum=TRUE;
   int  i;
 
-  do_int(pgrp->nat);
+  gmx_fio_do_int(fio,pgrp->nat);
   if (bRead)
     snew(pgrp->ind,pgrp->nat);
-  ndo_int(pgrp->ind,pgrp->nat,bDum);
-  do_int(pgrp->nweight);
+  bDum=gmx_fio_ndo_int(fio,pgrp->ind,pgrp->nat);
+  gmx_fio_do_int(fio,pgrp->nweight);
   if (bRead)
     snew(pgrp->weight,pgrp->nweight);
-  ndo_real(pgrp->weight,pgrp->nweight,bDum);
-  do_int(pgrp->pbcatom);
-  do_rvec(pgrp->vec);
-  do_rvec(pgrp->init);
-  do_real(pgrp->rate);
-  do_real(pgrp->k);
+  bDum=gmx_fio_ndo_real(fio,pgrp->weight,pgrp->nweight);
+  gmx_fio_do_int(fio,pgrp->pbcatom);
+  gmx_fio_do_rvec(fio,pgrp->vec);
+  gmx_fio_do_rvec(fio,pgrp->init);
+  gmx_fio_do_real(fio,pgrp->rate);
+  gmx_fio_do_real(fio,pgrp->k);
   if (file_version >= 56) {
-    do_real(pgrp->kB);
+    gmx_fio_do_real(fio,pgrp->kB);
   } else {
     pgrp->kB = pgrp->k;
   }
 }
 
-static void do_pull(t_pull *pull,bool bRead, int file_version)
+static void do_pull(t_fileio *fio, t_pull *pull,bool bRead, int file_version)
 {
   int g;
 
-  do_int(pull->ngrp);
-  do_int(pull->eGeom);
-  do_ivec(pull->dim);
-  do_real(pull->cyl_r1);
-  do_real(pull->cyl_r0);
-  do_real(pull->constr_tol);
-  do_int(pull->nstxout);
-  do_int(pull->nstfout);
+  gmx_fio_do_int(fio,pull->ngrp);
+  gmx_fio_do_int(fio,pull->eGeom);
+  gmx_fio_do_ivec(fio,pull->dim);
+  gmx_fio_do_real(fio,pull->cyl_r1);
+  gmx_fio_do_real(fio,pull->cyl_r0);
+  gmx_fio_do_real(fio,pull->constr_tol);
+  gmx_fio_do_int(fio,pull->nstxout);
+  gmx_fio_do_int(fio,pull->nstfout);
   if (bRead)
     snew(pull->grp,pull->ngrp+1);
   for(g=0; g<pull->ngrp+1; g++)
-    do_pullgrp(&pull->grp[g],bRead,file_version);
+    do_pullgrp(fio,&pull->grp[g],bRead,file_version);
 }
 
-static void do_rotgrp(t_rotgrp *rotg,bool bRead, int file_version)
+
+static void do_rotgrp(t_fileio *fio, t_rotgrp *rotg,bool bRead, int file_version)
 {
   bool bDum=TRUE;
   int  i;
 
-  do_int(rotg->eType);
-  do_int(rotg->bMassW);
-  do_int(rotg->nat);
+  gmx_fio_do_int(fio,rotg->eType);
+  gmx_fio_do_int(fio,rotg->bMassW);
+  gmx_fio_do_int(fio,rotg->nat);
   if (bRead)
     snew(rotg->ind,rotg->nat);
-  ndo_int(rotg->ind,rotg->nat,bDum);
+  gmx_fio_ndo_int(fio,rotg->ind,rotg->nat);
   if (bRead)
       snew(rotg->x_ref,rotg->nat);
-  ndo_rvec(rotg->x_ref,rotg->nat);
-  do_rvec(rotg->vec);
-  do_rvec(rotg->pivot);
-  do_real(rotg->rate);
-  do_real(rotg->k);
-  do_real(rotg->slab_dist);
-  do_real(rotg->min_gaussian);
-  do_real(rotg->eps);
-  do_int(rotg->eFittype);
+  gmx_fio_ndo_rvec(fio,rotg->x_ref,rotg->nat);
+  gmx_fio_do_rvec(fio,rotg->vec);
+  gmx_fio_do_rvec(fio,rotg->pivot);
+  gmx_fio_do_real(fio,rotg->rate);
+  gmx_fio_do_real(fio,rotg->k);
+  gmx_fio_do_real(fio,rotg->slab_dist);
+  gmx_fio_do_real(fio,rotg->min_gaussian);
+  gmx_fio_do_real(fio,rotg->eps);
+  gmx_fio_do_int(fio,rotg->eFittype);
 }
 
-static void do_rot(t_rot *rot,bool bRead, int file_version)
+static void do_rot(t_fileio *fio, t_rot *rot,bool bRead, int file_version)
 {
   int g;
 
-  do_int(rot->ngrp);
-  do_int(rot->nstrout);
-  do_int(rot->nsttout);
+  gmx_fio_do_int(fio,rot->ngrp);
+  gmx_fio_do_int(fio,rot->nstrout);
+  gmx_fio_do_int(fio,rot->nsttout);
   if (bRead)
     snew(rot->grp,rot->ngrp);
   for(g=0; g<rot->ngrp; g++)
-    do_rotgrp(&rot->grp[g],bRead,file_version);
+    do_rotgrp(fio, &rot->grp[g],bRead,file_version);
 }
 
-static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
-                       real *fudgeQQ)
+
+static void do_inputrec(t_fileio *fio, t_inputrec *ir,bool bRead, 
+                        int file_version, real *fudgeQQ)
 {
   int  i,j,k,*tmp,idum=0; 
   bool bDum=TRUE;
@@ -303,18 +307,18 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
 
   if (file_version >= 1) {  
     /* Basic inputrec stuff */  
-    do_int(ir->eI); 
+    gmx_fio_do_int(fio,ir->eI); 
     if (file_version >= 62) {
-      do_gmx_large_int(ir->nsteps);
+      gmx_fio_do_gmx_large_int(fio, ir->nsteps);
     } else {
-      do_int(idum);
+      gmx_fio_do_int(fio,idum);
       ir->nsteps = idum;
     }
     if(file_version > 25) {
       if (file_version >= 62) {
-       do_gmx_large_int(ir->init_step);
+       gmx_fio_do_gmx_large_int(fio, ir->init_step);
       } else {
-       do_int(idum);
+       gmx_fio_do_int(fio,idum);
        ir->init_step = idum;
       }
     }  else {
@@ -322,12 +326,12 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
     }
 
        if(file_version >= 58)
-         do_int(ir->simulation_part);
+         gmx_fio_do_int(fio,ir->simulation_part);
        else
          ir->simulation_part=1;
          
     if (file_version >= 67) {
-      do_int(ir->nstcalcenergy);
+      gmx_fio_do_int(fio,ir->nstcalcenergy);
     } else {
       ir->nstcalcenergy = 1;
     }
@@ -335,11 +339,11 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
       /* The pbc info has been moved out of do_inputrec,
        * since we always want it, also without reading the inputrec.
        */
-      do_int(ir->ePBC);
+      gmx_fio_do_int(fio,ir->ePBC);
       if ((file_version <= 15) && (ir->ePBC == 2))
        ir->ePBC = epbcNONE;
       if (file_version >= 45) {
-       do_int(ir->bPeriodicMols);
+       gmx_fio_do_int(fio,ir->bPeriodicMols);
       } else {
        if (ir->ePBC == 2) {
          ir->ePBC = epbcXYZ;
@@ -349,20 +353,20 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
        }
       }
     }
-    do_int(ir->ns_type);
-    do_int(ir->nstlist);
-    do_int(ir->ndelta);
+    gmx_fio_do_int(fio,ir->ns_type);
+    gmx_fio_do_int(fio,ir->nstlist);
+    gmx_fio_do_int(fio,ir->ndelta);
     if (file_version < 41) {
-      do_int(idum);
-      do_int(idum);
+      gmx_fio_do_int(fio,idum);
+      gmx_fio_do_int(fio,idum);
     }
     if (file_version >= 45)
-      do_real(ir->rtpi);
+      gmx_fio_do_real(fio,ir->rtpi);
     else
       ir->rtpi = 0.05;
-    do_int(ir->nstcomm); 
+    gmx_fio_do_int(fio,ir->nstcomm); 
     if (file_version > 34)
-      do_int(ir->comm_mode);
+      gmx_fio_do_int(fio,ir->comm_mode);
     else if (ir->nstcomm < 0) 
       ir->comm_mode = ecmANGULAR;
     else
@@ -370,58 +374,58 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
     ir->nstcomm = abs(ir->nstcomm);
     
     if(file_version > 25)
-      do_int(ir->nstcheckpoint);
+      gmx_fio_do_int(fio,ir->nstcheckpoint);
     else
       ir->nstcheckpoint=0;
     
-    do_int(ir->nstcgsteep); 
+    gmx_fio_do_int(fio,ir->nstcgsteep); 
 
     if(file_version>=30)
-      do_int(ir->nbfgscorr); 
+      gmx_fio_do_int(fio,ir->nbfgscorr); 
     else if (bRead)
       ir->nbfgscorr = 10;
 
-    do_int(ir->nstlog); 
-    do_int(ir->nstxout); 
-    do_int(ir->nstvout); 
-    do_int(ir->nstfout); 
-    do_int(ir->nstenergy); 
-    do_int(ir->nstxtcout); 
+    gmx_fio_do_int(fio,ir->nstlog); 
+    gmx_fio_do_int(fio,ir->nstxout); 
+    gmx_fio_do_int(fio,ir->nstvout); 
+    gmx_fio_do_int(fio,ir->nstfout); 
+    gmx_fio_do_int(fio,ir->nstenergy); 
+    gmx_fio_do_int(fio,ir->nstxtcout); 
     if (file_version >= 59) {
-      do_double(ir->init_t);
-      do_double(ir->delta_t);
+      gmx_fio_do_double(fio,ir->init_t);
+      gmx_fio_do_double(fio,ir->delta_t);
     } else {
-      do_real(rdum);
+      gmx_fio_do_real(fio,rdum);
       ir->init_t = rdum;
-      do_real(rdum);
+      gmx_fio_do_real(fio,rdum);
       ir->delta_t = rdum;
     }
-    do_real(ir->xtcprec); 
+    gmx_fio_do_real(fio,ir->xtcprec); 
     if (file_version < 19) {
-      do_int(idum); 
-      do_int(idum);
+      gmx_fio_do_int(fio,idum); 
+      gmx_fio_do_int(fio,idum);
     }
     if(file_version < 18)
-      do_int(idum); 
-    do_real(ir->rlist); 
+      gmx_fio_do_int(fio,idum); 
+    gmx_fio_do_real(fio,ir->rlist); 
     if (file_version >= 67) {
-      do_real(ir->rlistlong);
+      gmx_fio_do_real(fio,ir->rlistlong);
     }
-    do_int(ir->coulombtype); 
+    gmx_fio_do_int(fio,ir->coulombtype); 
     if (file_version < 32 && ir->coulombtype == eelRF)
       ir->coulombtype = eelRF_NEC;      
-    do_real(ir->rcoulomb_switch); 
-    do_real(ir->rcoulomb); 
-    do_int(ir->vdwtype);
-    do_real(ir->rvdw_switch); 
-    do_real(ir->rvdw); 
+    gmx_fio_do_real(fio,ir->rcoulomb_switch); 
+    gmx_fio_do_real(fio,ir->rcoulomb); 
+    gmx_fio_do_int(fio,ir->vdwtype);
+    gmx_fio_do_real(fio,ir->rvdw_switch); 
+    gmx_fio_do_real(fio,ir->rvdw); 
     if (file_version < 67) {
       ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
     }
-    do_int(ir->eDispCorr); 
-    do_real(ir->epsilon_r);
+    gmx_fio_do_int(fio,ir->eDispCorr); 
+    gmx_fio_do_real(fio,ir->epsilon_r);
     if (file_version >= 37) {
-      do_real(ir->epsilon_rf);
+      gmx_fio_do_real(fio,ir->epsilon_rf);
     } else {
       if (EEL_RF(ir->coulombtype)) {
        ir->epsilon_rf = ir->epsilon_r;
@@ -431,16 +435,16 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
       }
     }
     if (file_version >= 29)
-      do_real(ir->tabext);
+      gmx_fio_do_real(fio,ir->tabext);
     else
       ir->tabext=1.0;
  
     if(file_version > 25) {
-      do_int(ir->gb_algorithm);
-      do_int(ir->nstgbradii);
-      do_real(ir->rgbradii);
-      do_real(ir->gb_saltconc);
-      do_int(ir->implicit_solvent);
+      gmx_fio_do_int(fio,ir->gb_algorithm);
+      gmx_fio_do_int(fio,ir->nstgbradii);
+      gmx_fio_do_real(fio,ir->rgbradii);
+      gmx_fio_do_real(fio,ir->gb_saltconc);
+      gmx_fio_do_int(fio,ir->implicit_solvent);
     } else {
       ir->gb_algorithm=egbSTILL;
       ir->nstgbradii=1;
@@ -450,21 +454,21 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
     }
        if(file_version>=55)
        {
-               do_real(ir->gb_epsilon_solvent);
-               do_real(ir->gb_obc_alpha);
-               do_real(ir->gb_obc_beta);
-               do_real(ir->gb_obc_gamma);
+               gmx_fio_do_real(fio,ir->gb_epsilon_solvent);
+               gmx_fio_do_real(fio,ir->gb_obc_alpha);
+               gmx_fio_do_real(fio,ir->gb_obc_beta);
+               gmx_fio_do_real(fio,ir->gb_obc_gamma);
                if(file_version>=60)
                {
-                       do_real(ir->gb_dielectric_offset);
-                       do_int(ir->sa_algorithm);
+                       gmx_fio_do_real(fio,ir->gb_dielectric_offset);
+                       gmx_fio_do_int(fio,ir->sa_algorithm);
                }
                else
                {
                        ir->gb_dielectric_offset = 0.09;
                        ir->sa_algorithm = esaAPPROX;
                }
-               do_real(ir->sa_surface_tension);
+               gmx_fio_do_real(fio,ir->sa_surface_tension);
        }
        else
        {
@@ -477,41 +481,41 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
        }
 
          
-    do_int(ir->nkx); 
-    do_int(ir->nky); 
-    do_int(ir->nkz);
-    do_int(ir->pme_order);
-    do_real(ir->ewald_rtol);
+    gmx_fio_do_int(fio,ir->nkx); 
+    gmx_fio_do_int(fio,ir->nky); 
+    gmx_fio_do_int(fio,ir->nkz);
+    gmx_fio_do_int(fio,ir->pme_order);
+    gmx_fio_do_real(fio,ir->ewald_rtol);
 
     if (file_version >=24) 
-      do_int(ir->ewald_geometry);
+      gmx_fio_do_int(fio,ir->ewald_geometry);
     else
       ir->ewald_geometry=eewg3D;
 
     if (file_version <=17) {
       ir->epsilon_surface=0;
       if (file_version==17)
-       do_int(idum);
+       gmx_fio_do_int(fio,idum);
     } 
     else
-      do_real(ir->epsilon_surface);
+      gmx_fio_do_real(fio,ir->epsilon_surface);
     
-    do_int(ir->bOptFFT);
+    gmx_fio_do_bool(fio,ir->bOptFFT);
 
-    do_int(ir->bContinuation); 
-    do_int(ir->etc);
+    gmx_fio_do_bool(fio,ir->bContinuation); 
+    gmx_fio_do_int(fio,ir->etc);
     /* before version 18, ir->etc was a bool (ir->btc),
      * but the values 0 and 1 still mean no and
      * berendsen temperature coupling, respectively.
      */
     if (file_version <= 15)
-      do_int(idum);
+      gmx_fio_do_int(fio,idum);
     if (file_version <=17) {
-      do_int(ir->epct); 
+      gmx_fio_do_int(fio,ir->epct); 
       if (file_version <= 15) {
        if (ir->epct == 5)
          ir->epct = epctSURFACETENSION;
-       do_int(idum);
+       gmx_fio_do_int(fio,idum);
       }
       ir->epct -= 1;
       /* we have removed the NO alternative at the beginning */
@@ -523,188 +527,188 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
        ir->epc=epcBERENDSEN;
     } 
     else {
-      do_int(ir->epc);
-      do_int(ir->epct);
+      gmx_fio_do_int(fio,ir->epc);
+      gmx_fio_do_int(fio,ir->epct);
     }
-    do_real(ir->tau_p); 
+    gmx_fio_do_real(fio,ir->tau_p); 
     if (file_version <= 15) {
-      do_rvec(vdum);
+      gmx_fio_do_rvec(fio,vdum);
       clear_mat(ir->ref_p);
       for(i=0; i<DIM; i++)
        ir->ref_p[i][i] = vdum[i];
     } else {
-      do_rvec(ir->ref_p[XX]);
-      do_rvec(ir->ref_p[YY]);
-      do_rvec(ir->ref_p[ZZ]);
+      gmx_fio_do_rvec(fio,ir->ref_p[XX]);
+      gmx_fio_do_rvec(fio,ir->ref_p[YY]);
+      gmx_fio_do_rvec(fio,ir->ref_p[ZZ]);
     }
     if (file_version <= 15) {
-      do_rvec(vdum);
+      gmx_fio_do_rvec(fio,vdum);
       clear_mat(ir->compress);
       for(i=0; i<DIM; i++)
        ir->compress[i][i] = vdum[i];
     } 
     else {
-      do_rvec(ir->compress[XX]);
-      do_rvec(ir->compress[YY]);
-      do_rvec(ir->compress[ZZ]);
+      gmx_fio_do_rvec(fio,ir->compress[XX]);
+      gmx_fio_do_rvec(fio,ir->compress[YY]);
+      gmx_fio_do_rvec(fio,ir->compress[ZZ]);
     }
     if (file_version >= 47) {
-      do_int(ir->refcoord_scaling);
-      do_rvec(ir->posres_com);
-      do_rvec(ir->posres_comB);
+      gmx_fio_do_int(fio,ir->refcoord_scaling);
+      gmx_fio_do_rvec(fio,ir->posres_com);
+      gmx_fio_do_rvec(fio,ir->posres_comB);
     } else {
       ir->refcoord_scaling = erscNO;
       clear_rvec(ir->posres_com);
       clear_rvec(ir->posres_comB);
     }
     if(file_version > 25)
-      do_int(ir->andersen_seed);
+      gmx_fio_do_int(fio,ir->andersen_seed);
     else
       ir->andersen_seed=0;
     
     if(file_version < 26) {
-      do_int(bSimAnn); 
-      do_real(zerotemptime);
+      gmx_fio_do_bool(fio,bSimAnn); 
+      gmx_fio_do_real(fio,zerotemptime);
     }
     
     if (file_version < 37)
-      do_real(rdum); 
+      gmx_fio_do_real(fio,rdum); 
 
-    do_real(ir->shake_tol);
+    gmx_fio_do_real(fio,ir->shake_tol);
     if (file_version < 54)
-      do_real(*fudgeQQ);
-    do_int(ir->efep);
+      gmx_fio_do_real(fio,*fudgeQQ);
+    gmx_fio_do_int(fio,ir->efep);
     if (file_version <= 14 && ir->efep > efepNO)
       ir->efep = efepYES;
     if (file_version >= 59) {
-      do_double(ir->init_lambda); 
-      do_double(ir->delta_lambda);
+      gmx_fio_do_double(fio, ir->init_lambda); 
+      gmx_fio_do_double(fio, ir->delta_lambda);
     } else {
-      do_real(rdum);
+      gmx_fio_do_real(fio,rdum);
       ir->init_lambda = rdum;
-      do_real(rdum);
+      gmx_fio_do_real(fio,rdum);
       ir->delta_lambda = rdum;
     }
     if (file_version >= 64) {
-      do_int(ir->n_flambda);
+      gmx_fio_do_int(fio,ir->n_flambda);
       if (bRead) {
        snew(ir->flambda,ir->n_flambda);
       }
-      ndo_double(ir->flambda,ir->n_flambda,bDum);
+      bDum=gmx_fio_ndo_double(fio,ir->flambda,ir->n_flambda);
     } else {
       ir->n_flambda = 0;
       ir->flambda   = NULL;
     }
     if (file_version >= 13)
-      do_real(ir->sc_alpha);
+      gmx_fio_do_real(fio,ir->sc_alpha);
     else
       ir->sc_alpha = 0;
     if (file_version >= 38)
-      do_int(ir->sc_power);
+      gmx_fio_do_int(fio,ir->sc_power);
     else
       ir->sc_power = 2;
     if (file_version >= 15)
-      do_real(ir->sc_sigma);
+      gmx_fio_do_real(fio,ir->sc_sigma);
     else
       ir->sc_sigma = 0.3;
     if (file_version >= 64) {
-      do_int(ir->nstdhdl);
+      gmx_fio_do_int(fio,ir->nstdhdl);
     } else {
       ir->nstdhdl = 1;
     }
     if (file_version >= 57) {
-      do_int(ir->eDisre); 
+      gmx_fio_do_int(fio,ir->eDisre); 
     }
-    do_int(ir->eDisreWeighting); 
+    gmx_fio_do_int(fio,ir->eDisreWeighting); 
     if (file_version < 22) {
       if (ir->eDisreWeighting == 0)
        ir->eDisreWeighting = edrwEqual;
       else
        ir->eDisreWeighting = edrwConservative;
     }
-    do_int(ir->bDisreMixed); 
-    do_real(ir->dr_fc); 
-    do_real(ir->dr_tau); 
-    do_int(ir->nstdisreout);
+    gmx_fio_do_bool(fio,ir->bDisreMixed); 
+    gmx_fio_do_real(fio,ir->dr_fc); 
+    gmx_fio_do_real(fio,ir->dr_tau); 
+    gmx_fio_do_int(fio,ir->nstdisreout);
     if (file_version >= 22) {
-      do_real(ir->orires_fc);
-      do_real(ir->orires_tau);
-      do_int(ir->nstorireout);
+      gmx_fio_do_real(fio,ir->orires_fc);
+      gmx_fio_do_real(fio,ir->orires_tau);
+      gmx_fio_do_int(fio,ir->nstorireout);
     } else {
       ir->orires_fc = 0;
       ir->orires_tau = 0;
       ir->nstorireout = 0;
     }
     if(file_version >= 26) {
-      do_real(ir->dihre_fc);
+      gmx_fio_do_real(fio,ir->dihre_fc);
       if (file_version < 56) {
-       do_real(rdum);
-       do_int(idum);
+       gmx_fio_do_real(fio,rdum);
+       gmx_fio_do_int(fio,idum);
       }
     } else {
       ir->dihre_fc=0;
     }
 
-    do_real(ir->em_stepsize); 
-    do_real(ir->em_tol); 
+    gmx_fio_do_real(fio,ir->em_stepsize); 
+    gmx_fio_do_real(fio,ir->em_tol); 
     if (file_version >= 22) 
-      do_int(ir->bShakeSOR);
+      gmx_fio_do_bool(fio,ir->bShakeSOR);
     else if (bRead)
       ir->bShakeSOR = TRUE;
     if (file_version >= 11)
-      do_int(ir->niter);
+      gmx_fio_do_int(fio,ir->niter);
     else if (bRead) {
       ir->niter = 25;
       fprintf(stderr,"Note: niter not in run input file, setting it to %d\n",
              ir->niter);
     }
     if (file_version >= 21)
-      do_real(ir->fc_stepsize);
+      gmx_fio_do_real(fio,ir->fc_stepsize);
     else
       ir->fc_stepsize = 0;
-    do_int(ir->eConstrAlg);
-    do_int(ir->nProjOrder);
-    do_real(ir->LincsWarnAngle);
+    gmx_fio_do_int(fio,ir->eConstrAlg);
+    gmx_fio_do_int(fio,ir->nProjOrder);
+    gmx_fio_do_real(fio,ir->LincsWarnAngle);
     if (file_version <= 14)
-      do_int(idum);
+      gmx_fio_do_int(fio,idum);
     if (file_version >=26)
-      do_int(ir->nLincsIter);
+      gmx_fio_do_int(fio,ir->nLincsIter);
     else if (bRead) {
       ir->nLincsIter = 1;
       fprintf(stderr,"Note: nLincsIter not in run input file, setting it to %d\n",
              ir->nLincsIter);
     }
     if (file_version < 33)
-      do_real(bd_temp);
-    do_real(ir->bd_fric);
-    do_int(ir->ld_seed);
+      gmx_fio_do_real(fio,bd_temp);
+    gmx_fio_do_real(fio,ir->bd_fric);
+    gmx_fio_do_int(fio,ir->ld_seed);
     if (file_version >= 33) {
       for(i=0; i<DIM; i++)
-       do_rvec(ir->deform[i]);
+       gmx_fio_do_rvec(fio,ir->deform[i]);
     } else {
       for(i=0; i<DIM; i++)
        clear_rvec(ir->deform[i]);
     }
     if (file_version >= 14)
-      do_real(ir->cos_accel);
+      gmx_fio_do_real(fio,ir->cos_accel);
     else if (bRead)
       ir->cos_accel = 0;
-    do_int(ir->userint1); 
-    do_int(ir->userint2); 
-    do_int(ir->userint3); 
-    do_int(ir->userint4); 
-    do_real(ir->userreal1); 
-    do_real(ir->userreal2); 
-    do_real(ir->userreal3); 
-    do_real(ir->userreal4); 
+    gmx_fio_do_int(fio,ir->userint1); 
+    gmx_fio_do_int(fio,ir->userint2); 
+    gmx_fio_do_int(fio,ir->userint3); 
+    gmx_fio_do_int(fio,ir->userint4); 
+    gmx_fio_do_real(fio,ir->userreal1); 
+    gmx_fio_do_real(fio,ir->userreal2); 
+    gmx_fio_do_real(fio,ir->userreal3); 
+    gmx_fio_do_real(fio,ir->userreal4); 
     
     /* pull stuff */
     if (file_version >= 48) {
-      do_int(ir->ePull);
+      gmx_fio_do_int(fio,ir->ePull);
       if (ir->ePull != epullNO) {
        if (bRead)
          snew(ir->pull,1);
-       do_pull(ir->pull,bRead,file_version);
+       do_pull(fio, ir->pull,bRead,file_version);
       }
     } else {
       ir->ePull = epullNO;
@@ -712,26 +716,26 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
     
     /* Enforced rotation */
     if (file_version >= 71) {
-        do_int(ir->bRot);
+        gmx_fio_do_int(fio,ir->bRot);
         if (ir->bRot == TRUE) {
             if (bRead)
                 snew(ir->rot,1);
-            do_rot(ir->rot,bRead,file_version);
+            do_rot(fio, ir->rot,bRead,file_version);
         }
     } else {
         ir->bRot = FALSE;
     }
     
     /* grpopts stuff */
-    do_int(ir->opts.ngtc); 
+    gmx_fio_do_int(fio,ir->opts.ngtc); 
     if (file_version >= 69) {
-      do_int(ir->opts.nhchainlength);
+      gmx_fio_do_int(fio,ir->opts.nhchainlength);
     } else {
       ir->opts.nhchainlength = 1;
     }
-    do_int(ir->opts.ngacc); 
-    do_int(ir->opts.ngfrz); 
-    do_int(ir->opts.ngener);
+    gmx_fio_do_int(fio,ir->opts.ngacc); 
+    gmx_fio_do_int(fio,ir->opts.ngfrz); 
+    gmx_fio_do_int(fio,ir->opts.ngener);
     
     if (bRead) {
       snew(ir->opts.nrdf,   ir->opts.ngtc); 
@@ -748,26 +752,27 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
     if (ir->opts.ngtc > 0) {
       if (bRead && file_version<13) {
        snew(tmp,ir->opts.ngtc);
-       ndo_int (tmp, ir->opts.ngtc,bDum);
+       bDum=gmx_fio_ndo_int(fio,tmp, ir->opts.ngtc);
        for(i=0; i<ir->opts.ngtc; i++)
          ir->opts.nrdf[i] = tmp[i];
        sfree(tmp);
       } else {
-       ndo_real(ir->opts.nrdf, ir->opts.ngtc,bDum);
+       bDum=gmx_fio_ndo_real(fio,ir->opts.nrdf, ir->opts.ngtc);
       }
-      ndo_real(ir->opts.ref_t,ir->opts.ngtc,bDum); 
-      ndo_real(ir->opts.tau_t,ir->opts.ngtc,bDum); 
+      bDum=gmx_fio_ndo_real(fio,ir->opts.ref_t,ir->opts.ngtc); 
+      bDum=gmx_fio_ndo_real(fio,ir->opts.tau_t,ir->opts.ngtc); 
       if (file_version<33 && ir->eI==eiBD) {
        for(i=0; i<ir->opts.ngtc; i++)
          ir->opts.tau_t[i] = bd_temp;
       }
     }
     if (ir->opts.ngfrz > 0) 
-      ndo_ivec(ir->opts.nFreeze,ir->opts.ngfrz,bDum);
+      bDum=gmx_fio_ndo_ivec(fio,ir->opts.nFreeze,ir->opts.ngfrz);
     if (ir->opts.ngacc > 0) 
-      ndo_rvec(ir->opts.acc,ir->opts.ngacc); 
+      gmx_fio_ndo_rvec(fio,ir->opts.acc,ir->opts.ngacc); 
     if (file_version >= 12)
-      ndo_int(ir->opts.egp_flags,ir->opts.ngener*ir->opts.ngener,bDum);
+      bDum=gmx_fio_ndo_int(fio,ir->opts.egp_flags,
+                           ir->opts.ngener*ir->opts.ngener);
 
     if(bRead && file_version < 26) {
       for(i=0;i<ir->opts.ngtc;i++) {
@@ -792,31 +797,31 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
     } else {
       /* file version 26 or later */
       /* First read the lists with annealing and npoints for each group */
-      ndo_int(ir->opts.annealing,ir->opts.ngtc,bDum);
-      ndo_int(ir->opts.anneal_npoints,ir->opts.ngtc,bDum);
+      bDum=gmx_fio_ndo_int(fio,ir->opts.annealing,ir->opts.ngtc);
+      bDum=gmx_fio_ndo_int(fio,ir->opts.anneal_npoints,ir->opts.ngtc);
       for(j=0;j<(ir->opts.ngtc);j++) {
        k=ir->opts.anneal_npoints[j];
        if(bRead) {
          snew(ir->opts.anneal_time[j],k);
          snew(ir->opts.anneal_temp[j],k);
        }
-       ndo_real(ir->opts.anneal_time[j],k,bDum);
-       ndo_real(ir->opts.anneal_temp[j],k,bDum);
+       bDum=gmx_fio_ndo_real(fio,ir->opts.anneal_time[j],k);
+       bDum=gmx_fio_ndo_real(fio,ir->opts.anneal_temp[j],k);
       }
     }
     /* Walls */
     if (file_version >= 45) {
-      do_int(ir->nwall);
-      do_int(ir->wall_type);
+      gmx_fio_do_int(fio,ir->nwall);
+      gmx_fio_do_int(fio,ir->wall_type);
       if (file_version >= 50)
-       do_real(ir->wall_r_linpot);
+       gmx_fio_do_real(fio,ir->wall_r_linpot);
       else
        ir->wall_r_linpot = -1;
-      do_int(ir->wall_atomtype[0]);
-      do_int(ir->wall_atomtype[1]);
-      do_real(ir->wall_density[0]);
-      do_real(ir->wall_density[1]);
-      do_real(ir->wall_ewald_zfac);
+      gmx_fio_do_int(fio,ir->wall_atomtype[0]);
+      gmx_fio_do_int(fio,ir->wall_atomtype[1]);
+      gmx_fio_do_real(fio,ir->wall_density[0]);
+      gmx_fio_do_real(fio,ir->wall_density[1]);
+      gmx_fio_do_real(fio,ir->wall_ewald_zfac);
     } else {
       ir->nwall = 0;
       ir->wall_type = 0;
@@ -828,26 +833,26 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
     }
     /* Cosine stuff for electric fields */
     for(j=0; (j<DIM); j++) {
-      do_int  (ir->ex[j].n);
-      do_int  (ir->et[j].n);
+      gmx_fio_do_int(fio,ir->ex[j].n);
+      gmx_fio_do_int(fio,ir->et[j].n);
       if (bRead) {
        snew(ir->ex[j].a,  ir->ex[j].n);
        snew(ir->ex[j].phi,ir->ex[j].n);
        snew(ir->et[j].a,  ir->et[j].n);
        snew(ir->et[j].phi,ir->et[j].n);
       }
-      ndo_real(ir->ex[j].a,  ir->ex[j].n,bDum);
-      ndo_real(ir->ex[j].phi,ir->ex[j].n,bDum);
-      ndo_real(ir->et[j].a,  ir->et[j].n,bDum);
-      ndo_real(ir->et[j].phi,ir->et[j].n,bDum);
+      bDum=gmx_fio_ndo_real(fio,ir->ex[j].a,  ir->ex[j].n);
+      bDum=gmx_fio_ndo_real(fio,ir->ex[j].phi,ir->ex[j].n);
+      bDum=gmx_fio_ndo_real(fio,ir->et[j].a,  ir->et[j].n);
+      bDum=gmx_fio_ndo_real(fio,ir->et[j].phi,ir->et[j].n);
     }
     
     /* QMMM stuff */
     if(file_version>=39){
-      do_int(ir->bQMMM);
-      do_int(ir->QMMMscheme);
-      do_real(ir->scalefactor);
-      do_int(ir->opts.ngQM);
+      gmx_fio_do_bool(fio,ir->bQMMM);
+      gmx_fio_do_int(fio,ir->QMMMscheme);
+      gmx_fio_do_real(fio,ir->scalefactor);
+      gmx_fio_do_int(fio,ir->opts.ngQM);
       if (bRead) {
         snew(ir->opts.QMmethod,    ir->opts.ngQM);
         snew(ir->opts.QMbasis,     ir->opts.ngQM);
@@ -863,18 +868,18 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
         snew(ir->opts.bTS,         ir->opts.ngQM);
       }
       if (ir->opts.ngQM > 0) {
-        ndo_int(ir->opts.QMmethod,ir->opts.ngQM,bDum);
-        ndo_int(ir->opts.QMbasis,ir->opts.ngQM,bDum);
-        ndo_int(ir->opts.QMcharge,ir->opts.ngQM,bDum);
-        ndo_int(ir->opts.QMmult,ir->opts.ngQM,bDum);
-        ndo_int(ir->opts.bSH,ir->opts.ngQM,bDum);
-        ndo_int(ir->opts.CASorbitals,ir->opts.ngQM,bDum);
-        ndo_int(ir->opts.CASelectrons,ir->opts.ngQM,bDum);
-        ndo_real(ir->opts.SAon,ir->opts.ngQM,bDum);
-        ndo_real(ir->opts.SAoff,ir->opts.ngQM,bDum);
-        ndo_int(ir->opts.SAsteps,ir->opts.ngQM,bDum);
-        ndo_int(ir->opts.bOPT,ir->opts.ngQM,bDum);
-        ndo_int(ir->opts.bTS,ir->opts.ngQM,bDum);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.QMmethod,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.QMbasis,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.QMcharge,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.QMmult,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_bool(fio,ir->opts.bSH,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.CASorbitals,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.CASelectrons,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_real(fio,ir->opts.SAon,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_real(fio,ir->opts.SAoff,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_int(fio,ir->opts.SAsteps,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_bool(fio,ir->opts.bOPT,ir->opts.ngQM);
+        bDum=gmx_fio_ndo_bool(fio,ir->opts.bTS,ir->opts.ngQM);
       }
       /* end of QMMM stuff */
     }    
@@ -882,22 +887,23 @@ static void do_inputrec(t_inputrec *ir,bool bRead, int file_version,
 }
 
 
-static void do_harm(t_iparams *iparams,bool bRead)
+static void do_harm(t_fileio *fio, t_iparams *iparams,bool bRead)
 {
-  do_real(iparams->harmonic.rA);
-  do_real(iparams->harmonic.krA);
-  do_real(iparams->harmonic.rB);
-  do_real(iparams->harmonic.krB);
+  gmx_fio_do_real(fio,iparams->harmonic.rA);
+  gmx_fio_do_real(fio,iparams->harmonic.krA);
+  gmx_fio_do_real(fio,iparams->harmonic.rB);
+  gmx_fio_do_real(fio,iparams->harmonic.krB);
 }
 
-void do_iparams(t_functype ftype,t_iparams *iparams,bool bRead, int file_version)
+void do_iparams(t_fileio *fio, t_functype ftype,t_iparams *iparams,
+                bool bRead, int file_version)
 {
   int i;
   bool bDum;
   real rdum;
   
   if (!bRead)
-    set_comment(interaction_function[ftype].name);
+    gmx_fio_set_comment(fio, interaction_function[ftype].name);
   switch (ftype) {
   case F_ANGLES:
   case F_G96ANGLES:
@@ -905,7 +911,7 @@ void do_iparams(t_functype ftype,t_iparams *iparams,bool bRead, int file_version
   case F_G96BONDS:
   case F_HARMONIC:
   case F_IDIHS:
-    do_harm(iparams,bRead);
+    do_harm(fio, iparams,bRead);
     if ((ftype == F_ANGRES || ftype == F_ANGRESZ) && bRead) {
       /* Correct incorrect storage of parameters */
       iparams->pdihs.phiB = iparams->pdihs.phiA;
@@ -913,199 +919,199 @@ void do_iparams(t_functype ftype,t_iparams *iparams,bool bRead, int file_version
     }
     break;
   case F_FENEBONDS:
-    do_real(iparams->fene.bm);
-    do_real(iparams->fene.kb);
+    gmx_fio_do_real(fio,iparams->fene.bm);
+    gmx_fio_do_real(fio,iparams->fene.kb);
     break;
   case F_RESTRBONDS:
-    do_real(iparams->restraint.lowA);
-    do_real(iparams->restraint.up1A);
-    do_real(iparams->restraint.up2A);
-    do_real(iparams->restraint.kA);
-    do_real(iparams->restraint.lowB);
-    do_real(iparams->restraint.up1B);
-    do_real(iparams->restraint.up2B);
-    do_real(iparams->restraint.kB);
+    gmx_fio_do_real(fio,iparams->restraint.lowA);
+    gmx_fio_do_real(fio,iparams->restraint.up1A);
+    gmx_fio_do_real(fio,iparams->restraint.up2A);
+    gmx_fio_do_real(fio,iparams->restraint.kA);
+    gmx_fio_do_real(fio,iparams->restraint.lowB);
+    gmx_fio_do_real(fio,iparams->restraint.up1B);
+    gmx_fio_do_real(fio,iparams->restraint.up2B);
+    gmx_fio_do_real(fio,iparams->restraint.kB);
     break;
   case F_TABBONDS:
   case F_TABBONDSNC:
   case F_TABANGLES:
   case F_TABDIHS:
-    do_real(iparams->tab.kA);
-    do_int (iparams->tab.table);
-    do_real(iparams->tab.kB);
+    gmx_fio_do_real(fio,iparams->tab.kA);
+    gmx_fio_do_int(fio,iparams->tab.table);
+    gmx_fio_do_real(fio,iparams->tab.kB);
     break;
   case F_CROSS_BOND_BONDS:
-    do_real(iparams->cross_bb.r1e);
-    do_real(iparams->cross_bb.r2e);
-    do_real(iparams->cross_bb.krr);
+    gmx_fio_do_real(fio,iparams->cross_bb.r1e);
+    gmx_fio_do_real(fio,iparams->cross_bb.r2e);
+    gmx_fio_do_real(fio,iparams->cross_bb.krr);
     break;
   case F_CROSS_BOND_ANGLES:
-    do_real(iparams->cross_ba.r1e);
-    do_real(iparams->cross_ba.r2e);
-    do_real(iparams->cross_ba.r3e);
-    do_real(iparams->cross_ba.krt);
+    gmx_fio_do_real(fio,iparams->cross_ba.r1e);
+    gmx_fio_do_real(fio,iparams->cross_ba.r2e);
+    gmx_fio_do_real(fio,iparams->cross_ba.r3e);
+    gmx_fio_do_real(fio,iparams->cross_ba.krt);
     break;
   case F_UREY_BRADLEY:
-    do_real(iparams->u_b.theta);
-    do_real(iparams->u_b.ktheta);
-    do_real(iparams->u_b.r13);
-    do_real(iparams->u_b.kUB);
+    gmx_fio_do_real(fio,iparams->u_b.theta);
+    gmx_fio_do_real(fio,iparams->u_b.ktheta);
+    gmx_fio_do_real(fio,iparams->u_b.r13);
+    gmx_fio_do_real(fio,iparams->u_b.kUB);
     break;
   case F_QUARTIC_ANGLES:
-    do_real(iparams->qangle.theta);
-    ndo_real(iparams->qangle.c,5,bDum);
+    gmx_fio_do_real(fio,iparams->qangle.theta);
+    bDum=gmx_fio_ndo_real(fio,iparams->qangle.c,5);
     break;
   case F_BHAM:
-    do_real(iparams->bham.a);
-    do_real(iparams->bham.b);
-    do_real(iparams->bham.c);
+    gmx_fio_do_real(fio,iparams->bham.a);
+    gmx_fio_do_real(fio,iparams->bham.b);
+    gmx_fio_do_real(fio,iparams->bham.c);
     break;
   case F_MORSE:
-    do_real(iparams->morse.b0);
-    do_real(iparams->morse.cb);
-    do_real(iparams->morse.beta);
+    gmx_fio_do_real(fio,iparams->morse.b0);
+    gmx_fio_do_real(fio,iparams->morse.cb);
+    gmx_fio_do_real(fio,iparams->morse.beta);
     break;
   case F_CUBICBONDS:
-    do_real(iparams->cubic.b0);
-    do_real(iparams->cubic.kb);
-    do_real(iparams->cubic.kcub);
+    gmx_fio_do_real(fio,iparams->cubic.b0);
+    gmx_fio_do_real(fio,iparams->cubic.kb);
+    gmx_fio_do_real(fio,iparams->cubic.kcub);
     break;
   case F_CONNBONDS:
     break;
   case F_POLARIZATION:
-    do_real(iparams->polarize.alpha);
+    gmx_fio_do_real(fio,iparams->polarize.alpha);
     break;
   case F_WATER_POL:
     if (file_version < 31) 
       gmx_fatal(FARGS,"Old tpr files with water_polarization not supported. Make a new.");
-    do_real(iparams->wpol.al_x);
-    do_real(iparams->wpol.al_y);
-    do_real(iparams->wpol.al_z);
-    do_real(iparams->wpol.rOH);
-    do_real(iparams->wpol.rHH);
-    do_real(iparams->wpol.rOD);
+    gmx_fio_do_real(fio,iparams->wpol.al_x);
+    gmx_fio_do_real(fio,iparams->wpol.al_y);
+    gmx_fio_do_real(fio,iparams->wpol.al_z);
+    gmx_fio_do_real(fio,iparams->wpol.rOH);
+    gmx_fio_do_real(fio,iparams->wpol.rHH);
+    gmx_fio_do_real(fio,iparams->wpol.rOD);
     break;
   case F_THOLE_POL:
-    do_real(iparams->thole.a);
-    do_real(iparams->thole.alpha1);
-    do_real(iparams->thole.alpha2);
-    do_real(iparams->thole.rfac);
+    gmx_fio_do_real(fio,iparams->thole.a);
+    gmx_fio_do_real(fio,iparams->thole.alpha1);
+    gmx_fio_do_real(fio,iparams->thole.alpha2);
+    gmx_fio_do_real(fio,iparams->thole.rfac);
     break;
   case F_LJ:
-    do_real(iparams->lj.c6);
-    do_real(iparams->lj.c12);
+    gmx_fio_do_real(fio,iparams->lj.c6);
+    gmx_fio_do_real(fio,iparams->lj.c12);
     break;
   case F_LJ14:
-    do_real(iparams->lj14.c6A);
-    do_real(iparams->lj14.c12A);
-    do_real(iparams->lj14.c6B);
-    do_real(iparams->lj14.c12B);
+    gmx_fio_do_real(fio,iparams->lj14.c6A);
+    gmx_fio_do_real(fio,iparams->lj14.c12A);
+    gmx_fio_do_real(fio,iparams->lj14.c6B);
+    gmx_fio_do_real(fio,iparams->lj14.c12B);
     break;
   case F_LJC14_Q:
-    do_real(iparams->ljc14.fqq);
-    do_real(iparams->ljc14.qi);
-    do_real(iparams->ljc14.qj);
-    do_real(iparams->ljc14.c6);
-    do_real(iparams->ljc14.c12);
+    gmx_fio_do_real(fio,iparams->ljc14.fqq);
+    gmx_fio_do_real(fio,iparams->ljc14.qi);
+    gmx_fio_do_real(fio,iparams->ljc14.qj);
+    gmx_fio_do_real(fio,iparams->ljc14.c6);
+    gmx_fio_do_real(fio,iparams->ljc14.c12);
     break;
   case F_LJC_PAIRS_NB:
-    do_real(iparams->ljcnb.qi);
-    do_real(iparams->ljcnb.qj);
-    do_real(iparams->ljcnb.c6);
-    do_real(iparams->ljcnb.c12);
+    gmx_fio_do_real(fio,iparams->ljcnb.qi);
+    gmx_fio_do_real(fio,iparams->ljcnb.qj);
+    gmx_fio_do_real(fio,iparams->ljcnb.c6);
+    gmx_fio_do_real(fio,iparams->ljcnb.c12);
     break;
   case F_PDIHS:
   case F_PIDIHS:
   case F_ANGRES:
   case F_ANGRESZ:
-    do_real(iparams->pdihs.phiA);
-    do_real(iparams->pdihs.cpA);
+    gmx_fio_do_real(fio,iparams->pdihs.phiA);
+    gmx_fio_do_real(fio,iparams->pdihs.cpA);
     if ((ftype == F_ANGRES || ftype == F_ANGRESZ) && file_version < 42) {
       /* Read the incorrectly stored multiplicity */
-      do_real(iparams->harmonic.rB);
-      do_real(iparams->harmonic.krB);
+      gmx_fio_do_real(fio,iparams->harmonic.rB);
+      gmx_fio_do_real(fio,iparams->harmonic.krB);
       iparams->pdihs.phiB = iparams->pdihs.phiA;
       iparams->pdihs.cpB  = iparams->pdihs.cpA;
     } else {
-      do_real(iparams->pdihs.phiB);
-      do_real(iparams->pdihs.cpB);
-      do_int (iparams->pdihs.mult);
+      gmx_fio_do_real(fio,iparams->pdihs.phiB);
+      gmx_fio_do_real(fio,iparams->pdihs.cpB);
+      gmx_fio_do_int(fio,iparams->pdihs.mult);
     }
     break;
   case F_DISRES:
-    do_int (iparams->disres.label);
-    do_int (iparams->disres.type);
-    do_real(iparams->disres.low);
-    do_real(iparams->disres.up1);
-    do_real(iparams->disres.up2);
-    do_real(iparams->disres.kfac);
+    gmx_fio_do_int(fio,iparams->disres.label);
+    gmx_fio_do_int(fio,iparams->disres.type);
+    gmx_fio_do_real(fio,iparams->disres.low);
+    gmx_fio_do_real(fio,iparams->disres.up1);
+    gmx_fio_do_real(fio,iparams->disres.up2);
+    gmx_fio_do_real(fio,iparams->disres.kfac);
     break;
   case F_ORIRES:
-    do_int (iparams->orires.ex);
-    do_int (iparams->orires.label);
-    do_int (iparams->orires.power);
-    do_real(iparams->orires.c);
-    do_real(iparams->orires.obs);
-    do_real(iparams->orires.kfac);
+    gmx_fio_do_int(fio,iparams->orires.ex);
+    gmx_fio_do_int(fio,iparams->orires.label);
+    gmx_fio_do_int(fio,iparams->orires.power);
+    gmx_fio_do_real(fio,iparams->orires.c);
+    gmx_fio_do_real(fio,iparams->orires.obs);
+    gmx_fio_do_real(fio,iparams->orires.kfac);
     break;
   case F_DIHRES:
-    do_int (iparams->dihres.power);
-    do_int (iparams->dihres.label);
-    do_real(iparams->dihres.phi);
-    do_real(iparams->dihres.dphi);
-    do_real(iparams->dihres.kfac);
+    gmx_fio_do_int(fio,iparams->dihres.power);
+    gmx_fio_do_int(fio,iparams->dihres.label);
+    gmx_fio_do_real(fio,iparams->dihres.phi);
+    gmx_fio_do_real(fio,iparams->dihres.dphi);
+    gmx_fio_do_real(fio,iparams->dihres.kfac);
     break;
   case F_POSRES:
-    do_rvec(iparams->posres.pos0A);
-    do_rvec(iparams->posres.fcA);
+    gmx_fio_do_rvec(fio,iparams->posres.pos0A);
+    gmx_fio_do_rvec(fio,iparams->posres.fcA);
     if (bRead && file_version < 27) {
       copy_rvec(iparams->posres.pos0A,iparams->posres.pos0B);
       copy_rvec(iparams->posres.fcA,iparams->posres.fcB);
     } else {
-      do_rvec(iparams->posres.pos0B);
-      do_rvec(iparams->posres.fcB);
+      gmx_fio_do_rvec(fio,iparams->posres.pos0B);
+      gmx_fio_do_rvec(fio,iparams->posres.fcB);
     }
     break;
   case F_RBDIHS:
-    ndo_real(iparams->rbdihs.rbcA,NR_RBDIHS,bDum);
+    bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcA,NR_RBDIHS);
     if(file_version>=25) 
-      ndo_real(iparams->rbdihs.rbcB,NR_RBDIHS,bDum);
+      bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcB,NR_RBDIHS);
     break;
   case F_FOURDIHS:
     /* Fourier dihedrals are internally represented
      * as Ryckaert-Bellemans since those are faster to compute.
      */
-    ndo_real(iparams->rbdihs.rbcA, NR_RBDIHS, bDum);
-    ndo_real(iparams->rbdihs.rbcB, NR_RBDIHS, bDum);
+     bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcA, NR_RBDIHS);
+     bDum=gmx_fio_ndo_real(fio,iparams->rbdihs.rbcB, NR_RBDIHS);
     break;
   case F_CONSTR:
   case F_CONSTRNC:
-    do_real(iparams->constr.dA);
-    do_real(iparams->constr.dB);
+    gmx_fio_do_real(fio,iparams->constr.dA);
+    gmx_fio_do_real(fio,iparams->constr.dB);
     break;
   case F_SETTLE:
-    do_real(iparams->settle.doh);
-    do_real(iparams->settle.dhh);
+    gmx_fio_do_real(fio,iparams->settle.doh);
+    gmx_fio_do_real(fio,iparams->settle.dhh);
     break;
   case F_VSITE2:
-    do_real(iparams->vsite.a);
+    gmx_fio_do_real(fio,iparams->vsite.a);
     break;
   case F_VSITE3:
   case F_VSITE3FD:
   case F_VSITE3FAD:
-    do_real(iparams->vsite.a);
-    do_real(iparams->vsite.b);
+    gmx_fio_do_real(fio,iparams->vsite.a);
+    gmx_fio_do_real(fio,iparams->vsite.b);
     break;
   case F_VSITE3OUT:
   case F_VSITE4FD: 
   case F_VSITE4FDN: 
-    do_real(iparams->vsite.a);
-    do_real(iparams->vsite.b);
-    do_real(iparams->vsite.c);
+    gmx_fio_do_real(fio,iparams->vsite.a);
+    gmx_fio_do_real(fio,iparams->vsite.b);
+    gmx_fio_do_real(fio,iparams->vsite.c);
     break;
   case F_VSITEN:
-    do_int (iparams->vsiten.n);
-    do_real(iparams->vsiten.a);
+    gmx_fio_do_int(fio,iparams->vsiten.n);
+    gmx_fio_do_real(fio,iparams->vsiten.a);
     break;
   case F_GB12:
   case F_GB13:
@@ -1113,20 +1119,20 @@ void do_iparams(t_functype ftype,t_iparams *iparams,bool bRead, int file_version
     /* We got rid of some parameters in version 68 */
     if(bRead && file_version<68)
     {
-        do_real(rdum); 
-        do_real(rdum); 
-        do_real(rdum); 
-        do_real(rdum); 
-    }
-       do_real(iparams->gb.sar);       
-       do_real(iparams->gb.st);
-       do_real(iparams->gb.pi);
-       do_real(iparams->gb.gbr);
-       do_real(iparams->gb.bmlt);
+        gmx_fio_do_real(fio,rdum);     
+        gmx_fio_do_real(fio,rdum);     
+        gmx_fio_do_real(fio,rdum);     
+        gmx_fio_do_real(fio,rdum);     
+    }
+       gmx_fio_do_real(fio,iparams->gb.sar);   
+       gmx_fio_do_real(fio,iparams->gb.st);
+       gmx_fio_do_real(fio,iparams->gb.pi);
+       gmx_fio_do_real(fio,iparams->gb.gbr);
+       gmx_fio_do_real(fio,iparams->gb.bmlt);
        break;
   case F_CMAP:
-       do_int(iparams->cmap.cmapA);
-       do_int(iparams->cmap.cmapB);
+       gmx_fio_do_int(fio,iparams->cmap.cmapA);
+       gmx_fio_do_int(fio,iparams->cmap.cmapB);
     break;
   default:
     gmx_fatal(FARGS,"unknown function type %d (%s) in %s line %d",
@@ -1134,41 +1140,41 @@ void do_iparams(t_functype ftype,t_iparams *iparams,bool bRead, int file_version
                ftype,interaction_function[ftype].name,__FILE__,__LINE__);
   }
   if (!bRead)
-    unset_comment();
+    gmx_fio_unset_comment(fio);
 }
 
-static void do_ilist(t_ilist *ilist,bool bRead,int file_version,
+static void do_ilist(t_fileio *fio, t_ilist *ilist,bool bRead,int file_version,
                     int ftype)
 {
   int  i,k,idum;
   bool bDum=TRUE;
   
   if (!bRead) {
-    set_comment(interaction_function[ftype].name);
+    gmx_fio_set_comment(fio, interaction_function[ftype].name);
   }
   if (file_version < 44) {
     for(i=0; i<MAXNODES; i++)
-      do_int(idum);
+      gmx_fio_do_int(fio,idum);
   }
-  do_int (ilist->nr);
+  gmx_fio_do_int(fio,ilist->nr);
   if (bRead)
     snew(ilist->iatoms,ilist->nr);
-  ndo_int(ilist->iatoms,ilist->nr,bDum);
+  bDum=gmx_fio_ndo_int(fio,ilist->iatoms,ilist->nr);
   if (!bRead)
-    unset_comment();
+    gmx_fio_unset_comment(fio);
 }
 
-static void do_ffparams(gmx_ffparams_t *ffparams,
+static void do_ffparams(t_fileio *fio, gmx_ffparams_t *ffparams,
                        bool bRead, int file_version)
 {
   int  idum,i,j,k;
   bool bDum=TRUE;
 
-  do_int(ffparams->atnr);
+  gmx_fio_do_int(fio,ffparams->atnr);
   if (file_version < 57) {
-    do_int(idum);
+    gmx_fio_do_int(fio,idum);
   }
-  do_int(ffparams->ntypes);
+  gmx_fio_do_int(fio,ffparams->ntypes);
   if (bRead && debug)
     fprintf(debug,"ffparams->atnr = %d, ntypes = %d\n",
            ffparams->atnr,ffparams->ntypes);
@@ -1177,18 +1183,18 @@ static void do_ffparams(gmx_ffparams_t *ffparams,
     snew(ffparams->iparams,ffparams->ntypes);
   }
   /* Read/write all the function types */
-  ndo_int(ffparams->functype,ffparams->ntypes,bDum);
+  bDum=gmx_fio_ndo_int(fio,ffparams->functype,ffparams->ntypes);
   if (bRead && debug)
     pr_ivec(debug,0,"functype",ffparams->functype,ffparams->ntypes,TRUE);
 
   if (file_version >= 66) {
-    do_double(ffparams->reppow);
+    gmx_fio_do_double(fio,ffparams->reppow);
   } else {
     ffparams->reppow = 12.0;
   }
 
   if (file_version >= 57) {
-    do_real(ffparams->fudgeQQ);
+    gmx_fio_do_real(fio,ffparams->fudgeQQ);
   }
 
   /* Check whether all these function types are supported by the code.
@@ -1211,13 +1217,15 @@ static void do_ffparams(gmx_ffparams_t *ffparams,
          }
        }
     
-    do_iparams(ffparams->functype[i],&ffparams->iparams[i],bRead,file_version);
+    do_iparams(fio, ffparams->functype[i],&ffparams->iparams[i],bRead,
+               file_version);
     if (bRead && debug)
       pr_iparams(debug,ffparams->functype[i],&ffparams->iparams[i]);
   }
 }
 
-static void do_ilists(t_ilist *ilist,bool bRead, int file_version)
+static void do_ilists(t_fileio *fio, t_ilist *ilist,bool bRead, 
+                      int file_version)
 {
   int i,j,k,renum[F_NRE];
   bool bDum=TRUE,bClear;
@@ -1232,7 +1240,7 @@ static void do_ilists(t_ilist *ilist,bool bRead, int file_version)
       ilist[j].nr = 0;
       ilist[j].iatoms = NULL;
     } else {
-      do_ilist(&ilist[j],bRead,file_version,j);
+      do_ilist(fio, &ilist[j],bRead,file_version,j);
     }
     /*
     if (bRead && gmx_debug_at)
@@ -1242,77 +1250,78 @@ static void do_ilists(t_ilist *ilist,bool bRead, int file_version)
   }
 }
 
-static void do_idef(gmx_ffparams_t *ffparams,gmx_moltype_t *molt,
+static void do_idef(t_fileio *fio, gmx_ffparams_t *ffparams,gmx_moltype_t *molt,
                    bool bRead, int file_version)
 {
-  do_ffparams(ffparams,bRead,file_version);
+  do_ffparams(fio, ffparams,bRead,file_version);
     
   if (file_version >= 54) {
-    do_real(ffparams->fudgeQQ);
+    gmx_fio_do_real(fio,ffparams->fudgeQQ);
   }
 
-  do_ilists(molt->ilist,bRead,file_version);
+  do_ilists(fio, molt->ilist,bRead,file_version);
 }
 
-static void do_block(t_block *block,bool bRead,int file_version)
+static void do_block(t_fileio *fio, t_block *block,bool bRead,int file_version)
 {
   int  i,idum,dum_nra,*dum_a;
   bool bDum=TRUE;
 
   if (file_version < 44)
     for(i=0; i<MAXNODES; i++)
-      do_int(idum);
-  do_int (block->nr);
+      gmx_fio_do_int(fio,idum);
+  gmx_fio_do_int(fio,block->nr);
   if (file_version < 51)
-    do_int (dum_nra);
+    gmx_fio_do_int(fio,dum_nra);
   if (bRead) {
     block->nalloc_index = block->nr+1;
     snew(block->index,block->nalloc_index);
   }
-  ndo_int(block->index,block->nr+1,bDum);
+  bDum=gmx_fio_ndo_int(fio,block->index,block->nr+1);
 
   if (file_version < 51 && dum_nra > 0) {
     snew(dum_a,dum_nra);
-    ndo_int(dum_a,dum_nra,bDum);
+    bDum=gmx_fio_ndo_int(fio,dum_a,dum_nra);
     sfree(dum_a);
   }
 }
 
-static void do_blocka(t_blocka *block,bool bRead,int file_version)
+static void do_blocka(t_fileio *fio, t_blocka *block,bool bRead,
+                      int file_version)
 {
   int  i,idum;
   bool bDum=TRUE;
 
   if (file_version < 44)
     for(i=0; i<MAXNODES; i++)
-      do_int(idum);
-  do_int (block->nr);
-  do_int (block->nra);
+      gmx_fio_do_int(fio,idum);
+  gmx_fio_do_int(fio,block->nr);
+  gmx_fio_do_int(fio,block->nra);
   if (bRead) {
     block->nalloc_index = block->nr+1;
     snew(block->index,block->nalloc_index);
     block->nalloc_a = block->nra;
     snew(block->a,block->nalloc_a);
   }
-  ndo_int(block->index,block->nr+1,bDum);
-  ndo_int(block->a,block->nra,bDum);
+  bDum=gmx_fio_ndo_int(fio,block->index,block->nr+1);
+  bDum=gmx_fio_ndo_int(fio,block->a,block->nra);
 }
 
-static void do_atom(t_atom *atom,int ngrp,bool bRead, int file_version,
-                   gmx_groups_t *groups,int atnr)
+static void do_atom(t_fileio *fio, t_atom *atom,int ngrp,bool bRead, 
+                    int file_version, gmx_groups_t *groups,int atnr)
 { 
   int i,myngrp;
   
-  do_real (atom->m);
-  do_real (atom->q);
-  do_real (atom->mB);
-  do_real (atom->qB);
-  do_ushort(atom->type);
-  do_ushort(atom->typeB);
-  do_int (atom->ptype);
-  do_int (atom->resind);
+  gmx_fio_do_real(fio,atom->m);
+  gmx_fio_do_real(fio,atom->q);
+  gmx_fio_do_real(fio,atom->mB);
+  gmx_fio_do_real(fio,atom->qB);
+  gmx_fio_do_ushort(fio, atom->type);
+  gmx_fio_do_ushort(fio, atom->typeB);
+  gmx_fio_do_int(fio,atom->ptype);
+  gmx_fio_do_int(fio,atom->resind);
   if (file_version >= 52)
-    do_int(atom->atomnumber);
+    gmx_fio_do_int(fio,atom->atomnumber);
   else if (bRead)
     atom->atomnumber = NOTSET;
   if (file_version < 23) 
@@ -1324,7 +1333,7 @@ static void do_atom(t_atom *atom,int ngrp,bool bRead, int file_version,
 
   if (file_version < 57) {
     unsigned char uchar[egcNR];
-    do_nuchar(uchar,myngrp);
+    gmx_fio_ndo_uchar(fio,uchar,myngrp);
     for(i=myngrp; (i<ngrp); i++) {
       uchar[i] = 0;
     }
@@ -1335,7 +1344,8 @@ static void do_atom(t_atom *atom,int ngrp,bool bRead, int file_version,
   }
 }
 
-static void do_grps(int ngrp,t_grps grps[],bool bRead, int file_version)
+static void do_grps(t_fileio *fio, int ngrp,t_grps grps[],bool bRead, 
+                    int file_version)
 {
   int i,j,myngrp;
   bool bDum=TRUE;
@@ -1349,10 +1359,10 @@ static void do_grps(int ngrp,t_grps grps[],bool bRead, int file_version)
 
   for(j=0; (j<ngrp); j++) {
     if (j<myngrp) {
-      do_int (grps[j].nr);
+      gmx_fio_do_int(fio,grps[j].nr);
       if (bRead)
        snew(grps[j].nm_ind,grps[j].nr);
-      ndo_int(grps[j].nm_ind,grps[j].nr,bDum);
+      bDum=gmx_fio_ndo_int(fio,grps[j].nm_ind,grps[j].nr);
     }
     else {
       grps[j].nr = 1;
@@ -1361,38 +1371,39 @@ static void do_grps(int ngrp,t_grps grps[],bool bRead, int file_version)
   }
 }
 
-static void do_symstr(char ***nm,bool bRead,t_symtab *symtab)
+static void do_symstr(t_fileio *fio, char ***nm,bool bRead,t_symtab *symtab)
 {
   int ls;
   
   if (bRead) {
-    do_int(ls);
+    gmx_fio_do_int(fio,ls);
     *nm = get_symtab_handle(symtab,ls);
   }
   else {
     ls = lookup_symtab(symtab,*nm);
-    do_int(ls);
+    gmx_fio_do_int(fio,ls);
   }
 }
 
-static void do_strstr(int nstr,char ***nm,bool bRead,t_symtab *symtab)
+static void do_strstr(t_fileio *fio, int nstr,char ***nm,bool bRead,
+                      t_symtab *symtab)
 {
   int  j;
   
   for (j=0; (j<nstr); j++) 
-    do_symstr(&(nm[j]),bRead,symtab);
+    do_symstr(fio, &(nm[j]),bRead,symtab);
 }
 
-static void do_resinfo(int n,t_resinfo *ri,bool bRead,t_symtab *symtab,
-                      int file_version)
+static void do_resinfo(t_fileio *fio, int n,t_resinfo *ri,bool bRead,
+                       t_symtab *symtab, int file_version)
 {
   int  j;
   
   for (j=0; (j<n); j++) {
-    do_symstr(&(ri[j].name),bRead,symtab);
+    do_symstr(fio, &(ri[j].name),bRead,symtab);
     if (file_version >= 63) {
-      do_int  (ri[j].nr);
-      do_uchar(ri[j].ic);
+      gmx_fio_do_int(fio,ri[j].nr);
+      gmx_fio_do_uchar(fio, ri[j].ic);
     } else {
       ri[j].nr = j + 1;
       ri[j].ic = ' ';
@@ -1400,16 +1411,16 @@ static void do_resinfo(int n,t_resinfo *ri,bool bRead,t_symtab *symtab,
   }
 }
 
-static void do_atoms(t_atoms *atoms,bool bRead,t_symtab *symtab,
+static void do_atoms(t_fileio *fio, t_atoms *atoms,bool bRead,t_symtab *symtab,
                     int file_version,
                     gmx_groups_t *groups)
 {
   int i;
   
-  do_int(atoms->nr);
-  do_int(atoms->nres);
+  gmx_fio_do_int(fio,atoms->nr);
+  gmx_fio_do_int(fio,atoms->nres);
   if (file_version < 57) {
-    do_int(groups->ngrpname);
+    gmx_fio_do_int(fio,groups->ngrpname);
     for(i=0; i<egcNR; i++) {
       groups->ngrpnr[i] = atoms->nr;
       snew(groups->grpnr[i],groups->ngrpnr[i]);
@@ -1427,42 +1438,42 @@ static void do_atoms(t_atoms *atoms,bool bRead,t_symtab *symtab,
     atoms->pdbinfo = NULL;
   }
   for(i=0; (i<atoms->nr); i++) {
-    do_atom(&atoms->atom[i],egcNR,bRead, file_version,groups,i);
+    do_atom(fio, &atoms->atom[i],egcNR,bRead, file_version,groups,i);
   }
-  do_strstr(atoms->nr,atoms->atomname,bRead,symtab);
+  do_strstr(fio, atoms->nr,atoms->atomname,bRead,symtab);
   if (bRead && (file_version <= 20)) {
     for(i=0; i<atoms->nr; i++) {
       atoms->atomtype[i]  = put_symtab(symtab,"?");
       atoms->atomtypeB[i] = put_symtab(symtab,"?");
     }
   } else {
-    do_strstr(atoms->nr,atoms->atomtype,bRead,symtab);
-    do_strstr(atoms->nr,atoms->atomtypeB,bRead,symtab);
+    do_strstr(fio, atoms->nr,atoms->atomtype,bRead,symtab);
+    do_strstr(fio, atoms->nr,atoms->atomtypeB,bRead,symtab);
   }
-  do_resinfo(atoms->nres,atoms->resinfo,bRead,symtab,file_version);
+  do_resinfo(fio, atoms->nres,atoms->resinfo,bRead,symtab,file_version);
 
   if (file_version < 57) {
-    do_strstr(groups->ngrpname,groups->grpname,bRead,symtab);
+    do_strstr(fio, groups->ngrpname,groups->grpname,bRead,symtab);
   
-    do_grps(egcNR,groups->grps,bRead,file_version);
+    do_grps(fio, egcNR,groups->grps,bRead,file_version);
   }
 }
 
-static void do_groups(gmx_groups_t *groups,
+static void do_groups(t_fileio *fio, gmx_groups_t *groups,
                      bool bRead,t_symtab *symtab,
                      int file_version)
 {
   int  g,n,i;
   bool bDum=TRUE;
 
-  do_grps(egcNR,groups->grps,bRead,file_version);
-  do_int(groups->ngrpname);
+  do_grps(fio, egcNR,groups->grps,bRead,file_version);
+  gmx_fio_do_int(fio,groups->ngrpname);
   if (bRead) {
     snew(groups->grpname,groups->ngrpname);
   }
-  do_strstr(groups->ngrpname,groups->grpname,bRead,symtab);
+  do_strstr(fio, groups->ngrpname,groups->grpname,bRead,symtab);
   for(g=0; g<egcNR; g++) {
-    do_int(groups->ngrpnr[g]);
+    gmx_fio_do_int(fio,groups->ngrpnr[g]);
     if (groups->ngrpnr[g] == 0) {
       if (bRead) {
        groups->grpnr[g] = NULL;
@@ -1471,19 +1482,19 @@ static void do_groups(gmx_groups_t *groups,
       if (bRead) {
        snew(groups->grpnr[g],groups->ngrpnr[g]);
       }
-      ndo_nuchar(groups->grpnr[g],groups->ngrpnr[g],bDum);
+      bDum=gmx_fio_ndo_uchar(fio, groups->grpnr[g],groups->ngrpnr[g]);
     }
   }
 }
 
-static void do_atomtypes(t_atomtypes *atomtypes,bool bRead,
+static void do_atomtypes(t_fileio *fio, t_atomtypes *atomtypes,bool bRead,
                         t_symtab *symtab,int file_version)
 {
   int i,j;
   bool bDum = TRUE;
   
   if (file_version > 25) {
-    do_int(atomtypes->nr);
+    gmx_fio_do_int(fio,atomtypes->nr);
     j=atomtypes->nr;
     if (bRead) {
       snew(atomtypes->radius,j);
@@ -1493,17 +1504,17 @@ static void do_atomtypes(t_atomtypes *atomtypes,bool bRead,
       snew(atomtypes->gb_radius,j);
       snew(atomtypes->S_hct,j);
     }
-    ndo_real(atomtypes->radius,j,bDum);
-    ndo_real(atomtypes->vol,j,bDum);
-    ndo_real(atomtypes->surftens,j,bDum);
+    bDum=gmx_fio_ndo_real(fio,atomtypes->radius,j);
+    bDum=gmx_fio_ndo_real(fio,atomtypes->vol,j);
+    bDum=gmx_fio_ndo_real(fio,atomtypes->surftens,j);
     if(file_version >= 40)
     {
-        ndo_int(atomtypes->atomnumber,j,bDum);
+        bDum=gmx_fio_ndo_int(fio,atomtypes->atomnumber,j);
     }
        if(file_version >= 60)
        {
-               ndo_real(atomtypes->gb_radius,j,bDum);
-               ndo_real(atomtypes->S_hct,j,bDum);
+               bDum=gmx_fio_ndo_real(fio,atomtypes->gb_radius,j);
+               bDum=gmx_fio_ndo_real(fio,atomtypes->S_hct,j);
        }
   } else {
     /* File versions prior to 26 cannot do GBSA, 
@@ -1519,13 +1530,13 @@ static void do_atomtypes(t_atomtypes *atomtypes,bool bRead,
   }  
 }
 
-static void do_symtab(t_symtab *symtab,bool bRead)
+static void do_symtab(t_fileio *fio, t_symtab *symtab,bool bRead)
 {
   int i,nr;
   t_symbuf *symbuf;
   char buf[STRLEN];
   
-  do_int(symtab->nr);
+  gmx_fio_do_int(fio,symtab->nr);
   nr     = symtab->nr;
   if (bRead) {
     snew(symtab->symbuf,1);
@@ -1533,7 +1544,7 @@ static void do_symtab(t_symtab *symtab,bool bRead)
     symbuf->bufsize = nr;
     snew(symbuf->buf,nr);
     for (i=0; (i<nr); i++) {
-      do_string(buf);
+      gmx_fio_do_string(fio,buf);
       symbuf->buf[i]=strdup(buf);
     }
   }
@@ -1541,7 +1552,7 @@ static void do_symtab(t_symtab *symtab,bool bRead)
     symbuf = symtab->symbuf;
     while (symbuf!=NULL) {
       for (i=0; (i<symbuf->bufsize) && (i<nr); i++) 
-       do_string(symbuf->buf[i]);
+       gmx_fio_do_string(fio,symbuf->buf[i]);
       nr-=i;
       symbuf=symbuf->next;
     }
@@ -1550,13 +1561,12 @@ static void do_symtab(t_symtab *symtab,bool bRead)
   }
 }
 
-static void
-do_cmap(gmx_cmap_t *cmap_grid, bool bRead)
+static void do_cmap(t_fileio *fio, gmx_cmap_t *cmap_grid, bool bRead)
 {
        int i,j,ngrid,gs,nelem;
        
-       do_int(cmap_grid->ngrid);
-       do_int(cmap_grid->grid_spacing);
+       gmx_fio_do_int(fio,cmap_grid->ngrid);
+       gmx_fio_do_int(fio,cmap_grid->grid_spacing);
        
        ngrid = cmap_grid->ngrid;
        gs    = cmap_grid->grid_spacing;
@@ -1576,17 +1586,16 @@ do_cmap(gmx_cmap_t *cmap_grid, bool bRead)
        {
                for(j=0;j<nelem;j++)
                {
-                       do_real(cmap_grid->cmapdata[i].cmap[j*4]);
-                       do_real(cmap_grid->cmapdata[i].cmap[j*4+1]);
-                       do_real(cmap_grid->cmapdata[i].cmap[j*4+2]);
-                       do_real(cmap_grid->cmapdata[i].cmap[j*4+3]);
+                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4]);
+                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+1]);
+                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+2]);
+                       gmx_fio_do_real(fio,cmap_grid->cmapdata[i].cmap[j*4+3]);
                }
        }       
 }
 
 
-void 
-tpx_make_chain_identifiers(t_atoms *atoms,t_block *mols)
+void tpx_make_chain_identifiers(t_atoms *atoms,t_block *mols)
 {
   int m,a,a0,a1,r;
   unsigned char c,chain;
@@ -1612,56 +1621,57 @@ tpx_make_chain_identifiers(t_atoms *atoms,t_block *mols)
   }
 }
   
-static void do_moltype(gmx_moltype_t *molt,bool bRead,t_symtab *symtab,
-                      int file_version,
+static void do_moltype(t_fileio *fio, gmx_moltype_t *molt,bool bRead,
+                       t_symtab *symtab, int file_version,
                       gmx_groups_t *groups)
 {
   int i;
 
   if (file_version >= 57) {
-    do_symstr(&(molt->name),bRead,symtab);
+    do_symstr(fio, &(molt->name),bRead,symtab);
   }
 
-  do_atoms(&molt->atoms, bRead, symtab, file_version, groups);
+  do_atoms(fio, &molt->atoms, bRead, symtab, file_version, groups);
 
   if (bRead && gmx_debug_at) {
     pr_atoms(debug,0,"atoms",&molt->atoms,TRUE);
   }
   
   if (file_version >= 57) {
-    do_ilists(molt->ilist,bRead,file_version);
+    do_ilists(fio, molt->ilist,bRead,file_version);
 
-    do_block(&molt->cgs,bRead,file_version);
+    do_block(fio, &molt->cgs,bRead,file_version);
     if (bRead && gmx_debug_at) {
       pr_block(debug,0,"cgs",&molt->cgs,TRUE);
     }
   }
 
   /* This used to be in the atoms struct */
-  do_blocka(&molt->excls, bRead, file_version);
+  do_blocka(fio, &molt->excls, bRead, file_version);
 }
 
-static void do_molblock(gmx_molblock_t *molb,bool bRead,int file_version)
+static void do_molblock(t_fileio *fio, gmx_molblock_t *molb,bool bRead,
+                        int file_version)
 {
   int i;
 
-  do_int(molb->type);
-  do_int(molb->nmol);
-  do_int(molb->natoms_mol);
+  gmx_fio_do_int(fio,molb->type);
+  gmx_fio_do_int(fio,molb->nmol);
+  gmx_fio_do_int(fio,molb->natoms_mol);
   /* Position restraint coordinates */
-  do_int(molb->nposres_xA);
+  gmx_fio_do_int(fio,molb->nposres_xA);
   if (molb->nposres_xA > 0) {
     if (bRead) {
       snew(molb->posres_xA,molb->nposres_xA);
     }
-    ndo_rvec(molb->posres_xA,molb->nposres_xA);
+    gmx_fio_ndo_rvec(fio,molb->posres_xA,molb->nposres_xA);
   }
-  do_int(molb->nposres_xB);
+  gmx_fio_do_int(fio,molb->nposres_xB);
   if (molb->nposres_xB > 0) {
     if (bRead) {
       snew(molb->posres_xB,molb->nposres_xB);
     }
-    ndo_rvec(molb->posres_xB,molb->nposres_xB);
+    gmx_fio_ndo_rvec(fio,molb->posres_xB,molb->nposres_xB);
   }
 
 }
@@ -1768,23 +1778,24 @@ static void set_disres_npair(gmx_mtop_t *mtop)
   }
 }
 
-static void do_mtop(gmx_mtop_t *mtop,bool bRead, int file_version)
+static void do_mtop(t_fileio *fio, gmx_mtop_t *mtop,bool bRead, 
+                    int file_version)
 {
   int  mt,mb,i;
   t_blocka dumb;
 
   if (bRead)
     init_mtop(mtop);
-  do_symtab(&(mtop->symtab),bRead);
+  do_symtab(fio, &(mtop->symtab),bRead);
   if (bRead && debug) 
     pr_symtab(debug,0,"symtab",&mtop->symtab);
   
-  do_symstr(&(mtop->name),bRead,&(mtop->symtab));
+  do_symstr(fio, &(mtop->name),bRead,&(mtop->symtab));
   
   if (file_version >= 57) {
-    do_ffparams(&mtop->ffparams,bRead,file_version);
+    do_ffparams(fio, &mtop->ffparams,bRead,file_version);
 
-    do_int(mtop->nmoltype);
+    gmx_fio_do_int(fio,mtop->nmoltype);
   } else {
     mtop->nmoltype = 1;
   }
@@ -1795,12 +1806,12 @@ static void do_mtop(gmx_mtop_t *mtop,bool bRead, int file_version)
     }
   }
   for(mt=0; mt<mtop->nmoltype; mt++) {
-    do_moltype(&mtop->moltype[mt],bRead,&mtop->symtab,file_version,
+    do_moltype(fio, &mtop->moltype[mt],bRead,&mtop->symtab,file_version,
               &mtop->groups);
   }
 
   if (file_version >= 57) {
-    do_int(mtop->nmolblock);
+    gmx_fio_do_int(fio,mtop->nmolblock);
   } else {
     mtop->nmolblock = 1;
   }
@@ -1809,9 +1820,9 @@ static void do_mtop(gmx_mtop_t *mtop,bool bRead, int file_version)
   }
   if (file_version >= 57) {
     for(mb=0; mb<mtop->nmolblock; mb++) {
-      do_molblock(&mtop->molblock[mb],bRead,file_version);
+      do_molblock(fio, &mtop->molblock[mb],bRead,file_version);
     }
-    do_int(mtop->natoms);
+    gmx_fio_do_int(fio,mtop->natoms);
   } else {
     mtop->molblock[0].type = 0;
     mtop->molblock[0].nmol = 1;
@@ -1820,19 +1831,19 @@ static void do_mtop(gmx_mtop_t *mtop,bool bRead, int file_version)
     mtop->molblock[0].nposres_xB = 0;
   }
 
-  do_atomtypes (&(mtop->atomtypes),bRead,&(mtop->symtab), file_version);
+  do_atomtypes (fio, &(mtop->atomtypes),bRead,&(mtop->symtab), file_version);
   if (bRead && debug) 
     pr_atomtypes(debug,0,"atomtypes",&mtop->atomtypes,TRUE);
 
   if (file_version < 57) {
     /* Debug statements are inside do_idef */    
-    do_idef (&mtop->ffparams,&mtop->moltype[0],bRead,file_version);
+    do_idef (fio, &mtop->ffparams,&mtop->moltype[0],bRead,file_version);
     mtop->natoms = mtop->moltype[0].atoms.nr;
   }
        
   if(file_version >= 65)
   {
-      do_cmap(&mtop->ffparams.cmap_grid,bRead);
+      do_cmap(fio, &mtop->ffparams.cmap_grid,bRead);
   }
   else
   {
@@ -1842,15 +1853,15 @@ static void do_mtop(gmx_mtop_t *mtop,bool bRead, int file_version)
   }
          
   if (file_version >= 57) {
-    do_groups(&mtop->groups,bRead,&(mtop->symtab),file_version);
+    do_groups(fio, &mtop->groups,bRead,&(mtop->symtab),file_version);
   }
 
   if (file_version < 57) {
-    do_block(&mtop->moltype[0].cgs,bRead,file_version);
+    do_block(fio, &mtop->moltype[0].cgs,bRead,file_version);
     if (bRead && gmx_debug_at) {
       pr_block(debug,0,"cgs",&mtop->moltype[0].cgs,TRUE);
     }
-    do_block(&mtop->mols,bRead,file_version);
+    do_block(fio, &mtop->mols,bRead,file_version);
     /* Add the posres coordinates to the molblock */
     add_posres_molblock(mtop);
   }
@@ -1865,7 +1876,7 @@ static void do_mtop(gmx_mtop_t *mtop,bool bRead, int file_version)
 
   if (file_version < 51) {
     /* Here used to be the shake blocks */
-    do_blocka(&dumb,bRead,file_version);
+    do_blocka(fio, &dumb,bRead,file_version);
     if (dumb.nr > 0)
       sfree(dumb.index);
     if (dumb.nra > 0)
@@ -1887,8 +1898,9 @@ static void do_mtop(gmx_mtop_t *mtop,bool bRead, int file_version)
  * 
  * If possible, we will read the inputrec even when TopOnlyOK is TRUE.
  */
-static void do_tpxheader(int fp,bool bRead,t_tpxheader *tpx, bool TopOnlyOK, 
-                         int *file_version, int *file_generation)
+static void do_tpxheader(t_fileio *fio,bool bRead,t_tpxheader *tpx, 
+                         bool TopOnlyOK, int *file_version, 
+                         int *file_generation)
 {
   char  buf[STRLEN];
   bool  bDouble;
@@ -1896,42 +1908,43 @@ static void do_tpxheader(int fp,bool bRead,t_tpxheader *tpx, bool TopOnlyOK,
   int   fver,fgen;
   int   idum=0;
   real  rdum=0;
-  gmx_fio_select(fp);
-  gmx_fio_setdebug(fp,bDebugMode());
+
+  gmx_fio_checktype(fio);
+  gmx_fio_setdebug(fio,bDebugMode());
   
   /* NEW! XDR tpb file */
   precision = sizeof(real);
   if (bRead) {
-    do_string(buf);
+    gmx_fio_do_string(fio,buf);
     if (strncmp(buf,"VERSION",7))
       gmx_fatal(FARGS,"Can not read file %s,\n"
                  "             this file is from a Gromacs version which is older than 2.0\n"
                  "             Make a new one with grompp or use a gro or pdb file, if possible",
-                 gmx_fio_getname(fp));
-    do_int(precision);
+                 gmx_fio_getname(fio));
+    gmx_fio_do_int(fio,precision);
     bDouble = (precision == sizeof(double));
     if ((precision != sizeof(float)) && !bDouble)
       gmx_fatal(FARGS,"Unknown precision in file %s: real is %d bytes "
                  "instead of %d or %d",
-                 gmx_fio_getname(fp),precision,sizeof(float),sizeof(double));
-    gmx_fio_setprecision(fp,bDouble);
+                 gmx_fio_getname(fio),precision,sizeof(float),sizeof(double));
+    gmx_fio_setprecision(fio,bDouble);
     fprintf(stderr,"Reading file %s, %s (%s precision)\n",
-           gmx_fio_getname(fp),buf,bDouble ? "double" : "single");
+           gmx_fio_getname(fio),buf,bDouble ? "double" : "single");
   }
   else {
-    do_string(GromacsVersion());
+    gmx_fio_write_string(fio,GromacsVersion());
     bDouble = (precision == sizeof(double));
-    gmx_fio_setprecision(fp,bDouble);
-    do_int(precision);
+    gmx_fio_setprecision(fio,bDouble);
+    gmx_fio_do_int(fio,precision);
     fver = tpx_version;
     fgen = tpx_generation;
   }
   
   /* Check versions! */
-  do_int(fver);
+  gmx_fio_do_int(fio,fver);
   
   if(fver>=26)
-    do_int(fgen);
+    gmx_fio_do_int(fio,fgen);
   else
     fgen=0;
  
@@ -1945,25 +1958,25 @@ static void do_tpxheader(int fp,bool bRead,t_tpxheader *tpx, bool TopOnlyOK,
       ((fver > tpx_version) && !TopOnlyOK) ||
       (fgen > tpx_generation))
     gmx_fatal(FARGS,"reading tpx file (%s) version %d with version %d program",
-               gmx_fio_getname(fp),fver,tpx_version);
+               gmx_fio_getname(fio),fver,tpx_version);
   
-  do_section(eitemHEADER,bRead);
-  do_int (tpx->natoms);
+  do_section(fio,eitemHEADER,bRead);
+  gmx_fio_do_int(fio,tpx->natoms);
   if (fver >= 28)
-    do_int(tpx->ngtc);
+    gmx_fio_do_int(fio,tpx->ngtc);
   else
     tpx->ngtc = 0;
   if (fver < 62) {
-    do_int (idum);
-    do_real(rdum);
+    gmx_fio_do_int(fio,idum);
+    gmx_fio_do_real(fio,rdum);
   }
-  do_real(tpx->lambda);
-  do_int (tpx->bIr);
-  do_int (tpx->bTop);
-  do_int (tpx->bX);
-  do_int (tpx->bV);
-  do_int (tpx->bF);
-  do_int (tpx->bBox);
+  gmx_fio_do_real(fio,tpx->lambda);
+  gmx_fio_do_int(fio,tpx->bIr);
+  gmx_fio_do_int(fio,tpx->bTop);
+  gmx_fio_do_int(fio,tpx->bX);
+  gmx_fio_do_int(fio,tpx->bV);
+  gmx_fio_do_int(fio,tpx->bF);
+  gmx_fio_do_int(fio,tpx->bBox);
 
   if((fgen > tpx_generation)) {
     /* This can only happen if TopOnlyOK=TRUE */
@@ -1971,7 +1984,7 @@ static void do_tpxheader(int fp,bool bRead,t_tpxheader *tpx, bool TopOnlyOK,
   }
 }
 
-static int do_tpx(int fp,bool bRead,
+static int do_tpx(t_fileio *fio, bool bRead,
                  t_inputrec *ir,t_state *state,rvec *f,gmx_mtop_t *mtop,
                  bool bXVallocated)
 {
@@ -1999,7 +2012,7 @@ static int do_tpx(int fp,bool bRead,
   
   TopOnlyOK = (ir==NULL);
   
-  do_tpxheader(fp,bRead,&tpx,TopOnlyOK,&file_version,&file_generation);
+  do_tpxheader(fio,bRead,&tpx,TopOnlyOK,&file_version,&file_generation);
 
   if (bRead) {
     state->flags  = 0;
@@ -2018,23 +2031,23 @@ static int do_tpx(int fp,bool bRead,
     }
   }
 
-#define do_test(b,p) if (bRead && (p!=NULL) && !b) gmx_fatal(FARGS,"No %s in %s",#p,gmx_fio_getname(fp)) 
+#define do_test(fio,b,p) if (bRead && (p!=NULL) && !b) gmx_fatal(FARGS,"No %s in %s",#p,gmx_fio_getname(fio)) 
 
-  do_test(tpx.bBox,state->box);
-  do_section(eitemBOX,bRead);
+  do_test(fio,tpx.bBox,state->box);
+  do_section(fio,eitemBOX,bRead);
   if (tpx.bBox) {
-    ndo_rvec(state->box,DIM);
+    gmx_fio_ndo_rvec(fio,state->box,DIM);
     if (file_version >= 51) {
-      ndo_rvec(state->box_rel,DIM);
+      gmx_fio_ndo_rvec(fio,state->box_rel,DIM);
     } else {
       /* We initialize box_rel after reading the inputrec */
       clear_mat(state->box_rel);
     }
     if (file_version >= 28) {
-      ndo_rvec(state->boxv,DIM);
+      gmx_fio_ndo_rvec(fio,state->boxv,DIM);
       if (file_version < 56) {
        matrix mdum;
-       ndo_rvec(mdum,DIM);
+       gmx_fio_ndo_rvec(fio,mdum,DIM);
       }
     }
   }
@@ -2046,10 +2059,10 @@ static int do_tpx(int fp,bool bRead,
     /*ndo_double(state->therm_integral,state->ngtc,bDum);*/
     snew(dumv,state->ngtc);
     if (file_version < 69) {
-      ndo_real(dumv,state->ngtc,bDum);
+      bDum=gmx_fio_ndo_real(fio,dumv,state->ngtc);
     }
     /* These used to be the Berendsen tcoupl_lambda's */
-    ndo_real(dumv,state->ngtc,bDum);
+    bDum=gmx_fio_ndo_real(fio,dumv,state->ngtc);
     sfree(dumv);
   }
 
@@ -2058,16 +2071,18 @@ static int do_tpx(int fp,bool bRead,
    * for analysis/viewer programs.
    */
   if(file_version<26) {
-    do_test(tpx.bIr,ir);
-    do_section(eitemIR,bRead);
+    do_test(fio,tpx.bIr,ir);
+    do_section(fio,eitemIR,bRead);
     if (tpx.bIr) {
       if (ir) {
-       do_inputrec(ir,bRead,file_version,mtop ? &mtop->ffparams.fudgeQQ : NULL);
+       do_inputrec(fio, ir,bRead,file_version,
+                    mtop ? &mtop->ffparams.fudgeQQ : NULL);
        if (bRead && debug) 
          pr_inputrec(debug,0,"inputrec",ir,FALSE);
       }
       else {
-       do_inputrec(&dum_ir,bRead,file_version,mtop ? &mtop->ffparams.fudgeQQ :NULL);
+       do_inputrec(fio, &dum_ir,bRead,file_version,
+                    mtop ? &mtop->ffparams.fudgeQQ :NULL);
        if (bRead && debug) 
          pr_inputrec(debug,0,"inputrec",&dum_ir,FALSE);
        done_inputrec(&dum_ir);
@@ -2076,37 +2091,37 @@ static int do_tpx(int fp,bool bRead,
     }
   }
   
-  do_test(tpx.bTop,mtop);
-  do_section(eitemTOP,bRead);
+  do_test(fio,tpx.bTop,mtop);
+  do_section(fio,eitemTOP,bRead);
   if (tpx.bTop) {
     if (mtop) {
-      do_mtop(mtop,bRead, file_version);
+      do_mtop(fio,mtop,bRead, file_version);
     } else {
-      do_mtop(&dum_top,bRead,file_version);
+      do_mtop(fio,&dum_top,bRead,file_version);
       done_mtop(&dum_top,TRUE);
     }
   }
-  do_test(tpx.bX,state->x);  
-  do_section(eitemX,bRead);
+  do_test(fio,tpx.bX,state->x);  
+  do_section(fio,eitemX,bRead);
   if (tpx.bX) {
     if (bRead) {
       state->flags |= (1<<estX);
     }
-    ndo_rvec(state->x,state->natoms);
+    gmx_fio_ndo_rvec(fio,state->x,state->natoms);
   }
   
-  do_test(tpx.bV,state->v);
-  do_section(eitemV,bRead);
+  do_test(fio,tpx.bV,state->v);
+  do_section(fio,eitemV,bRead);
   if (tpx.bV) {
     if (bRead) {
       state->flags |= (1<<estV);
     }
-    ndo_rvec(state->v,state->natoms);
+    gmx_fio_ndo_rvec(fio,state->v,state->natoms);
   }
 
-  do_test(tpx.bF,f);
-  do_section(eitemF,bRead);
-  if (tpx.bF) ndo_rvec(f,state->natoms);
+  do_test(fio,tpx.bF,f);
+  do_section(fio,eitemF,bRead);
+  if (tpx.bF) gmx_fio_ndo_rvec(fio,f,state->natoms);
 
   /* Starting with tpx version 26, we have the inputrec
    * at the end of the file, so we can ignore it 
@@ -2118,8 +2133,8 @@ static int do_tpx(int fp,bool bRead,
   ePBC = -1;
   bPeriodicMols = FALSE;
   if (file_version >= 26) {
-    do_test(tpx.bIr,ir);
-    do_section(eitemIR,bRead);
+    do_test(fio,tpx.bIr,ir);
+    do_section(fio,eitemIR,bRead);
     if (tpx.bIr) {
       if (file_version >= 53) {
        /* Removed the pbc info from do_inputrec, since we always want it */
@@ -2127,11 +2142,11 @@ static int do_tpx(int fp,bool bRead,
          ePBC          = ir->ePBC;
          bPeriodicMols = ir->bPeriodicMols;
        }
-       do_int(ePBC);
-       do_int(bPeriodicMols);
+       gmx_fio_do_int(fio,ePBC);
+       gmx_fio_do_bool(fio,bPeriodicMols);
       }
       if (file_generation <= tpx_generation && ir) {
-       do_inputrec(ir,bRead,file_version,mtop ? &mtop->ffparams.fudgeQQ : NULL);
+       do_inputrec(fio, ir,bRead,file_version,mtop ? &mtop->ffparams.fudgeQQ : NULL);
        if (bRead && debug) 
          pr_inputrec(debug,0,"inputrec",ir,FALSE);
        if (file_version < 51)
@@ -2211,59 +2226,59 @@ static int do_tpx(int fp,bool bRead,
  *
  ************************************************************/
 
-int open_tpx(const char *fn,const char *mode)
+t_fileio *open_tpx(const char *fn,const char *mode)
 {
   return gmx_fio_open(fn,mode);
 }    
  
-void close_tpx(int fp)
+void close_tpx(t_fileio *fio)
 {
-  gmx_fio_close(fp);
+  gmx_fio_close(fio);
 }
 
 void read_tpxheader(const char *fn, t_tpxheader *tpx, bool TopOnlyOK,
                     int *file_version, int *file_generation)
 {
-  int fp;
+  t_fileio *fio;
 
-  fp = open_tpx(fn,"r");
-  do_tpxheader(fp,TRUE,tpx,TopOnlyOK,file_version,file_generation);
-  close_tpx(fp);
+  fio = open_tpx(fn,"r");
+  do_tpxheader(fio,TRUE,tpx,TopOnlyOK,file_version,file_generation);
+  close_tpx(fio);
 }
 
 void write_tpx_state(const char *fn,
                     t_inputrec *ir,t_state *state,gmx_mtop_t *mtop)
 {
-  int fp;
+  t_fileio *fio;
 
-  fp = open_tpx(fn,"w");
-  do_tpx(fp,FALSE,ir,state,NULL,mtop,FALSE);
-  close_tpx(fp);
+  fio = open_tpx(fn,"w");
+  do_tpx(fio,FALSE,ir,state,NULL,mtop,FALSE);
+  close_tpx(fio);
 }
 
 void read_tpx_state(const char *fn,
                    t_inputrec *ir,t_state *state,rvec *f,gmx_mtop_t *mtop)
 {
-  int fp;
+  t_fileio *fio;
        
-  fp = open_tpx(fn,"r");
-  do_tpx(fp,TRUE,ir,state,f,mtop,FALSE);
-  close_tpx(fp);
+  fio = open_tpx(fn,"r");
+  do_tpx(fio,TRUE,ir,state,f,mtop,FALSE);
+  close_tpx(fio);
 }
 
 int read_tpx(const char *fn,
             t_inputrec *ir, matrix box,int *natoms,
             rvec *x,rvec *v,rvec *f,gmx_mtop_t *mtop)
 {
-  int fp;
+  t_fileio *fio;
   t_state state;
   int ePBC;
 
   state.x = x;
   state.v = v;
-  fp = open_tpx(fn,"r");
-  ePBC = do_tpx(fp,TRUE,ir,&state,f,mtop,TRUE);
-  close_tpx(fp);
+  fio = open_tpx(fn,"r");
+  ePBC = do_tpx(fio,TRUE,ir,&state,f,mtop,TRUE);
+  close_tpx(fio);
   *natoms = state.natoms;
   if (box) 
     copy_mat(state.box,box);
index 41cc143b5332b7dd0f8e3e4ce7a25f3b74737e74..55dcacd6ecc83d1c2c62fa13cbab62c79c3f18b9 100644 (file)
@@ -1239,6 +1239,37 @@ gmx_ana_indexmap_init(gmx_ana_indexmap_t *m, gmx_ana_index_t *g,
     m->bMapStatic = TRUE;
 }
 
+/*!
+ * \param[in,out] m    Mapping structure to initialize.
+ * \param[in]     b    Block information to use for data.
+ *
+ * Frees some memory that is not necessary for static index group mappings.
+ * Internal pointers are set to point to data in \p b; it is the responsibility
+ * of the caller to ensure that the block information matches the contents of
+ * the mapping.
+ * After this function has been called, the index group provided to
+ * gmx_ana_indexmap_update() should always be the same as \p g given here.
+ *
+ * This function breaks modularity of the index group mapping interface in an
+ * ugly way, but allows reducing memory usage of static selections by a
+ * significant amount.
+ */
+void
+gmx_ana_indexmap_set_static(gmx_ana_indexmap_t *m, t_blocka *b)
+{
+    sfree(m->mapid);
+    m->mapid = m->orgid;
+    sfree(m->b.index);
+    m->b.nalloc_index = 0;
+    m->b.index = b->index;
+    sfree(m->mapb.index);
+    m->mapb.nalloc_index = 0;
+    m->mapb.index = m->b.index;
+    sfree(m->b.a);
+    m->b.nalloc_a = 0;
+    m->b.a = b->a;
+}
+
 /*!
  * \param[in,out] dest Destination data structure.
  * \param[in]     src  Source mapping.
@@ -1401,10 +1432,22 @@ void
 gmx_ana_indexmap_deinit(gmx_ana_indexmap_t *m)
 {
     sfree(m->refid);
-    sfree(m->mapid);
-    sfree(m->mapb.index);
+    if (m->mapid != m->orgid)
+    {
+        sfree(m->mapid);
+    }
+    if (m->mapb.nalloc_index > 0)
+    {
+        sfree(m->mapb.index);
+    }
     sfree(m->orgid);
-    sfree(m->b.index);
-    sfree(m->b.a);
+    if (m->b.nalloc_index > 0)
+    {
+        sfree(m->b.index);
+    }
+    if (m->b.nalloc_a > 0)
+    {
+        sfree(m->b.a);
+    }
     gmx_ana_indexmap_clear(m);
 }
index 9382d8b6825c51aa734898c8a41db11ad56d4fc1..47f1d25f1c29fb18eac51f0084229dc273dd60a4 100644 (file)
  * When the data structure is no longer required, it can be freed with
  * gmx_ana_nbsearch_free().
  *
- * \todo
- * Implement grid-based searching
- * (currently everything is implemented using an expensive O(n^2) loop).
- * Optimally, the MD neighborhood searching routines could be used, but
- * currently they are quite difficult to interface flexibly.
- *
- * \todo
- * Implement a set of functions for looping through all pairs within a cutoff.
+ * \internal
  *
  * \todo
- * Implement an API that allows for excluding certain pairs of atoms from
- * neighborhood searching.
+ * The grid implementation could still be optimized in several different ways:
+ *   - Triclinic grid cells are not the most efficient shape, but make PBC
+ *     handling easier.
+ *   - Precalculating the required PBC shift for a pair of cells outside the
+ *     inner loop. After this is done, it should be quite straightforward to
+ *     move to rectangular cells.
+ *   - Pruning grid cells from the search list if they are completely outside
+ *     the sphere that is being considered.
+ *   - A better heuristic could be added for falling back to simple loops for a
+ *     small number of reference particles.
+ *   - A better heuristic for selecting the grid size.
+ *   - A multi-level grid implementation could be used to be able to use small
+ *     grids for short cutoffs with very inhomogeneous particle distributions
+ *     without a memory cost.
  */
 /*! \internal \file
  * \brief Implementation of functions in nbsearch.h.
@@ -61,6 +66,8 @@
 #include <config.h>
 #endif
 
+#include <math.h>
+
 #include <smalloc.h>
 #include <typedefs.h>
 #include <pbc.h>
  */
 struct gmx_ana_nbsearch_t
 {
+    /** The cutoff. */
+    real           cutoff;
     /** The cutoff squared. */
     real           cutoff2;
     /** Maximum number of reference points. */
     int            maxnref;
+
     /** Number of reference points for the current frame. */
     int            nref;
     /** Reference point positions. */
     rvec          *xref;
+    /** Reference position ids (NULL if not available). */
+    int           *refid;
     /** PBC data. */
     t_pbc         *pbc;
+
+    /** Number of excluded reference positions for current test particle. */
+    int            nexcl;
+    /** Exclusions for current test particle. */
+    int           *excl;
+
+    /** Whether to try grid searching. */
+    bool           bTryGrid;
+    /** Whether grid searching is actually used for the current positions. */
+    bool           bGrid;
+    /** Array allocated for storing in-unit-cell reference positions. */
+    rvec          *xref_alloc;
+    /** FALSE if the box is rectangular. */
+    bool           bTric;
+    /** Box vectors of a single grid cell. */
+    matrix         cellbox;
+    /** The reciprocal cell vectors as columns; the inverse of \p cellbox. */
+    matrix         recipcell;
+    /** Number of cells along each dimension. */
+    ivec           ncelldim;
+    /** Total number of cells. */
+    int            ncells;
+    /** Number of reference positions in each cell. */
+    int           *ncatoms;
+    /** List of reference positions in each cell. */
+    atom_id      **catom;
+    /** Allocation counts for each \p catom[i]. */
+    int           *catom_nalloc;
+    /** Allocation count for the per-cell arrays. */
+    int            cells_nalloc;
+    /** Number of neighboring cells to consider. */
+    int            ngridnb;
+    /** Offsets of the neighboring cells to consider. */
+    ivec          *gnboffs;
+    /** Allocation count for \p gnboffs. */
+    int            gnboffs_nalloc;
+
+    /** Stores test position during a pair loop. */
+    rvec           xtest;
+    /** Stores the previous returned position during a pair loop. */
+    int            previ;
+    /** Stores the current exclusion index during loops. */
+    int            exclind;
+    /** Stores the test particle cell index during loops. */
+    ivec           testcell;
+    /** Stores the current cell neighbor index during pair loops. */
+    int            prevnbi;
+    /** Stores the index within the current cell during pair loops. */
+    int            prevcai;
 };
 
 /*!
@@ -99,12 +160,31 @@ gmx_ana_nbsearch_create(gmx_ana_nbsearch_t **data, real cutoff, int maxn)
     gmx_ana_nbsearch_t *d;
     
     snew(d, 1);
+    d->bTryGrid = TRUE;
     if (cutoff <= 0)
     {
         cutoff = HUGE_VAL;
+        d->bTryGrid = FALSE;
     }
+    d->cutoff = cutoff;
     d->cutoff2 = sqr(cutoff);
     d->maxnref = maxn;
+
+    d->xref = NULL;
+    d->nexcl = 0;
+    d->exclind = 0;
+
+    d->xref_alloc = NULL;
+    d->ncells = 0;
+    d->ncatoms = NULL;
+    d->catom = NULL;
+    d->catom_nalloc = 0;
+    d->cells_nalloc = 0;
+
+    d->ngridnb = 0;
+    d->gnboffs = NULL;
+    d->gnboffs_nalloc = 0;
+
     *data = d;
     return 0;
 }
@@ -117,9 +197,246 @@ gmx_ana_nbsearch_create(gmx_ana_nbsearch_t **data, real cutoff, int maxn)
 void
 gmx_ana_nbsearch_free(gmx_ana_nbsearch_t *d)
 {
+    sfree(d->xref_alloc);
+    sfree(d->ncatoms);
+    if (d->catom)
+    {
+        int ci;
+
+        for (ci = 0; ci < d->ncells; ++ci)
+        {
+            sfree(d->catom[ci]);
+        }
+        sfree(d->catom);
+    }
+    sfree(d->catom_nalloc);
+    sfree(d->gnboffs);
     sfree(d);
 }
 
+/*! \brief
+ * Calculates offsets to neighboring grid cells that should be considered.
+ *
+ * \param[in,out] d    Grid information.
+ * \param[in]     pbc  Information about the box.
+ */
+static void
+grid_init_cell_nblist(gmx_ana_nbsearch_t *d, t_pbc *pbc)
+{
+    int   maxx, maxy, maxz;
+    int   x, y, z, i;
+    real  rvnorm;
+
+    /* Find the extent of the sphere in triclinic coordinates */
+    maxz = (int)(d->cutoff * d->recipcell[ZZ][ZZ]) + 1;
+    rvnorm = sqrt(sqr(d->recipcell[YY][YY]) + sqr(d->recipcell[ZZ][YY]));
+    maxy = (int)(d->cutoff * rvnorm) + 1;
+    rvnorm = sqrt(sqr(d->recipcell[XX][XX]) + sqr(d->recipcell[YY][XX])
+                  + sqr(d->recipcell[ZZ][XX]));
+    maxx = (int)(d->cutoff * rvnorm) + 1;
+
+    /* Calculate the number of cells and reallocate if necessary */
+    d->ngridnb = (2 * maxx + 1) * (2 * maxy + 1) * (2 * maxz + 1);
+    if (d->gnboffs_nalloc < d->ngridnb)
+    {
+        d->gnboffs_nalloc = d->ngridnb;
+        srenew(d->gnboffs, d->gnboffs_nalloc);
+    }
+
+    /* Store the whole cube */
+    /* TODO: Prune off corners that are not needed */
+    i = 0;
+    for (x = -maxx; x <= maxx; ++x)
+    {
+        for (y = -maxy; y <= maxy; ++y)
+        {
+            for (z = -maxz; z <= maxz; ++z)
+            {
+                d->gnboffs[i][XX] = x;
+                d->gnboffs[i][YY] = y;
+                d->gnboffs[i][ZZ] = z;
+                ++i;
+            }
+        }
+    }
+}
+
+/*! \brief
+ * Determines a suitable grid size.
+ *
+ * \param[in,out] d    Grid information.
+ * \param[in]     pbc  Information about the box.
+ * \returns  FALSE if grid search is not suitable.
+ */
+static bool
+grid_setup_cells(gmx_ana_nbsearch_t *d, t_pbc *pbc)
+{
+    real targetsize;
+    int  dd;
+
+#ifdef HAVE_CBRT
+    targetsize = cbrt(pbc->box[XX][XX] * pbc->box[YY][YY] * pbc->box[ZZ][ZZ]
+                      * 10 / d->nref);
+#else
+    targetsize = pow(pbc->box[XX][XX] * pbc->box[YY][YY] * pbc->box[ZZ][ZZ]
+                      * 10 / d->nref, 1./3.);
+#endif
+
+    d->ncells = 1;
+    for (dd = 0; dd < DIM; ++dd)
+    {
+        d->ncelldim[dd] = (int)(pbc->box[dd][dd] / targetsize);
+        d->ncells *= d->ncelldim[dd];
+        if (d->ncelldim[dd] < 3)
+        {
+            return FALSE;
+        }
+    }
+    /* Reallocate if necessary */
+    if (d->cells_nalloc < d->ncells)
+    {
+        int  i;
+
+        srenew(d->ncatoms, d->ncells);
+        srenew(d->catom, d->ncells);
+        srenew(d->catom_nalloc, d->ncells);
+        for (i = d->cells_nalloc; i < d->ncells; ++i)
+        {
+            d->catom[i] = NULL;
+            d->catom_nalloc[i] = 0;
+        }
+        d->cells_nalloc = d->ncells;
+    }
+    return TRUE;
+}
+
+/*! \brief
+ * Sets ua a search grid for a given box.
+ *
+ * \param[in,out] d    Grid information.
+ * \param[in]     pbc  Information about the box.
+ * \returns  FALSE if grid search is not suitable.
+ */
+static bool
+grid_set_box(gmx_ana_nbsearch_t *d, t_pbc *pbc)
+{
+    int dd;
+
+    /* TODO: This check could be improved. */
+    if (0.5*pbc->max_cutoff2 < d->cutoff2)
+    {
+        return FALSE;
+    }
+
+    if (!grid_setup_cells(d, pbc))
+    {
+        return FALSE;
+    }
+
+    d->bTric = TRICLINIC(pbc->box);
+    if (d->bTric)
+    {
+        for (dd = 0; dd < DIM; ++dd)
+        {
+            svmul(1.0 / d->ncelldim[dd], pbc->box[dd], d->cellbox[dd]);
+        }
+        m_inv_ur0(d->cellbox, d->recipcell);
+    }
+    else
+    {
+        for (dd = 0; dd < DIM; ++dd)
+        {
+            d->cellbox[dd][dd] = pbc->box[dd][dd] / d->ncelldim[dd];
+            d->recipcell[dd][dd] = 1 / d->cellbox[dd][dd];
+        }
+    }
+    grid_init_cell_nblist(d, pbc);
+    return TRUE;
+}
+
+/*! \brief
+ * Maps a point into a grid cell.
+ *
+ * \param[in]  d    Grid information.
+ * \param[in]  x    Point to map.
+ * \param[out] cell Indices of the grid cell in which \p x lies.
+ *
+ * \p x should be in the triclinic unit cell.
+ */
+static void
+grid_map_onto(gmx_ana_nbsearch_t *d, const rvec x, ivec cell)
+{
+    int dd;
+
+    if (d->bTric)
+    {
+        rvec tx;
+
+        tmvmul_ur0(d->recipcell, x, tx);
+        for (dd = 0; dd < DIM; ++dd)
+        {
+            cell[dd] = (int)tx[dd];
+        }
+    }
+    else
+    {
+        for (dd = 0; dd < DIM; ++dd)
+        {
+            cell[dd] = (int)(x[dd] * d->recipcell[dd][dd]);
+        }
+    }
+}
+
+/*! \brief
+ * Calculates linear index of a grid cell.
+ *
+ * \param[in]  d    Grid information.
+ * \param[in]  cell Cell indices.
+ * \returns    Linear index of \p cell.
+ */
+static int
+grid_index(gmx_ana_nbsearch_t *d, const ivec cell)
+{
+    return cell[XX] + cell[YY] * d->ncelldim[XX]
+        + cell[ZZ] * d->ncelldim[YY] * d->ncelldim[ZZ];
+}
+
+/*! \brief
+ * Clears all grid cells.
+ *
+ * \param[in,out] d    Grid information.
+ */
+static void
+grid_clear_cells(gmx_ana_nbsearch_t *d)
+{
+    int  ci;
+
+    for (ci = 0; ci < d->ncells; ++ci)
+    {
+        d->ncatoms[ci] = 0;
+    }
+}
+
+/*! \brief
+ * Adds an index into a grid cell.
+ *
+ * \param[in,out] d    Grid information.
+ * \param[in]     cell Cell into which \p i should be added.
+ * \param[in]     i    Index to add.
+ */
+static void
+grid_add_to_cell(gmx_ana_nbsearch_t *d, const ivec cell, int i)
+{
+    int ci = grid_index(d, cell);
+
+    if (d->ncatoms[ci] == d->catom_nalloc[ci])
+    {
+        d->catom_nalloc[ci] += 10;
+        srenew(d->catom[ci], d->catom_nalloc[ci]);
+    }
+    d->catom[ci][d->ncatoms[ci]++] = i;
+}
+
 /*!
  * \param[in,out] d   Neighborhood search data structure.
  * \param[in]     pbc PBC information for the frame.
@@ -135,7 +452,43 @@ gmx_ana_nbsearch_init(gmx_ana_nbsearch_t *d, t_pbc *pbc, int n, rvec x[])
 {
     d->pbc  = pbc;
     d->nref = n;
-    d->xref = x;
+    if (!pbc)
+    {
+        d->bGrid = FALSE;
+    }
+    else if (d->bTryGrid)
+    {
+        d->bGrid = grid_set_box(d, pbc);
+    }
+    if (d->bGrid)
+    {
+        int  i;
+
+        if (!d->xref_alloc)
+        {
+            snew(d->xref_alloc, d->maxnref);
+        }
+        d->xref = d->xref_alloc;
+        grid_clear_cells(d);
+
+        for (i = 0; i < n; ++i)
+        {
+            copy_rvec(x[i], d->xref[i]);
+        }
+        put_atoms_in_triclinic_unitcell(ecenterTRIC, pbc->box, n, d->xref);
+        for (i = 0; i < n; ++i)
+        {
+            ivec refcell;
+
+            grid_map_onto(d, d->xref[i], refcell);
+            grid_add_to_cell(d, refcell, i);
+        }
+    }
+    else
+    {
+        d->xref = x;
+    }
+    d->refid = NULL;
     return 0;
 }
 
@@ -150,39 +503,206 @@ gmx_ana_nbsearch_init(gmx_ana_nbsearch_t *d, t_pbc *pbc, int n, rvec x[])
 int
 gmx_ana_nbsearch_pos_init(gmx_ana_nbsearch_t *d, t_pbc *pbc, gmx_ana_pos_t *p)
 {
-    return gmx_ana_nbsearch_init(d, pbc, p->nr, p->x);
+    int rc;
+
+    rc = gmx_ana_nbsearch_init(d, pbc, p->nr, p->x);
+    d->refid = (p->nr < d->maxnref ? p->m.refid : NULL);
+    return rc;
 }
 
 /*!
- * \param[in] d   Neighborhood search data structure.
- * \param[in] x   Test position.
- * \returns   TRUE if \p x is within the cutoff of any reference position,
- *   FALSE otherwise.
+ * \param[in,out] d     Neighborhood search data structure.
+ * \param[in]     nexcl Number of reference positions to exclude from next
+ *      search.
+ * \param[in]     excl  Indices of reference positions to exclude.
+ * \returns       0 on success.
+ *
+ * The set exclusions remain in effect until the next call of this function.
  */
-bool
-gmx_ana_nbsearch_is_within(gmx_ana_nbsearch_t *d, rvec x)
+int
+gmx_ana_nbsearch_set_excl(gmx_ana_nbsearch_t *d, int nexcl, int excl[])
 {
-    int  i;
-    rvec dx;
 
-    for (i = 0; i < d->nref; ++i)
+    d->nexcl = nexcl;
+    d->excl = excl;
+    return 0;
+}
+
+/*! \brief
+ * Helper function to check whether a reference point should be excluded.
+ */
+static bool
+is_excluded(gmx_ana_nbsearch_t *d, int j)
+{
+    if (d->exclind < d->nexcl)
     {
-        if (d->pbc)
+        if (d->refid)
         {
-            pbc_dx(d->pbc, x, d->xref[i], dx);
+            while (d->exclind < d->nexcl && d->refid[j] > d->excl[d->exclind])
+            {
+                ++d->exclind;
+            }
+            if (d->exclind < d->nexcl && d->refid[j] == d->excl[d->exclind])
+            {
+                ++d->exclind;
+                return TRUE;
+            }
         }
         else
         {
-            rvec_sub(x, d->xref[i], dx);
+            while (d->bGrid && d->exclind < d->nexcl && d->excl[d->exclind] < j)
+            {
+                ++d->exclind;
+            }
+            if (d->excl[d->exclind] == j)
+            {
+                ++d->exclind;
+                return TRUE;
+            }
         }
-        if (norm2(dx) <= d->cutoff2)
+    }
+    return FALSE;
+}
+
+/*! \brief
+ * Initializes a grid search to find reference positions neighboring \p x.
+ */
+static void
+grid_search_start(gmx_ana_nbsearch_t *d, rvec x)
+{
+    copy_rvec(x, d->xtest);
+    if (d->bGrid)
+    {
+        put_atoms_in_triclinic_unitcell(ecenterTRIC, d->pbc->box, 1, &d->xtest);
+        grid_map_onto(d, d->xtest, d->testcell);
+        d->prevnbi = 0;
+        d->prevcai = -1;
+    }
+    else
+    {
+        d->previ = -1;
+    }
+    d->exclind = 0;
+}
+
+/*! \brief
+ * Does a grid search.
+ */
+static bool
+grid_search(gmx_ana_nbsearch_t *d,
+            bool (*action)(gmx_ana_nbsearch_t *d, int i, real r2))
+{
+    int  i;
+    rvec dx;
+    real r2;
+
+    if (d->bGrid)
+    {
+        int  nbi, ci, cai;
+
+        nbi = d->prevnbi;
+        cai = d->prevcai + 1;
+
+        for ( ; nbi < d->ngridnb; ++nbi)
+        {
+            ivec cell;
+
+            ivec_add(d->testcell, d->gnboffs[nbi], cell);
+            /* TODO: Support for 2D and screw PBC */
+            cell[XX] = (cell[XX] + d->ncelldim[XX]) % d->ncelldim[XX];
+            cell[YY] = (cell[YY] + d->ncelldim[YY]) % d->ncelldim[YY];
+            cell[ZZ] = (cell[ZZ] + d->ncelldim[ZZ]) % d->ncelldim[ZZ];
+            ci = grid_index(d, cell);
+            /* TODO: Calculate the required PBC shift outside the inner loop */
+            for ( ; cai < d->ncatoms[ci]; ++cai)
+            {
+                i = d->catom[ci][cai];
+                if (is_excluded(d, i))
+                {
+                    continue;
+                }
+                pbc_dx_aiuc(d->pbc, d->xtest, d->xref[i], dx);
+                r2 = norm2(dx);
+                if (r2 <= d->cutoff2)
+                {
+                    if (action(d, i, r2))
+                    {
+                        d->prevnbi = nbi;
+                        d->prevcai = cai;
+                        d->previ   = i;
+                        return TRUE;
+                    }
+                }
+            }
+            d->exclind = 0;
+            cai = 0;
+        }
+    }
+    else
+    {
+        i = d->previ + 1;
+        for ( ; i < d->nref; ++i)
         {
-            return TRUE;
+            if (is_excluded(d, i))
+            {
+                continue;
+            }
+            if (d->pbc)
+            {
+                pbc_dx(d->pbc, d->xtest, d->xref[i], dx);
+            }
+            else
+            {
+                rvec_sub(d->xtest, d->xref[i], dx);
+            }
+            r2 = norm2(dx);
+            if (r2 <= d->cutoff2)
+            {
+                if (action(d, i, r2))
+                {
+                    d->previ = i;
+                    return TRUE;
+                }
+            }
         }
     }
     return FALSE;
 }
 
+/*! \brief
+ * Helper function to use with grid_search() to find the next neighbor.
+ *
+ * Simply breaks the loop on the first found neighbor.
+ */
+static bool
+within_action(gmx_ana_nbsearch_t *d, int i, real r2)
+{
+    return TRUE;
+}
+
+/*! \brief
+ * Helper function to use with grid_search() to find the minimum distance.
+ */
+static bool
+mindist_action(gmx_ana_nbsearch_t *d, int i, real r2)
+{
+    d->cutoff2 = r2;
+    return FALSE;
+}
+
+/*!
+ * \param[in] d   Neighborhood search data structure.
+ * \param[in] x   Test position.
+ * \returns   TRUE if \p x is within the cutoff of any reference position,
+ *   FALSE otherwise.
+ */
+bool
+gmx_ana_nbsearch_is_within(gmx_ana_nbsearch_t *d, rvec x)
+{
+    grid_search_start(d, x);
+    return grid_search(d, &within_action);
+}
+
 /*!
  * \param[in] d   Neighborhood search data structure.
  * \param[in] p   Test positions.
@@ -205,28 +725,13 @@ gmx_ana_nbsearch_pos_is_within(gmx_ana_nbsearch_t *d, gmx_ana_pos_t *p, int i)
 real
 gmx_ana_nbsearch_mindist(gmx_ana_nbsearch_t *d, rvec x)
 {
-    int  i;
-    rvec dx;
-    real d2, mind2;
+    real mind;
 
-    mind2 = d->cutoff2;
-    for (i = 0; i < d->nref; ++i)
-    {
-        if (d->pbc)
-        {
-            pbc_dx(d->pbc, x, d->xref[i], dx);
-        }
-        else
-        {
-            rvec_sub(x, d->xref[i], dx);
-        }
-        d2 = norm2(dx);
-        if (d2 < mind2)
-        {
-            mind2 = d2;
-        }
-    }
-    return sqrt(mind2);
+    grid_search_start(d, x);
+    grid_search(d, &mindist_action);
+    mind = sqrt(d->cutoff2);
+    d->cutoff2 = sqr(d->cutoff);
+    return mind;
 }
 
 /*!
@@ -241,3 +746,48 @@ gmx_ana_nbsearch_pos_mindist(gmx_ana_nbsearch_t *d, gmx_ana_pos_t *p, int i)
 {
     return gmx_ana_nbsearch_mindist(d, p->x[i]);
 }
+
+/*!
+ * \param[in]  d   Neighborhood search data structure.
+ * \param[in]  n   Number of test positions in \p x.
+ * \param[in]  x   Test positions.
+ * \param[out] jp  Index of the reference position in the first pair.
+ * \returns    TRUE if there are positions within the cutoff.
+ */
+bool
+gmx_ana_nbsearch_first_within(gmx_ana_nbsearch_t *d, rvec x, int *jp)
+{
+    grid_search_start(d, x);
+    return gmx_ana_nbsearch_next_within(d, jp);
+}
+
+/*!
+ * \param[in]  d   Neighborhood search data structure.
+ * \param[in]  p   Test positions.
+ * \param[in]  i   Use the i'th position in \p p.
+ * \param[out] jp  Index of the reference position in the first pair.
+ * \returns    TRUE if there are positions within the cutoff.
+ */
+bool
+gmx_ana_nbsearch_pos_first_within(gmx_ana_nbsearch_t *d, gmx_ana_pos_t *p,
+                                  int i, int *jp)
+{
+    return gmx_ana_nbsearch_first_within(d, p->x[i], jp);
+}
+
+/*!
+ * \param[in]  d   Neighborhood search data structure.
+ * \param[out] jp  Index of the test position in the next pair.
+ * \returns    TRUE if there are positions within the cutoff.
+ */
+bool
+gmx_ana_nbsearch_next_within(gmx_ana_nbsearch_t *d, int *jp)
+{
+    if (grid_search(d, &within_action))
+    {
+        *jp = d->previ;
+        return TRUE;
+    }
+    *jp = -1;
+    return FALSE;
+}
index 1a214ab0a13ce33d5f3a8a80ef343dc38cd048a2..21e4ea67c5d40cb04720ab6177959d638a230298 100644 (file)
@@ -1094,6 +1094,10 @@ void
 gmx_ana_poscalc_init_pos(gmx_ana_poscalc_t *pc, gmx_ana_pos_t *p)
 {
     gmx_ana_indexmap_init(&p->m, &pc->gmax, pc->coll->top, pc->itype);
+    if (!(pc->flags & POS_DYNAMIC))
+    {
+        gmx_ana_indexmap_set_static(&p->m, &pc->b);
+    }
     gmx_ana_pos_reserve(p, p->m.nr, 0);
     if (pc->flags & POS_VELOCITIES)
     {
@@ -1210,12 +1214,18 @@ gmx_ana_poscalc_init_eval(gmx_ana_poscalc_coll_t *pcc)
             }
         }
         /* Free the block data for dynamic calculations */
-        if ((pc->flags & POS_DYNAMIC) && pc->b.nalloc_index > 0)
+        if (pc->flags & POS_DYNAMIC)
         {
-            sfree(pc->b.index);
-            sfree(pc->b.a);
-            pc->b.nalloc_index = 0;
-            pc->b.nalloc_a     = 0;
+            if (pc->b.nalloc_index > 0)
+            {
+                sfree(pc->b.index);
+                pc->b.nalloc_index = 0;
+            }
+            if (pc->b.nalloc_a > 0)
+            {
+                sfree(pc->b.a);
+                pc->b.nalloc_a = 0;
+            }
         }
         pc = pc->next;
     }
index 6c5e149e8666f3b5c83b21720fd0b64cfc010a00..6f870821d9d42ab7ef127bf5390988e009f56b23 100644 (file)
@@ -176,17 +176,17 @@ struct gmx_ana_traj_t
     bool                      bPBC;
 
     /** Name of the trajectory file (NULL if not provided). */
-    const char               *trjfile;
+    char                     *trjfile;
     /** Name of the topology file (NULL if no topology loaded). */
-    const char               *topfile;
+    char                     *topfile;
     /** Non-NULL name of the topology file. */
-    const char               *topfile_notnull;
+    char                     *topfile_notnull;
     /** Name of the index file (NULL if no index file provided). */
-    const char               *ndxfile;
+    char                     *ndxfile;
     /** Name of the selection file (NULL if no file provided). */
-    const char               *selfile;
+    char                     *selfile;
     /** The selection string (NULL if not provided). */
-    const char               *selection;
+    char                     *selection;
 
     /** The topology structure, or \p NULL if no topology loaded. */
     t_topology               *top;
@@ -202,7 +202,7 @@ struct gmx_ana_traj_t
     /** The current frame, or \p NULL if no frame loaded yet. */
     t_trxframe               *fr;
     /** Used to store the status variable from read_first_frame(). */
-    int                       status;
+    t_trxstatus              *status;
     /** The number of frames read. */
     int                       nframes;
 
@@ -306,7 +306,7 @@ gmx_ana_traj_create(gmx_ana_traj_t **data, unsigned long flags)
         *data = NULL;
         return rc;
     }
-    d->status          = -1;
+    d->status          = NULL;
     d->oenv            = NULL;
 
     *data              = d;
@@ -321,6 +321,11 @@ gmx_ana_traj_free(gmx_ana_traj_t *d)
 {
     int                 i;
 
+    sfree(d->trjfile);
+    sfree(d->topfile);
+    sfree(d->topfile_notnull);
+    sfree(d->ndxfile);
+    sfree(d->selfile);
     if (d->top)
     {
         done_top(d->top);
@@ -339,6 +344,7 @@ gmx_ana_traj_free(gmx_ana_traj_t *d)
     gmx_ana_selcollection_free(d->sc);
     gmx_ana_poscalc_coll_free(d->pcc);
     sfree(d->grpnames);
+    output_env_done(d->oenv);
     sfree(d);
 }
 
@@ -682,6 +688,7 @@ parse_trjana_args(gmx_ana_traj_t *d,
     size_t              i;
     int                 k;
     int                 rc;
+    const char         *tmp_fnm;
 
     t_filenm            def_fnm[] = {
         {efTRX, NULL,  NULL,        ffOPTRD},
@@ -838,20 +845,15 @@ parse_trjana_args(gmx_ana_traj_t *d,
                       ndesc, desc, nbugs, bugs,oenv);
     d->oenv = *oenv;
 
-    /* Copy the results back */
-    for (k = 0; k < nfile; ++k)
-    {
-        memcpy(&(fnm[k]), &(all_fnm[fnm_map[k]]), sizeof(fnm[k]));
-    }
-    for (i = 0, k = npall - npargs; i < (size_t)npargs; ++i, ++k)
-    {
-        memcpy(&(pa[i]), &(all_pa[k]), sizeof(pa[i]));
-    }
-
-    d->trjfile         = ftp2fn_null(efTRX, nfall, all_fnm);
-    d->topfile         = ftp2fn_null(efTPS, nfall, all_fnm);
-    d->topfile_notnull = ftp2fn(efTPS, nfall, all_fnm);
-    d->ndxfile         = ftp2fn_null(efNDX, nfall, all_fnm);
+    /* Process our own options.
+     * Make copies of file names for easier memory management. */
+    tmp_fnm            = ftp2fn_null(efTRX, nfall, all_fnm);
+    d->trjfile         = tmp_fnm ? strdup(tmp_fnm) : NULL;
+    tmp_fnm            = ftp2fn_null(efTPS, nfall, all_fnm);
+    d->topfile         = tmp_fnm ? strdup(tmp_fnm) : NULL;
+    d->topfile_notnull = strdup(ftp2fn(efTPS, nfall, all_fnm));
+    tmp_fnm            = ftp2fn_null(efNDX, nfall, all_fnm);
+    d->ndxfile         = tmp_fnm ? strdup(tmp_fnm) : NULL;
     if (!(d->flags & ANA_NOUSER_RMPBC))
     {
         d->bRmPBC      = bRmPBC;
@@ -861,8 +863,24 @@ parse_trjana_args(gmx_ana_traj_t *d,
         d->bPBC        = bPBC;
     }
     d->selection       = selection;
-    d->selfile         = opt2fn_null("-sf", nfall, all_fnm);
+    tmp_fnm            = opt2fn_null("-sf", nfall, all_fnm);
+    d->selfile         = tmp_fnm ? strdup(tmp_fnm) : NULL;
 
+    /* Copy the results back */
+    for (k = 0; k < nfile; ++k)
+    {
+        memcpy(&(fnm[k]), &(all_fnm[fnm_map[k]]), sizeof(fnm[k]));
+        /* Delegate responsibility of freeing the file names to caller. */
+        all_fnm[fnm_map[k]].nfiles = 0;
+        all_fnm[fnm_map[k]].fns    = NULL;
+    }
+    for (i = 0, k = npall - npargs; i < (size_t)npargs; ++i, ++k)
+    {
+        memcpy(&(pa[i]), &(all_pa[k]), sizeof(pa[i]));
+    }
+
+    /* Free memory we have allocated. */
+    done_filenms(nfall, all_fnm);
     sfree(all_fnm);
     sfree(fnm_map);
     sfree(all_pa);
@@ -1596,7 +1614,8 @@ int gmx_ana_do(gmx_ana_traj_t *d, int flags, gmx_analysisfunc analyze, void *dat
     t_pbc               pbc;
     t_pbc              *ppbc;
     int                 rc;
-
+    gmx_rmpbc_t         gpbc=NULL;
+    
     rc = init_first_frame(d);
     if (rc != 0)
     {
@@ -1608,14 +1627,16 @@ int gmx_ana_do(gmx_ana_traj_t *d, int flags, gmx_analysisfunc analyze, void *dat
     {
         d->bRmPBC = FALSE;
     }
-
+    if (d->bRmPBC) 
+    {
+       gpbc = gmx_rmpbc_init(&d->top->idef,d->ePBC,d->fr->natoms,d->fr->box);
+    }
     d->nframes = 0;
     do
     {
         if (d->bRmPBC)
         {
-            rm_pbc(&d->top->idef, d->ePBC, d->fr->natoms, d->fr->box,
-                   d->fr->x, d->fr->x);
+           gmx_rmpbc(gpbc,d->fr->box,d->fr->x, d->fr->x);
         }
         if (ppbc)
         {
@@ -1640,7 +1661,10 @@ int gmx_ana_do(gmx_ana_traj_t *d, int flags, gmx_analysisfunc analyze, void *dat
         d->nframes++;
     }
     while (d->trjfile && read_next_frame(d->oenv, d->status, d->fr));
-
+    if (d->bRmPBC)
+    {
+        gmx_rmpbc_done(gpbc);
+    }
     if (d->trjfile)
     {
         close_trj(d->status);
index 933cc436a76fa132e906839969e48dccdf97ea1c..fc8042827ccb12ad1576335112ecbff9bd697052 100644 (file)
@@ -70,51 +70,53 @@ static int nFloatSize(t_trnheader *sh)
   return nflsize;
 }
 
-static bool do_trnheader(int fp,bool bRead,t_trnheader *sh, bool *bOK)
+static bool do_trnheader(t_fileio *fio,bool bRead,t_trnheader *sh, bool *bOK)
 {
-  const int magic=GROMACS_MAGIC;
-  const char *version = "GMX_trn_file";
+  int magic=GROMACS_MAGIC;
   static bool bFirst=TRUE;
   char buf[256];
   
   *bOK=TRUE;
 
-  gmx_fio_select(fp);
-  if (!do_int(magic))
+  gmx_fio_checktype(fio);
+
+  if (!gmx_fio_do_int(fio,magic) || magic!=GROMACS_MAGIC)
     return FALSE;
   
   if (bRead) {
-    *bOK = *bOK && do_string(buf);
+    *bOK = *bOK && gmx_fio_do_string(fio,buf);
     if (bFirst)
       fprintf(stderr,"trn version: %s ",buf);
   }
-  else
-    *bOK = *bOK && do_string(version);
-  *bOK = *bOK && do_int(sh->ir_size);
-  *bOK = *bOK && do_int(sh->e_size);
-  *bOK = *bOK && do_int(sh->box_size);
-  *bOK = *bOK && do_int(sh->vir_size);
-  *bOK = *bOK && do_int(sh->pres_size);
-  *bOK = *bOK && do_int(sh->top_size); 
-  *bOK = *bOK && do_int(sh->sym_size); 
-  *bOK = *bOK && do_int(sh->x_size); 
-  *bOK = *bOK && do_int(sh->v_size); 
-  *bOK = *bOK && do_int(sh->f_size); 
-  *bOK = *bOK && do_int(sh->natoms);
+  else {
+    sprintf(buf,"GMX_trn_file");
+    *bOK = *bOK && gmx_fio_do_string(fio,buf);
+  }
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->ir_size);
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->e_size);
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->box_size);
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->vir_size);
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->pres_size);
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->top_size); 
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->sym_size); 
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->x_size); 
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->v_size); 
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->f_size); 
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->natoms);
 
   if (!*bOK) return *bOK; 
   sh->bDouble = (nFloatSize(sh) == sizeof(double));
-  gmx_fio_setprecision(fp,sh->bDouble);
+  gmx_fio_setprecision(fio,sh->bDouble);
 
   if (bRead && bFirst) {
     fprintf(stderr,"(%s precision)\n",sh->bDouble ? "double" : "single");
     bFirst = FALSE;
   }
   
-  *bOK = *bOK && do_int(sh->step); 
-  *bOK = *bOK && do_int(sh->nre); 
-  *bOK = *bOK && do_real(sh->t); 
-  *bOK = *bOK && do_real(sh->lambda); 
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->step); 
+  *bOK = *bOK && gmx_fio_do_int(fio,sh->nre); 
+  *bOK = *bOK && gmx_fio_do_real(fio,sh->t); 
+  *bOK = *bOK && gmx_fio_do_real(fio,sh->lambda); 
   
   return *bOK;
 }
@@ -143,24 +145,24 @@ void pr_trnheader(FILE *fp,int indent,char *title,t_trnheader *sh)
   }
 }
 
-static bool do_htrn(int fp,bool bRead,t_trnheader *sh,
+static bool do_htrn(t_fileio *fio,bool bRead,t_trnheader *sh,
                    rvec *box,rvec *x,rvec *v,rvec *f)
 {
   matrix pv;
   bool bOK;
 
   bOK = TRUE;
-  if (sh->box_size != 0) bOK = bOK && ndo_rvec(box,DIM);
-  if (sh->vir_size != 0) bOK = bOK && ndo_rvec(pv,DIM);
-  if (sh->pres_size!= 0) bOK = bOK && ndo_rvec(pv,DIM);
-  if (sh->x_size   != 0) bOK = bOK && ndo_rvec(x,sh->natoms);
-  if (sh->v_size   != 0) bOK = bOK && ndo_rvec(v,sh->natoms);
-  if (sh->f_size   != 0) bOK = bOK && ndo_rvec(f,sh->natoms);
+  if (sh->box_size != 0) bOK = bOK && gmx_fio_ndo_rvec(fio,box,DIM);
+  if (sh->vir_size != 0) bOK = bOK && gmx_fio_ndo_rvec(fio,pv,DIM);
+  if (sh->pres_size!= 0) bOK = bOK && gmx_fio_ndo_rvec(fio,pv,DIM);
+  if (sh->x_size   != 0) bOK = bOK && gmx_fio_ndo_rvec(fio,x,sh->natoms);
+  if (sh->v_size   != 0) bOK = bOK && gmx_fio_ndo_rvec(fio,v,sh->natoms);
+  if (sh->f_size   != 0) bOK = bOK && gmx_fio_ndo_rvec(fio,f,sh->natoms);
 
   return bOK;
 }
 
-static bool do_trn(int fp,bool bRead,int *step,real *t,real *lambda,
+static bool do_trn(t_fileio *fio,bool bRead,int *step,real *t,real *lambda,
                   rvec *box,int *natoms,rvec *x,rvec *v,rvec *f)
 {
   t_trnheader *sh;
@@ -178,7 +180,7 @@ static bool do_trn(int fp,bool bRead,int *step,real *t,real *lambda,
     sh->t      = *t;
     sh->lambda = *lambda;
   }
-  if (!do_trnheader(fp,bRead,sh,&bOK))
+  if (!do_trnheader(fio,bRead,sh,&bOK))
     return FALSE;
   if (bRead) {
     *natoms = sh->natoms;
@@ -194,7 +196,7 @@ static bool do_trn(int fp,bool bRead,int *step,real *t,real *lambda,
     if (sh->sym_size)
       gmx_file("symbol table in trn file");
   }
-  bOK = do_htrn(fp,bRead,sh,box,x,v,f);
+  bOK = do_htrn(fio,bRead,sh,box,x,v,f);
 
   sfree(sh);
   
@@ -209,67 +211,68 @@ static bool do_trn(int fp,bool bRead,int *step,real *t,real *lambda,
  
 void read_trnheader(const char *fn,t_trnheader *trn)
 {
-  int  fp;
+  t_fileio *fio;
   bool bOK;
   
-  fp = open_trn(fn,"r");
-  if (!do_trnheader(fp,TRUE,trn,&bOK))
+  fio = open_trn(fn,"r");
+  if (!do_trnheader(fio,TRUE,trn,&bOK))
     gmx_fatal(FARGS,"Empty file %s",fn);
-  close_trn(fp);
+  close_trn(fio);
 }
 
-bool fread_trnheader(int fp,t_trnheader *trn, bool *bOK)
+bool fread_trnheader(t_fileio *fio,t_trnheader *trn, bool *bOK)
 {
-  return do_trnheader(fp,TRUE,trn,bOK);
+  return do_trnheader(fio,TRUE,trn,bOK);
 }
 
 void write_trn(const char *fn,int step,real t,real lambda,
               rvec *box,int natoms,rvec *x,rvec *v,rvec *f)
 {
-  int fp;
+  t_fileio *fio;
   
-  fp = open_trn(fn,"w");
-  do_trn(fp,FALSE,&step,&t,&lambda,box,&natoms,x,v,f);
-  close_trn(fp);
+  fio = open_trn(fn,"w");
+  do_trn(fio,FALSE,&step,&t,&lambda,box,&natoms,x,v,f);
+  close_trn(fio);
 }
 
 void read_trn(const char *fn,int *step,real *t,real *lambda,
              rvec *box,int *natoms,rvec *x,rvec *v,rvec *f)
 {
-  int fp;
+  t_fileio *fio;
   
-  fp = open_trn(fn,"r");
-  (void) do_trn(fp,TRUE,step,t,lambda,box,natoms,x,v,f);
-  close_trn(fp);
+  fio = open_trn(fn,"r");
+  (void) do_trn(fio,TRUE,step,t,lambda,box,natoms,x,v,f);
+  close_trn(fio);
 }
 
-void fwrite_trn(int fp,int step,real t,real lambda,
+void fwrite_trn(t_fileio *fio,int step,real t,real lambda,
                rvec *box,int natoms,rvec *x,rvec *v,rvec *f)
 {
-  if( do_trn(fp,FALSE,&step,&t,&lambda,box,&natoms,x,v,f) == FALSE)
+  if( do_trn(fio,FALSE,&step,&t,&lambda,box,&natoms,x,v,f) == FALSE)
   {
-         gmx_file("Cannot write trajectory frame; maybe you are out of quota?");
+      gmx_file("Cannot write trajectory frame; maybe you are out of quota?");
   }
 }
 
 
-bool fread_trn(int fp,int *step,real *t,real *lambda,
+bool fread_trn(t_fileio *fio,int *step,real *t,real *lambda,
               rvec *box,int *natoms,rvec *x,rvec *v,rvec *f)
 {
-  return do_trn(fp,TRUE,step,t,lambda,box,natoms,x,v,f);
+  return do_trn(fio,TRUE,step,t,lambda,box,natoms,x,v,f);
 }
 
-bool fread_htrn(int fp,t_trnheader *trn,rvec *box,rvec *x,rvec *v,rvec *f)
+bool fread_htrn(t_fileio *fio,t_trnheader *trn,rvec *box,rvec *x,rvec *v,
+                rvec *f)
 {
-  return do_htrn(fp,TRUE,trn,box,x,v,f);
+  return do_htrn(fio,TRUE,trn,box,x,v,f);
 }
 
-int open_trn(const char *fn,const char *mode)
+t_fileio *open_trn(const char *fn,const char *mode)
 {
   return gmx_fio_open(fn,mode);
 }
 
-void close_trn(int fp)
+void close_trn(t_fileio *fio)
 {
-  gmx_fio_close(fp);
+  gmx_fio_close(fio);
 }
index 3a7f6ec29c9e6af797ea05bd6074a14571d17216..d4c9f11032cff059d941249ff39c365592677d73 100644 (file)
 #include <math.h>
 
 /* defines for frame counter output */
-static int __frame=NOTSET;
 #define SKIP1   10
 #define SKIP2  100
 #define SKIP3 1000
-#define INITCOUNT __frame=-1
 
+/* Globals for gromos-87 input */
+typedef enum { effXYZ, effXYZBox, effG87, effG87Box, effNR } eFileFormat;
 
-/* frames for read_first/next_x */
-static t_trxframe *xframe=NULL;
-static int nxframe=0;
+struct t_trxstatus
+{
+    int __frame;
+    t_trxframe *xframe;
+    int nxframe;
+    t_fileio *fio;
+    eFileFormat eFF;
+    int         NATOMS;
+    double      DT,BOX[3];
+    bool        bReadBox;
+};
+
+static void initcount(t_trxstatus *status)
+{
+    status->__frame=-1;
+}
 
+static void status_init(t_trxstatus *status)
+{
+    status->nxframe=0;
+    status->xframe=NULL;
+    status->fio=NULL;
+    status->__frame=-1;
+}
 
-int nframes_read(void)
+
+int nframes_read(t_trxstatus *status)
 {
-  return __frame;
+    return status->__frame;
 }
 
-static void printcount_(const output_env_t oenv,const char *l,real t)
+static void printcount_(t_trxstatus *status, const output_env_t oenv,
+                        const char *l,real t)
 {
-  if ((__frame < 2*SKIP1 || __frame % SKIP1 == 0) &&
-      (__frame < 2*SKIP2 || __frame % SKIP2 == 0) &&
-      (__frame < 2*SKIP3 || __frame % SKIP3 == 0))
-    fprintf(stderr,"\r%-14s %6d time %8.3f   ",l,__frame,output_env_conv_time(oenv,t));
+  if ((status->__frame < 2*SKIP1 || status->__frame % SKIP1 == 0) &&
+      (status->__frame < 2*SKIP2 || status->__frame % SKIP2 == 0) &&
+      (status->__frame < 2*SKIP3 || status->__frame % SKIP3 == 0))
+    fprintf(stderr,"\r%-14s %6d time %8.3f   ",l,status->__frame,
+            output_env_conv_time(oenv,t));
 }
 
-static void printcount(const output_env_t oenv,real t,bool bSkip)
+static void printcount(t_trxstatus *status, const output_env_t oenv,real t,
+                       bool bSkip)
 {
-  __frame++;
-  printcount_(oenv,bSkip ? "Skipping frame" : "Reading frame",t);
+  status->__frame++;
+  printcount_(status, oenv,bSkip ? "Skipping frame" : "Reading frame",t);
 }
 
-static void printlast(const output_env_t oenv,real t)
+static void printlast(t_trxstatus *status, const output_env_t oenv,real t)
 {
-  printcount_(oenv,"Last frame",t);
+  printcount_(status, oenv,"Last frame",t);
   fprintf(stderr,"\n");
 }
 
-static void printincomp(t_trxframe *fr)
+static void printincomp(t_trxstatus *status, t_trxframe *fr)
 {
   if (fr->not_ok & HEADER_NOT_OK)
     fprintf(stderr,"WARNING: Incomplete header: nr %d time %g\n",
-           __frame+1,fr->time);
+           status->__frame+1,fr->time);
   else if (fr->not_ok)
     fprintf(stderr,"WARNING: Incomplete frame: nr %d time %g\n",
-           __frame+1,fr->time);
+           status->__frame+1,fr->time);
 }
 
 int prec2ndec(real prec)
@@ -112,12 +136,13 @@ int prec2ndec(real prec)
   return (int)(log(prec)/log(10.0)+0.5);
 }
 
-/* Globals for gromos-87 input */
-typedef enum { effXYZ, effXYZBox, effG87, effG87Box, effNR } eFileFormat;
-static eFileFormat eFF;
-static int         NATOMS;
-static double      DT,BOX[3];
-static bool        bReadBox;
+
+t_fileio *trx_get_fileio(t_trxstatus *status)
+{
+    return status->fio;
+}
+
+
 
 void clear_trxframe(t_trxframe *fr,bool bFirst)
 {
@@ -160,8 +185,8 @@ void set_trxframe_ePBC(t_trxframe *fr,int ePBC)
   fr->ePBC = ePBC;
 }
 
-int write_trxframe_indexed(int fnum,t_trxframe *fr,int nind,atom_id *ind,
-                          gmx_conect gc)
+int write_trxframe_indexed(t_trxstatus *status,t_trxframe *fr,int nind,
+                           atom_id *ind, gmx_conect gc)
 {
   char title[STRLEN];
   rvec *xout=NULL,*vout=NULL,*fout=NULL;
@@ -173,18 +198,18 @@ int write_trxframe_indexed(int fnum,t_trxframe *fr,int nind,atom_id *ind,
   else
     prec = 1000.0;
   
-  switch (gmx_fio_getftp(fnum)) {
+  switch (gmx_fio_getftp(status->fio)) {
   case efTRJ:
   case efTRR:
     break;
   default:
     if (!fr->bX)
       gmx_fatal(FARGS,"Need coordinates to write a %s trajectory",
-                 ftp2ext(gmx_fio_getftp(fnum)));
+                 ftp2ext(gmx_fio_getftp(status->fio)));
     break;
   }
 
-  switch (gmx_fio_getftp(fnum)) {
+  switch (gmx_fio_getftp(status->fio)) {
   case efTRJ:
   case efTRR:
     if (fr->bV) {
@@ -209,13 +234,13 @@ int write_trxframe_indexed(int fnum,t_trxframe *fr,int nind,atom_id *ind,
     break;
   }
 
-  switch (gmx_fio_getftp(fnum)) {
+  switch (gmx_fio_getftp(status->fio)) {
   case efXTC: 
-    write_xtc(fnum,nind,fr->step,fr->time,fr->box,xout,prec);
+    write_xtc(status->fio,nind,fr->step,fr->time,fr->box,xout,prec);
     break;
   case efTRJ:
   case efTRR:  
-    fwrite_trn(fnum,nframes_read(),
+    fwrite_trn(status->fio,nframes_read(status),
               fr->time,fr->step,fr->box,nind,xout,vout,fout);
     break;
   case efGRO:
@@ -224,29 +249,29 @@ int write_trxframe_indexed(int fnum,t_trxframe *fr,int nind,atom_id *ind,
   case efENT:
     if (!fr->bAtoms)
       gmx_fatal(FARGS,"Can not write a %s file without atom names",
-                 ftp2ext(gmx_fio_getftp(fnum)));
+                 ftp2ext(gmx_fio_getftp(status->fio)));
     sprintf(title,"frame t= %.3f",fr->time);
-    if (gmx_fio_getftp(fnum) == efGRO)
-      write_hconf_indexed_p(gmx_fio_getfp(fnum),title,fr->atoms,nind,ind,
+    if (gmx_fio_getftp(status->fio) == efGRO)
+      write_hconf_indexed_p(gmx_fio_getfp(status->fio),title,fr->atoms,nind,ind,
                            prec2ndec(prec),
                            fr->x,fr->bV ? fr->v : NULL,fr->box);
     else
-      write_pdbfile_indexed(gmx_fio_getfp(fnum),title,fr->atoms,
+      write_pdbfile_indexed(gmx_fio_getfp(status->fio),title,fr->atoms,
                            fr->x,-1,fr->box,0,fr->step,nind,ind,gc);
     break;
   case efG87:
-    write_gms(gmx_fio_getfp(fnum),nind,xout,fr->box);
+    write_gms(gmx_fio_getfp(status->fio),nind,xout,fr->box);
     break;
   case efG96:
-    write_g96_conf(gmx_fio_getfp(fnum),fr,nind,ind); 
+    write_g96_conf(gmx_fio_getfp(status->fio),fr,nind,ind); 
     break;
   default:
     gmx_fatal(FARGS,"Sorry, write_trxframe_indexed can not write %s",
-               ftp2ext(gmx_fio_getftp(fnum)));
+               ftp2ext(gmx_fio_getftp(status->fio)));
     break;
   }
 
-  switch (gmx_fio_getftp(fnum)) {
+  switch (gmx_fio_getftp(status->fio)) {
   case efTRN:
   case efTRJ:
   case efTRR:
@@ -263,7 +288,7 @@ int write_trxframe_indexed(int fnum,t_trxframe *fr,int nind,atom_id *ind,
   return 0;
 }
 
-int write_trxframe(int fnum,t_trxframe *fr,gmx_conect gc)
+int write_trxframe(t_trxstatus *status,t_trxframe *fr,gmx_conect gc)
 {
   char title[STRLEN];
   real prec;
@@ -273,24 +298,24 @@ int write_trxframe(int fnum,t_trxframe *fr,gmx_conect gc)
   else
     prec = 1000.0;
 
-  switch (gmx_fio_getftp(fnum)) {
+  switch (gmx_fio_getftp(status->fio)) {
   case efTRJ:
   case efTRR:
     break;
   default:
     if (!fr->bX)
       gmx_fatal(FARGS,"Need coordinates to write a %s trajectory",
-                 ftp2ext(gmx_fio_getftp(fnum)));
+                 ftp2ext(gmx_fio_getftp(status->fio)));
     break;
   }
 
-  switch (gmx_fio_getftp(fnum)) {
+  switch (gmx_fio_getftp(status->fio)) {
   case efXTC:
-    write_xtc(fnum,fr->natoms,fr->step,fr->time,fr->box,fr->x,prec);
+    write_xtc(status->fio,fr->natoms,fr->step,fr->time,fr->box,fr->x,prec);
     break;
   case efTRJ:
   case efTRR:  
-    fwrite_trn(fnum,fr->step,fr->time,fr->lambda,fr->box,fr->natoms,
+    fwrite_trn(status->fio,fr->step,fr->time,fr->lambda,fr->box,fr->natoms,
               fr->bX ? fr->x:NULL,fr->bV ? fr->v:NULL ,fr->bF ? fr->f:NULL);
     break;
   case efGRO:
@@ -299,32 +324,32 @@ int write_trxframe(int fnum,t_trxframe *fr,gmx_conect gc)
   case efENT:
     if (!fr->bAtoms)
       gmx_fatal(FARGS,"Can not write a %s file without atom names",
-                 ftp2ext(gmx_fio_getftp(fnum)));
+                 ftp2ext(gmx_fio_getftp(status->fio)));
     sprintf(title,"frame t= %.3f",fr->time);
-    if (gmx_fio_getftp(fnum) == efGRO)
-      write_hconf_p(gmx_fio_getfp(fnum),title,fr->atoms,
+    if (gmx_fio_getftp(status->fio) == efGRO)
+      write_hconf_p(gmx_fio_getfp(status->fio),title,fr->atoms,
                    prec2ndec(prec),fr->x,fr->bV ? fr->v : NULL,fr->box);
     else
-      write_pdbfile(gmx_fio_getfp(fnum),title,
+      write_pdbfile(gmx_fio_getfp(status->fio),title,
                    fr->atoms,fr->x,fr->bPBC ? fr->ePBC : -1,fr->box,
                    0,fr->step,gc);
     break;
   case efG87:
-    write_gms(gmx_fio_getfp(fnum),fr->natoms,fr->x,fr->box);
+    write_gms(gmx_fio_getfp(status->fio),fr->natoms,fr->x,fr->box);
     break;
   case efG96:
-    write_g96_conf(gmx_fio_getfp(fnum),fr,-1,NULL); 
+    write_g96_conf(gmx_fio_getfp(status->fio),fr,-1,NULL); 
     break;
   default:
     gmx_fatal(FARGS,"Sorry, write_trxframe can not write %s",
-               ftp2ext(gmx_fio_getftp(fnum)));
+               ftp2ext(gmx_fio_getftp(status->fio)));
     break;
   }
 
   return 0;
 }
 
-int write_trx(int fnum,int nind,atom_id *ind,t_atoms *atoms,
+int write_trx(t_trxstatus *status,int nind,atom_id *ind,t_atoms *atoms,
              int step,real time,matrix box,rvec x[],rvec *v,
              gmx_conect gc)
 {
@@ -344,30 +369,36 @@ int write_trx(int fnum,int nind,atom_id *ind,t_atoms *atoms,
   fr.bBox = TRUE;
   copy_mat(box,fr.box);
   
-  return write_trxframe_indexed(fnum,&fr,nind,ind,gc);
+  return write_trxframe_indexed(status,&fr,nind,ind,gc);
 }
 
-void close_trx(int status)
+void close_trx(t_trxstatus *status)
 {
-  gmx_fio_close(status);
+  gmx_fio_close(status->fio);
+  sfree(status);
 }
 
-int open_trx(const char *outfile,const char *filemode)
+t_trxstatus *open_trx(const char *outfile,const char *filemode)
 {
-  if (filemode[0]!='w' && filemode[0]!='a' && filemode[1]!='+')
-    gmx_fatal(FARGS,"Sorry, write_trx can only write");
+    t_trxstatus *stat;
+    if (filemode[0]!='w' && filemode[0]!='a' && filemode[1]!='+')
+        gmx_fatal(FARGS,"Sorry, write_trx can only write");
+
+    snew(stat,1);
+    status_init(stat);
 
-  return gmx_fio_open(outfile,filemode);
+    stat->fio=gmx_fio_open(outfile,filemode);
+    return stat;
 }
 
-static bool gmx_next_frame(int status,t_trxframe *fr)
+static bool gmx_next_frame(t_trxstatus *status,t_trxframe *fr)
 {
   t_trnheader sh;
   bool bOK,bRet;
   
   bRet = FALSE;
 
-  if (fread_trnheader(status,&sh,&bOK)) {
+  if (fread_trnheader(status->fio,&sh,&bOK)) {
     fr->bDouble=sh.bDouble;
     fr->natoms=sh.natoms;
     fr->bStep=TRUE;
@@ -392,7 +423,7 @@ static bool gmx_next_frame(int status,t_trxframe *fr)
        snew(fr->f,sh.natoms);
       fr->bF = sh.f_size>0;
     }
-    if (fread_htrn(status,&sh,fr->box,fr->x,fr->v,fr->f))
+    if (fread_htrn(status->fio,&sh,fr->box,fr->x,fr->v,fr->f))
       bRet = TRUE;
     else
       fr->not_ok = DATA_NOT_OK;
@@ -403,10 +434,12 @@ static bool gmx_next_frame(int status,t_trxframe *fr)
   return bRet;    
 }
 
-static void choose_ff(FILE *status)
+static void choose_ff(FILE *fp)
 {
   int i,m,c;
   int rc;
+  eFileFormat eFF;
+  t_trxstatus *stat;
 
   printf("\n\n");
   printf("   Select File Format\n");
@@ -416,6 +449,9 @@ static void choose_ff(FILE *status)
   printf("3. Gromos-87 Ascii Trajectory\n");
   printf("4. Gromos-87 Ascii Trajectory with Box\n");
 
+  snew(stat,1);
+  status_init(stat);
+
   do {
     printf("\nChoice: ");
     fflush(stdout);
@@ -428,16 +464,16 @@ static void choose_ff(FILE *status)
   } while ((i < 0) || (i >= effNR));
   printf("\n");
   
-  eFF = (eFileFormat) i;
+  stat->eFF = (eFileFormat) i;
 
-  for(m=0; (m<DIM); m++) BOX[m]=0;
+  for(m=0; (m<DIM); m++) stat->BOX[m]=0;
   
-  bReadBox = (eFF == effG87Box) || (eFF == effXYZBox);
+  stat->bReadBox = (stat->eFF == effG87Box) || (stat->eFF == effXYZBox);
     
-  switch (eFF) {
+  switch (stat->eFF) {
   case effXYZ:
   case effXYZBox:
-    if( 5 != fscanf(status,"%d%lf%lf%lf%lf",&NATOMS,&BOX[XX],&BOX[YY],&BOX[ZZ],&DT)) 
+    if( 5 != fscanf(fp,"%d%lf%lf%lf%lf",&stat->NATOMS,&stat->BOX[XX],&stat->BOX[YY],&stat->BOX[ZZ],&stat->DT)) 
     {
       gmx_fatal(FARGS,"Error reading natoms/box in file");
     }
@@ -447,28 +483,28 @@ static void choose_ff(FILE *status)
     printf("GROMOS! OH DEAR...\n\n");
     printf("Number of atoms ? ");
     fflush(stdout);
-    if (1 != scanf("%d",&NATOMS))
+    if (1 != scanf("%d",&stat->NATOMS))
     {
        gmx_fatal(FARGS,"Error reading natoms in file");
     }
 
     printf("Time between timeframes ? ");
     fflush(stdout);
-    if( 1 != scanf("%lf",&DT))
+    if( 1 != scanf("%lf",&stat->DT))
     {
        gmx_fatal(FARGS,"Error reading dt from file");
     }
 
-    if (eFF == effG87) {
+    if (stat->eFF == effG87) {
       printf("Box X Y Z ? ");
       fflush(stdout);
-      if(3 != scanf("%lf%lf%lf",&BOX[XX],&BOX[YY],&BOX[ZZ]))
+      if(3 != scanf("%lf%lf%lf",&stat->BOX[XX],&stat->BOX[YY],&stat->BOX[ZZ]))
       { 
          gmx_fatal(FARGS,"Error reading box in file");
       }
     }
     do {
-      c=fgetc(status);
+      c=fgetc(fp);
       printf("%c",c);
     } while (c != '\n');
     printf("\n");
@@ -479,14 +515,15 @@ static void choose_ff(FILE *status)
   }
 }
 
-static bool do_read_xyz(FILE *status,int natoms,rvec x[],matrix box)
+static bool do_read_xyz(t_trxstatus *status, FILE *fp,int natoms,
+                        rvec x[],matrix box)
 {
   int    i,m;
   double x0;
 
   for(i=0; (i<natoms); i++) {
     for(m=0; (m<DIM); m++) {
-      if (fscanf(status,"%lf",&x0) != 1) {
+      if (fscanf(fp,"%lf",&x0) != 1) {
        if (i || m)
          fprintf(stderr,"error reading statusfile: x[%d][%d]\n",i,m);
        /* else eof! */
@@ -495,9 +532,9 @@ static bool do_read_xyz(FILE *status,int natoms,rvec x[],matrix box)
       x[i][m]=x0;
     }
   }
-  if (bReadBox) {
+  if (status->bReadBox) {
     for(m=0; (m<DIM); m++) {
-      if (fscanf(status,"%lf",&x0) != 1) 
+      if (fscanf(fp,"%lf",&x0) != 1) 
        return FALSE;
       box[m][m]=x0;
     }
@@ -505,7 +542,7 @@ static bool do_read_xyz(FILE *status,int natoms,rvec x[],matrix box)
   return TRUE;
 }
 
-static bool xyz_next_x(FILE *status, const output_env_t oenv,
+static bool xyz_next_x(t_trxstatus *status, FILE *fp, const output_env_t oenv,
                        real *t, int natoms, rvec x[], matrix box)
      /* Reads until a new x can be found (return TRUE)
       * or eof (return FALSE)
@@ -515,52 +552,52 @@ static bool xyz_next_x(FILE *status, const output_env_t oenv,
   
   pt=*t;
   while (!bTimeSet(TBEGIN) || (*t < rTimeValue(TBEGIN))) {
-    if (!do_read_xyz(status,natoms,x,box))
+    if (!do_read_xyz(status,fp,natoms,x,box))
       return FALSE;
-    printcount(oenv,*t,FALSE);
-    *t+=DT;
+    printcount(status,oenv,*t,FALSE);
+    *t+=status->DT;
     pt=*t;
   }
   if (!bTimeSet(TEND) || (*t <= rTimeValue(TEND))) {
-    if (!do_read_xyz(status,natoms,x,box)) {
-      printlast(oenv,*t);
+    if (!do_read_xyz(status,fp,natoms,x,box)) {
+      printlast(status, oenv,*t);
       return FALSE;
     }
-    printcount(oenv,*t,FALSE);
+    printcount(status,oenv,*t,FALSE);
     pt=*t;
-    *t+=DT;
+    *t+=status->DT;
     return TRUE;
   }
-  printlast(oenv,pt);
+  printlast(status,oenv,pt);
   return FALSE;
 }
 
-static int xyz_first_x(FILE *status, const output_env_t oenv, 
+static int xyz_first_x(t_trxstatus *status, FILE *fp, const output_env_t oenv, 
                        real *t, rvec **x, matrix box)
-/* Reads status, mallocs x, and returns x and box
- * Returns natoms when succesful, FALSE otherwise
+/* Reads fp, mallocs x, and returns x and box
+ * Returns natoms when successful, FALSE otherwise
  */
 {
   int    m;
   
-  INITCOUNT;
+  initcount(status);
 
   clear_mat(box);
-  choose_ff(status);
+  choose_ff(fp);
 
   for(m=0; (m<DIM); m++)
-    box[m][m]=BOX[m];
+    box[m][m]=status->BOX[m];
 
-  snew(*x,NATOMS);
-  *t=DT;
-  if (!xyz_next_x(status,oenv,t,NATOMS,*x,box)) 
+  snew(*x,status->NATOMS);
+  *t=status->DT;
+  if (!xyz_next_x(status, fp,oenv,t,status->NATOMS,*x,box)) 
     return 0;
   *t=0.0;
   
-  return NATOMS;
+  return status->NATOMS;
 }
 
-static bool pdb_next_x(FILE *status,t_trxframe *fr)
+static bool pdb_next_x(t_trxstatus *status, FILE *fp,t_trxframe *fr)
 {
   t_atoms   atoms;
   matrix    boxpdb;
@@ -573,9 +610,9 @@ static bool pdb_next_x(FILE *status,t_trxframe *fr)
   atoms.pdbinfo=NULL;
   /* the other pointers in atoms should not be accessed if these are NULL */
   model_nr=NOTSET;
-  na=read_pdbfile(status,title,&model_nr,&atoms,fr->x,&ePBC,boxpdb,TRUE,NULL);
+  na=read_pdbfile(fp,title,&model_nr,&atoms,fr->x,&ePBC,boxpdb,TRUE,NULL);
   set_trxframe_ePBC(fr,ePBC);
-  if (nframes_read()==0)
+  if (nframes_read(status)==0)
     fprintf(stderr," '%s', %d atoms\n",title, fr->natoms);
   fr->bPrec = TRUE;
   fr->prec = 10000;
@@ -601,39 +638,40 @@ static bool pdb_next_x(FILE *status,t_trxframe *fr)
     if (fr->bStep)
       fr->time=(real)fr->step;
     else
-      fr->time=(real)nframes_read();
+      fr->time=(real)nframes_read(status);
   }
   if (na == 0) {
     return FALSE;
   } else { 
     if (na != fr->natoms)
       gmx_fatal(FARGS,"Number of atoms in pdb frame %d is %d instead of %d",
-                 nframes_read(),na,fr->natoms);
+                 nframes_read(status),na,fr->natoms);
     return TRUE;
   }
 }
 
-static int pdb_first_x(FILE *status, t_trxframe *fr)
+static int pdb_first_x(t_trxstatus *status, FILE *fp, t_trxframe *fr)
 {
-  INITCOUNT;
+  initcount(status);
   
   fprintf(stderr,"Reading frames from pdb file");
-  frewind(status);
-  get_pdb_coordnum(status, &fr->natoms);
+  frewind(fp);
+  get_pdb_coordnum(fp, &fr->natoms);
   if (fr->natoms==0)
     gmx_fatal(FARGS,"\nNo coordinates in pdb file\n");
-  frewind(status);
+  frewind(fp);
   snew(fr->x,fr->natoms);
-  pdb_next_x(status, fr);
+  pdb_next_x(status, fp, fr);
 
   return fr->natoms;
 }
 
-bool read_next_frame(const output_env_t oenv,int status,t_trxframe *fr)
+bool read_next_frame(const output_env_t oenv,t_trxstatus *status,t_trxframe *fr)
 {
   real pt;
   int  ct;
   bool bOK,bRet,bMissingData=FALSE,bSkip=FALSE;
+  int dummy=0;
 
   bRet = FALSE;
   pt=fr->time; 
@@ -643,7 +681,7 @@ bool read_next_frame(const output_env_t oenv,int status,t_trxframe *fr)
     fr->tppf = fr->tpf;
     fr->tpf  = fr->time;
     
-    switch (gmx_fio_getftp(status)) {
+    switch (gmx_fio_getftp(status->fio)) {
     case efTRJ:
     case efTRR:
         bRet = gmx_next_frame(status,fr);
@@ -652,12 +690,12 @@ bool read_next_frame(const output_env_t oenv,int status,t_trxframe *fr)
       /* Checkpoint files can not contain mulitple frames */
       break;
     case efG96:
-      read_g96_conf(gmx_fio_getfp(status),NULL,fr);
+      read_g96_conf(gmx_fio_getfp(status->fio),NULL,fr);
       bRet = (fr->natoms > 0);
       break;
     case efG87:
-      bRet = xyz_next_x(gmx_fio_getfp(status),oenv,&fr->time,fr->natoms,
-                        fr->x,fr->box);
+      bRet = xyz_next_x(status, gmx_fio_getfp(status->fio),oenv,&fr->time,
+                        fr->natoms, fr->x,fr->box);
       fr->bTime = bRet;
       fr->bX    = bRet;
       fr->bBox  = bRet;
@@ -671,12 +709,12 @@ bool read_next_frame(const output_env_t oenv,int status,t_trxframe *fr)
        * accuracy of the control over -b and -e options.
        */
         if (bTimeSet(TBEGIN) && (fr->time < rTimeValue(TBEGIN))) {
-            if (xtc_seek_time(rTimeValue(TBEGIN),status,fr->natoms)) {
+            if (xtc_seek_time(status->fio, rTimeValue(TBEGIN),fr->natoms)) {
                 gmx_fatal(FARGS,"Specified frame doesn't exist or file not seekable");
             }
-            INITCOUNT;
+            initcount(status);
         }
-      bRet = read_next_xtc(status,fr->natoms,&fr->step,&fr->time,fr->box,
+      bRet = read_next_xtc(status->fio,fr->natoms,&fr->step,&fr->time,fr->box,
                           fr->x,&fr->prec,&bOK);
       fr->bPrec = (bRet && fr->prec > 0);
       fr->bStep = bRet;
@@ -690,17 +728,18 @@ bool read_next_frame(const output_env_t oenv,int status,t_trxframe *fr)
       }
       break;
     case efPDB:
-      bRet = pdb_next_x(gmx_fio_getfp(status),fr);
+      bRet = pdb_next_x(status, gmx_fio_getfp(status->fio),fr);
       break;
     case efGRO:
-      bRet = gro_next_x_or_v(gmx_fio_getfp(status),fr);
+      bRet = gro_next_x_or_v(gmx_fio_getfp(status->fio),fr);
       break;
     default:
 #ifdef GMX_DLOPEN
-      bRet = read_next_vmd_frame(status,fr);
+      bRet = read_next_vmd_frame(dummy,fr);
 #else
-      gmx_fatal(FARGS,"DEATH HORROR in read_next_frame ftp=%s,status=%d",
-                ftp2ext(gmx_fio_getftp(status)),status);
+      gmx_fatal(FARGS,"DEATH HORROR in read_next_frame ftp=%s,status=%s",
+                ftp2ext(gmx_fio_getftp(status->fio)),
+                gmx_fio_getname(status->fio));
 #endif
     }
     
@@ -712,11 +751,11 @@ bool read_next_frame(const output_env_t oenv,int status,t_trxframe *fr)
       if (!bMissingData) {
        ct=check_times2(fr->time,fr->t0,fr->tpf,fr->tppf,fr->bDouble);
        if (ct == 0 || (fr->flags & TRX_DONT_SKIP && ct<0)) {
-         printcount(oenv,fr->time,FALSE);
+         printcount(status, oenv,fr->time,FALSE);
        } else if (ct > 0)
          bRet = FALSE;
        else {
-         printcount(oenv,fr->time,TRUE);
+         printcount(status, oenv,fr->time,TRUE);
          bSkip = TRUE;
        }
       }
@@ -725,59 +764,66 @@ bool read_next_frame(const output_env_t oenv,int status,t_trxframe *fr)
   } while (bRet && (bMissingData || bSkip));
   
   if (!bRet) {
-    printlast(oenv,pt);
+    printlast(status, oenv,pt);
     if (fr->not_ok)
-      printincomp(fr);
+      printincomp(status, fr);
   }
   
   return bRet;
 }
 
-int read_first_frame(const output_env_t oenv,int *status,
+int read_first_frame(const output_env_t oenv,t_trxstatus **status,
                      const char *fn,t_trxframe *fr,int flags)
 {
-  int  fp;
+  t_fileio *fio;
   bool bFirst,bOK;
+  int dummy=0;
 
   clear_trxframe(fr,TRUE);
   fr->flags = flags;
 
   bFirst = TRUE;
-  INITCOUNT;
+
+  snew((*status), 1);
+
+  status_init( *status );
+  (*status)->nxframe=1;
+  initcount(*status);
   
-  fp = *status =gmx_fio_open(fn,"r");
-  switch (gmx_fio_getftp(fp)) 
+  fio = (*status)->fio =gmx_fio_open(fn,"r");
+  switch (gmx_fio_getftp(fio)) 
   {
   case efTRJ:
   case efTRR:
     break;
   case efCPT:
-    read_checkpoint_trxframe(fp,fr);
+    read_checkpoint_trxframe(fio,fr);
     bFirst = FALSE;
     break;
   case efG96:
     /* Can not rewind a compressed file, so open it twice */
-    read_g96_conf(gmx_fio_getfp(fp),fn,fr);
-    gmx_fio_close(fp);
+    read_g96_conf(gmx_fio_getfp(fio),fn,fr);
+    gmx_fio_close(fio);
     clear_trxframe(fr,FALSE);
     if (flags & (TRX_READ_X | TRX_NEED_X))
       snew(fr->x,fr->natoms);
     if (flags & (TRX_READ_V | TRX_NEED_V))
       snew(fr->v,fr->natoms);
-    fp = *status =gmx_fio_open(fn,"r");
+    fio = (*status)->fio =gmx_fio_open(fn,"r");
     break;
   case efG87:
-    fr->natoms=xyz_first_x(gmx_fio_getfp(fp),oenv,&fr->time,&fr->x,fr->box);
+    fr->natoms=xyz_first_x(*status, gmx_fio_getfp(fio),oenv,&fr->time,
+                           &fr->x,fr->box);
     if (fr->natoms) {
       fr->bTime = TRUE;
       fr->bX    = TRUE;
       fr->bBox  = TRUE;
-      printcount(oenv,fr->time,FALSE);
+      printcount(*status,oenv,fr->time,FALSE);
     }
     bFirst = FALSE;
     break;
   case efXTC:
-    if (read_first_xtc(fp,&fr->natoms,&fr->step,&fr->time,fr->box,&fr->x,
+    if (read_first_xtc(fio,&fr->natoms,&fr->step,&fr->time,fr->box,&fr->x,
                       &fr->prec,&bOK) == 0) {
       if (bOK) {
        gmx_fatal(FARGS,"No XTC!\n");
@@ -787,32 +833,32 @@ int read_first_frame(const output_env_t oenv,int *status,
     }
     if (fr->not_ok) {
       fr->natoms = 0;
-      printincomp(fr);
+      printincomp(*status,fr);
     } else {
       fr->bPrec = (fr->prec > 0);
       fr->bStep = TRUE;
       fr->bTime = TRUE;
       fr->bX    = TRUE;
       fr->bBox  = TRUE;
-      printcount(oenv,fr->time,FALSE);
+      printcount(*status,oenv,fr->time,FALSE);
     }
     bFirst = FALSE;
     break;
   case efPDB:
-    pdb_first_x(gmx_fio_getfp(fp),fr);
+    pdb_first_x(*status, gmx_fio_getfp(fio),fr);
     if (fr->natoms)
-      printcount(oenv,fr->time,FALSE);
+      printcount(*status,oenv,fr->time,FALSE);
     bFirst = FALSE;
     break;
   case efGRO:
-    if (gro_first_x_or_v(gmx_fio_getfp(fp),fr))
-      printcount(oenv,fr->time,FALSE);
+    if (gro_first_x_or_v(gmx_fio_getfp(fio),fr))
+      printcount(*status,oenv,fr->time,FALSE);
     bFirst = FALSE;
     break;
   default:
 #ifdef GMX_DLOPEN
-      gmx_fio_fp_close(fp); /*only close the file without removing FIO entry*/
-      if (!read_first_vmd_frame(status,fn,fr,flags))
+      gmx_fio_fp_close(fio); /*only close the file without removing FIO entry*/
+      if (!read_first_vmd_frame(&dummy,fn,fr,flags))
       {
          gmx_fatal(FARGS,"Not supported in read_first_frame: %s",fn);
       }
@@ -821,6 +867,12 @@ int read_first_frame(const output_env_t oenv,int *status,
 #endif
       break;
   }
+
+  /* Return FALSE if we read a frame that's past the set ending time. */
+  if (!bFirst && (!(fr->flags & TRX_DONT_SKIP) && check_times(fr->time) > 0)) {
+    fr->t0 = fr->time;
+    return FALSE;
+  }
   
   if (bFirst || 
       (!(fr->flags & TRX_DONT_SKIP) && check_times(fr->time) < 0))
@@ -834,47 +886,47 @@ int read_first_frame(const output_env_t oenv,int *status,
 
 /***** C O O R D I N A T E   S T U F F *****/
 
-int read_first_x(const output_env_t oenv,int *status,const char *fn,
+int read_first_x(const output_env_t oenv,t_trxstatus **status,const char *fn,
                 real *t,rvec **x,matrix box)
 {
   t_trxframe fr;
 
   read_first_frame(oenv,status,fn,&fr,TRX_NEED_X);
-  if (*status >= nxframe) {
-    nxframe = *status+1;
-    srenew(xframe,nxframe);
-  }
-  xframe[*status] = fr;
-  *t = xframe[*status].time;
-  *x = xframe[*status].x;
-  copy_mat(xframe[*status].box,box);
+
+  snew((*status)->xframe, 1);
+  (*status)->nxframe=1;
+  (*(*status)->xframe) = fr;
+  *t = (*status)->xframe->time;
+  *x = (*status)->xframe->x;
+  copy_mat((*status)->xframe->box,box);
   
-  return xframe[*status].natoms;
+  return (*status)->xframe->natoms;
 }
 
-bool read_next_x(const output_env_t oenv, int status,real *t, int natoms
-                 rvec x[], matrix box)
+bool read_next_x(const output_env_t oenv, t_trxstatus *status,real *t
+                 int natoms, rvec x[], matrix box)
 {
   bool bRet;
-  
-  xframe[status].x = x;
-  bRet = read_next_frame(oenv,status,&xframe[status]);
-  *t = xframe[status].time;
-  copy_mat(xframe[status].box,box);
+  status->xframe->x= x;
+  /*xframe[status].x = x;*/
+  bRet = read_next_frame(oenv,status,status->xframe);
+  *t = status->xframe->time;
+  copy_mat(status->xframe->box,box);
   
   return bRet;
 }
 
-void close_trj(int status)
+void close_trj(t_trxstatus *status)
 {
-    gmx_fio_close(status);
+    gmx_fio_close(status->fio);
 }
 
-void rewind_trj(int status)
+void rewind_trj(t_trxstatus *status)
 {
-  INITCOUNT;
+  initcount(status);
   
-  gmx_fio_rewind(status);
+  gmx_fio_rewind(status->fio);
 }
 
 /***** V E L O C I T Y   S T U F F *****/
@@ -888,8 +940,8 @@ static void clear_v(t_trxframe *fr)
       clear_rvec(fr->v[i]);
 }
 
-int read_first_v(const output_env_t oenv, int *status,const char *fn,real *t,
-                 rvec **v,matrix box)
+int read_first_v(const output_env_t oenv, t_trxstatus **status,const char *fn,
+                 real *t, rvec **v,matrix box)
 {
   t_trxframe fr;
 
@@ -902,8 +954,8 @@ int read_first_v(const output_env_t oenv, int *status,const char *fn,real *t,
   return fr.natoms;
 }
 
-bool read_next_v(const output_env_t oenv,int status,real *t,int natoms,rvec v[],
-                 matrix box)
+bool read_next_v(const output_env_t oenv,t_trxstatus *status,real *t,
+                 int natoms,rvec v[], matrix box)
 {
   t_trxframe fr;
   bool bRet;
index 180b024247489e0436a5504949f7203d673d829e..d5d2b8c4f5961d77ebf5cd13d1ca17e6de504bfc 100644 (file)
@@ -277,6 +277,8 @@ void done_atom (t_atoms *at)
   sfree(at->atom);
   sfree(at->resinfo);
   sfree(at->atomname);
+  sfree(at->atomtype);
+  sfree(at->atomtypeB);
 }
 
 void done_atomtypes(t_atomtypes *atype)
@@ -285,6 +287,7 @@ void done_atomtypes(t_atomtypes *atype)
   sfree(atype->radius);
   sfree(atype->vol);
   sfree(atype->surftens);
+  sfree(atype->atomnumber);
   sfree(atype->gb_radius);
   sfree(atype->S_hct);
 }
@@ -339,8 +342,17 @@ void done_mtop(gmx_mtop_t *mtop,bool bDoneSymtab)
 
 void done_top(t_topology *top)
 {
-  int i;
+  int f;
   
+  sfree(top->idef.functype);
+  sfree(top->idef.iparams);
+  for (f = 0; f < F_NRE; ++f)
+  {
+      sfree(top->idef.il[f].iatoms);
+      top->idef.il[f].iatoms = NULL;
+      top->idef.il[f].nalloc = 0;
+  }
+
   done_atom (&(top->atoms));
 
   /* For GB */
@@ -662,6 +674,7 @@ void t_atoms_set_resinfo(t_atoms *atoms,int atom_ind,t_symtab *symtab,
 
   ri = &atoms->resinfo[atoms->atom[atom_ind].resind];
   ri->name  = put_symtab(symtab,resname);
+  ri->rtp   = NULL;
   ri->nr    = resnr;
   ri->ic    = ic;
   ri->chain = chain;
index a283def01ecd10d224c8717653fc847b2c83523a..f7eee35e91959c9ab2e56624cf45ca5a592e3cef 100644 (file)
 #include "gstat.h"
 #include "wgms.h"
 
-static int     n=0;
+/*static int     n=0;*/
 #define FPL 10
 
 void write_gms(FILE *fp,int natoms,rvec x[],matrix box)
 {
-  int i,j;
+  int i,j,n;
 
   n=0;
   for(i=0;(i<natoms);i++)
@@ -65,7 +65,7 @@ void write_gms(FILE *fp,int natoms,rvec x[],matrix box)
 
 void write_gms_ndx(FILE *fp,int isize,atom_id index[],rvec x[],matrix box)
 {
-  int i,j;
+  int i,j,n;
 
   n=0;
   for(i=0;(i<isize);i++)
index cd7ba88880139bf61503f4e6ac0f2c4f279b45ed..cfab228f1ae35d43ff8a8e0e9ca4a33eaccf19d1 100644 (file)
@@ -57,7 +57,7 @@ int xdr_real(XDR *xdrs,real *r)
 #endif
 }
 
-int xdr3drcoord(XDR *xdrs, real *fp, int *size, real *precision)
+int xdr3drcoord(XDR *xdrs, real *fp, int *size, real *precision, bool bRead)
 {
 #ifdef GMX_DOUBLE
   float *ffp;
@@ -73,7 +73,7 @@ int xdr3drcoord(XDR *xdrs, real *fp, int *size, real *precision)
   for(i=0; (i<isize); i++)
     ffp[i]=fp[i];
   fprec=*precision;
-  ret=xdr3dfcoord(xdrs,ffp,size,&fprec);
+  ret=xdr3dfcoord(xdrs,ffp,size,&fprec,bRead);
   
   *precision=fprec;
   for(i=0; (i<isize); i++)
@@ -82,7 +82,7 @@ int xdr3drcoord(XDR *xdrs, real *fp, int *size, real *precision)
   sfree(ffp);
   return ret;
 #else
-  return xdr3dfcoord(xdrs,(float *)fp,size,(float *)precision);
+  return xdr3dfcoord(xdrs,(float *)fp,size,(float *)precision,bRead);
 #endif
 }
 
index af7832f1e07bf9218f8a11adab55f939478c1054..cd1f270fcad60f76ba23208c16f8c6cf49d01b1a 100644 (file)
@@ -68,14 +68,14 @@ static int xdr_r2f(XDR *xdrs,real *r,bool bRead)
 }
 
 
-int open_xtc(const char *fn,const char *mode)
+t_fileio *open_xtc(const char *fn,const char *mode)
 {
-  return gmx_fio_open(fn,mode);
+    return gmx_fio_open(fn,mode);
 }
 
-void close_xtc(int fp)
+void close_xtc(t_fileio *fio)
 {
-  gmx_fio_close(fp);
+    gmx_fio_close(fio);
 }
 
 static void check_xtc_magic(int magic)
@@ -153,7 +153,7 @@ static int xtc_coord(XDR *xd,int *natoms,matrix box,rvec *x,real *prec, bool bRe
       }
       fprec = *prec;
   }
-  result=XTC_CHECK("x",xdr3dfcoord(xd,ftmp,natoms,&fprec));
+  result=XTC_CHECK("x",xdr3dfcoord(xd,ftmp,natoms,&fprec,bRead));
   
   /* Copy from temp. array if reading */
   if(bRead)
@@ -168,7 +168,7 @@ static int xtc_coord(XDR *xd,int *natoms,matrix box,rvec *x,real *prec, bool bRe
   }  
   sfree(ftmp);
 #else
-    result=XTC_CHECK("x",xdr3dfcoord(xd,x[0],natoms,prec)); 
+    result=XTC_CHECK("x",xdr3dfcoord(xd,x[0],natoms,prec,bRead)); 
 #endif 
     
   return result;
@@ -176,7 +176,7 @@ static int xtc_coord(XDR *xd,int *natoms,matrix box,rvec *x,real *prec, bool bRe
 
 
 
-int write_xtc(int fp,
+int write_xtc(t_fileio *fio,
              int natoms,int step,real time,
              matrix box,rvec *x,real prec)
 {
@@ -185,7 +185,7 @@ int write_xtc(int fp,
   bool bDum;
   int bOK;
        
-  xd = gmx_fio_getxdr(fp);
+  xd = gmx_fio_getxdr(fio);
   /* write magic number and xtc identidier */
   if (xtc_header(xd,&magic_number,&natoms,&step,&time,FALSE,&bDum) == 0)
   {
@@ -197,7 +197,7 @@ int write_xtc(int fp,
 
   if(bOK)
   {
-         if(gmx_fio_flush(fp) !=0)
+         if(gmx_fio_flush(fio) !=0)
          {
                  bOK = 0;
          }
@@ -205,14 +205,14 @@ int write_xtc(int fp,
   return bOK;  /* 0 if bad, 1 if writing went well */
 }
 
-int read_first_xtc(int fp,int *natoms,int *step,real *time,
+int read_first_xtc(t_fileio *fio,int *natoms,int *step,real *time,
                   matrix box,rvec **x,real *prec,bool *bOK)
 {
   int magic;
   XDR *xd;
   
   *bOK=TRUE;
-  xd = gmx_fio_getxdr(fp);
+  xd = gmx_fio_getxdr(fio);
   
   /* read header and malloc x */
   if ( !xtc_header(xd,&magic,natoms,step,time,TRUE,bOK))
@@ -228,7 +228,7 @@ int read_first_xtc(int fp,int *natoms,int *step,real *time,
   return *bOK;
 }
 
-int read_next_xtc(int fp,
+int read_next_xtc(t_fileio* fio,
                  int natoms,int *step,real *time,
                  matrix box,rvec *x,real *prec,bool *bOK)
 {
@@ -237,7 +237,7 @@ int read_next_xtc(int fp,
   XDR *xd;
 
   *bOK=TRUE;
-  xd = gmx_fio_getxdr(fp);
+  xd = gmx_fio_getxdr(fio);
   
   /* read header */
   if (!xtc_header(xd,&magic,&n,step,time,TRUE,bOK))
index 1d171340e619b9ce06a46a3ef624f9d5a99cb8ad..48fbdef90dfdb941eb6a9bef1afdcc7dcd04486e 100644 (file)
@@ -39,16 +39,24 @@ set(MDRUN_SOURCES
 
 add_library(gmxpreprocess ${GMXPREPROCESS_SOURCES})
 target_link_libraries(gmxpreprocess md)
+set_target_properties(gmxpreprocess PROPERTIES OUTPUT_NAME "gmxpreprocess${GMX_BINARY_SUFFIX}")
+set_target_properties(md PROPERTIES OUTPUT_NAME "md${GMX_BINARY_SUFFIX}")
 
 if(GMX_OPENMM) 
     add_subdirectory(gmx_gpu_utils)
     include_directories(./gmx_gpu_utils ${OpenMM_INCLUDE_DIR})
     link_directories(${OpenMM_LIBRARY_DIR}) 
-    add_definitions( -DOPENMM_PLUGIN_DIR="${OpenMM_PLUGIN_DIR}" ) 
+    # only define if this is a local build not a release 
+    # we assume that the auto-generated version is not used && 
+    # version string does not contain "-dev" => it's a release build
+    if(NOT USE_VERSION_H AND NOT PROJECT_VERSION MATCHES ".*-dev.*")  
+        add_definitions( -DOPENMM_PLUGIN_DIR="${OpenMM_PLUGIN_DIR}" ) 
+    else()
+        add_definitions( -DOPENMM_PLUGIN_DIR="" )
+    endif()
     add_library(openmm_api_wrapper openmm_wrapper.cpp)
 #    remove_definitions( -DOPENMM_PLUGIN_DIR="${OpenMM_PLUGIN_DIR}" )  # TODO where should this go?!
     set(GMX_OPENMM_LIBRARIES openmm_api_wrapper gmx_gpu_utils OpenMM)   
-    install(TARGETS openmm_api_wrapper DESTINATION ${LIB_INSTALL_DIR})   
 endif(GMX_OPENMM)
 
 if(GMX_FAHCORE)
@@ -59,43 +67,74 @@ list(APPEND GMX_EXTRA_LIBRARIES gmxpreprocess md)
 
 add_executable(grompp grompp.c)
 target_link_libraries(grompp ${GMX_EXTRA_LIBRARIES})
+set_target_properties(grompp PROPERTIES OUTPUT_NAME "grompp${GMX_BINARY_SUFFIX}")
 
 add_executable(tpbconv tpbconv.c)
 target_link_libraries(tpbconv ${GMX_EXTRA_LIBRARIES})
+set_target_properties(tpbconv PROPERTIES OUTPUT_NAME "tpbconv${GMX_BINARY_SUFFIX}")
 
 add_executable(pdb2gmx pdb2gmx.c)
 target_link_libraries(pdb2gmx ${GMX_EXTRA_LIBRARIES})
+set_target_properties(pdb2gmx PROPERTIES OUTPUT_NAME "pdb2gmx${GMX_BINARY_SUFFIX}")
 
-add_executable(protonate protonate.c)
-target_link_libraries(protonate ${GMX_EXTRA_LIBRARIES})
+add_executable(g_protonate g_protonate.c)
+target_link_libraries(g_protonate ${GMX_EXTRA_LIBRARIES})
+set_target_properties(g_protonate PROPERTIES OUTPUT_NAME "g_protonate${GMX_BINARY_SUFFIX}")
 
-add_executable(luck luck.c)
-target_link_libraries(luck ${GMX_EXTRA_LIBRARIES})
+add_executable(g_luck g_luck.c)
+target_link_libraries(g_luck ${GMX_EXTRA_LIBRARIES})
+set_target_properties(g_luck PROPERTIES OUTPUT_NAME "g_luck${GMX_BINARY_SUFFIX}")
 
 add_executable(gmxdump gmxdump.c)
 target_link_libraries(gmxdump ${GMX_EXTRA_LIBRARIES})
+set_target_properties(gmxdump PROPERTIES OUTPUT_NAME "gmxdump${GMX_BINARY_SUFFIX}")
 
-add_executable(x2top x2top.c)
-target_link_libraries(x2top ${GMX_EXTRA_LIBRARIES})
+add_executable(g_x2top g_x2top.c)
+target_link_libraries(g_x2top ${GMX_EXTRA_LIBRARIES})
+set_target_properties(g_x2top PROPERTIES OUTPUT_NAME "g_x2top${GMX_BINARY_SUFFIX}")
 
 add_executable(gmxcheck gmxcheck.c)
 target_link_libraries(gmxcheck ${GMX_EXTRA_LIBRARIES})
+set_target_properties(gmxcheck PROPERTIES OUTPUT_NAME "gmxcheck${GMX_BINARY_SUFFIX}")
 
 add_executable(mdrun ${MDRUN_SOURCES})
 target_link_libraries(mdrun ${GMX_EXTRA_LIBRARIES} ${GMX_OPENMM_LIBRARIES})
+# set binary name to mdrun-gpu
+if(GMX_OPENMM)
+    set(_mdrun_exec_name "mdrun-gpu")    
+else()
+    set(_mdrun_exec_name "mdrun${GMX_BINARY_SUFFIX}")
+endif()
+set_target_properties(mdrun PROPERTIES OUTPUT_NAME "${_mdrun_exec_name}")
+
+# this is to circumvent the following MSVC error: 
+# warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs
+# fatal error LNK1169: one or more multiply defined symbols found
+if(GMX_OPENMM AND MSVC)
+    set_target_properties(mdrun PROPERTIES LINK_FLAGS "/NODEFAULTLIB:LIBCMT")
+endif()
+
 
 install(TARGETS 
         grompp
         tpbconv
         pdb2gmx
-        protonate
-        luck
+        g_protonate
+        g_luck
         gmxdump
-        x2top
+        g_x2top
         gmxcheck
         mdrun
        gmxpreprocess DESTINATION ${LIB_INSTALL_DIR}
         RUNTIME DESTINATION ${BIN_INSTALL_DIR})
 
+
+get_target_property(MDRUN_PATH mdrun LOCATION)
+add_custom_target(install-mdrun
+        COMMAND ${CMAKE_COMMAND} -E copy "${MDRUN_PATH}" 
+            "${CMAKE_INSTALL_PREFIX}/bin/${_mdrun_exec_name}"
+        DEPENDS mdrun
+        COMMENT "Installing mdrun")
+
 endif(GMX_FAHCORE)
 
index 1aad0cf17b122941f4b0eac5182c9c518b701929..6733c51fa282c66a191d707ae56207ccbb5784e3 100644 (file)
@@ -56,10 +56,10 @@ xlate.c             xlate.h
 
 bin_PROGRAMS = \
        grompp          mdrun           tpbconv         pdb2gmx         \
-       protonate       luck            gmxdump                         \
-       gmxcheck        x2top
+       g_protonate     g_luck          gmxdump                         \
+       gmxcheck        g_x2top
 
-x2top_SOURCES = x2top.c nm2type.c x2top.h
+g_x2top_SOURCES = g_x2top.c nm2type.c g_x2top.h
 
 mdrun_SOURCES = \
        gctio.c         \
index 75ac0e8740d8f82df01ef8b082450a537e900429..22bcb2e1daada8145b9bd9540d556e7bac91b058 100644 (file)
@@ -97,7 +97,7 @@ void fflib_filename_base(const char *filename,char *filebase,int maxlen)
     {
         cptr = filename;
     }
-    if (strlen(filename) >= maxlen)
+    if (strlen(filename) >= (size_t)maxlen)
     {
         gmx_fatal(FARGS,"filename is longer (%d) than maxlen (%d)",
                   strlen(filename),maxlen);
@@ -143,6 +143,7 @@ static void sort_filenames(int n,char **name,char **name2)
 }
 
 static int low_fflib_search_file_end(const char *ffdir,
+                                     bool bAddCWD,
                                      const char *file_end,
                                      bool bFatalError,
                                      char ***filenames,
@@ -179,23 +180,26 @@ static int low_fflib_search_file_end(const char *ffdir,
         /* GMXLIB can be a path now */
         lib = getenv("GMXLIB");
         snew(libpath,GMX_PATH_MAX);
+        if (bAddCWD)
+        {
+            sprintf(libpath,"%s%s",".",PATH_SEPARATOR);
+        }
         if (lib != NULL)
         {
             env_is_set = TRUE;
-            strncpy(libpath,lib,GMX_PATH_MAX);
+            strncat(libpath,lib,GMX_PATH_MAX);
         } 
-        else if (!get_libdir(libpath))
+        else if (!get_libdir(libpath+strlen(libpath)))
         {
-            strncpy(libpath,GMXLIBDIR,GMX_PATH_MAX);
+            strncat(libpath,GMXLIBDIR,GMX_PATH_MAX);
         }
     }
     s = libpath;
     n = 0;
     fns       = NULL;
     fns_short = NULL;
-    /* Start with the current directory, continue with libpath */
-    dir = ".";
-    do
+    /* Loop over all the entries in libpath */
+    while ((dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL)
     {
         dirptr = opendir(dir);
         if (dirptr != NULL)
@@ -258,10 +262,11 @@ static int low_fflib_search_file_end(const char *ffdir,
                 }
             }
 
-            sort_filenames(n_thisdir,fns+n-n_thisdir,fns_short+n-n_thisdir);
+            sort_filenames(n_thisdir,
+                           fns+n-n_thisdir,
+                           fns_short==NULL ? NULL : fns_short+n-n_thisdir);
         }
     }
-    while((dir=gmx_strsep(&s, PATH_SEPARATOR)) != NULL);
 
     sfree(libpath);
 
@@ -287,11 +292,13 @@ static int low_fflib_search_file_end(const char *ffdir,
 #endif
 }
 
-int fflib_search_file_end(const char *ffdir,const char *file_end,
+int fflib_search_file_end(const char *ffdir,bool bAddCWD,
+                          const char *file_end,
                           bool bFatalError,
                           char ***filenames)
 {
-    return low_fflib_search_file_end(ffdir,file_end,bFatalError,filenames,NULL);
+    return low_fflib_search_file_end(ffdir,bAddCWD,file_end,bFatalError,
+                                     filenames,NULL);
 }
 
 int fflib_search_file_in_dirend(const char *filename,const char *dirend,
@@ -309,7 +316,7 @@ int fflib_search_file_in_dirend(const char *filename,const char *dirend,
     struct dirent *dirent;
 
     /* Find all files (not only dir's) ending on dirend */
-    nf = low_fflib_search_file_end(NULL,dirend,FALSE,&f,&f_short);
+    nf = low_fflib_search_file_end(NULL,TRUE,dirend,FALSE,&f,&f_short);
 
     n = 0;
     dns = NULL;
index 980e7e0c0406562c844a458615f078507f8ed915..51b396b5a97f0bb1ec57a03f97f90d4042963276 100644 (file)
@@ -62,11 +62,13 @@ extern void fflib_filename_base(const char *filename,char *filebase,int maxlen);
  * base should be at least of size maxlen.
  */
 
-extern int fflib_search_file_end(const char *ffdir,const char *file_end,
+extern int fflib_search_file_end(const char *ffdir,bool bAddCWD,
+                                const char *file_end,
                                 bool bFatalError,
                                 char ***filenames);
 /* Search for files ending on file_end in the force field directory fflib.
- * fflib should be in the current working directory or the GROMACS lib.path.
+ * fflib should be in the GROMACS lib.path or, when bAddCWD is set,
+ * in the current working directory.
  * Return the number of files and the file names in filenames.
  */
 
similarity index 100%
rename from src/kernel/luck.c
rename to src/kernel/g_luck.c
similarity index 99%
rename from src/kernel/protonate.c
rename to src/kernel/g_protonate.c
index 1c19009ebcd2ce124c7c98f508e64b3f3f7d0a0b..5ac1b28a44c7bef3ccdbba181a79b27815aaeef2 100644 (file)
@@ -74,7 +74,8 @@ int main (int argc,char *argv[])
   t_atoms     *atoms,*iatoms;
   t_protonate protdata;
   atom_id     *index;
-  int         status,out;
+  t_trxstatus *status;
+  t_trxstatus *out;
   t_trxframe  fr,frout;
   rvec        *x,*ix;
   int         nidx,natoms,natoms_out;
similarity index 94%
rename from src/kernel/x2top.c
rename to src/kernel/g_x2top.c
index 36f79464e75807f51a6b7be0b1b9acb89b0030c1..ec1cc05247ca02c7fbaf144c8f952ba125977007 100644 (file)
@@ -59,7 +59,7 @@
 #include "gen_ad.h"
 #include "gpp_nextnb.h"
 #include "vec.h"
-#include "x2top.h"
+#include "g_x2top.h"
 #include "atomprop.h"
 
 char atp[7] = "HCNOSX";
@@ -142,7 +142,7 @@ void mk_bonds(int nnm,t_nm2type nmt[],
     b.c[i] = 0.0;
     
   if (bPBC)
-    set_pbc(&pbc,epbcXYZ,box);
+    set_pbc(&pbc,-1,box);
   for(i=0; (i<atoms->nr); i++) {
     if ((i % 10) == 0)
       fprintf(stderr,"\ratom %d",i);
@@ -374,15 +374,12 @@ int main(int argc, char *argv[])
     "and force constants will be printed in the topology for all",
     "interactions. The equilibrium distances and angles are taken",
     "from the input coordinates, the force constant are set with",
-    "command line options."
-    "The force fields supported currently are:[PAR]",
-    "G43a1  GROMOS96 43a1 Forcefield (official distribution)[PAR]",
+    "command line options.",
+    "The force fields somewhat supported currently are:[PAR]",
+    "G53a5  GROMOS96 53a5 Forcefield (official distribution)[PAR]",
     "oplsaa OPLS-AA/L all-atom force field (2001 aminoacid dihedrals)[PAR]",
-    "G43b1  GROMOS96 43b1 Vacuum Forcefield (official distribution)[PAR]",
-    "gmx    Gromacs Forcefield (a modified GROMOS87, see manual)[PAR]",
-    "G43a2  GROMOS96 43a2 Forcefield (development) (improved alkane dihedrals)[PAR]",
     "The corresponding data files can be found in the library directory",
-    "with names like ffXXXX.YYY. Check chapter 5 of the manual for more",
+    "with name atomname2type.n2t. Check chapter 5 of the manual for more",
     "information about file formats. By default the forcefield selection",
     "is interactive, but you can use the [TT]-ff[tt] option to specify",
     "one of the short names above on the command line instead. In that",
@@ -392,7 +389,7 @@ int main(int argc, char *argv[])
     "The atom type selection is primitive. Virtually no chemical knowledge is used",
     "Periodic boundary conditions screw up the bonding",
     "No improper dihedrals are generated",
-    "The atoms to atomtype translation table is incomplete (ffG43a1.n2t file in the $GMXLIB directory). Please extend it and send the results back to the GROMACS crew."
+    "The atoms to atomtype translation table is incomplete (atomname2type.n2t files in the data directory). Please extend it and send the results back to the GROMACS crew."
   };
   FILE       *fp;
   t_params   plist[F_NRE];
@@ -416,6 +413,7 @@ int main(int argc, char *argv[])
   bool       bRTP,bTOP,bOPLS;
   t_symtab   symtab;
   real       cutoff,qtot,mtot;
+  char       n2t[STRLEN];
   output_env_t oenv;
   
   t_filenm fnm[] = {
@@ -424,6 +422,7 @@ int main(int argc, char *argv[])
     { efRTP, "-r", "out",  ffOPTWR }
   };
 #define NFILE asize(fnm)
+  static bool bAddCWD = FALSE;
   static real scale = 1.1, kb = 4e5,kt = 400,kp = 5;
   static int  nexcl = 3;
   static bool bRemoveDih = FALSE;
@@ -434,7 +433,9 @@ int main(int argc, char *argv[])
   static const char *ff = "oplsaa";
   t_pargs pa[] = {
     { "-ff",     FALSE, etSTR, {&ff},
-      "Force field for your simulation. Type \"select\" for interactive selcection." },
+      "Force field for your simulation. Type \"select\" for interactive selection." },
+    { "-cwd",    FALSE, etBOOL, {&bAddCWD},
+      "Also read force field files from the current working directory" },
     { "-v",      FALSE, etBOOL, {&bVerbose},
       "Generate verbose output in the top file." },
     { "-nexcl", FALSE, etINT,  {&nexcl},
@@ -482,7 +483,7 @@ int main(int argc, char *argv[])
            forcefield,sizeof(forcefield),
            ffdir,sizeof(ffdir));
 
-  bOPLS = (strcmp(forcefield,"ffoplsaa") == 0);
+  bOPLS = (strcmp(forcefield,"oplsaa") == 0);
   
     
   mymol.name = strdup(molnm);
@@ -501,11 +502,15 @@ int main(int argc, char *argv[])
 
   read_stx_conf(opt2fn("-f",NFILE,fnm),title,atoms,x,NULL,&epbc,box);
 
-  nm2t = rd_nm2type(ffdir,&nnm);
-  printf("There are %d name to type translations\n",nnm);
+  sprintf(n2t,"%s",ffdir);
+  nm2t = rd_nm2type(n2t,bAddCWD,&nnm);
+  if (nnm == 0)
+    gmx_fatal(FARGS,"No or incorrect atomname2type.n2t file found (looking for %s)",
+             n2t);
+  else
+    printf("There are %d name to type translations in file %s\n",nnm,n2t);
   if (debug)
     dump_nm2type(debug,nnm,nm2t);
-  
   printf("Generating bonds from distances...\n");
   snew(nbonds,atoms->nr);
   mk_bonds(nnm,nm2t,atoms,x,&(plist[F_BONDS]),nbonds,forcefield,
similarity index 96%
rename from src/kernel/x2top.h
rename to src/kernel/g_x2top.h
index 79cd43421d890b64ff24e4f4941ccee8691c1617..52ccfca831b4fcad97f50b78afa90f0aba3d4cb8 100644 (file)
@@ -47,7 +47,7 @@ typedef struct {
   double *blen;
 } t_nm2type;
 
-extern t_nm2type *rd_nm2type(const char *ffdir,int *nnm);
+extern t_nm2type *rd_nm2type(const char *ffdir,bool bAddCWD,int *nnm);
 /* Read the name 2 type database. nnm is the number of entries 
  * ff is the force field.
  */
index 721eae2b8795a0238bf56ae269812bd615f069d9..b7edc30e29a9e58c973adb08ca9d12bd71446ffa 100644 (file)
@@ -1332,7 +1332,7 @@ void do_vsites(int nrtp, t_restp rtp[], gpp_atomtype_t atype,
               t_atoms *at, t_symtab *symtab, rvec *x[], 
               t_params plist[], int *vsite_type[], int *cgnr[], 
               real mHmult, bool bVsiteAromatics,
-              const char *ffdir)
+              const char *ffdir,bool bAddCWD)
 {
 #define MAXATOMSPERRESIDUE 16
   int  i,j,k,i0,ni0,whatres,resind,add_shift,ftype,nvsite,nadd;
@@ -1408,7 +1408,7 @@ void do_vsites(int nrtp, t_restp rtp[], gpp_atomtype_t atype,
     fprintf(debug,"# # # VSITES # # #\n");
   }
 
-  ndb = fflib_search_file_end(ffdir,".vsd",FALSE,&db);
+  ndb = fflib_search_file_end(ffdir,bAddCWD,".vsd",FALSE,&db);
   nvsiteconf    = 0;
   vsiteconflist = NULL;
   nvsitetop     = 0;
index c5e11ba8d2effcdebc7e60ef33c457faed5a6f30..853067713b21adf6114017eff7696ba7d9418bdd 100644 (file)
@@ -47,7 +47,7 @@ extern void do_vsites(int nrtp, t_restp rtp[], gpp_atomtype_t atype,
                      t_atoms *at, t_symtab *symtab, rvec *x[], 
                      t_params plist[], int *dummy_type[], int *cgnr[], 
                      real mHmult, bool bVSiteAromatics,
-                     const char *ffdir);
+                     const char *ffdir,bool bAddCWD);
 
 extern void do_h_mass(t_params *psb, int vsite_type[], t_atoms *at, real mHmult,
                      bool bDeuterate);
index 8617c15c9fa841227c7493b04047116f0f23d8d5..eb0ff7d8f24ec44494cd9f16c2d280765d7c9223 100644 (file)
@@ -154,8 +154,6 @@ static t_hackblock *get_hackblocks(t_atoms *pdba, int nah, t_hackblock ah[],
   return hb;
 }
 
-static const char Hnum[] = "123456";
-
 static void expand_hackblocks_one(t_hackblock *hbr, char *atomname, 
                                  int *nabi, t_hack **abi, bool bN, bool bC)
 {
@@ -190,8 +188,7 @@ static void expand_hackblocks_one(t_hackblock *hbr, char *atomname,
       srenew(*abi,*nabi + hbr->hack[j].nr);
       for(k=0; k < hbr->hack[j].nr; k++) {
        copy_t_hack(&hbr->hack[j], &(*abi)[*nabi + k]);
-       for(d=0; d<DIM; d++)
-         (*abi)[*nabi + k].newx[d]=NOTSET;
+       (*abi)[*nabi + k].bXSet = FALSE;
        /* if we're adding (oname==NULL) and don't have a new name (nname) 
           yet, build it from atomname */
        if ( (*abi)[*nabi + k].nname==NULL ) {
@@ -209,11 +206,24 @@ static void expand_hackblocks_one(t_hackblock *hbr, char *atomname,
          sfree((*abi)[*nabi + k].nname);
          (*abi)[*nabi + k].nname=strdup(hbr->hack[j].nname);
        }
-       /* if adding more than one atom, number them */
-       if ( hbr->hack[j].nr > 1 ) {
+
+       if (hbr->hack[j].tp == 10 && k == 2) {
+         /* This is a water virtual site, not a hydrogen */
+         /* Ugly hardcoded name hack */
+         (*abi)[*nabi + k].nname[0] = 'M';
+       } else if (hbr->hack[j].tp == 11 && k >= 2) {
+         /* This is a water lone pair, not a hydrogen */
+         /* Ugly hardcoded name hack */
+         srenew((*abi)[*nabi + k].nname,4);
+         (*abi)[*nabi + k].nname[0] = 'L';
+         (*abi)[*nabi + k].nname[1] = 'P';
+         (*abi)[*nabi + k].nname[2] = '1' + k - 2;
+         (*abi)[*nabi + k].nname[3] = '\0';
+       } else if ( hbr->hack[j].nr > 1 ) {
+         /* adding more than one atom, number them */
          l = strlen((*abi)[*nabi + k].nname);
          srenew((*abi)[*nabi + k].nname, l+2);
-         (*abi)[*nabi + k].nname[l] = Hnum[k]; /* 1, 2, 3 .... */
+         (*abi)[*nabi + k].nname[l]   = '1' + k;
          (*abi)[*nabi + k].nname[l+1] = '\0';
        }
       }
@@ -336,8 +346,10 @@ static void calc_all_pos(t_atoms *pdba, rvec x[], int nab[], t_hack *ab[],
              else
                xh[m][d] = NOTSET;
          calc_h_pos(ab[i][j].tp, xa, xh, &l);
-         for(m=0; m<ab[i][j].nr; m++)
+         for(m=0; m<ab[i][j].nr; m++) {
            copy_rvec(xh[m],ab[i][j+m].newx);
+           ab[i][j+m].bXSet = TRUE;
+         }
        }
       }
     }
@@ -363,7 +375,6 @@ static int add_h_low(t_atoms **pdbaptr, rvec *xptr[],
                     bool bUpdate_pdba, bool bKeep_old_pdba)
 {
   t_atoms     *newpdba=NULL,*pdba=NULL;
-  bool        bSet;
   int         nadd;
   int         i,newi,j,d,natoms,nalreadypresent;
   int         *nab=NULL;
@@ -520,10 +531,7 @@ static int add_h_low(t_atoms **pdbaptr, rvec *xptr[],
 /*           newpdba->atom[newi].type = ab[i][j].atom->type; */
            }
          }
-         bSet=TRUE;
-         for(d=0; d<DIM; d++)
-           bSet = bSet && ab[i][j].newx[d]!=NOTSET;
-         if (bSet)
+         if (ab[i][j].bXSet)
            copy_rvec(ab[i][j].newx, xn[newi]);
          }
          if (bUpdate_pdba && debug) 
@@ -632,13 +640,13 @@ int protonate(t_atoms **atomsptr,rvec **xptr,t_protonate *protdata)
     /* set forcefield to use: */
     strcpy(protdata->FF,"ffgmx2");
     /* get the databases: */
-    protdata->nah=read_h_db(protdata->FF,&protdata->ah);
+    protdata->nah=read_h_db(protdata->FF,FALSE,&protdata->ah);
     open_symtab(&protdata->tab); 
-    protdata->atype=read_atype(protdata->FF,&protdata->tab);
-    nntdb = read_ter_db(protdata->FF,'n',&protdata->ntdb,protdata->atype);
+    protdata->atype=read_atype(protdata->FF,FALSE,&protdata->tab);
+    nntdb = read_ter_db(protdata->FF,FALSE,'n',&protdata->ntdb,protdata->atype);
     if (nntdb < 1)
       gmx_fatal(FARGS,"no n-terminus db");
-    nctdb = read_ter_db(protdata->FF,'c',&protdata->ctdb,protdata->atype);
+    nctdb = read_ter_db(protdata->FF,FALSE,'c',&protdata->ctdb,protdata->atype);
     if (nctdb < 1)
       gmx_fatal(FARGS,"no c-terminus db");
     
index ab9ce99c551233f6d43c3c3ecddc11b44dae9dc2..d6b6527baf3b22f678f566fd62f8f6d94697c3c0 100644 (file)
@@ -1,4 +1,19 @@
 
+# (slightly sloppy) OS definitions required by memtestG80
+set(_os_def)
+if(UNIX)
+    if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+        set(_os_def "-DOSX")
+    else() # everything that's UNIX & UNIX-like except OS X
+        set(_os_def "-DLINUX")
+    endif()
+else()
+    if(WIN32)
+        set(_os_def "-DWINDOWS")
+    else()
+        message(FATAL_ERROR " Could not detect OS required for memtestG80.")
+    endif()
+endif()
 
 CUDA_INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
 set(CUDA_ATTACH_VS_BUILD_RULE_TO_CUDA_FILE OFF)        
@@ -6,14 +21,14 @@ if(CMAKE_BUILD_TYPE STREQUAL "DEBUG")
     CUDA_ADD_LIBRARY(gmx_gpu_utils  
         gmx_gpu_utils.cu 
         memtestG80_core.cu 
-        OPTIONS "-DLINUX"
+        OPTIONS ${_os_def}
         DEBUG -g -D_DEBUG_=1 
         )
 else()
     CUDA_ADD_LIBRARY(gmx_gpu_utils 
         gmx_gpu_utils.cu 
         memtestG80_core.cu 
-        OPTIONS "-DLINUX"
+        OPTIONS ${_os_def}
         )
 endif()
 CUDA_BUILD_CLEAN_TARGET()
index 2f17df4f42ecc4c66edaae25db71f24e88f45e38..775c2434ef62405ed2aceae87a519483181d283f 100644 (file)
@@ -1,3 +1,38 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 
 
 #include "memtestG80_core.h"
 
-#include "gmx_fatal.h"
-#include "string2.h"
-
-#define BMARK_MEM       80
-
-#define QUICK_MEM       250
-#define QUICK_TESTS     MOD_20_32BIT | LOGIC_4_ITER_SHMEM | RANDOM_BLOCKS
-#define QUICK_ITER      3 /* TODO adjust this for production version */
-
-#define FULL_MEM        -1
-#define FULL_TESTS      0x3FFF
-#define FULL_ITER       25 /* TODO adjust this for production version */
-
-#ifndef _DEBUG_
-#define _DEBUG_           0
+/*! \cond  TEST */
+#ifdef _DEBUG_
+#undef _DEBUG_
 #endif
+#define _DEBUG_           0
 
-#if _DEBUG_ == 1
+#if _DEBUG_ >= 1
+#define debug stderr 
 #define DUPME(msg) printf("---> %s\n", msg);
 #else
 #define DUPME(msg) ;
 #endif
+/*! \endcond TEST*/
 
+#if _DEBUG_ == 0/* no gromacs utils in debug mode */
+#include "gmx_fatal.h"
+#include "string2.h"
+#endif
+
+#define QUICK_MEM       250 /*!< Amount of memory to be used in quick memtest. */
+#define QUICK_TESTS     MOD_20_32BIT | LOGIC_4_ITER_SHMEM | RANDOM_BLOCKS /*!< Bitflag with type of tests 
+                                                                            to run in quick memtest. */
+#define QUICK_ITER      3 /*!< Number of iterations in quick memtest. */
+
+#define FULL_TESTS      0x3FFF /*!<  Bitflag with all test set on for full memetest. */
+#define FULL_ITER       25 /*!< Number of iterations in full memtest. */
+
+#define TIMED_TESTS     MOD_20_32BIT | LOGIC_4_ITER_SHMEM | RANDOM_BLOCKS /*!< Bitflag with type of tests to 
+                                                                            run in time constrained memtest. */
+
+/*! Number of supported GPUs */
 #define NB_GPUS (sizeof(SupportedGPUs)/sizeof(SupportedGPUs[0]))
 
 /*
-TODO fine-tune parameters for quick/full test
-TODO add logging capability when integrating into gmx
-TODO add verbosity level
+TODO add proper gromacs logging?
 */
-/** Bit-flags which refer to memtestG80 test types and are used in do_memtest to specify which tests to run. */
+
+/*! Bit-flags which refer to memtestG80 test types and are used in do_memtest to specify which tests to run. */
 enum memtest_G80_test_types {
     MOVING_INVERSIONS_10 =      0x1,
     MOVING_INVERSIONS_RAND =    0x2,
@@ -53,10 +95,18 @@ enum memtest_G80_test_types {
     LOGIC_4_ITER_SHMEM =        0x1000
 };
 
-/*  List of GPUs that we want to support. */
 // TODO put this list into an external file and include it so that the list is easily accessible
-/** List of supported GPU names. */
+/*! List of supported GPUs. */
 static const char * const SupportedGPUs[] = {
+    /* GT400 */
+    "Geforce GTX 480",
+    "Geforce GTX 470",
+
+    "Tesla C2070",
+    "Tesla C2050",
+    "Tesla S2070",
+    "Tesla S2050",
+
     /* GT200 */
     "Geforce GTX 295",
     "Geforce GTX 285",
@@ -64,9 +114,14 @@ static const char * const SupportedGPUs[] = {
     "Geforce GTX 275",
     "Geforce GTX 260",
     "GeForce GTS 250",
+    "GeForce GTS 150",
+
+    "GeForce GTX 285M",
+    "GeForce GTX 280M",
 
     "Tesla S1070",
     "Tesla C1060",
+    "Tesla M1060",
 
     "Quadro FX 5800",
     "Quadro FX 4800",
@@ -75,59 +130,31 @@ static const char * const SupportedGPUs[] = {
     "Quadro Plex 2200 S4",
 
     /* G90 */
-    "GeForce 9800 G", /*GX2, GTX, GTX+ */
-    "GeForce 9600 G",  /* */
+    "GeForce 9800 G", /* GX2, GTX, GTX+, GT */
+    "GeForce 9800M GTX",
 
     "Quadro FX 4700",
     "Quadro Plex 2100 D4"
 };
 
+/*! \cond  TEST */
 #ifndef _string2_h
-#include <string.h>
-/* - duplicated from ~/src/gmxlib/string2.c - */
-void ltrim (char *str)
-{
-  char *tr;
-  int c;
-
-  if (!str)
-    return;
-
-  tr = strdup (str);
-  c  = 0;
-  while ((tr[c] == ' ') || (tr[c] == '\t'))
-    c++;
-
-  strcpy (str,tr+c);
-  free (tr);
-}
-
-void rtrim (char *str)
-{
-  int nul;
-
-  if (!str)
-    return;
-
-  nul = strlen(str)-1;
-  while ((nul > 0) && ((str[nul] == ' ') || (str[nul] == '\t')) ) {
-    str[nul] = '\0';
-    nul--;
-  }
-}
-
-void trim (char *str)
-{
-  ltrim (str);
-  rtrim (str);
-}
+/* debug functions, see @the end */
+void ltrim (char *);
+void rtrim (char *);
+void trim  (char *);
+int gmx_strncasecmp(const char*, const char*, int);
 #endif
+/*! \endcond  TEST */
 
-/** Runs sanity checks and returned properties of a device with given id or the one that has
-  * already been selected in the case if of dev_id == -1.
+
+/*! 
+  * \brief Runs GPU sanity checks.
+  * Returnes properties of a device with given id or the one that has
+  * already been initialized earlier in the case if of dev_id == -1.
   *
-  * @param dev_id       the device id of the GPU or -1 if the device has laredy been selected
-  * @param dev_prop     pointer to the structure in which the device properties will be returned
+  * \param[in] dev_id       the device id of the GPU or -1 if the device has laredy been selected
+  * \param[out] dev_prop    pointer to the structure in which the device properties will be returned
   */
 static int do_sanity_checks(int dev_id, cudaDeviceProp *dev_prop)
 {
@@ -189,7 +216,7 @@ static int do_sanity_checks(int dev_id, cudaDeviceProp *dev_prop)
 
     if ((dev_id != -1) && (cu_err = cudaSetDevice(dev_id)) != cudaSuccess)
     {
-         fprintf(stderr, "Error %d while switching to device #%d: %s\n", cu_err, dev_id,
+        fprintf(stderr, "Error %d while switching to device #%d: %s\n", cu_err, dev_id,
                 cudaGetErrorString(cu_err));
         return -1;
     }
@@ -197,13 +224,11 @@ static int do_sanity_checks(int dev_id, cudaDeviceProp *dev_prop)
     return 0;
 }
 
-/**
- * Checks whether the GPU with the given name is supported or not. In case of a positive
- * answer returns 1, otherwise 0;
- *
- * @param dev_id    the device id of the GPU or -1 if the device has laredy been selected
- * @param gpu_name  the name of the CUDA device
- * @returns         1 if the device is supported, otherwise 0
+/*! 
+ * \brief Checks whether the GPU with the given name is supported.
+ * 
+ * \param[in] gpu_name  the name of the CUDA device
+ * \returns             1 if the device is supported, otherwise 0
  */
 static int is_supported_gpu_n(char *gpuName)
 {
@@ -217,15 +242,12 @@ static int is_supported_gpu_n(char *gpuName)
     return 0;
 }
 
-/**
- * Checks whether the GPU with the given device id is supported or not. In case of a positive
- * answer returns 1, otherwise 0;
+/*! \brief Checks whether the GPU with the given device id is supported. 
  *
- * @param dev_id    the device id of the GPU or -1 if the device has laredy been selected
- * @param gpu_name  the name of the CUDA device
- * @returns         1 if the device is supported, otherwise 0
+ * \param[in] dev_id    the device id of the GPU or -1 if the device has laredy been selected
+ * \param[out] gpu_name Set to contain the name of the CUDA device, if NULL passed, no device name is set. 
+ * \returns             1 if the device is supported, otherwise 0
  */
-
 int is_supported_cuda_gpu(int dev_id, char *gpu_name)
 {
     cudaDeviceProp dev_prop;
@@ -235,20 +257,27 @@ int is_supported_cuda_gpu(int dev_id, char *gpu_name)
     if (do_sanity_checks(dev_id, &dev_prop) != 0)
         return -1;
 
-    strcpy(gpu_name, dev_prop.name);
+    if (gpu_name != NULL)
+    { 
+        strcpy(gpu_name, dev_prop.name);
+    }
     return is_supported_gpu_n(dev_prop.name);
 }
 
 
-/**
- * Runs a set of memory tests specified by the given bit-flags. In case if an error is detected
- * it stops without finishing the remainings steps/iterations and returns greater then zero value.
- * In case of other errors (e.g. kernel launch errors, device querying erros) -1 is returned.
+/*!
+ * \brief Runs a set of memory tests specified by the given bit-flags.
+ * Tries to allocate and do the test on \p megs Mb memory or 
+ * the greatest amount that can be allocated (>10Mb).
+ * In case if an error is detected it stops without finishing the remainings 
+ * steps/iterations and returns greater then zero value.  
+ * In case of other errors (e.g. kernel launch errors, device querying erros) 
+ * -1 is returned.
  *
- * @param which_tests   - variable with bit-flags of the requested tests
- * @param megs          - amount of memory that will be tested in MB
- * @param iter          - number of iterations
- * @returns             - 0 if no error was detected, otherwise >0
+ * \param[in] which_tests   variable with bit-flags of the requested tests
+ * \param[in] megs          amount of memory that will be tested in MB
+ * \param[in] iter          number of iterations
+ * \returns                 0 if no error was detected, otherwise >0
  */
 static int do_memtest(unsigned int which_tests, int megs, int iter)
 {
@@ -390,18 +419,18 @@ static int do_memtest(unsigned int which_tests, int megs, int iter)
     return err_count;
 }
 
-/**
- * Runs a quick memory test and returns 0 in case if no error is detected. If an error is detected it stops
- * before completing the test and returns a value greater then 0. In case of other errors
- * (e.g. kernel launch errors, device querying erros) -1 is returned.
+/*! \brief Runs a quick memory test and returns 0 in case if no error is detected. 
+ * If an error is detected it stops before completing the test and returns a 
+ * value greater then 0. In case of other errors (e.g. kernel launch errors, 
+ * device querying erros) -1 is returned.
  *
- * @param dev_id    the device id of the GPU or -1 if the device has laredy been selected
- * @returns         0 if no error was detected, otherwise >0
+ * \param[in] dev_id    the device id of the GPU or -1 if the device has laredy been selected
+ * \returns             0 if no error was detected, otherwise >0
  */
 int do_quick_memtest(int dev_id)
 {
     cudaDeviceProp  dev_prop;
-    int             devmem, res, time;
+    int             devmem, res, time=0;
 
     if (debug) { time = getTimeMilliseconds(); }
 
@@ -411,10 +440,9 @@ int do_quick_memtest(int dev_id)
         return -1;
     }
 
-    devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
-
     if (debug)
     {
+        devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
         fprintf(debug, ">> Running QUICK memtests on %d MiB (out of total %d MiB), %d iterations\n",
             QUICK_MEM, devmem, QUICK_ITER);
     }
@@ -432,19 +460,19 @@ int do_quick_memtest(int dev_id)
     return res;
 }
 
-/**
- * Runs a full memory test and returns 0 in case if no error is detected. If an error is detected  it stops
- * before completing the test and returns a value greater then 0. In case of other errors
- * (e.g. kernel launch errors, device querying erros) -1 is returned.
+/*! \brief Runs a full memory test and returns 0 in case if no error is detected. 
+ * If an error is detected  it stops before completing the test and returns a 
+ * value greater then 0. In case of other errors (e.g. kernel launch errors, 
+ * device querying erros) -1 is returned.
  *
- * @param dev_id    the device id of the GPU or -1 if the device has laredy been selected
- * @returns         0 if no error was detected, otherwise >0
+ * \param[in] dev_id    the device id of the GPU or -1 if the device has laredy been selected
+ * \returns             0 if no error was detected, otherwise >0
  */
 
 int do_full_memtest(int dev_id)
 {
     cudaDeviceProp  dev_prop;
-    int             devmem, res, time;
+    int             devmem, res, time=0;
 
     if (debug) { time = getTimeMilliseconds(); }
 
@@ -455,9 +483,14 @@ int do_full_memtest(int dev_id)
     }
 
     devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
-    if (debug) { fprintf(debug, ">> Running FULL memtests on %d MiB (out of total %d MiB), %d iterations\n",
-            devmem, devmem, FULL_ITER); }
 
+    if (debug) 
+    { 
+        fprintf(debug, ">> Running FULL memtests on %d MiB (out of total %d MiB), %d iterations\n",
+            devmem, devmem, FULL_ITER); 
+    }
+
+    /* do all test on the entire memory */
     res = do_memtest(FULL_TESTS, devmem, FULL_ITER);
 
     if (debug)
@@ -471,24 +504,20 @@ int do_full_memtest(int dev_id)
     return res;
 }
 
-/*******************************************************/
-/* FIXME test it! */
-
-/**
- * Runs a time constrained memory test and returns 0 in case if no error is detected. If an error is detected
- * it stops before completing the test and returns a value greater then zero. In case of other errors
- * (e.g. kernel launch errors, device querying erros) -1 is returned. Note, that test iterations are not
- * interrupted therefor the total runtime of the test will always be multipple of one iteration's runtime.
+/*! \brief Runs a time constrained memory test and returns 0 in case if no error is detected.
+ * If an error is detected it stops before completing the test and returns a value greater 
+ * than zero. In case of other errors (e.g. kernel launch errors, device querying erros) -1 
+ * is returned. Note, that test iterations are not interrupted therefor the total runtime of 
+ * the test will always be multipple of one iteration's runtime.
  *
- * @param dev_id        the device id of the GPU or -1 if the device has laredy been selected
- * @param time_constr   the time limit of the testing
- * @returns             0 if no error was detected, otherwise >0
+ * \param[in] dev_id        the device id of the GPU or -1 if the device has laredy been selected
+ * \param[in] time_constr   the time limit of the testing
+ * \returns                 0 if no error was detected, otherwise >0
  */
-
 int do_timed_memtest(int dev_id, int time_constr)
 {
     cudaDeviceProp  dev_prop;
-    int             devmem, res, time, startt;
+    int             devmem, res=0, time=0, startt;
 
     if (debug) { time = getTimeMilliseconds(); }
 
@@ -502,12 +531,18 @@ int do_timed_memtest(int dev_id, int time_constr)
     }
 
     devmem = dev_prop.totalGlobalMem/(1024*1024); // in MiB
-    if (debug) { fprintf(debug, ">> Running time constrained memtests on %d MiB (out of total %d MiB), time limit of %d s \n",
-            devmem, devmem, time_constr); }
 
-    while ( (getTimeMilliseconds() - startt) < time_constr)
-    {
-        res = do_memtest(QUICK_TESTS, devmem, 1);
+    if (debug) 
+    { 
+        fprintf(debug, ">> Running time constrained memtests on %d MiB (out of total %d MiB), time limit of %d s \n",
+        devmem, devmem, time_constr); 
+    }
+
+    /* do the TIMED_TESTS set, one step at a time on the entire memory 
+       that can be allocated, and stop when the given time is exceeded */
+    while ( ((int)getTimeMilliseconds() - startt) < time_constr)
+    {        
+        res = do_memtest(TIMED_TESTS, devmem, 1);
         if (res != 0) break;
     }
 
@@ -521,8 +556,11 @@ int do_timed_memtest(int dev_id, int time_constr)
     if (dev_id != -1) cudaThreadExit();
     return res;
 }
-/*******************************************************/
 
+/*! \cond TEST */
+
+/*******************************************************
+ * The code below is for testing purposes. */
 int do_custom_memtest(int dev_id)
 {
     cudaDeviceProp  dev_prop;
@@ -545,11 +583,11 @@ int do_custom_memtest(int dev_id)
 //    tester.deallocate();
 
 //    devmem   = dev_prop.totalGlobalMem/(1024*1024); // in MiB
-    mem2test = BMARK_MEM;
+    mem2test = 80;
 
 #if _DEBUG_ >= 1
-    printf(">> Running CUSTOM memtests [%x] on %d MiB (out of total %d MiB), %d iterations\n",
-        QUICK_TESTS, mem2test, devmem, 1);
+    printf(">> Running CUSTOM memtests [%x] on %d MiB, %d iterations\n",
+        QUICK_TESTS, mem2test, 1);
 #endif
 
     res = do_memtest(QUICK_TESTS, mem2test, 1);
@@ -563,7 +601,7 @@ int do_custom_memtest(int dev_id)
 }
 
 #if _DEBUG_ > 1
-/**
+/*!
  * Only for debugging purposes, compile with:
  * nvcc -DLINUX -D_DEBUG_=2  -L -O  -Xcompiler -Wall memtestG80_core.o gmx_gpu_utils.cu  -o gmx_gpu_utils_test
  */
@@ -572,7 +610,7 @@ int main( int argc, char** argv)
     int dev_id = 0;
     char msg[100];
     sprintf(msg, "Device #%d supported: ", dev_id);
-    switch (is_supported_cuda_gpu(dev_id))
+    switch (is_supported_cuda_gpu(dev_id, NULL))
     {
         case -1: strcat(msg, "error occured"); break;
         case  0: strcat(msg, "no"); break;
@@ -583,7 +621,62 @@ int main( int argc, char** argv)
 
     printf("Doing memtest.\n");
     printf("quick memtest result: %d\n", do_quick_memtest(dev_id));
+    printf("timed memtest result: %d\n", do_timed_memtest(dev_id, 15));
     printf("full memtest result: %d\n", do_full_memtest(dev_id));
     return 0;
 }
 #endif
+
+
+#ifndef _string2_h
+#include <string.h>
+/* 
+    Functions only used if this file is compiled in debug mode (_DEBUG_ > 0)
+    when the gromacs version are not available.
+    - string trimming function - duplicated from ~/src/gmxlib/string2.c 
+    - case agnostic straing compare
+ */
+static void ltrim (char *str)
+{
+  char *tr;
+  int c;
+
+  if (!str)
+    return;
+
+  tr = strdup (str);
+  c  = 0;
+  while ((tr[c] == ' ') || (tr[c] == '\t'))
+    c++;
+
+  strcpy (str,tr+c);
+  free (tr);
+}
+
+static void rtrim (char *str)
+{
+  int nul;
+
+  if (!str)
+    return;
+
+  nul = strlen(str)-1;
+  while ((nul > 0) && ((str[nul] == ' ') || (str[nul] == '\t')) ) {
+    str[nul] = '\0';
+    nul--;
+  }
+}
+
+static void trim (char *str)
+{
+  ltrim (str);
+  rtrim (str);
+}
+
+static int gmx_strncasecmp(const char* s1, const char* s2, int len)
+{
+  return strncasecmp(s1, s2, len);
+}
+#endif
+
+/*! \endcond TEST */
index 1fd37b445cd913716092e3aa420753888840f61f..76070804eafe41f3ddeec2e56a8277cdd6831454 100644 (file)
@@ -1,3 +1,38 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
 #ifndef _GMX_GPU_UTILS_H_
 #define _GMX_GPU_UTILS_H_
 
 extern "C" {
 #endif
 
-/** Runs a quick memory test and returns 0 in case if no error is detected. */
 int do_quick_memtest(int /*dev_id*/);
 
-/** Runs a full memory test and returns 0 in case if no error is detected. */
 int do_full_memtest(int /*dev_id*/);
 
-/** Runs a time constrained memory test and returns 0 in case if no error is detected. */
 int do_timed_memtest(int /*dev_id*/, int /*time_limit*/);
 
-/** Checks whether the GPU with the given device id is supported or not. */
 int is_supported_cuda_gpu(int /*dev_id*/, char* /*gpu_name*/);
 
 #ifndef __cplusplus
index 7248fa1f67268025e6d6b8e93dff6aefaf127a5d..44ef0d8ec6d716ad81da2a7a63582732f603f35a 100644 (file)
-/*\r
- * memtestG80_core.h\r
- * Public API for core memory test functions for MemtestG80\r
- * Includes functional and OO interfaces to GPU test functions.\r
- *\r
- * Author: Imran Haque, 2009\r
- * Copyright 2009, Stanford University\r
- *\r
- * This file is licensed under the terms of the LGPL. Please see\r
- * the COPYING file in the accompanying source distribution for\r
- * full license terms.\r
- *\r
- */\r
-#ifndef _MEMTESTG80_CORE_H_\r
-#define _MEMTESTG80_CORE_H_\r
-\r
-#if defined (WINDOWS) || defined (WINNV)\r
-    #include <windows.h>\r
-    inline unsigned int getTimeMilliseconds(void) {\r
-        return GetTickCount();\r
-    }\r
-    #include <windows.h>\r
-       #define SLEEPMS(x) Sleep(x)\r
-#elif defined (LINUX) || defined (OSX)\r
-    #include <sys/time.h>\r
-    inline unsigned int getTimeMilliseconds(void) {\r
-        struct timeval tv;\r
-        gettimeofday(&tv,NULL);\r
-        return tv.tv_sec*1000 + tv.tv_usec/1000;\r
-    }\r
-    #include <unistd.h>\r
-    #define SLEEPMS(x) usleep(x*1000)\r
-#else\r
-    #error Must #define LINUX, WINDOWS, WINNV, or OSX\r
-#endif\r
-\r
-// By default the driver will spinwait when blocked on a kernel call\r
-// Use the SOFTWAIT macro to replace this with a thread sleep and occasional poll\r
-// limit expresses the max time we're willing to stay in the sleep loop - default = 15sec\r
-inline int _pollStatus(unsigned length=1,unsigned limit=15000) {\r
-    //while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(length);}\r
-    unsigned startTime = getTimeMilliseconds();\r
-    while (cudaStreamQuery(0) == cudaErrorNotReady) {\r
-        if ((getTimeMilliseconds() - startTime) > limit) return -1;\r
-        SLEEPMS(length);\r
-    }\r
-    return 0;\r
-}\r
-#define SOFTWAIT() if (_pollStatus() != 0) {return 0xFFFFFFFE;} // -2\r
-#define SOFTWAIT_LIM(lim) if (_pollStatus(1,lim) != 0) {return 0xFFFFFFFE;} // -2\r
-//#define SOFTWAIT()\r
-//#define SOFTWAIT(delay) if (_pollStatus(delay) != 0) return -2;\r
-//#define SOFTWAIT(delay,limit) if (_pollStatus(delay,limit) != 0) return -2;\r
-//#define SOFTWAIT() while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(1);}\r
-//#define SOFTWAIT(x) while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(x);}\r
-//#define SOFTWAIT()\r
-\r
-// Use this macro to check for kernel errors\r
-#define CHECK_LAUNCH_ERROR() if (cudaGetLastError() != cudaSuccess) {return 0xFFFFFFFF; /* -1 */}\r
-\r
-\r
-typedef unsigned int uint;\r
-\r
-// OO interface to MemtestG80 functions\r
-class memtestState {\r
-protected:\r
-       const uint nBlocks;\r
-       const uint nThreads;\r
-    uint loopIters;\r
-       uint megsToTest;\r
-    int lcgPeriod;\r
-       uint* devTestMem;\r
-       uint* devTempMem;\r
-       uint* hostTempMem;\r
-       bool allocated;\r
-public:\r
-    uint initTime;\r
-       memtestState() : nBlocks(1024), nThreads(512), allocated(false), devTestMem(NULL),devTempMem(NULL),hostTempMem(NULL), initTime(0),lcgPeriod(1024) {};\r
-    ~memtestState() {deallocate();}\r
-\r
-       uint allocate(uint mbToTest);\r
-       void deallocate();\r
-       bool isAllocated() const {return allocated;}\r
-       uint size() const {return megsToTest;}\r
-    void setLCGPeriod(int period) {lcgPeriod = period;}\r
-    int getLCGPeriod() const {return lcgPeriod;}\r
-\r
-    bool gpuMemoryBandwidth(double& bandwidth,uint mbToTest,uint iters=5);\r
-       bool gpuWriteConstant(const uint constant) const;\r
-       bool gpuVerifyConstant(uint& errorCount,const uint constant) const;\r
-       bool gpuShortLCG0(uint& errorCount,const uint repeats) const;\r
-       bool gpuShortLCG0Shmem(uint& errorCount,const uint repeats) const;\r
-       bool gpuMovingInversionsOnesZeros(uint& errorCount) const;\r
-       bool gpuWalking8BitM86(uint& errorCount,const uint shift) const;\r
-       bool gpuWalking8Bit(uint& errorCount,const bool ones,const uint shift) const;\r
-       bool gpuMovingInversionsRandom(uint& errorCount) const;\r
-       bool gpuWalking32Bit(uint& errorCount,const bool ones,const uint shift) const;\r
-       bool gpuRandomBlocks(uint& errorCount,const uint seed) const;\r
-       bool gpuModuloX(uint& errorCount,const uint shift,const uint pattern,const uint modulus,const uint overwriteIters) const;\r
-};\r
-\r
-// Utility functions\r
-__host__ double gpuMemoryBandwidth(uint* src,uint* dst,uint mbToTest,uint iters);\r
-__host__ void gpuWriteConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);\r
-__host__ uint gpuVerifyConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant,uint* blockErrorCount,uint* errorCounts);\r
-\r
-__host__ void cpuWriteConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);\r
-__host__ uint cpuVerifyConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);\r
-\r
-// Logic tests\r
-__host__ uint gpuShortLCG0(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint repeats,const int period,uint* blockErrorCounts,uint* errorCounts);\r
-__host__ uint gpuShortLCG0Shmem(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint repeats,const int period,uint* blockErrorCounts,uint* errorCounts);\r
-\r
-// Memtest86 Test 2: tseq=0,4\r
-__host__ uint gpuMovingInversionsOnesZeros(const uint nBlocks,const uint nThreads,uint* base,uint N,uint* blockErrorCounts,uint* errorCounts);\r
-\r
-// Memtest86 Test 3: tseq=1\r
-__host__ uint gpuWalking8BitM86(const uint nBlocks,const uint nThreads,uint* base,uint N,uint shift,uint* blockErrorCounts,uint* errorCounts);\r
-__host__ uint cpuWalking8BitM86(const uint nBlocks,const uint nThreads,uint* base,uint N,uint shift);\r
-__host__ uint gpuWalking8Bit(const uint nBlocks,const uint nThreads,uint* base,uint N,bool ones,uint shift,uint* blockErrorCount,uint* errorCounts);\r
-\r
-// Memtest86 Test 4: tseq=10\r
-__host__ uint gpuMovingInversionsRandom(const uint nBlocks,const uint nThreads,uint* base,uint N,uint* blockErrorCounts,uint* errorCounts);\r
-\r
-// Memtest86 Test 6: tseq=2\r
-__host__ uint gpuWalking32Bit(const uint nBlocks,const uint nThreads,uint* base,uint N,bool ones,uint shift,uint* blockErrorCount,uint* errorCounts);\r
-//\r
-// Memtest86 Test 7: tseq=9\r
-__host__ uint gpuRandomBlocks(const uint nBlocks,const uint nThreads,uint* base,uint N,uint seed,uint* blockErrorCount,uint* errorCounts);\r
-\r
-// Memtest86 Test 8: tseq=3 (M86 uses modulus = 20)\r
-__host__ uint gpuModuloX(const uint nBlocks,const uint nThreads,uint* base,const uint N,uint shift,uint pattern1,const uint modulus,const uint iters,uint* blockErrorCount,uint* errorCounts);\r
-\r
-#endif\r
+/*
+ * memtestG80_core.h
+ * Public API for core memory test functions for MemtestG80
+ * Includes functional and OO interfaces to GPU test functions.
+ *
+ * Author: Imran Haque, 2009
+ * Copyright 2009, Stanford University
+ *
+ * This file is licensed under the terms of the LGPL. Please see
+ * the COPYING file in the accompanying source distribution for
+ * full license terms.
+ *
+ */
+#ifndef _MEMTESTG80_CORE_H_
+#define _MEMTESTG80_CORE_H_
+
+#if defined (WINDOWS) || defined (WINNV)
+    #include <windows.h>
+    inline unsigned int getTimeMilliseconds(void) {
+        return GetTickCount();
+    }
+    #include <windows.h>
+       #define SLEEPMS(x) Sleep(x)
+#elif defined (LINUX) || defined (OSX)
+    #include <sys/time.h>
+    inline unsigned int getTimeMilliseconds(void) {
+        struct timeval tv;
+        gettimeofday(&tv,NULL);
+        return tv.tv_sec*1000 + tv.tv_usec/1000;
+    }
+    #include <unistd.h>
+    #define SLEEPMS(x) usleep(x*1000)
+#else
+    #error Must #define LINUX, WINDOWS, WINNV, or OSX
+#endif
+
+// By default the driver will spinwait when blocked on a kernel call
+// Use the SOFTWAIT macro to replace this with a thread sleep and occasional poll
+// limit expresses the max time we're willing to stay in the sleep loop - default = 15sec
+inline int _pollStatus(unsigned length=1,unsigned limit=15000) {
+    //while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(length);}
+    unsigned startTime = getTimeMilliseconds();
+    while (cudaStreamQuery(0) == cudaErrorNotReady) {
+        if ((getTimeMilliseconds() - startTime) > limit) return -1;
+        SLEEPMS(length);
+    }
+    return 0;
+}
+#define SOFTWAIT() if (_pollStatus() != 0) {return 0xFFFFFFFE;} // -2
+#define SOFTWAIT_LIM(lim) if (_pollStatus(1,lim) != 0) {return 0xFFFFFFFE;} // -2
+//#define SOFTWAIT()
+//#define SOFTWAIT(delay) if (_pollStatus(delay) != 0) return -2;
+//#define SOFTWAIT(delay,limit) if (_pollStatus(delay,limit) != 0) return -2;
+//#define SOFTWAIT() while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(1);}
+//#define SOFTWAIT(x) while (cudaStreamQuery(0) != cudaSuccess) {SLEEPMS(x);}
+//#define SOFTWAIT()
+
+// Use this macro to check for kernel errors
+#define CHECK_LAUNCH_ERROR() if (cudaGetLastError() != cudaSuccess) {return 0xFFFFFFFF; /* -1 */}
+
+
+typedef unsigned int uint;
+
+// OO interface to MemtestG80 functions
+class memtestState {
+protected:
+       const uint nBlocks;
+       const uint nThreads;
+    uint loopIters;
+       uint megsToTest;
+    int lcgPeriod;
+       uint* devTestMem;
+       uint* devTempMem;
+       uint* hostTempMem;
+       bool allocated;
+public:
+    uint initTime;
+       memtestState() : nBlocks(1024), nThreads(512), allocated(false), devTestMem(NULL),devTempMem(NULL),hostTempMem(NULL), initTime(0),lcgPeriod(1024) {};
+    ~memtestState() {deallocate();}
+
+       uint allocate(uint mbToTest);
+       void deallocate();
+       bool isAllocated() const {return allocated;}
+       uint size() const {return megsToTest;}
+    void setLCGPeriod(int period) {lcgPeriod = period;}
+    int getLCGPeriod() const {return lcgPeriod;}
+
+    bool gpuMemoryBandwidth(double& bandwidth,uint mbToTest,uint iters=5);
+       bool gpuWriteConstant(const uint constant) const;
+       bool gpuVerifyConstant(uint& errorCount,const uint constant) const;
+       bool gpuShortLCG0(uint& errorCount,const uint repeats) const;
+       bool gpuShortLCG0Shmem(uint& errorCount,const uint repeats) const;
+       bool gpuMovingInversionsOnesZeros(uint& errorCount) const;
+       bool gpuWalking8BitM86(uint& errorCount,const uint shift) const;
+       bool gpuWalking8Bit(uint& errorCount,const bool ones,const uint shift) const;
+       bool gpuMovingInversionsRandom(uint& errorCount) const;
+       bool gpuWalking32Bit(uint& errorCount,const bool ones,const uint shift) const;
+       bool gpuRandomBlocks(uint& errorCount,const uint seed) const;
+       bool gpuModuloX(uint& errorCount,const uint shift,const uint pattern,const uint modulus,const uint overwriteIters) const;
+};
+
+// Utility functions
+__host__ double gpuMemoryBandwidth(uint* src,uint* dst,uint mbToTest,uint iters);
+__host__ void gpuWriteConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);
+__host__ uint gpuVerifyConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant,uint* blockErrorCount,uint* errorCounts);
+
+__host__ void cpuWriteConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);
+__host__ uint cpuVerifyConstant(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint constant);
+
+// Logic tests
+__host__ uint gpuShortLCG0(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint repeats,const int period,uint* blockErrorCounts,uint* errorCounts);
+__host__ uint gpuShortLCG0Shmem(const uint nBlocks,const uint nThreads,uint* base,uint N,const uint repeats,const int period,uint* blockErrorCounts,uint* errorCounts);
+
+// Memtest86 Test 2: tseq=0,4
+__host__ uint gpuMovingInversionsOnesZeros(const uint nBlocks,const uint nThreads,uint* base,uint N,uint* blockErrorCounts,uint* errorCounts);
+
+// Memtest86 Test 3: tseq=1
+__host__ uint gpuWalking8BitM86(const uint nBlocks,const uint nThreads,uint* base,uint N,uint shift,uint* blockErrorCounts,uint* errorCounts);
+__host__ uint cpuWalking8BitM86(const uint nBlocks,const uint nThreads,uint* base,uint N,uint shift);
+__host__ uint gpuWalking8Bit(const uint nBlocks,const uint nThreads,uint* base,uint N,bool ones,uint shift,uint* blockErrorCount,uint* errorCounts);
+
+// Memtest86 Test 4: tseq=10
+__host__ uint gpuMovingInversionsRandom(const uint nBlocks,const uint nThreads,uint* base,uint N,uint* blockErrorCounts,uint* errorCounts);
+
+// Memtest86 Test 6: tseq=2
+__host__ uint gpuWalking32Bit(const uint nBlocks,const uint nThreads,uint* base,uint N,bool ones,uint shift,uint* blockErrorCount,uint* errorCounts);
+//
+// Memtest86 Test 7: tseq=9
+__host__ uint gpuRandomBlocks(const uint nBlocks,const uint nThreads,uint* base,uint N,uint seed,uint* blockErrorCount,uint* errorCounts);
+
+// Memtest86 Test 8: tseq=3 (M86 uses modulus = 20)
+__host__ uint gpuModuloX(const uint nBlocks,const uint nThreads,uint* base,const uint N,uint shift,uint pattern1,const uint modulus,const uint iters,uint* blockErrorCount,uint* errorCounts);
+
+#endif
index 1ee01e110fb232bcdd56ccaec94189545e43fd2f..79d1ffb84734c08c5b623bf1db96384dde25ddfe 100644 (file)
@@ -108,7 +108,7 @@ static void tpx2params(FILE *fp,t_inputrec *ir)
   fprintf(fp,"\\subsection{Simulation settings}\n");
   fprintf(fp,"A total of %g ns were simulated with a time step of %g fs.\n",
          ir->nsteps*ir->delta_t*0.001,1000*ir->delta_t);
-  fprintf(fp,"Neighborsearching was performed every %d steps.\n",ir->nstlist);
+  fprintf(fp,"Neighbor searching was performed every %d steps.\n",ir->nstlist);
   fprintf(fp,"The %s algorithm was used for electrostatic interactions.\n",
          EELTYPE(ir->coulombtype));
   fprintf(fp,"with a cut-off of %g nm.\n",ir->rcoulomb);  
@@ -247,7 +247,7 @@ void chk_trj(const output_env_t oenv,const char *fn,const char *tpr,real tol)
   off_t        fpos;
   real         rdum,tt,old_t1,old_t2,prec;
   bool         bShowTimestep=TRUE,bOK,newline=FALSE;
-  int          status;
+  t_trxstatus *status;
   gmx_mtop_t   mtop;
   gmx_localtop_t *top;
   t_state      state;
@@ -339,7 +339,7 @@ void chk_trj(const output_env_t oenv,const char *fn,const char *tpr,real tol)
     INC(fr,count,first,last,bF);
     INC(fr,count,first,last,bBox);
 #undef INC
-    fpos = gmx_fio_ftell(status);
+    fpos = gmx_fio_ftell(trx_get_fileio(status));
   } while (read_next_frame(oenv,status,&fr));
   
   fprintf(stderr,"\n");
@@ -605,13 +605,13 @@ int main(int argc,char *argv[])
     "radii) and atoms outside the box (these may occur often and are",
     "no problem). If velocities are present, an estimated temperature",
     "will be calculated from them.[PAR]",
-    "If an index file is given it's contents will be sumamrized.[PAR]",
+    "If an index file, is given its contents will be summarized.[PAR]",
     "If both a trajectory and a tpr file are given (with [TT]-s1[tt])",
     "the program will check whether the bond lengths defined in the tpr",
     "file are indeed correct in the trajectory. If not you may have",
     "non-matching files due to e.g. deshuffling or due to problems with",
-    "virtual sites. With these flags, gmxcheck provides a quick check for such problems.[PAR]"
-    "The program can compare run two input ([TT].tpr[tt], [TT].tpb[tt] or",
+    "virtual sites. With these flags, gmxcheck provides a quick check for such problems.[PAR]",
+    "The program can compare two run input ([TT].tpr[tt], [TT].tpb[tt] or",
     "[TT].tpa[tt]) files",
     "when both [TT]-s1[tt] and [TT]-s2[tt] are supplied.",
     "Similarly a pair of trajectory files can be compared (using the [TT]-f2[tt]",
@@ -619,7 +619,7 @@ int main(int argc,char *argv[])
     "For free energy simulations the A and B state topology from one",
     "run input file can be compared with options [TT]-s1[tt] and [TT]-ab[tt].[PAR]",
     "In case the [TT]-m[tt] flag is given a LaTeX file will be written",
-    "consisting a rough outline for a methods section for a paper."
+    "consisting of a rough outline for a methods section for a paper."
   };
   t_filenm fnm[] = {
     { efTRX, "-f",  NULL, ffOPTRD },
index c6f023b2154eb515230a0ab659546ae6a652cd75..2beb70aee23daca42e7cb672f3222694ae3548c7 100644 (file)
@@ -207,7 +207,8 @@ static void list_top(const char *fn)
 
 static void list_trn(const char *fn)
 {
-  int         fpread,fpwrite,nframe,indent;
+  t_fileio    *fpread, *fpwrite;
+  int         nframe,indent;
   char        buf[256];
   rvec        *x,*v,*f;
   matrix      box;
@@ -261,7 +262,8 @@ static void list_trn(const char *fn)
 
 void list_xtc(const char *fn, bool bXVG)
 {
-  int    xd,indent;
+  t_fileio *xd;
+  int    indent;
   char   buf[256];
   rvec   *x;
   matrix box;
index 8d4ef04a34a5e5abd058c10d230cbae469b0cfe3..a5541f84f26aca80b33c67cc3e37adaaa1c06a11 100644 (file)
@@ -68,8 +68,9 @@ int get_atomtype_type(const char *str,gpp_atomtype_t ga)
 {
   int i;
 
+  /* Atom types are always case sensitive */
   for (i=0; (i<ga->nr); i++)
-    if (strcasecmp(str,*(ga->atomname[i])) == 0)
+    if (strcmp(str,*(ga->atomname[i])) == 0)
       return i;
   
   return NOTSET;
@@ -265,7 +266,8 @@ int add_atomtype(gpp_atomtype_t ga,t_symtab *tab,
   
   for(i=0; (i<ga->nr); i++) {
     if (strcmp(*ga->atomname[i],name) == 0) {
-      fprintf(stderr,"Trying to add atomtype %s again. Skipping it.\n",name);
+      if (NULL != debug)
+       fprintf(debug,"Trying to add atomtype %s again. Skipping it.\n",name);
       break;
     }
   }
index e11fdf523c9cdf0e03367f3126fc4c3b7bc1c35d..807639b7b0d737ce5d8aa1ad4b085dc277bb7461 100644 (file)
@@ -436,7 +436,7 @@ static void cont_status(const char *slog,const char *ener,
      /* If fr_time == -1 read the last frame available which is complete */
 {
   t_trxframe  fr;
-  int         fp;
+  t_trxstatus *fp;
 
   fprintf(stderr,
          "Reading Coordinates%s and Box size from old trajectory\n",
@@ -935,12 +935,12 @@ int main (int argc, char *argv[])
     "unless the [TT]-time[tt] option is used.",
     "Note that these velocities will not be used when [TT]gen_vel = yes[tt]",
     "in your [TT].mdp[tt] file. An energy file can be supplied with",
-    "[TT]-e[tt] to have exact restarts when using pressure and/or",
-    "Nose-Hoover temperature coupling. For an exact restart do not forget",
-    "to turn off velocity generation and turn on unconstrained starting",
-    "when constraints are present in the system.",
-    "If you want to continue a crashed run, it is",
-    "easier to use [TT]tpbconv[tt].[PAR]",
+    "[TT]-e[tt] to read Nose-Hoover and/or Parrinello-Rahman coupling",
+    "variables. Note that for continuation it is better and easier to supply",
+    "a checkpoint file directly to mdrun, since that always contains",
+    "the complete state of the system and you don't need to generate",
+    "a new run input file. Note that if you only want to change the number",
+    "of run steps tpbconv is more convenient than grompp.[PAR]",
 
     "Using the [TT]-morse[tt] option grompp can convert the harmonic bonds",
     "in your topology to morse potentials. This makes it possible to break",
@@ -1013,6 +1013,8 @@ int main (int argc, char *argv[])
   static int  i,maxwarn=0;
   static real fr_time=-1;
   t_pargs pa[] = {
+    { "-v",       FALSE, etBOOL,{&bVerbose},  
+      "Be loud and noisy" },
     { "-time",    FALSE, etREAL, {&fr_time},
       "Take frame at or first after this time." },
     { "-rmvsbds",FALSE, etBOOL, {&bRmVSBds},
@@ -1035,7 +1037,6 @@ int main (int argc, char *argv[])
   /* Parse the command line */
   parse_common_args(&argc,argv,0,NFILE,fnm,asize(pa),pa,
                     asize(desc),desc,0,NULL,&oenv);
-  bVerbose = (output_env_get_verbosity(oenv) > 0);
   
   wi = init_warning(TRUE,maxwarn);
   
@@ -1262,7 +1263,7 @@ int main (int argc, char *argv[])
     if (ir->ePBC==epbcXY && ir->nwall==2)
       svmul(ir->wall_ewald_zfac,box[ZZ],box[ZZ]);
     max_spacing = calc_grid(stdout,box,opts->fourierspacing,
-                           &(ir->nkx),&(ir->nky),&(ir->nkz),1);
+                            &(ir->nkx),&(ir->nky),&(ir->nkz));
     if ((ir->coulombtype == eelPPPM) && (max_spacing > 0.1)) {
         set_warning_line(wi,mdparin,-1);
         warning_note(wi,"Grid spacing larger then 0.1 while using PPPM.");
index 42fcda58d1f2bedd6dc17340aecd1f347a20e13d..ea167b08225a1950978cbabc3022cc026b931c77 100644 (file)
@@ -95,14 +95,17 @@ void read_ab(char *line,const char *fn,t_hack *hack)
   hack->nctl = ns - 3;
   if ((hack->nctl != ncontrol[hack->tp]) && (ncontrol[hack->tp] != -1))
     gmx_fatal(FARGS,"Error in hdb file %s:\nWrong number of control atoms (%d iso %d) on line:\n%s\n",fn,hack->nctl,ncontrol[hack->tp],line);
-  for(i=0; (i<hack->nctl); i++) 
+  for(i=0; (i<hack->nctl); i++) {
     hack->a[i]=strdup(a[i]);
-  for(   ; i<4; i++)
+  }
+  for(   ; i<4; i++) {
     hack->a[i]=NULL;
+  }
   hack->oname=NULL;
   hack->nname=strdup(hn);
   hack->atom=NULL;
   hack->cgnr=NOTSET;
+  hack->bXSet=FALSE;
   for(i=0; i<DIM; i++)
     hack->newx[i]=NOTSET;
 }
@@ -187,7 +190,7 @@ static void read_h_db_file(const char *hfn,int *nahptr,t_hackblock **ah)
   *ah     = aah;
 }
 
-int read_h_db(const char *ffdir,t_hackblock **ah)
+int read_h_db(const char *ffdir,bool bAddCWD,t_hackblock **ah)
 {
   int  nhdbf,f;
   char **hdbf;
@@ -197,7 +200,7 @@ int read_h_db(const char *ffdir,t_hackblock **ah)
   /* Read the hydrogen database file(s).
    * Do not generate an error when no files are found.
    */
-  nhdbf = fflib_search_file_end(ffdir,".hdb",FALSE,&hdbf);
+  nhdbf = fflib_search_file_end(ffdir,bAddCWD,".hdb",FALSE,&hdbf);
   nah = 0;
   *ah = NULL;
   for(f=0; f<nhdbf; f++) {
index 6329e67b71fc3d666de739383e9bad1c2a5ea153..53d69f455d4195f4c9966083c0ba1c01f6ce51d6 100644 (file)
@@ -47,7 +47,7 @@ extern const int ncontrol[];
 extern void read_ab(char *line,const char *fn,t_hack *ab);
 /* Read one add block */
 
-extern int read_h_db(const char *ffdir,t_hackblock **ah);
+extern int read_h_db(const char *ffdir,bool bAddCWD,t_hackblock **ah);
 /* Read the database from hdb file(s) in ffdir or current dir */
 
 extern void print_ab(FILE *out,t_hack *ab,char *nname);
index 543c59ea56e2c501ab5d8ff36396ea430a2df30e..8d8386d905af2de7c17c66badf96570bf57f3fb3 100644 (file)
@@ -189,7 +189,7 @@ void set_histp(t_atoms *pdba,rvec *x,real angle,real dist){
   bool bHDd,bHEd;
   rvec xh1,xh2;
   int  natom;
-  int  i,j,nd,na,aj,hisind,his0,type=-1;
+  int  i,nd,na,aj,hisind,his0,type=-1;
   int  nd1,ne2,cg,cd2,ce1;
   t_blocka *hb;
   real d;
@@ -229,18 +229,20 @@ void set_histp(t_atoms *pdba,rvec *x,real angle,real dist){
        
        /* Find the  atoms in the ring */
        nd1=ne2=cg=cd2=ce1=-1;
-       for(j=i; (pdba->atom[j].resind==hisind) && (j<natom); j++) {
-         atomnm=*pdba->atomname[j];
+       while (i<natom && pdba->atom[i].resind==hisind) {
+         atomnm = *pdba->atomname[i];
          if (strcmp(atomnm,"CD2") == 0)
-           cd2=j;
+           cd2 = i;
          else if (strcmp(atomnm,"CG") == 0)
-           cg=j;
+           cg  = i;
          else if (strcmp(atomnm,"CE1") == 0)
-           ce1=j;
+           ce1 = i;
          else if (strcmp(atomnm,"ND1") == 0)
-           nd1=j;
+           nd1 = i;
          else if (strcmp(atomnm,"NE2") == 0)
-           ne2=j;
+           ne2 = i;
+
+         i++;
        }
        
        if (!((cg == -1 ) || (cd2 == -1) || (ce1 == -1) ||
@@ -268,8 +270,8 @@ void set_histp(t_atoms *pdba,rvec *x,real angle,real dist){
          gmx_fatal(FARGS,"Incomplete ring in HIS%d",
                    pdba->resinfo[hisind].nr);
        
-       sfree(*pdba->resinfo[hisind].name);
-       *pdba->resinfo[hisind].name = strdup(hh[type]);
+       snew(pdba->resinfo[hisind].rtp,1);
+       *pdba->resinfo[hisind].rtp = strdup(hh[type]);
       }
     }
   }
index 8f6a0931d32bc61b919fe22f1e03d361e58d8ceb..3b420b75a6c9235c2820d739caef7366630549ac 100644 (file)
 #endif
 
 
-
-enum { eglsNABNSB, eglsCHKPT, eglsTERM, eglsRESETCOUNTERS, eglsNR };
+/* simulation conditions to transmit. Keep in mind that they are 
+   transmitted to other nodes through an MPI_Reduce after
+   casting them to a real (so the signals can be sent together with other 
+   data). This means that the only meaningful values are positive, 
+   negative or zero. */
+enum { eglsNABNSB, eglsCHKPT, eglsSTOPCOND, eglsRESETCOUNTERS, eglsNR };
 /* Is the signal in one simulation independent of other simulations? */
 bool gs_simlocal[eglsNR] = { TRUE, FALSE, FALSE, TRUE };
 
@@ -309,10 +313,12 @@ static void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr,
 
     /* we calculate a full state kinetic energy either with full-step velocity verlet
        or half step where we need the pressure */
-    bEkinAveVel = (ir->eI==eiVV || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir) && bPres) || bReadEkin);
-
+    /*bEkinAveVel = (ir->eI==eiVV || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir) && bPres) || bReadEkin);*/
+    
+    bEkinAveVel = (ir->eI==eiVV || (ir->eI==eiVVAK && bPres) || bReadEkin);
+    
     /* in initalization, it sums the shake virial in vv, and to 
-       sums ekinh_old in leapfrog (or if we are calculating ekinh_old for other reasons */
+       sums ekinh_old in leapfrog (or if we are calculating ekinh_old) for other reasons */
 
     /* ########## Kinetic energy  ############## */
     
@@ -435,9 +441,9 @@ static void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr,
     if (bTemp) 
     {
         /* Sum the kinetic energies of the groups & calc temp */
-        /* compute full step kinetic energies if vv, or if vv2 and we are computing the pressure with IR_NPT_TROTTER */
+        /* compute full step kinetic energies if vv, or if vv-avek and we are computing the pressure with IR_NPT_TROTTER */
         /* three maincase:  VV with AveVel (md-vv), vv with AveEkin (md-vv-avek), leap with AveEkin (md).  
-           Leap with AveVel is also an option for the future but not supported now.  
+           Leap with AveVel is not supported; it's not clear that it will actually work.  
            bEkinAveVel: If TRUE, we simply multiply ekin by ekinscale to get a full step kinetic energy. 
            If FALSE, we average ekinh_old and ekinh*ekinscale_nhc to get an averaged half step kinetic energy.
            bSaveEkinOld: If TRUE (in the case of iteration = bIterate is TRUE), we don't reset the ekinscale_nhc.  
@@ -829,15 +835,15 @@ void check_ir_old_tpx_versions(t_commrec *cr,FILE *fplog,
         }
         check_nst_param(fplog,cr,"nstlist",ir->nstlist,
                         "nstcalcenergy",&ir->nstcalcenergy);
-    }
-    check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
-                    "nstenergy",&ir->nstenergy);
-    check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
-                    "nstlog",&ir->nstlog);
-    if (ir->efep != efepNO)
-    {
-        check_nst_param(fplog,cr,"nstdhdl",ir->nstdhdl,
+        check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
                         "nstenergy",&ir->nstenergy);
+        check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+                        "nstlog",&ir->nstlog);
+        if (ir->efep != efepNO)
+        {
+            check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+                            "nstdhdl",&ir->nstdhdl);
+        }
     }
 }
 
@@ -947,6 +953,47 @@ static void set_nlistheuristics(gmx_nlheur_t *nlh,bool bReset,gmx_large_int_t st
     }
 }
 
+static void rerun_parallel_comm(t_commrec *cr,t_trxframe *fr,
+                                bool *bNotLastFrame)
+{
+    bool bAlloc;
+    rvec *xp,*vp;
+
+    bAlloc = (fr->natoms == 0);
+
+    if (MASTER(cr) && !*bNotLastFrame)
+    {
+        fr->natoms = -1;
+    }
+    xp = fr->x;
+    vp = fr->v;
+    gmx_bcast(sizeof(*fr),fr,cr);
+    fr->x = xp;
+    fr->v = vp;
+
+    *bNotLastFrame = (fr->natoms >= 0);
+
+    if (*bNotLastFrame && PARTDECOMP(cr))
+    {
+        /* x and v are the only variable size quantities stored in trr
+         * that are required for rerun (f is not needed).
+         */
+        if (bAlloc)
+        {
+            snew(fr->x,fr->natoms);
+            snew(fr->v,fr->natoms);
+        }
+        if (fr->bX)
+        {
+            gmx_bcast(fr->natoms*sizeof(fr->x[0]),fr->x[0],cr);
+        }
+        if (fr->bV)
+        {
+            gmx_bcast(fr->natoms*sizeof(fr->v[0]),fr->v[0],cr);
+        }
+    }
+}
+
 double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
              const output_env_t oenv, bool bVerbose,bool bCompact,
              int nstglobalcomm,
@@ -968,7 +1015,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     gmx_large_int_t step,step_rel;
     double     run_time;
     double     t,t0,lam0;
-    bool       bGStatEveryStep,bGStat,bNstEner,bCalcPres,bCalcEner;
+    bool       bGStatEveryStep,bGStat,bNstEner,bCalcEnerPres;
     bool       bNS,bNStList,bSimAnn,bStopCM,bRerunMD,bNotLastFrame=FALSE,
                bFirstStep,bStateFromTPX,bInitStep,bLastStep,
                bBornRadii,bStartingFromCpt;
@@ -979,7 +1026,8 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     bool       bMasterState;
     int        force_flags,cglo_flags;
     tensor     force_vir,shake_vir,total_vir,tmp_vir,pres;
-    int        i,m,status;
+    int        i,m;
+    t_trxstatus *status;
     rvec       mu_tot;
     t_vcm      *vcm;
     t_state    *bufstate=NULL;   
@@ -1013,7 +1061,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     bool        bTCR=FALSE,bConverged=TRUE,bOK,bSumEkinhOld,bExchanged;
     bool        bAppend;
     bool        bResetCountersHalfMaxH=FALSE;
-    bool        bVV,bIterations,bIterate,bFirstIterate,bTemp,bPres,bTrotter;
+    bool        bVV,bIterations,bFirstIterate,bTemp,bPres,bTrotter;
     real        temp0,mu_aver=0,dvdl;
     int         a0,a1,gnx=0,ii;
     atom_id     *grpindex=NULL;
@@ -1031,7 +1079,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
        t_extmass   MassQ;
     int         **trotter_seq; 
     char        sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
-    int         handledSignal=-1; /* compare to last_signal_recvd */
+    int         handled_stop_condition=gmx_stop_cond_none; /* compare to get_stop_condition*/
     gmx_iterate_t iterate;
 #ifdef GMX_FAHCORE
     /* Temporary addition for FAHCORE checkpointing */
@@ -1055,7 +1103,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     }
 
     /* md-vv uses averaged full step velocities for T-control 
-       md-vv2 uses averaged half step velocities for T-control (but full step ekin for P control)
+       md-vv-avek uses averaged half step velocities for T-control (but full step ekin for P control)
        md uses averaged half step kinetic energies to determine temperature unless defined otherwise by GMX_EKIN_AVE_VEL; */
     bVV = EI_VV(ir->eI);
     if (bVV) /* to store the initial velocities while computing virial */
@@ -1304,9 +1352,10 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                     top_global,&pcurr,top_global->natoms,&bSumEkinhOld,cglo_flags);
     if (ir->eI == eiVVAK) {
         /* a second call to get the half step temperature initialized as well */ 
-        /* we do the same call as above, but turn the pressure off -- internally, this 
-           is recognized as a velocity verlet half-step kinetic energy calculation.
-           This minimized excess variables, but perhaps loses some logic?*/
+        /* we do the same call as above, but turn the pressure off -- internally to 
+           compute_globals, this is recognized as a velocity verlet half-step 
+           kinetic energy calculation.  This minimized excess variables, but 
+           perhaps loses some logic?*/
         
         compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
                         wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
@@ -1351,7 +1400,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                     "RMS relative constraint deviation after constraining: %.2e\n",
                     constr_rmsd(constr,FALSE));
         }
-        if (bVV) 
+        if (!bVV) 
         {
             enerd->term[F_TEMP] *= 2; /* result of averages being done over previous and current step,
                                          and there is no previous step */
@@ -1428,27 +1477,39 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             bForceUpdate = TRUE;
         }
 
-        bNotLastFrame = read_first_frame(oenv,&status,
-                                         opt2fn("-rerun",nfile,fnm),
-                                         &rerun_fr,TRX_NEED_X | TRX_READ_V);
-        if (rerun_fr.natoms != top_global->natoms)
-        {
-            gmx_fatal(FARGS,
-                      "Number of atoms in trajectory (%d) does not match the "
-                      "run input file (%d)\n",
-                      rerun_fr.natoms,top_global->natoms);
-        }
-        if (ir->ePBC != epbcNONE)
+        rerun_fr.natoms = 0;
+        if (MASTER(cr))
         {
-            if (!rerun_fr.bBox)
+            bNotLastFrame = read_first_frame(oenv,&status,
+                                             opt2fn("-rerun",nfile,fnm),
+                                             &rerun_fr,TRX_NEED_X | TRX_READ_V);
+            if (rerun_fr.natoms != top_global->natoms)
             {
-                gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f does not contain a box, while pbc is used",rerun_fr.step,rerun_fr.time);
+                gmx_fatal(FARGS,
+                          "Number of atoms in trajectory (%d) does not match the "
+                          "run input file (%d)\n",
+                          rerun_fr.natoms,top_global->natoms);
             }
-            if (max_cutoff2(ir->ePBC,rerun_fr.box) < sqr(fr->rlistlong))
+            if (ir->ePBC != epbcNONE)
             {
-                gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f has too small box dimensions",rerun_fr.step,rerun_fr.time);
+                if (!rerun_fr.bBox)
+                {
+                    gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f does not contain a box, while pbc is used",rerun_fr.step,rerun_fr.time);
+                }
+                if (max_cutoff2(ir->ePBC,rerun_fr.box) < sqr(fr->rlistlong))
+                {
+                    gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f has too small box dimensions",rerun_fr.step,rerun_fr.time);
+                }
             }
+        }
+
+        if (PAR(cr))
+        {
+            rerun_parallel_comm(cr,&rerun_fr,&bNotLastFrame);
+        }
 
+        if (ir->ePBC != epbcNONE)
+        {
             /* Set the shift vectors.
              * Necessary here when have a static box different from the tpr box.
              */
@@ -1613,7 +1674,9 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             }
         } 
 
-        if (gs.set[eglsTERM] > 0 || (gs.set[eglsTERM] < 0 && bNS))
+        /* < 0 means stop at next step, > 0 means stop at next NS step */
+        if ( (gs.set[eglsSTOPCOND] < 0 ) ||
+             ( (gs.set[eglsSTOPCOND] > 0 ) && ( bNS || ir->nstlist==0)) )
         {
             bLastStep = TRUE;
         }
@@ -1727,26 +1790,22 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             gs.set[eglsCHKPT] = 0;
         }
 
-        /* Determine the pressure:
-         * always when we want exact averages in the energy file,
-         * at ns steps when we have pressure coupling,
-         * otherwise only at energy output steps (set below).
+        /* Determine the energy and pressure:
+         * at nstcalcenergy steps and at energy output steps (set below).
          */
         bNstEner = (bGStatEveryStep || do_per_step(step,ir->nstcalcenergy));
-        bCalcEner = bNstEner;
-        bCalcPres = (bNstEner || (ir->epc != epcNO && bNS));
+        bCalcEnerPres = bNstEner;
 
         /* Do we need global communication ? */
-        bGStat = (bCalcEner || bStopCM ||
+        bGStat = (bCalcEnerPres || bStopCM ||
                   (ir->nstlist == -1 && !bRerunMD && step >= nlh.step_nscheck));
 
         do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
 
         if (do_ene || do_log)
         {
-            bCalcPres = TRUE;
-            bCalcEner = TRUE;
-            bGStat    = TRUE;
+            bCalcEnerPres = TRUE;
+            bGStat        = TRUE;
         }
         
         /* these CGLO_ options remain the same throughout the iteration */
@@ -1761,7 +1820,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                        GMX_FORCE_ALLFORCES |
                        (bNStList ? GMX_FORCE_DOLR : 0) |
                        GMX_FORCE_SEPLRF |
-                       (bCalcEner ? GMX_FORCE_VIRIAL : 0) |
+                       (bCalcEnerPres ? GMX_FORCE_VIRIAL : 0) |
                        (bDoDHDL ? GMX_FORCE_DHDL : 0)
             );
         
@@ -1819,42 +1878,36 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         
         if (!bStartingFromCpt && !bRerunMD)
         {
-            if (ir->eI == eiVV)
+            if (ir->eI==eiVV && bInitStep) 
             {
-                if (bInitStep)
-                {
-                    /* if using velocity verlet with full time step Ekin,
-                     * take the first half step only to compute the 
-                     * virial for the first step. From there,
-                     * revert back to the initial coordinates
-                     * so that the input is actually the initial step.
-                     */
-                    copy_rvecn(state->v,cbuf,0,state->natoms); /* should make this better for parallelizing? */
-                }
-                
+                /* if using velocity verlet with full time step Ekin,
+                 * take the first half step only to compute the 
+                 * virial for the first step. From there,
+                 * revert back to the initial coordinates
+                 * so that the input is actually the initial step.
+                 */
+                copy_rvecn(state->v,cbuf,0,state->natoms); /* should make this better for parallelizing? */
+            } else {
                 /* this is for NHC in the Ekin(t+dt/2) version of vv */
-                if (!bInitStep)
-                {
-                    trotter_update(ir,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[1]);            
-                }
-                
-                update_coords(fplog,step,ir,mdatoms,state,
-                              f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
-                              ekind,M,wcycle,upd,bInitStep,etrtVELOCITY,
-                              cr,nrnb,constr,&top->idef);
-                
-                if (bIterations)
-                {
-                    gmx_iterate_init(&iterate,bIterations && !bInitStep);
-                }
-                /* for iterations, we save these vectors, as we will be self-consistently iterating
-                   the calculations */
-                /*#### UPDATE EXTENDED VARIABLES IN TROTTER FORMULATION */
-                
-                /* save the state */
-                if (bIterations && iterate.bIterate) { 
-                    copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
-                }
+                trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[1]);            
+            }
+            
+            update_coords(fplog,step,ir,mdatoms,state,
+                          f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+                          ekind,M,wcycle,upd,bInitStep,etrtVELOCITY,
+                          cr,nrnb,constr,&top->idef);
+            
+            if (bIterations)
+            {
+                gmx_iterate_init(&iterate,bIterations && !bInitStep);
+            }
+            /* for iterations, we save these vectors, as we will be self-consistently iterating
+               the calculations */
+            /*#### UPDATE EXTENDED VARIABLES IN TROTTER FORMULATION */
+            
+            /* save the state */
+            if (bIterations && iterate.bIterate) { 
+                copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
             }
             
             bFirstIterate = TRUE;
@@ -1874,7 +1927,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                            of veta.  */
                         
                         veta_save = state->veta;
-                        trotter_update(ir,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[0]);
+                        trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[0]);
                         vetanew = state->veta;
                         state->veta = veta_save;
                     } 
@@ -1887,7 +1940,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                     update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
                                        &top->idef,shake_vir,NULL,
                                        cr,nrnb,wcycle,upd,constr,
-                                       bInitStep,TRUE,bCalcPres,vetanew);
+                                       bInitStep,TRUE,bCalcEnerPres,vetanew);
                     
                     if (!bOK && !bFFscan)
                     {
@@ -1904,9 +1957,13 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                 
                 if (bVV) {
                     /* if VV, compute the pressure and constraints */
-                    /* if VV2, the pressure and constraints only if using pressure control.*/
-                    bPres = (ir->eI==eiVV || IR_NPT_TROTTER(ir)); 
-                    bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir)));
+                    /* For VV2, we strictly only need this if using pressure control, but we really would 
+                       like to have accurate pressures printed out.  Think about ways around this in the future?
+                       For now, keep this choice in comments  */
+                    /*bPres = (ir->eI==eiVV || IR_NPT_TROTTER(ir)); */
+                    /*bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir)));*/
+                    bPres = TRUE;
+                    bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK));
                     compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
                                     wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
                                     constr,NULL,FALSE,state->box,
@@ -1916,7 +1973,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                                     | (bTemp ? CGLO_TEMPERATURE:0) 
                                     | (bPres ? CGLO_PRESSURE : 0) 
                                     | (bPres ? CGLO_CONSTRAINT : 0)
-                                    | (iterate.bIterate ? CGLO_ITERATE : 0)  
+                                    | ((bIterations && iterate.bIterate) ? CGLO_ITERATE : 0)  
                                     | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
                                     | CGLO_SCALEEKIN 
                         );
@@ -1925,14 +1982,14 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                    a) We compute Ekin at the full time step
                    if 1) we are using the AveVel Ekin, and it's not the
                    initial step, or 2) if we are using AveEkin, but need the full
-                   time step kinetic energy for the pressure.
+                   time step kinetic energy for the pressure (always true now, since we want accurate statistics).
                    b) If we are using EkinAveEkin for the kinetic energy for the temperture control, we still feed in 
                    EkinAveVel because it's needed for the pressure */
                 
                 /* temperature scaling and pressure scaling to produce the extended variables at t+dt */
                 if (bVV && !bInitStep) 
                 {
-                    trotter_update(ir,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[2]);
+                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[2]);
                 }
                 
                 if (bIterations &&
@@ -2097,8 +2154,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
          */
     
         bNstEner = (bGStatEveryStep || do_per_step(step,ir->nstcalcenergy));
-        bCalcEner = bNstEner;
-        bCalcPres = (bNstEner || (ir->epc != epcNO && bNS));
+        bCalcEnerPres = bNstEner;
         
         /* Do we need global communication ? */
         bGStat = (bGStatEveryStep || bStopCM || bNS ||
@@ -2108,47 +2164,46 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         
         if (do_ene || do_log)
         {
-            bCalcPres = TRUE;
-            bGStat    = TRUE;
+            bCalcEnerPres = TRUE;
+            bGStat        = TRUE;
         }
 
         /* Determine the wallclock run time up till now */
         run_time = gmx_gettime() - (double)runtime->real;
 
         /* Check whether everything is still allright */    
-        if ((bGotStopNextStepSignal || bGotStopNextNSStepSignal) && 
-            (handledSignal!=last_signal_number_recvd) &&
+        if (((int)gmx_get_stop_condition() > handled_stop_condition) &&
             MASTERTHREAD(cr))
         {
-            if (bGotStopNextStepSignal || ir->nstlist == 0)
-            {
-                gs.sig[eglsTERM] = 1;
-            }
-            else
-            {
-                gs.sig[eglsTERM] = -1;
-            }
+            /* this is just make gs.sig compatible with the hack 
+               of sending signals around by MPI_Reduce with together with
+               other floats */
+            if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
+                gs.sig[eglsSTOPCOND]=1;
+            if ( gmx_get_stop_condition() == gmx_stop_cond_next )
+                gs.sig[eglsSTOPCOND]=-1;
+            /* < 0 means stop at next step, > 0 means stop at next NS step */
             if (fplog)
             {
                 fprintf(fplog,
                         "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
-                        signal_name[last_signal_number_recvd], 
-                        gs.sig[eglsTERM]==-1 ? "NS " : "");
+                        gmx_get_signal_name(),
+                        gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
                 fflush(fplog);
             }
             fprintf(stderr,
                     "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
-                    signal_name[last_signal_number_recvd], 
-                    gs.sig[eglsTERM]==-1 ? "NS " : "");
+                    gmx_get_signal_name(),
+                    gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
             fflush(stderr);
-            handledSignal=last_signal_number_recvd;
+            handled_stop_condition=(int)gmx_get_stop_condition();
         }
         else if (MASTER(cr) && (bNS || ir->nstlist <= 0) &&
                  (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
-                 gs.sig[eglsTERM] == 0)
+                 gs.sig[eglsSTOPCOND] == 0 && gs.set[eglsSTOPCOND] == 0)
         {
             /* Signal to terminate the run */
-            gs.sig[eglsTERM] = (ir->nstlist == 0 ? 1 : -1);
+            gs.sig[eglsSTOPCOND] = 1;
             if (fplog)
             {
                 fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
@@ -2224,17 +2279,18 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             
             /* #########   START SECOND UPDATE STEP ################# */
             GMX_MPE_LOG(ev_update_start);
+            /* Box is changed in update() when we do pressure coupling,
+             * but we should still use the old box for energy corrections and when
+             * writing it to the energy file, so it matches the trajectory files for
+             * the same timestep above. Make a copy in a separate array.
+             */
+            copy_mat(state->box,lastbox);
+
             bOK = TRUE;
-            if (!bRerunMD || rerun_fr.bV || bForceUpdate) 
+            if (!(bRerunMD && !rerun_fr.bV && !bForceUpdate))
             {
                 wallcycle_start(wcycle,ewcUPDATE);
                 dvdl = 0;
-                /* Box is changed in update() when we do pressure coupling,
-                 * but we should still use the old box for energy corrections and when
-                 * writing it to the energy file, so it matches the trajectory files for
-                 * the same timestep above. Make a copy in a separate array.
-                 */
-                copy_mat(state->box,lastbox);
                 /* UPDATE PRESSURE VARIABLES IN TROTTER FORMULATION WITH CONSTRAINTS */
                 if (bTrotter) 
                 {
@@ -2253,7 +2309,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                         m_add(force_vir,shake_vir,total_vir);
                         clear_mat(shake_vir);
                     }
-                    trotter_update(ir,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[3]);
+                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[3]);
                 }
                 /* We can only do Berendsen coupling after we have summed
                  * the kinetic energy or virial. Since the happens
@@ -2285,7 +2341,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                 update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
                                    &top->idef,shake_vir,force_vir,
                                    cr,nrnb,wcycle,upd,constr,
-                                   bInitStep,FALSE,bCalcPres,state->veta);  
+                                   bInitStep,FALSE,bCalcEnerPres,state->veta);  
                 
                 if (ir->eI==eiVVAK) 
                 {
@@ -2295,10 +2351,10 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                                     wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
                                     constr,NULL,FALSE,lastbox,
                                     top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
-                                    cglo_flags | CGLO_TEMPERATURE | CGLO_CONSTRAINT    
+                                    cglo_flags | CGLO_TEMPERATURE    
                         );
                     wallcycle_start(wcycle,ewcUPDATE);
-                    trotter_update(ir,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[4]);            
+                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[4]);            
                     /* now we know the scaling, we can compute the positions again again */
                     copy_rvecn(cbuf,state->x,0,state->natoms);
 
@@ -2314,7 +2370,8 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                     update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
                                        &top->idef,tmp_vir,force_vir,
                                        cr,nrnb,wcycle,upd,NULL,
-                                       bInitStep,FALSE,bCalcPres,state->veta);  
+                                       bInitStep,FALSE,bCalcEnerPres,
+                                       state->veta);  
                 }
                 if (!bOK && !bFFscan) 
                 {
@@ -2541,7 +2598,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
 
 
         /* Remaining runtime */
-        if (MULTIMASTER(cr) && do_verbose) 
+        if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
         {
             if (shellfc) 
             {
@@ -2558,20 +2615,14 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             bExchanged = replica_exchange(fplog,cr,repl_ex,
                                           state_global,enerd->term,
                                           state,step,t);
-        }
-        if (bExchanged && PAR(cr)) 
-        {
-            if (DOMAINDECOMP(cr)) 
+
+            if (bExchanged && DOMAINDECOMP(cr)) 
             {
                 dd_partition_system(fplog,step,cr,TRUE,1,
                                     state_global,top_global,ir,
                                     state,&f,mdatoms,top,fr,
                                     vsite,shellfc,constr,
                                     nrnb,wcycle,FALSE);
-            } 
-            else 
-            {
-                bcast_state(cr,state,FALSE);
             }
         }
         
@@ -2605,8 +2656,16 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         
         if (bRerunMD) 
         {
-            /* read next frame from input trajectory */
-            bNotLastFrame = read_next_frame(oenv,status,&rerun_fr);
+            if (MASTER(cr))
+            {
+                /* read next frame from input trajectory */
+                bNotLastFrame = read_next_frame(oenv,status,&rerun_fr);
+            }
+
+            if (PAR(cr))
+            {
+                rerun_parallel_comm(cr,&rerun_fr,&bNotLastFrame);
+            }
         }
         
         if (!bRerunMD || !rerun_fr.bStep)
@@ -2628,6 +2687,8 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             /* Reset all the counters related to performance over the run */
             reset_all_counters(fplog,cr,step,&step_rel,ir,wcycle,nrnb,runtime);
             wcycle_set_reset_counters(wcycle,-1);
+            /* Correct max_hours for the elapsed time */
+            max_hours -= run_time/(60.0*60.0);
             bResetCountersHalfMaxH = FALSE;
             gs.set[eglsRESETCOUNTERS] = 0;
         }
@@ -2638,7 +2699,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     /* Stop the time */
     runtime_end(runtime);
     
-    if (bRerunMD)
+    if (bRerunMD && MASTER(cr))
     {
         close_trj(status);
     }
@@ -2651,7 +2712,7 @@ double do_md(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     
     if (MASTER(cr))
     {
-        if (bGStatEveryStep && !bRerunMD) 
+        if (ir->nstcalcenergy > 0 && !bRerunMD) 
         {
             print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
                        eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
index 9a0919fc70f1ef0d8d48488cde968f984aa35e52..03d1769dc05098a29cfce7375a7a2b1d9f35899c 100644 (file)
@@ -1,3 +1,38 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
 /* include even when OpenMM not used to force compilation of do_md_openmm */
 #include "openmm_wrapper.h"
 
+/* simulation conditions to transmit */
+enum { eglsNABNSB, eglsCHKPT, eglsSTOPCOND, eglsRESETCOUNTERS, eglsNR };
 
-enum { eglsNABNSB, eglsCHKPT, eglsTERM, eglsRESETCOUNTERS, eglsNR };
-
-typedef struct {
+typedef struct
+{
     int nstms;       /* The frequency for intersimulation communication */
     int sig[eglsNR]; /* The signal set by one process in do_md */
     int set[eglsNR]; /* The communicated signal, equal for all processes */
@@ -83,7 +119,7 @@ static int multisim_min(const gmx_multisim_t *ms,int nmin,int n)
     gmx_sumi_sim(ms->nsim,buf,ms);
     bPos   = TRUE;
     bEqual = TRUE;
-    for(s=0; s<ms->nsim; s++)
+    for (s=0; s<ms->nsim; s++)
     {
         bPos   = bPos   && (buf[s] > 0);
         bEqual = bEqual && (buf[s] == buf[0]);
@@ -97,7 +133,7 @@ static int multisim_min(const gmx_multisim_t *ms,int nmin,int n)
         else
         {
             /* Find the least common multiple */
-            for(d=2; d<nmin; d++)
+            for (d=2; d<nmin; d++)
             {
                 s = 0;
                 while (s < ms->nsim && d % buf[s] == 0)
@@ -152,7 +188,7 @@ static void init_global_signals(globsig_t *gs,const t_commrec *cr,
 
     gs->nstms = 1;
 
-    for(i=0; i<eglsNR; i++)
+    for (i=0; i<eglsNR; i++)
     {
         gs->sig[i] = 0;
         gs->set[i] = 0;
@@ -161,38 +197,38 @@ static void init_global_signals(globsig_t *gs,const t_commrec *cr,
 
 
 double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
-             const output_env_t oenv, bool bVerbose,bool bCompact,
-             int nstglobalcomm,
-             gmx_vsite_t *vsite,gmx_constr_t constr,
-             int stepout,t_inputrec *ir,
-             gmx_mtop_t *top_global,
-             t_fcdata *fcd,
-             t_state *state_global,
-             t_mdatoms *mdatoms,
-             t_nrnb *nrnb,gmx_wallcycle_t wcycle,
-             gmx_edsam_t ed,t_forcerec *fr,
-             int repl_ex_nst,int repl_ex_seed,
-             real cpt_period,real max_hours,
-             const char *deviceOptions,
-             unsigned long Flags,
-             gmx_runtime_t *runtime)
+                    const output_env_t oenv, bool bVerbose,bool bCompact,
+                    int nstglobalcomm,
+                    gmx_vsite_t *vsite,gmx_constr_t constr,
+                    int stepout,t_inputrec *ir,
+                    gmx_mtop_t *top_global,
+                    t_fcdata *fcd,
+                    t_state *state_global,
+                    t_mdatoms *mdatoms,
+                    t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+                    gmx_edsam_t ed,t_forcerec *fr,
+                    int repl_ex_nst,int repl_ex_seed,
+                    real cpt_period,real max_hours,
+                    const char *deviceOptions,
+                    unsigned long Flags,
+                    gmx_runtime_t *runtime)
 {
     gmx_mdoutf_t *outf;
     gmx_large_int_t step,step_rel;
     double     run_time;
     double     t,t0,lam0;
     bool       bSimAnn,
-               bFirstStep,bStateFromTPX,bLastStep,bStartingFromCpt;
+    bFirstStep,bStateFromTPX,bLastStep,bStartingFromCpt;
     bool       bInitStep=TRUE;
     bool       bNEMD,do_ene,do_log, do_verbose,
-               bX,bV,bF,bXTC,bCPT;
+    bX,bV,bF,bCPT;
     tensor     force_vir,shake_vir,total_vir,pres;
     int        i,m;
     int        mdof_flags;
     rvec       mu_tot;
     t_vcm      *vcm;
     int        nchkpt=1;
-    gmx_localtop_t *top;       
+    gmx_localtop_t *top;
     t_mdebin *mdebin=NULL;
     t_state    *state=NULL;
     rvec       *f_global=NULL;
@@ -212,9 +248,8 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     matrix      lastbox;
     real        reset_counters=0,reset_counters_now=0;
     char        sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
-    int         handledSignal=-1; /* compare to last_signal_recvd */
-    bool        bHandledSignal=FALSE;
+    int         handled_stop_condition=gmx_stop_cond_none; 
+
     const char *ommOptions = NULL;
     void   *openmmData;
 
@@ -242,7 +277,7 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     /* needed for iteration of constraints */
     snew(ekind_save,1);
     init_ekindata(fplog,top_global,&(ir->opts),ekind_save);
-    /* Copy the cos acceleration to the groups struct */    
+    /* Copy the cos acceleration to the groups struct */
     ekind->cosacc.cos_accel = ir->cos_accel;
 
     gstat = global_stat_init(ir);
@@ -256,51 +291,51 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                     io);
     }
 
-            top = gmx_mtop_generate_local_top(top_global,ir);
+    top = gmx_mtop_generate_local_top(top_global,ir);
 
-            a0 = 0;
-            a1 = top_global->natoms;
+    a0 = 0;
+    a1 = top_global->natoms;
 
-        state = partdec_init_local_state(cr,state_global);
-        f_global = f;
+    state = partdec_init_local_state(cr,state_global);
+    f_global = f;
 
-        atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
+    atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
 
-        if (vsite) {
-            set_vsite_top(vsite,top,mdatoms,cr);
-        }
+    if (vsite)
+    {
+        set_vsite_top(vsite,top,mdatoms,cr);
+    }
 
-        if (ir->ePBC != epbcNONE && !ir->bPeriodicMols) {
-            graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
-        }
+    if (ir->ePBC != epbcNONE && !ir->bPeriodicMols)
+    {
+        graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
+    }
 
     update_mdatoms(mdatoms,state->lambda);
 
-                                                                                                                                                                                              
-      if(deviceOptions[0]=='\0')                                                                                                                                                              
-      {                                                                                                                                                                                       
-          /* empty options, which should default to OpenMM in this build */                                                                                                                   
-          ommOptions=deviceOptions;                                                                                                                                                           
-      }                                                                                                                                                                                       
-      else                                                                                                                                                                                    
-      {                                                                                                                                                                                       
-          if(gmx_strncasecmp(deviceOptions,"OpenMM",6)!=0)                                                                                                                                    
-          {                                                                                                                                                                                   
-              gmx_fatal(FARGS, "This Gromacs version currently only works with OpenMM. Use -device \"OpenMM:<options>\"");                                                                    
-          }                                                                                                                                                                                   
-          else                                                                                                                                                                                
-          {                                                                                                                                                                                   
-              ommOptions=strchr(deviceOptions,':');                                                                                                                                           
-              if(NULL!=ommOptions)                                                                                                                                                            
-              {                                                                                                                                                                               
-                  /* Increase the pointer to skip the colon */                                                                                                                                
-                  ommOptions++;                                     
-            }                                                                                                                                                                               
-          }                                                                                                                                                                                   
-      }                                                                                                                                                                                       
-
-      openmmData = openmm_init(fplog, ommOptions, cr, ir, top_global, top, mdatoms, fr, state);                                                                                         
+    if (deviceOptions[0]=='\0')
+    {
+        /* empty options, which should default to OpenMM in this build */
+        ommOptions=deviceOptions;
+    }
+    else
+    {
+        if (gmx_strncasecmp(deviceOptions,"OpenMM",6)!=0)
+        {
+            gmx_fatal(FARGS, "This Gromacs version currently only works with OpenMM. Use -device \"OpenMM:<options>\"");
+        }
+        else
+        {
+            ommOptions=strchr(deviceOptions,':');
+            if (NULL!=ommOptions)
+            {
+                /* Increase the pointer to skip the colon */
+                ommOptions++;
+            }
+        }
+    }
 
+    openmmData = openmm_init(fplog, ommOptions, ir, top_global, top, mdatoms, fr, state);
 
     if (MASTER(cr))
     {
@@ -311,10 +346,11 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         }
         /* Set the initial energy history in state to zero by updating once */
         update_energyhistory(&state_global->enerhist,mdebin);
-    }  
+    }
 
-    if (constr) {
-            set_constraints(constr,top,ir,mdatoms,cr);
+    if (constr)
+    {
+        set_constraints(constr,top,ir,mdatoms,cr);
     }
 
     if (!ir->bContinuation)
@@ -322,9 +358,9 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         if (mdatoms->cFREEZE && (state->flags & (1<<estV)))
         {
             /* Set the velocities of frozen particles to zero */
-            for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
+            for (i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
             {
-                for(m=0; m<DIM; m++)
+                for (m=0; m<DIM; m++)
                 {
                     if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m])
                     {
@@ -350,7 +386,7 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     }
 
     debug_gmx();
-  
+
     if (MASTER(cr))
     {
         char tbuf[20];
@@ -393,7 +429,7 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     debug_gmx();
     /***********************************************************
      *
-     *             Loop over MD steps 
+     *             Loop over MD steps
      *
      ************************************************************/
 
@@ -410,10 +446,8 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     step = ir->init_step;
     step_rel = 0;
 
-    bLastStep = ((ir->nsteps >= 0 && step_rel > ir->nsteps));
-
-    while (!bLastStep) {
-
+    while (!bLastStep)
+    {
         wallcycle_start(wcycle,ewcSTEP);
 
         GMX_MPE_LOG(ev_timestep1);
@@ -421,14 +455,14 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         bLastStep = (step_rel == ir->nsteps);
         t = t0 + step*ir->delta_t;
 
-        if (gs.set[eglsTERM] != 0 )
+        if (gs.set[eglsSTOPCOND] != 0)
         {
             bLastStep = TRUE;
         }
 
         do_log = do_per_step(step,ir->nstlog) || bFirstStep || bLastStep;
         do_verbose = bVerbose &&
-                  (step % stepout == 0 || bFirstStep || bLastStep);
+                     (step % stepout == 0 || bFirstStep || bLastStep);
 
         if (MASTER(cr) && do_log)
         {
@@ -451,7 +485,7 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             gs.set[eglsCHKPT] = 0;
         }
 
-        /* Now we have the energies and forces corresponding to the 
+        /* Now we have the energies and forces corresponding to the
          * coordinates at time t. We must output all of this before
          * the update.
          * for RerunMD t is read from input trajectory
@@ -459,37 +493,55 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         GMX_MPE_LOG(ev_output_start);
 
         mdof_flags = 0;
-        if (do_per_step(step,ir->nstxout)) { mdof_flags |= MDOF_X; }
-        if (do_per_step(step,ir->nstvout)) { mdof_flags |= MDOF_V; }
-        if (do_per_step(step,ir->nstfout)) { mdof_flags |= MDOF_F; }
-        if (do_per_step(step,ir->nstxtcout)) { mdof_flags |= MDOF_XTC; }
-        if (bCPT) { mdof_flags |= MDOF_CPT; };
-        bX   = MDOF_X || (bLastStep && ir->nstxout);
-        bV   = MDOF_V || (bLastStep && ir->nstvout);
-        bF   = MDOF_F || (bLastStep && ir->nstfout);
-        bXTC = MDOF_XTC || (bLastStep && ir->nstxtcout);
-        do_ene = do_per_step(step,ir->nstenergy) || (bLastStep && ir->nstenergy);
-
-      if( bX || bXTC || bV ){                                                                                                                                                                 
-        wallcycle_start(wcycle,ewcTRAJ);                                                                                                                                                              
-        openmm_copy_state(openmmData, state, &t, f, enerd, bX||bXTC, bV, 0, 0);                                                                                                               
-        wallcycle_stop(wcycle,ewcTRAJ);                                                                                                                                                       
-      }                                                                                                                                                                                       
-
-      openmm_take_one_step(openmmData);                                                                                                                                                       
-
-      if (bX || bV || bF || bXTC || do_ene) {
-        wallcycle_start(wcycle,ewcTRAJ);
-        if( bF || do_ene ){                                                                                                                                                                   
-           openmm_copy_state(openmmData, state, &t, f, enerd, 0, 0, bF, do_ene);                                                                                                              
-      }                                                                                                                                                                                     
-     upd_mdebin(mdebin, NULL,TRUE,
-                t,mdatoms->tmass,enerd,state,lastbox,
-                shake_vir,force_vir,total_vir,pres,
-                ekind,mu_tot,constr);
-         print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,fplog,step,t,
-                       eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
+        if (do_per_step(step,ir->nstxout))
+        {
+            mdof_flags |= MDOF_X;
+        }
+        if (do_per_step(step,ir->nstvout))
+        {
+            mdof_flags |= MDOF_V;
+        }
+        if (do_per_step(step,ir->nstfout))
+        {
+            mdof_flags |= MDOF_F;
+        }
+        if (do_per_step(step,ir->nstxtcout))
+        {
+            mdof_flags |= MDOF_XTC;
+        }
+        if (bCPT)
+        {
+            mdof_flags |= MDOF_CPT;
+        };
+        do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
+
+        if (mdof_flags != 0)
+        {
+            bX = (mdof_flags & (MDOF_X | MDOF_XTC | MDOF_CPT));
+            bV = (mdof_flags & (MDOF_V | MDOF_CPT));
 
+            wallcycle_start(wcycle,ewcTRAJ);
+            openmm_copy_state(openmmData, state, &t, f, enerd, bX, bV, 0, 0);
+            wallcycle_stop(wcycle,ewcTRAJ);
+        }
+
+        openmm_take_one_step(openmmData);
+
+        if (mdof_flags != 0 || do_ene || do_log)
+        {
+            wallcycle_start(wcycle,ewcTRAJ);
+            bF = (mdof_flags & MDOF_F);
+            if (bF || do_ene || do_log)
+            {
+                openmm_copy_state(openmmData, state, &t, f, enerd, 0, 0, bF, do_ene);
+            }
+            upd_mdebin(mdebin, NULL,TRUE,
+                       t,mdatoms->tmass,enerd,state,lastbox,
+                       shake_vir,force_vir,total_vir,pres,
+                       ekind,mu_tot,constr);
+            print_ebin(outf->fp_ene,do_ene,FALSE,FALSE,do_log?fplog:NULL,
+                       step,t,
+                       eprNORMAL,bCompact,mdebin,fcd,groups,&(ir->opts));
             write_traj(fplog,cr,outf,mdof_flags,top_global,
                        step,t,state,state_global,f,f_global,&n_xtc,&x_xtc);
             if (bCPT)
@@ -499,7 +551,7 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             }
             debug_gmx();
             if (bLastStep && step_rel == ir->nsteps &&
-                (Flags & MD_CONFOUT) && MASTER(cr))
+                    (Flags & MD_CONFOUT) && MASTER(cr))
             {
                 /* x and v have been collected in write_traj,
                  * because a checkpoint file will always be written
@@ -520,109 +572,110 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
             wallcycle_stop(wcycle,ewcTRAJ);
         }
         GMX_MPE_LOG(ev_output_finish);
-        
+
 
         /* Determine the wallclock run time up till now */
         run_time = gmx_gettime() - (double)runtime->real;
 
-        /* Check whether everything is still allright */    
-        if ((bGotStopNextStepSignal || bGotStopNextNSStepSignal) && 
-            (handledSignal!=last_signal_number_recvd) &&
+        /* Check whether everything is still allright */
+        if (((int)gmx_get_stop_condition() > handled_stop_condition) &&
             MASTERTHREAD(cr))
         {
-            if (bGotStopNextStepSignal)
-            {
-                gs.set[eglsTERM] = 1;
-            }
-            else
-            {
-                gs.set[eglsTERM] = -1;
-            }
+           /* this is just make gs.sig compatible with the hack 
+               of sending signals around by MPI_Reduce with together with
+               other floats */
+            /* NOTE: this only works for serial code. For code that allows
+               MPI nodes to propagate their condition, see kernel/md.c*/
+            if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
+                gs.set[eglsSTOPCOND]=1;
+            if ( gmx_get_stop_condition() == gmx_stop_cond_next )
+                gs.set[eglsSTOPCOND]=1;
+            /* < 0 means stop at next step, > 0 means stop at next NS step */
             if (fplog)
             {
                 fprintf(fplog,
                         "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
-                        signal_name[last_signal_number_recvd], 
-                        gs.set[eglsTERM]==-1 ? "NS " : "");
+                        gmx_get_signal_name(),
+                        gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
                 fflush(fplog);
             }
             fprintf(stderr,
                     "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
-                    signal_name[last_signal_number_recvd], 
-                    gs.set[eglsTERM]==-1 ? "NS " : "");
+                    gmx_get_signal_name(),
+                    gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
             fflush(stderr);
-            handledSignal=last_signal_number_recvd;
+            handled_stop_condition=(int)gmx_get_stop_condition();
         }
         else if (MASTER(cr) &&
                  (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
-                 gs.set[eglsTERM] == 0)
+                 gs.set[eglsSTOPCOND] == 0)
         {
             /* Signal to terminate the run */
-            gs.set[eglsTERM] = 1;
+            gs.set[eglsSTOPCOND] = 1;
             if (fplog)
             {
                 fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
             }
             fprintf(stderr, "\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
         }
-        
 
         /* checkpoints */
         if (MASTER(cr) && (cpt_period >= 0 &&
-                           (cpt_period == 0 || 
+                           (cpt_period == 0 ||
                             run_time >= nchkpt*cpt_period*60.0)) &&
-            gs.set[eglsCHKPT] == 0)
+                gs.set[eglsCHKPT] == 0)
         {
             gs.set[eglsCHKPT] = 1;
         }
-  
-         
+
         /* Time for performance */
-        if (((step % stepout) == 0) || bLastStep) 
+        if (((step % stepout) == 0) || bLastStep)
         {
             runtime_upd_proc(runtime);
         }
 
-            if (do_per_step(step,ir->nstlog))
+        if (do_per_step(step,ir->nstlog))
+        {
+            if (fflush(fplog) != 0)
             {
-                if(fflush(fplog) != 0)
-                {
-                    gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of quota?");
-                }
+                gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of quota?");
             }
-
+        }
 
         /* Remaining runtime */
-        if (MULTIMASTER(cr) && do_verbose) 
+        if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
         {
             print_time(stderr,runtime,step,ir,cr);
         }
 
-
         bFirstStep = FALSE;
         bInitStep = FALSE;
         bStartingFromCpt = FALSE;
         step++;
         step_rel++;
-
-
-
     }
     /* End of main MD loop */
     debug_gmx();
-    
-    openmm_cleanup(fplog, openmmData);
 
     /* Stop the time */
     runtime_end(runtime);
-    
+
+    if (MASTER(cr))
+    {
+        if (ir->nstcalcenergy > 0) 
+        {
+            print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
+                       eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
+        }
+    }
+
+    openmm_cleanup(fplog, openmmData);
 
     done_mdoutf(outf);
 
     debug_gmx();
 
     runtime->nsteps_done = step_rel;
-    
+
     return 0;
 }
index 31c7f4e36103e857cfd26e44dce7c0687ccbef7c..18c4a2a77e91db84d12f29d998c34eda2ffa385f 100644 (file)
@@ -1,3 +1,37 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
 #ifndef _MD_OPENMM_H
 #define _MD_OPENMM_H
 
@@ -18,4 +52,4 @@ double do_md_openmm(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
              unsigned long Flags,
              gmx_runtime_t *runtime);
 
-#endif // _MD_OPENMM_H
+#endif /* _MD_OPENMM_H */
index 712dca246f0c197fb8b5283edbb31b350b41ea58..fda1b044612f1a1929bde994dac23930872d2b60 100644 (file)
@@ -70,8 +70,8 @@ int main(int argc,char *argv[])
        " * The current release runs only on modern nVidia GPU hardware with CUDA support.",
        "Make sure that the necessary CUDA drivers and libraries for your operating system",
        "are already installed. The CUDA SDK also should be installed in order to compile",
-       "the program from source (http://www.nvidia.com/object/cuda_home.html).[PAR]"
-       " * Multiple GPU cards are not supported.[PAR]"
+       "the program from source (http://www.nvidia.com/object/cuda_home.html).[PAR]",
+       " * Multiple GPU cards are not supported.[PAR]",
        " * Only a small subset of the GROMACS features and options are supported on the GPUs.",
        "See below for a detailed list.[PAR]",
        " * Consumer level GPU cards are known to often have problems with faulty memory.",
@@ -79,7 +79,7 @@ int main(int argc,char *argv[])
        "(for example, using the memtest=full option).",
        "A partial memory check (for example, memtest=15) before and",
        "after the simulation run would help spot",
-       "problems resulting from processor overheating.[PAR]"
+       "problems resulting from processor overheating.[PAR]",
        " * The maximum size of the simulated systems depends on the available",
        "GPU memory,for example, a GTX280 with 1GB memory has been tested with systems",
        "of up to about 100,000 atoms.[PAR]",
@@ -87,7 +87,7 @@ int main(int argc,char *argv[])
        "have been implemented in a very different way than they are on the CPUs.",
        "Therefore numercal correspondence between properties of the state of",
        "simulated systems should not be expected. Moreover, the values will likely vary",
-       "when simulations are done on different GPU hardware.[PAR]"
+       "when simulations are done on different GPU hardware.[PAR]",
        " * Frequent retrieval of system state information such as",
        "trajectory coordinates and energies can greatly influence the performance",
        "of the program due to slow CPU<->GPU memory transfer speed.[PAR]",
@@ -98,14 +98,14 @@ int main(int argc,char *argv[])
        "can be as high as 20 times, but in most other setups involving cutoffs and PME the",
        "acceleration is usually only 4~6 times relative to a 3GHz CPU.[PAR]",
        "Supported features:[PAR]",
-       " * Integrators: md, md-vv, md-vv2, sd and bd.\n",
+       " * Integrators: md/md-vv/md-vv-avek, sd/sd1 and bd.\n",
        " * Long-range interactions (option coulombtype): Reaction-Field, Ewald, PME.\n",
-       " * Temperature control: Supported only with the sd, bd, md-vv and md-vv2 integrators.\n",
+       " * Temperature control: Supported only with the md/md-vv/md-vv-avek, sd/sd1 and bd integrators.\n",
        " * Pressure control: Not supported.\n",
        " * Implicit solvent: Supported.\n",
        "A detailed description can be found on the website:\n",
-       "http://www.gromacs.org/index.php?title=Download_%26_Installation/Related_Software/OpenMM[PAR]",
-// From the original mdrun documentaion
+       "http://www.gromacs.org/gpu[PAR]",
+/* From the original mdrun documentaion */
     "The mdrun program reads the run input file ([TT]-s[tt])",
     "and distributes the topology over nodes if needed.",
     "mdrun produces at least four output files.",
@@ -119,7 +119,7 @@ int main(int argc,char *argv[])
     "pressure, etc, a lot of these things are also printed in the log file.",
     "Optionally coordinates can be written to a compressed trajectory file",
     "([TT]-x[tt]).[PAR]",
-//////////////////////////////////////
+/* openmm specific information */
        "Usage with OpenMM:[BR]",
        "$ mdrun -device \"OpenMM:platform=Cuda,memtest=15,deviceid=0,force-device=no\"[PAR]",
        "Options:[PAR]",
@@ -229,7 +229,7 @@ int main(int argc,char *argv[])
     "high or low spatial inhomogeneity of the system.",
     "[PAR]",
     "The option [TT]-gcom[tt] can be used to only do global communication",
-    "every n steps."
+    "every n steps.",
     "This can improve performance for highly parallel simulations",
     "where this global communication step becomes the bottleneck.",
     "For a global thermostat and/or barostat the temperature",
@@ -294,12 +294,25 @@ int main(int argc,char *argv[])
     "The previous checkpoint is backed up to [TT]state_prev.cpt[tt] to",
     "make sure that a recent state of the system is always available,",
     "even when the simulation is terminated while writing a checkpoint.",
+    "With [TT]-cpnum[tt] all checkpoint files are kept and appended",
+    "with the step number.",
     "A simulation can be continued by reading the full state from file",
     "with option [TT]-cpi[tt]. This option is intelligent in the way that",
     "if no checkpoint file is found, Gromacs just assumes a normal run and",
-    "starts from the first step of the tpr file.",
-    "The simulation part number is added to all output files,",
-    "unless [TT]-append[tt] or [TT]-noaddpart[tt] are set.",
+    "starts from the first step of the tpr file. By default the output",
+    "will be appending to the existing output files. The checkpoint file",
+    "contains checksums of all output files, such that you will never",
+    "loose data when some output files are modified, corrupt or removed.",
+    "There are three scenarios with [TT]-cpi[tt]:[BR]",
+    "* no files with matching names are present: new output files are written[BR]",
+    "* all files are present with names and checksums matching those stored",
+    "in the checkpoint file: files are appended[BR]",
+    "* otherwise no files are modified and a fatal error is generated[BR]",
+    "With [TT]-noappend[tt] new output files are opened and the simulation",
+    "part number is added to all output file names.",
+    "Note that in all cases the checkpoint file itself is not renamed",
+    "and will be overwritten, unless its name does not match",
+    "the [TT]-cpo[tt] option.",
     "[PAR]",
     "With checkpointing the output is appended to previously written",
     "output files, unless [TT]-noappend[tt] is used or none of the previous",
@@ -312,7 +325,7 @@ int main(int argc,char *argv[])
     "The result with appending will be the same as from a single run.",
     "The contents will be binary identical, unless you use a different number",
     "of nodes or dynamic load balancing or the FFT library uses optimizations",
-    "through timing."
+    "through timing.",
     "[PAR]",
     "With option [TT]-maxh[tt] a simulation is terminated and a checkpoint",
     "file is written at the first neighbor search step where the run time",
@@ -340,12 +353,6 @@ int main(int argc,char *argv[])
     { efSTO, "-c",      "confout",  ffWRITE },
     { efEDR, "-e",      "ener",     ffWRITE },
     { efLOG, "-g",      "md",       ffWRITE },
-    { efEDI, "-ei",     "sam",      ffOPTRD },
-    { efTRX, "-rerun",  "rerun",    ffOPTRD },
-    { efXVG, "-table",  "table",    ffOPTRD },
-    { efXVG, "-tablep", "tablep",   ffOPTRD },
-    { efXVG, "-tableb", "table",    ffOPTRD },
-#ifndef GMX_OPENMM
     { efXVG, "-dhdl",   "dhdl",     ffOPTWR },
     { efXVG, "-field",  "field",    ffOPTWR },
     { efXVG, "-table",  "table",    ffOPTRD },
@@ -369,7 +376,6 @@ int main(int argc,char *argv[])
     { efLOG, "-rt",     "rottorque",ffOPTWR },
     { efMTX, "-mtx",    "nm",       ffOPTWR },
     { efNDX, "-dn",     "dipole",   ffOPTWR }
-#endif
   };
 #define NFILE asize(fnm)
 
@@ -404,25 +410,22 @@ int main(int argc,char *argv[])
   real rdd=0.0,rconstr=0.0,dlb_scale=0.8,pforce=-1;
   char *ddcsx=NULL,*ddcsy=NULL,*ddcsz=NULL;
   real cpt_period=15.0,max_hours=-1;
-  bool bAppendFiles=TRUE,bAddPart=TRUE;
+  bool bAppendFiles=TRUE;
+  bool bKeepAndNumCPT=FALSE;
   bool bResetCountersHalfWay=FALSE;
   output_env_t oenv=NULL;
   const char *deviceOptions = "";
 
   t_pargs pa[] = {
 
-// arguments relevant to OPENMM only
-#ifdef GMX_OPENMM
-    { "-device",  FALSE, etSTR, {&deviceOptions},
-      "Device option string" },
-// args for non-OpenMM binaries
-#else
     { "-pd",      FALSE, etBOOL,{&bPartDec},
       "Use particle decompostion" },
     { "-dd",      FALSE, etRVEC,{&realddxyz},
       "Domain decomposition grid, 0 is optimize" },
+#ifdef GMX_THREADS
     { "-nt",      FALSE, etINT, {&nthreads},
       "Number of threads to start (0 is guess)" },
+#endif
     { "-npme",    FALSE, etINT, {&npme},
       "Number of separate nodes to be used for PME, -1 is guess" },
     { "-ddorder", FALSE, etENUM, {ddno_opt},
@@ -447,6 +450,8 @@ int main(int argc,char *argv[])
       "HIDDENThe DD cell sizes in z" },
     { "-gcom",    FALSE, etINT,{&nstglobalcomm},
       "Global communication frequency" },
+    { "-v",       FALSE, etBOOL,{&bVerbose},  
+      "Be loud and noisy" },
     { "-compact", FALSE, etBOOL,{&bCompact},  
       "Write a compact log file" },
     { "-seppot",  FALSE, etBOOL, {&bSepPot},
@@ -455,6 +460,14 @@ int main(int argc,char *argv[])
       "Print all forces larger than this (kJ/mol nm)" },
     { "-reprod",  FALSE, etBOOL,{&bReproducible},  
       "Try to avoid optimizations that affect binary reproducibility" },
+    { "-cpt",     FALSE, etREAL, {&cpt_period},
+      "Checkpoint interval (minutes)" },
+    { "-cpnum",   FALSE, etBOOL, {&bKeepAndNumCPT},
+      "Keep and number checkpoint files" },
+    { "-append",  FALSE, etBOOL, {&bAppendFiles},
+      "Append to previous output files when continuing from checkpoint instead of adding the simulation part number to all file names" },
+    { "-maxh",   FALSE, etREAL, {&max_hours},
+      "Terminate after 0.99 times this time (hours)" },
     { "-multi",   FALSE, etINT,{&nmultisim}, 
       "Do multiple simulations in parallel" },
     { "-replex",  FALSE, etINT, {&repl_ex_nst}, 
@@ -472,25 +485,18 @@ int main(int argc,char *argv[])
     { "-resetstep", FALSE, etINT, {&resetstep},
       "HIDDENReset cycle counters after these many time steps" },
     { "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
-      "HIDDENReset the cycle counters after half the number of steps or halfway -maxh" },
+      "HIDDENReset the cycle counters after half the number of steps or halfway -maxh" }
+#ifdef GMX_OPENMM
+    ,
+    { "-device",  FALSE, etSTR, {&deviceOptions},
+      "Device option string" }
 #endif
-// args for both
-    { "-v",       FALSE, etBOOL,{&bVerbose},  
-      "Be loud and noisy" },
-    { "-maxh",   FALSE, etREAL, {&max_hours},
-      "Terminate after 0.99 times this time (hours)" },
-    { "-cpt",     FALSE, etREAL, {&cpt_period},
-      "Checkpoint interval (minutes)" },
-    { "-append",  FALSE, etBOOL, {&bAppendFiles},
-      "Append to previous output files when continuing from checkpoint" },
-    { "-addpart",  FALSE, etBOOL, {&bAddPart},
-      "Add the simulation part number to all output files when continuing from checkpoint" },
   };
   gmx_edsam_t  ed;
   unsigned long Flags, PCA_Flags;
   ivec     ddxyz;
   int      dd_node_order;
-  bool     HaveCheckpoint;
+  bool     bAddPart;
   FILE     *fplog,*fptest;
   int      sim_part,sim_part_fn;
   const char *part_suffix=".part";
@@ -499,7 +505,10 @@ int main(int argc,char *argv[])
 
 
   cr = init_par(&argc,&argv);
-   
+
+  if (MASTER(cr))
+    CopyRight(stderr, argv[0]);
+
   PCA_Flags = (PCA_KEEP_ARGS | PCA_NOEXIT_ON_ARGS | PCA_CAN_SET_DEFFNM
               | (MASTER(cr) ? 0 : PCA_QUIET));
   
@@ -519,19 +528,17 @@ int main(int argc,char *argv[])
   parse_common_args(&argc,argv,PCA_Flags, NFILE,fnm,asize(pa),pa,
                     asize(desc),desc,0,NULL, &oenv);
 
-#ifdef GMX_THREADS
-  if (nthreads<1)
-  {
-      nthreads=tMPI_Get_recommended_nthreads();
-  }
-#else
+  /* we set these early because they might be used in init_multisystem() 
+     Note that there is the potential for npme>nnodes until the number of
+     threads is set later on, if there's thread parallelization. That shouldn't
+     lead to problems. */ 
+  dd_node_order = nenum(ddno_opt);
+  cr->npmenodes = npme;
+
+#ifndef GMX_THREADS
   nthreads=1;
 #endif
-  cr->nthreads = nthreads;
 
-  dd_node_order = nenum(ddno_opt);
-  cr->npmenodes = npme;
 
   if (repl_ex_nst != 0 && nmultisim < 2)
       gmx_fatal(FARGS,"Need at least two replicas for replica exchange (option -multi)");
@@ -544,45 +551,50 @@ int main(int argc,char *argv[])
 #endif
   }
 
-    /* Check if there is ANY checkpoint file available */      
-    sim_part    = 1;
-    sim_part_fn = sim_part;
-    if (opt2bSet("-cpi",NFILE,fnm))
-    {
-        bAppendFiles =
-            read_checkpoint_simulation_part(opt2fn_master("-cpi",NFILE,fnm,cr),
-                                            &sim_part_fn,NULL,cr,
-                                            bAppendFiles,
-                                            part_suffix,&bAddPart);
-        if (sim_part_fn==0 && MASTER(cr))
-        {
-            fprintf(stdout,"No previous checkpoint file present, assuming this is a new run.\n");
-        }
-        else
-        {
-            sim_part = sim_part_fn + 1;
-        }
-    } 
-    else
-    {
-        bAppendFiles = FALSE;
-    }
-    
-    if (!bAppendFiles)
-    {
-        sim_part_fn = sim_part;
-    }
-
-    if (bAddPart && sim_part_fn > 1)
-    {
-        /* This is a continuation run, rename trajectory output files 
-           (except checkpoint files) */
-        /* create new part name first (zero-filled) */
-        sprintf(suffix,"%s%04d",part_suffix,sim_part_fn);
-
-        add_suffix_to_output_names(fnm,NFILE,suffix);
-        fprintf(stdout,"Checkpoint file is from part %d, new output files will be suffixed '%s'.\n",sim_part-1,suffix);
-    }
+  bAddPart = !bAppendFiles;
+
+  /* Check if there is ANY checkpoint file available */        
+  sim_part    = 1;
+  sim_part_fn = sim_part;
+  if (opt2bSet("-cpi",NFILE,fnm))
+  {
+      bAppendFiles =
+                read_checkpoint_simulation_part(opt2fn_master("-cpi", NFILE,
+                                                              fnm,cr),
+                                                &sim_part_fn,NULL,cr,
+                                                bAppendFiles,
+                                                part_suffix,&bAddPart);
+      if (sim_part_fn==0 && MASTER(cr))
+      {
+          fprintf(stdout,"No previous checkpoint file present, assuming this is a new run.\n");
+      }
+      else
+      {
+          sim_part = sim_part_fn + 1;
+      }
+  } 
+  else
+  {
+      bAppendFiles = FALSE;
+  }
+
+  if (!bAppendFiles)
+  {
+      sim_part_fn = sim_part;
+  }
+
+  if (bAddPart)
+  {
+      /* Rename all output files (except checkpoint files) */
+      /* create new part name first (zero-filled) */
+      sprintf(suffix,"%s%04d",part_suffix,sim_part_fn);
+
+      add_suffix_to_output_names(fnm,NFILE,suffix);
+      if (MASTER(cr))
+      {
+          fprintf(stdout,"Checkpoint file is from part %d, new output files will be suffixed '%s'.\n",sim_part-1,suffix);
+      }
+  }
 
   Flags = opt2bSet("-rerun",NFILE,fnm) ? MD_RERUN : 0;
   Flags = Flags | (bSepPot       ? MD_SEPPOT       : 0);
@@ -594,6 +606,7 @@ int main(int argc,char *argv[])
   Flags = Flags | (bRerunVSite   ? MD_RERUN_VSITE  : 0);
   Flags = Flags | (bReproducible ? MD_REPRODUCIBLE : 0);
   Flags = Flags | (bAppendFiles  ? MD_APPENDFILES  : 0); 
+  Flags = Flags | (bKeepAndNumCPT ? MD_KEEPANDNUMCPT : 0); 
   Flags = Flags | (sim_part>1    ? MD_STARTFROMCPT : 0); 
   Flags = Flags | (bResetCountersHalfWay ? MD_RESETCOUNTERSHALFWAY : 0);
 
@@ -615,27 +628,15 @@ int main(int argc,char *argv[])
       fplog = NULL;
   }
 
-#if 0
-  /* this is now done in mdrunner: */
-  /* Essential dynamics */
-  if (opt2bSet("-ei",NFILE,fnm)) {
-      /* Open input and output files, allocate space for ED data structure */
-      ed = ed_open(NFILE,fnm,cr);
-  } else
-      ed=NULL;
-#endif
-
   ddxyz[XX] = (int)(realddxyz[XX] + 0.5);
   ddxyz[YY] = (int)(realddxyz[YY] + 0.5);
   ddxyz[ZZ] = (int)(realddxyz[ZZ] + 0.5);
 
-  /* even if nthreads = 1, we still call this one */
-  rc = mdrunner_threads(nthreads,
-                        fplog,cr,NFILE,fnm,oenv,bVerbose,bCompact,nstglobalcomm,
-                        ddxyz,dd_node_order,rdd,rconstr,
-                        dddlb_opt[0],dlb_scale,ddcsx,ddcsy,ddcsz,
-                        nstepout,resetstep,nmultisim,repl_ex_nst,repl_ex_seed,
-                        pforce, cpt_period,max_hours,deviceOptions,Flags);
+  rc = mdrunner(nthreads, fplog,cr,NFILE,fnm,oenv,bVerbose,bCompact,
+                nstglobalcomm, ddxyz,dd_node_order,rdd,rconstr,
+                dddlb_opt[0],dlb_scale,ddcsx,ddcsy,ddcsz,
+                nstepout,resetstep,nmultisim,repl_ex_nst,repl_ex_seed,
+                pforce, cpt_period,max_hours,deviceOptions,Flags);
 
   if (gmx_parallel_env_initialized())
       gmx_finalize();
index 1d07db41d9b832f9331346d444b4a10b96079f63..e4f907c823e08f62a3141f8f0d3701592f49a97c 100644 (file)
@@ -58,7 +58,7 @@
 #include "pdb2top.h"
 #include "gpp_nextnb.h"
 #include "gpp_atomtype.h"
-#include "x2top.h"
+#include "g_x2top.h"
 #include "fflibutil.h"
 
 static void rd_nm2type_file(const char *fn,int *nnm,t_nm2type **nmp)
@@ -73,7 +73,9 @@ static void rd_nm2type_file(const char *fn,int *nnm,t_nm2type **nmp)
   t_nm2type *nm2t=NULL;
   
   fp = fflib_open(fn);
-  
+  if (NULL == fp)
+    gmx_fatal(FARGS,"Can not find %s in library directory",fn);
+    
   nnnm = *nnm;
   nm2t = *nmp;
   do {
@@ -119,13 +121,13 @@ static void rd_nm2type_file(const char *fn,int *nnm,t_nm2type **nmp)
   *nmp = nm2t;
 }
 
-t_nm2type *rd_nm2type(const char *ffdir,int *nnm)
+t_nm2type *rd_nm2type(const char *ffdir,bool bAddCWD,int *nnm)
 {
   int  nff,f;
   char **ff;
   t_nm2type *nm;
 
-  nff = fflib_search_file_end(ffdir,".n2t",FALSE,&ff);
+  nff = fflib_search_file_end(ffdir,bAddCWD,".n2t",FALSE,&ff);
   *nnm = 0;
   nm   = NULL;
   for(f=0; f<nff; f++) {
index a5f9eb552ca7c1b284d912736c55b6245cb2aa04..a4466825562878322a72f7316a5f3a27f1d45ac2 100644 (file)
@@ -1,3 +1,44 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
+/*
+ * Note, that parts of this source code originate from the Simtk release 
+ * of OpenMM accelerated Gromacs, for more details see: 
+ * https://simtk.org/project/xml/downloads.xml?group_id=161#package_id600
+ */
+
 #include <cmath>
 #include <set>
 #include <iostream>
@@ -19,35 +60,48 @@ using namespace std;
 #include "string2.h"
 #include "gmx_gpu_utils.h"
 #include "mtop_util.h"
-#include "warninp.h"
 
 #include "openmm_wrapper.h"
 
 using namespace OpenMM;
 
+/*! \cond */
 #define MEM_ERR_MSG(str) \
     "The %s-simulation GPU memory test detected errors. As memory errors would cause incorrect " \
     "simulation results, gromacs has aborted execution.\n Make sure that your GPU's memory is not " \
     "overclocked and that the device is properly cooled.\n", (str)
-
-
-/** Convert string to type T. */
+/*! \endcond */
+
+#define COMBRULE_CHK_TOL            1e-6
+#define COMBRULE_SIGMA(sig1, sig2)  (((sig1) + (sig2))/2)
+#define COMBRULE_EPS(eps1, eps2)    (sqrt((eps1) * (eps2)))
+
+/*! 
+ * \brief Convert string to integer type.
+ * \param[in]  s    String to convert from.
+ * \param[in]  f    Basefield format flag that takes any of the following I/O
+ *                  manipulators: dec, hex, oct.
+ * \param[out] t    Destination variable to convert to.
+ */
 template <class T>
 static bool from_string(T& t, const string& s, ios_base& (*f)(ios_base&))
 {
-  istringstream iss(s);
-  return !(iss >> f >> t).fail();
+    istringstream iss(s);
+    return !(iss >> f >> t).fail();
 }
 
-/**
- * Split string around a given delimiter.
+/*!
+ * \brief Split string around a given delimiter.
+ * \param[in] s      String to split.
+ * \param[in] delim  Delimiter character.
+ * \returns          Vector of strings found in \p s.
  */
 static vector<string> split(const string &s, char delim)
 {
     vector<string> elems;
     stringstream ss(s);
     string item;
-    while(getline(ss, item, delim))
+    while (getline(ss, item, delim))
     {
         if (item.length() != 0)
             elems.push_back(item);
@@ -55,10 +109,16 @@ static vector<string> split(const string &s, char delim)
     return elems;
 }
 
-/**
- * Split a string "option=value" into "option" and "value" strings.
+/*!
+ * \brief Split a string of the form "option=value" into "option" and "value" strings.
+ * This string corresponds to one option and the associated value from the option list 
+ * in the mdrun -device argument.
+ *
+ * \param[in]  s    A string containing an "option=value" pair that needs to be split up.
+ * \param[out] opt  The name of the option.
+ * \param[out] val  Value of the option. 
  */
-static void split_opt_val(const string &s, string &opt, string &val)
+static void splitOptionValue(const string &s, string &opt, string &val)
 {
     size_t eqPos = s.find('=');
     if (eqPos != string::npos)
@@ -68,16 +128,25 @@ static void split_opt_val(const string &s, string &opt, string &val)
     }
 }
 
-/**
- * Compare two strings ignoring case.
+/*!
+ * \brief Compare two strings ignoring case.
+ * This function is in fact a wrapper around the gromacs function gmx_strncasecmp().
+ * \param[in] s1 String. 
+ * \param[in] s2 String.
+ * \returns      Similarly to the C function strncasecmp(), the return value is an  
+                 integer less than, equal to, or greater than 0 if \p s1 less than, 
+                 identical to, or greater than \p s2.
  */
 static bool isStringEqNCase(const string s1, const string s2)
 {
     return (gmx_strncasecmp(s1.c_str(), s2.c_str(), max(s1.length(), s2.length())) == 0);
 }
 
-/**
- * Conver string to upper case.
+/*!
+ * \brief Convert string to upper case.
+ *
+ * \param[in]  s    String to convert to uppercase.
+ * \returns         The given string converted to uppercase.
  */
 static string toUpper(const string &s)
 {
@@ -86,47 +155,80 @@ static string toUpper(const string &s)
     return stmp;
 }
 
-#define SIZEOF_PLATFORMS    1
-#define SIZEOF_MEMTESTS     3
-#define SIZEOF_DEVICEIDS    1
-#define SIZEOF_FORCE_DEV    2
-
-/** Possible options of the mdrun -device parameter. */
-static const char *devOptStrings[] = { "platform", "deviceid", "memtest", "force-device" };
-enum devOpt {
-        PLATFORM     = 0,
-        DEVICEID     = 1,
-        MEMTEST      = 2,
-        FORCE_DEVICE = 3
+/*! 
+  \name Sizes of constant device option arrays GmxOpenMMPlatformOptions#platforms, 
+  GmxOpenMMPlatformOptions#memtests, GmxOpenMMPlatformOptions#deviceid, 
+  GmxOpenMMPlatformOptions#force_dev.  */
+/* {@ */
+#define SIZEOF_PLATFORMS    1  // 2
+#define SIZEOF_MEMTESTS     3 
+#define SIZEOF_DEVICEIDS    1 
+#define SIZEOF_FORCE_DEV    2 
+
+#define SIZEOF_CHECK_COMBRULE 2
+/* @} */
+
+/*! Possible platform options in the mdrun -device option. */
+static const char *devOptStrings[] = { "platform", "deviceid", "memtest", "force-device", "check-combrule" }; 
+
+/*! Enumerated platform options in the mdrun -device option. */
+enum devOpt
+{
+    PLATFORM     = 0,
+    DEVICEID     = 1,
+    MEMTEST      = 2,
+    FORCE_DEVICE = 3
 };
 
-/**
- * Parse the options string provided to mdrun.
+/*!
+ * \brief Class to extract and manage the platform options in the mdrun -device option.
+ * 
  */
 class GmxOpenMMPlatformOptions
 {
 public:
-  GmxOpenMMPlatformOptions(const char *optionString);
-//    GmxOpenMMPlatformOptions(string &optionString);
+    GmxOpenMMPlatformOptions(const char *opt);
     ~GmxOpenMMPlatformOptions() { options.clear(); }
-    string getOptionValue(const string &optName);
-    void remOption(const string &optName) { options.erase(toUpper(optName)); }
+    string getOptionValue(const string &opt);
+    void remOption(const string &opt);
+    void print();
 private:
     void setOption(const string &opt, const string &val);
-    map<string, string> options;
-    static const char * const platforms[SIZEOF_PLATFORMS];
-    static const char * const memtests[SIZEOF_MEMTESTS];
-    static const char * const deviceid[SIZEOF_DEVICEIDS];
-    static const char * const force_dev[SIZEOF_FORCE_DEV];
-};
 
-/* possible values of the parameters that will not be passed to OMM
-   first value will always be the default used in case if the option is not specified */
-const char * const GmxOpenMMPlatformOptions::platforms[SIZEOF_PLATFORMS] = { "Cuda" /*,"OpenCL"*/ };
-const char * const GmxOpenMMPlatformOptions::memtests[SIZEOF_MEMTESTS]  = { "15", "full", "off" }; /* also valid any positive integer >15 */
-const char * const GmxOpenMMPlatformOptions::deviceid[SIZEOF_DEVICEIDS]  = { "0" };       /* also valid any positive integer */
-const char * const GmxOpenMMPlatformOptions::force_dev[SIZEOF_FORCE_DEV]   = { "no", "yes" };
+    map<string, string> options; /*!< Data structure to store the option (name, value) pairs. */
+
+    static const char * const platforms[SIZEOF_PLATFORMS];  /*!< Available OpenMM platforms; size #SIZEOF_PLATFORMS */
+    static const char * const memtests[SIZEOF_MEMTESTS];    /*!< Available types of memory tests, also valid 
+                                                                 any positive integer >=15; size #SIZEOF_MEMTESTS */
+    static const char * const deviceid[SIZEOF_DEVICEIDS];   /*!< Possible values for deviceid option; 
+                                                                 also valid any positive integer; size #SIZEOF_DEVICEIDS */
+    static const char * const force_dev[SIZEOF_FORCE_DEV];  /*!< Possible values for for force-device option; 
+                                                                 size #SIZEOF_FORCE_DEV */
+    static const char * const check_combrule[SIZEOF_CHECK_COMBRULE]; /* XXX temporary debug feature to 
+                                                                      turn off combination rule check */
+};
 
+const char * const GmxOpenMMPlatformOptions::platforms[SIZEOF_PLATFORMS]
+                    = {"CUDA"};
+                    //= { "Reference", "CUDA" /*,"OpenCL"*/ };
+const char * const GmxOpenMMPlatformOptions::memtests[SIZEOF_MEMTESTS]
+                    = { "15", "full", "off" };
+const char * const GmxOpenMMPlatformOptions::deviceid[SIZEOF_DEVICEIDS]
+                    = { "0" };
+const char * const GmxOpenMMPlatformOptions::force_dev[SIZEOF_FORCE_DEV]
+                    = { "no", "yes" };
+const char * const GmxOpenMMPlatformOptions::check_combrule[SIZEOF_CHECK_COMBRULE] 
+                    = { "yes", "no" };
+
+/*!
+ * \brief Contructor.
+ * Takes the option list, parses it, checks the options and their values for validity.
+ * When certain options are not provided by the user, as default value the first item  
+ * of the respective constant array is taken (GmxOpenMMPlatformOptions#platforms, 
+ * GmxOpenMMPlatformOptions#memtests, GmxOpenMMPlatformOptions#deviceid, 
+ * GmxOpenMMPlatformOptions#force_dev). 
+ * \param[in] optionString  Option list part of the mdrun -device parameter.
+ */
 GmxOpenMMPlatformOptions::GmxOpenMMPlatformOptions(const char *optionString)
 {
     // set default values
@@ -134,10 +236,11 @@ GmxOpenMMPlatformOptions::GmxOpenMMPlatformOptions(const char *optionString)
     setOption("memtest",        memtests[0]);
     setOption("deviceid",       deviceid[0]);
     setOption("force-device",   force_dev[0]);
+    setOption("check-combrule", check_combrule[0]);
 
     string opt(optionString);
 
-    // remove all the whitespaces
+    // remove all whitespaces
     opt.erase(remove_if(opt.begin(), opt.end(), ::isspace), opt.end());
     // tokenize around ","-s
     vector<string> tokens = split(opt, ',');
@@ -145,26 +248,29 @@ GmxOpenMMPlatformOptions::GmxOpenMMPlatformOptions(const char *optionString)
     for (vector<string>::iterator it = tokens.begin(); it != tokens.end(); ++it)
     {
         string opt = "", val = "";
-        split_opt_val(*it, opt, val);
+        splitOptionValue(*it, opt, val);
 
         if (isStringEqNCase(opt, "platform"))
         {
+            /* no check, this will fail if platform does not exist when we try to set it */
             setOption(opt, val);
             continue;
         }
 
         if (isStringEqNCase(opt, "memtest"))
         {
-            if (!isStringEqNCase(val, "full") && !isStringEqNCase(val, "off")) /* the value has to be an integer >15 */
+            /* the value has to be an integer >15(s) or "full" OR "off" */
+            if (!isStringEqNCase(val, "full") && !isStringEqNCase(val, "off")) 
             {
                 int secs;
                 if (!from_string<int>(secs, val, std::dec))
                 {
-                    gmx_fatal(FARGS, "Invalid value for option memtestoption: \"%s\"!\n", val.c_str());
+                    gmx_fatal(FARGS, "Invalid value for option memtest option: \"%s\"!", val.c_str());
                 }
                 if (secs < 15)
                 {
-                    gmx_fatal(FARGS, "Incorrect value for memtest option (%d). Memtest needs to run for at least 15s!\n", secs);
+                    gmx_fatal(FARGS, "Incorrect value for memtest option (%d). "
+                            "Memtest needs to run for at least 15s!", secs);
                 }
             }
             setOption(opt, val);
@@ -176,38 +282,52 @@ GmxOpenMMPlatformOptions::GmxOpenMMPlatformOptions(const char *optionString)
             int id;
             if (!from_string<int>(id, val, std::dec) )
             {
-                gmx_fatal(FARGS, "Invalid device id: \"%s\"!\n", val.c_str());
+                gmx_fatal(FARGS, "Invalid device id: \"%s\"!", val.c_str());
+            }
+            setOption(opt, val);
+            continue;
+        }
+
+        if (isStringEqNCase(opt, "force-device"))
+        {
+            /* */
+            if (!isStringEqNCase(val, "yes") && !isStringEqNCase(val, "no"))
+            {
+                gmx_fatal(FARGS, "Invalid OpenMM force option: \"%s\"!", val.c_str());
             }
             setOption(opt, val);
             continue;
         }
 
-        if (isStringEqNCase(opt,"force-device"))
+        if (isStringEqNCase(opt, "check-combrule"))
         {
+            /* */
             if (!isStringEqNCase(val, "yes") && !isStringEqNCase(val, "no"))
             {
-                gmx_fatal(FARGS, "Invalid OpenMM force option: \"%s\"!\n", val.c_str());
+                gmx_fatal(FARGS, "Invalid OpenMM force option: \"%s\"!", val.c_str());
             }
             setOption(opt, val);
             continue;
         }
 
+
         // if we got till here something went wrong
-        gmx_fatal(FARGS, "Invalid OpenMM platform option: \"%s\"!\n", (*it).c_str());
+        gmx_fatal(FARGS, "Invalid OpenMM platform option: \"%s\"!", (*it).c_str());
     }
-
-/*    cout << "== platform = " << getOptionValue("platform") << endl
-         << "== deviceID = " << getOptionValue("deviceid") << endl
-         << "== memtest  = " << getOptionValue("memtest") << endl
-         << "== force    = " << getOptionValue("force-device") << endl;
-*/
 }
 
-string GmxOpenMMPlatformOptions::getOptionValue(const string &optName)
+
+/*!
+ * \brief Getter function.
+ * \param[in] opt   Name of the option.
+ * \returns         Returns the value associated to an option. 
+ */
+string GmxOpenMMPlatformOptions::getOptionValue(const string &opt)
 {
-    if (options.find(toUpper(optName)) != options.end())
+       map<string, string> :: const_iterator it = options.find(toUpper(opt));
+       if (it != options.end())
     {
-        return options[toUpper(optName)];
+               return it->second;
     }
     else
     {
@@ -215,33 +335,73 @@ string GmxOpenMMPlatformOptions::getOptionValue(const string &optName)
     }
 }
 
+/*!
+ * \brief Setter function - private, only used from contructor.
+ * \param[in] opt   Name of the option.
+ * \param[in] val   Value for the option. 
+ */
 void GmxOpenMMPlatformOptions::setOption(const string &opt, const string &val)
 {
     options[toUpper(opt)] = val;
 }
 
+/*!
+ * \brief Removes an option with its value from the map structure. If the option 
+ * does not exist, returns without any action.
+ * \param[in] opt   Name of the option.
+ */
+void GmxOpenMMPlatformOptions::remOption(const string &opt) 
+{ 
+    options.erase(toUpper(opt)); 
+}
+
+/*!
+ * \brief Print option-value pairs to a file (debugging function). 
+ */
+void GmxOpenMMPlatformOptions::print()
+{
+    cout << ">> Platform options: " << endl 
+         << ">> platform     = " << getOptionValue("platform") << endl
+         << ">> deviceID     = " << getOptionValue("deviceid") << endl
+         << ">> memtest      = " << getOptionValue("memtest") << endl
+         << ">> force-device = " << getOptionValue("force-device") << endl;
+}
+
+/*!
+ * \brief Container for OpenMM related data structures that represent the bridge 
+ *        between the Gromacs data-structures and the OpenMM library and is but it's 
+ *        only passed through the API functions as void to disable direct access. 
+ */
 class OpenMMData
 {
 public:
-    System* system;
-    Context* context;
-    Integrator* integrator;
-    bool removeCM;
-    GmxOpenMMPlatformOptions *platformOpt;
+    System* system;      /*! The system to simulate. */
+    Context* context;   /*! The OpenMM context in which the simulation is carried out. */
+    Integrator* integrator; /*! The integrator used in the simulation. */
+    bool removeCM;          /*! If \true remove venter of motion, false otherwise. */
+    GmxOpenMMPlatformOptions *platformOpt; /*! Platform options. */
 };
 
-void run_memtest(FILE* fplog, int devId, const char* pre_post, GmxOpenMMPlatformOptions *opt)
+/*!
+ *  \brief Runs memtest on the GPU that has alreaby been initialized by OpenMM.
+ *  \param[in] fplog    Pointer to gromacs log file.
+ *  \param[in] devId    Device id of the GPU to run the test on. 
+                        Note: as OpenMM previously creates the context,for now this is always -1.
+ *  \param[in] pre_post Contains either "Pre" or "Post" just to be able to differentiate in 
+ *                      stdout messages/log between memtest carried out before and after simulation.
+ *  \param[in] opt      Pointer to platform options object.
+ */
+static void runMemtest(FILE* fplog, int devId, const char* pre_post, GmxOpenMMPlatformOptions *opt)
 {
+    char        strout_buf[STRLEN];
+    int         which_test;
+    int         res = 0;
+    string      s = opt->getOptionValue("memtest");
+    const char  *test_type = s.c_str();
 
-    char warn_buf[STRLEN];
-
-    // TODO I guess the log entries should go on stdout as well, shouldn't they? [sz]
-    int which_test;
-    int res;
-    const char * test_type = opt->getOptionValue("memtest").c_str();
     if (!gmx_strcasecmp(test_type, "off"))
     {
-            which_test = 0;
+        which_test = 0;
     }
     else
     {
@@ -251,421 +411,667 @@ void run_memtest(FILE* fplog, int devId, const char* pre_post, GmxOpenMMPlatform
         }
         else
         {
-             from_string<int>(which_test, test_type, std::dec);
+            from_string<int>(which_test, test_type, std::dec);
         }
     }
 
+    if (which_test < 0) 
+    {
+        gmx_fatal(FARGS, "Amount of seconds for memetest is negative (%d). ", which_test);
+    }
+
     switch (which_test)
     {
         case 0: /* no memtest */
-
-            sprintf(warn_buf, "%s-simulation GPU memtest skipped. Note, that faulty memory can cause "
-                    "incorrect results!\n", pre_post);
-            fprintf(fplog, "%s", warn_buf);
-            gmx_warning(warn_buf);
+            sprintf(strout_buf, "%s-simulation GPU memtest skipped. Note, that faulty memory can cause "
+                "incorrect results!", pre_post);
+            fprintf(fplog, "%s\n", strout_buf);
+            gmx_warning(strout_buf);
             break; /* case 0 */
 
         case 1: /* quick memtest */
             fprintf(fplog,  "%s-simulation %s GPU memtest in progress...\n", pre_post, test_type);
             fprintf(stdout, "\n%s-simulation %s GPU memtest in progress...", pre_post, test_type);
-            fflush(fplog); fflush(stdout);
-            if (do_quick_memtest(-1) != 0)
-            {
-                gmx_fatal(FARGS,MEM_ERR_MSG(pre_post));
-
-            }
-            else
-            {
-                fprintf(fplog,  "Memory test completed without errors.\n");
-                fprintf(stdout, "done, no errors detected\n");
-            }
+            fflush(fplog);
+            fflush(stdout);
+            res = do_quick_memtest(devId);
             break; /* case 1 */
 
         case 2: /* full memtest */
             fprintf(fplog,  "%s-simulation %s memtest in progress...\n", pre_post, test_type);
             fprintf(stdout, "\n%s-simulation %s memtest in progress...", pre_post, test_type);
-            fflush(fplog); fflush(stdout);
-            if (do_full_memtest(-1) != 0)
-            {
-                gmx_fatal(FARGS, MEM_ERR_MSG(pre_post) );
-
-            }
-            else
-            {
-                fprintf(fplog, "Memory test completed without errors.\n");
-                fprintf(stdout, "done, no errors detected\n");
-            }
+            fflush(fplog);
+            fflush(stdout);
+            res = do_full_memtest(devId);
             break; /* case 2 */
 
         default: /* timed memtest */
-            fprintf(fplog,  "%s-simulation memtest for ~%ds in progress...\n", pre_post, which_test);
-            fprintf(stdout, "\n%s-simulation memtest for ~%ds in progress...", pre_post, which_test);
-            fflush(fplog); fflush(stdout);
-            if (do_timed_memtest(-1, which_test) != 0)
+            fprintf(fplog,  "%s-simulation ~%ds memtest in progress...\n", pre_post, which_test);
+            fprintf(stdout, "\n%s-simulation ~%ds memtest in progress...", pre_post, which_test);
+            fflush(fplog);
+            fflush(stdout);
+            res = do_timed_memtest(devId, which_test);
+        }
+
+        if (which_test != 0)
+        {
+            if (res != 0)
             {
                 gmx_fatal(FARGS, MEM_ERR_MSG(pre_post));
-
             }
             else
             {
-                fprintf(fplog, "Memory test completed without errors.\n");
-                fprintf(stdout, "done, no errors detected.\n");
+                fprintf(fplog,  "Memory test completed without errors.\n");
+                fflush(fplog);
+                fprintf(stdout, "done, no errors detected\n");
+                fflush(stdout);           
             }
-    }
-    fflush(fplog); fflush(stdout);
+        }
 }
 
-void checkGmxOptions(t_inputrec *ir, gmx_localtop_t *top)
+/*!
+ * \brief Convert Lennard-Jones parameters c12 and c6 to sigma and epsilon.
+ * 
+ * \param[in] c12
+ * \param[in] c6
+ * \param[out] sigma 
+ * \param[out] epsilon
+ */
+static void convert_c_12_6(double c12, double c6, double *sigma, double *epsilon)
 {
+    if (c12 == 0 && c6 == 0)
+    {
+        *epsilon    = 0.0;        
+        *sigma      = 1.0;
+    }
+    else if (c12 > 0 && c6 > 0)
+    {
+        *epsilon    = (c6*c6)/(4.0*c12);
+        *sigma      = pow(c12/c6, 1.0/6.0);
+    }
+    else 
+    {
+        gmx_fatal(FARGS,"OpenMM only supports c6 > 0 and c12 > 0 or c6 = c12 = 0.");
+    } 
+}
 
-    char warn_buf[STRLEN];
+/*!
+ * \brief Does gromacs option checking.
+ *
+ * Checks the gromacs mdp options for features unsupported in OpenMM, case in which 
+ * interrupts the execution. It also warns the user about pecularities of OpenMM 
+ * implementations.
+ * \param[in] fplog         Gromacs log file pointer.
+ * \param[in] ir            Gromacs input parameters, see ::t_inputrec
+ * \param[in] top           Gromacs node local topology, \see gmx_localtop_t
+ * \param[in] state         Gromacs state structure \see ::t_state
+ * \param[in] mdatoms       Gromacs atom parameters, \see ::t_mdatoms
+ * \param[in] fr            \see ::t_forcerec
+ * \param[in] state         Gromacs systems state, \see ::t_state
+ */
+static void checkGmxOptions(FILE* fplog, GmxOpenMMPlatformOptions *opt,
+                            t_inputrec *ir, gmx_localtop_t *top,
+                            t_forcerec *fr, t_state *state)
+{
+    char    warn_buf[STRLEN];
+    int     i, j, natoms;
+    double  c6, c12;
+    double  sigma_ij=0, sigma_ji=0, sigma_ii=0, sigma_jj=0, sigma_comb;
+    double  eps_ij=0, eps_ji=0, eps_ii=0, eps_jj=0, eps_comb;
 
-    // Abort if unsupported critical options are present
+    /* Abort if unsupported critical options are present */
 
     /* Integrator */
     if (ir->eI ==  eiMD)
-        gmx_warning(FARGS, "OpenMM does not support leap-frog, will use velocity-verlet integrator.\n");
+    {
+        gmx_warning( "OpenMM does not support leap-frog, will use velocity-verlet integrator.");
+    }
 
-    if ( (ir->eI !=  eiMD)   &&  
-         (ir->eI !=  eiVV)   &&  
-         (ir->eI !=  eiVVAK) && 
-         (ir->eI !=  eiSD1)  && 
-         (ir->eI !=  eiSD2)  && 
-         (ir->eI !=  eiBD) 
-       )
+    if (    (ir->eI !=  eiMD)   &&
+            (ir->eI !=  eiVV)   &&
+            (ir->eI !=  eiVVAK) &&
+            (ir->eI !=  eiSD1)  &&
+            (ir->eI !=  eiSD2)  &&
+            (ir->eI !=  eiBD) )
     {
-        gmx_fatal(FARGS, "OpenMM supports only the following integrators: md-vv/md-vvak, sd/sd1, and bd.\n");
+        gmx_fatal(FARGS, "OpenMM supports only the following integrators: md/md-vv/md-vv-avek, sd/sd1, and bd.");
     }
 
     /* Electroctstics */
-    if (
-         (ir->coulombtype != eelPME) && 
-         (ir->coulombtype != eelRF) &&  
-         (ir->coulombtype != eelEWALD) &&
-         // no-cutoff
-         ( !(ir->coulombtype == eelCUT && ir->rcoulomb == 0 &&  ir->rvdw == 0))
-       )
-    {
-        gmx_fatal(FARGS,"OpenMM supports only the following methods for electrostatics: NoCutoff (i.e. rcoulomb = rvdw = 0 ),Reaction-Field, Ewald or PME.\n");
+    if (    (ir->coulombtype != eelPME) &&
+            (ir->coulombtype != eelRF) &&
+            (ir->coulombtype != eelEWALD) &&
+            // no-cutoff
+            ( !(ir->coulombtype == eelCUT && ir->rcoulomb == 0 &&  ir->rvdw == 0)) )
+    {
+        gmx_fatal(FARGS,"OpenMM supports only the following methods for electrostatics: "
+                "NoCutoff (i.e. rcoulomb = rvdw = 0 ),Reaction-Field, Ewald or PME.");
     }
 
-    if ( (ir->etc != etcNO) &&
-         (ir->eI !=  eiSD1)  && 
-         (ir->eI !=  eiSD2)  && 
-         (ir->eI !=  eiBD) ) 
-        gmx_warning("OpenMM supports only Andersen thermostat with the md-vv/md-vvak integrators.\n");
+    if (ir->etc != etcNO &&
+        ir->eI  != eiSD1 &&
+        ir->eI  != eiSD2 &&
+        ir->eI  != eiBD )
+    {
+        gmx_warning("OpenMM supports only Andersen thermostat with the md/md-vv/md-vv-avek integrators.");
+    }
+
+    if (ir->implicit_solvent == eisGBSA &&
+        ir->gb_algorithm != egbOBC  )
+    {
+        gmx_warning("OpenMM does not support the specified algorithm for Generalized Born, will use OBC instead.");
+    }
 
     if (ir->opts.ngtc > 1)
-        gmx_fatal(FARGS,"OpenMM does not support multiple temperature coupling groups.\n");
+        gmx_fatal(FARGS,"OpenMM does not support multiple temperature coupling groups.");
 
     if (ir->epc != etcNO)
-        gmx_fatal(FARGS,"OpenMM does not support pressure coupling.\n");
+        gmx_fatal(FARGS,"OpenMM does not support pressure coupling.");
 
     if (ir->opts.annealing[0])
-        gmx_fatal(FARGS,"OpenMM does not support simulated annealing.\n");
-
-    if (ir->eConstrAlg != econtSHAKE)
-        gmx_warning("Constraints in OpenMM are done by a combination "
-                "of SHAKE, SETTLE and CCMA. Accuracy is based on the SHAKE tolerance set "
-                "by the \"shake_tol\" option.\n");
+        gmx_fatal(FARGS,"OpenMM does not support simulated annealing.");
+    
+    if (top->idef.il[F_CONSTR].nr > 0 && ir->eConstrAlg != econtSHAKE)
+        gmx_warning("OpenMM provides contraints as a combination "
+                    "of SHAKE, SETTLE and CCMA. Accuracy is based on the SHAKE tolerance set "
+                    "by the \"shake_tol\" option.");
 
     if (ir->nwall != 0)
-        gmx_fatal(FARGS,"OpenMM does not support walls.\n");
+        gmx_fatal(FARGS,"OpenMM does not support walls.");
 
     if (ir->ePull != epullNO)
-        gmx_fatal(FARGS,"OpenMM does not support pulling.\n");
-
-    if (top->idef.il[F_DISRES].nr > 0)
-        gmx_fatal(FARGS,"OpenMM does not support distant restraints.\n");
+        gmx_fatal(FARGS,"OpenMM does not support pulling.");
 
-    if (top->idef.il[F_ORIRES].nr > 0)
-        gmx_fatal(FARGS,"OpenMM does not support orientation restraints.\n");
-
-    if (top->idef.il[F_ANGRES].nr > 0)
-        gmx_fatal(FARGS,"OpenMM does not support angle restraints.\n");
-
-    if (top->idef.il[F_DIHRES].nr > 0)
-        gmx_fatal(FARGS,"OpenMM does not support dihedral restraints.\n");
+    /* check for interaction types */
+    for (i = 0; i < F_EPOT; i++)
+    {
+        if (!(i == F_CONSTR ||
+            i == F_SETTLE   ||
+            i == F_BONDS    ||            
+            i == F_UREY_BRADLEY ||
+            i == F_ANGLES   ||
+            i == F_PDIHS    ||
+            i == F_RBDIHS   ||
+            i == F_LJ14     ||
+            i == F_GB12     || /* The GB parameters are hardcoded both in */
+            i == F_GB13     || /* Gromacs and OpenMM */
+            i == F_GB14   ) &&
+            top->idef.il[i].nr > 0)
+        {
+            gmx_fatal(FARGS, "OpenMM does not support (some) of the provided interaction " 
+                    "type(s) (%s) ", interaction_function[i].longname);
+        }
+    }
 
     if (ir->efep != efepNO)
-        gmx_fatal(FARGS,"OpenMM does not support free energy calculations.\n");
+        gmx_fatal(FARGS,"OpenMM does not support free energy calculations.");
 
     if (ir->opts.ngacc > 1)
-        gmx_fatal(FARGS,"OpenMM does not support non-equilibrium MD (accelerated groups).\n");
+        gmx_fatal(FARGS,"OpenMM does not support non-equilibrium MD (accelerated groups).");
 
     if (IR_ELEC_FIELD(*ir))
-        gmx_fatal(FARGS,"OpenMM does not support electric fields.\n");
+        gmx_fatal(FARGS,"OpenMM does not support electric fields.");
 
     if (ir->bQMMM)
-        gmx_fatal(FARGS,"OpenMM does not support QMMM calculations.\n");
+        gmx_fatal(FARGS,"OpenMM does not support QMMM calculations.");
 
     if (ir->rcoulomb != ir->rvdw)
         gmx_fatal(FARGS,"OpenMM uses a single cutoff for both Coulomb "
-                "and VdW interactions. Please set rcoulomb equal to rvdw.\n");
+                  "and VdW interactions. Please set rcoulomb equal to rvdw.");
+    
+    if (EEL_FULL(ir->coulombtype))
+    {
+        if (ir->ewald_geometry == eewg3DC)
+            gmx_fatal(FARGS,"OpenMM supports only Ewald 3D geometry.");
+        if (ir->epsilon_surface != 0)
+            gmx_fatal(FARGS,"OpenMM does not support dipole correction in Ewald summation.");
+    }
+
+    if (TRICLINIC(state->box))        
+    {
+        gmx_fatal(FARGS,"OpenMM does not support triclinic unit cells.");
+    }
+
+    /* XXX this is just debugging code to disable the combination rule check */
+    if ( isStringEqNCase(opt->getOptionValue("check-combrule"), "yes") )
+    {
+    /* As OpenMM by default uses hardcoded combination rules 
+       sigma_ij = (sigma_i + sigma_j)/2, eps_ij = sqrt(eps_i * eps_j)
+       we need to check whether the force field params obey this 
+       and if not, we can't use this force field so we exit 
+       grace-fatal-fully. */
+    real *nbfp = fr->nbfp;
+    natoms = fr->ntype;
+    if (debug) 
+    {   
+        fprintf(debug, ">> Atom parameters: <<\n%10s%5s %5s %5s %5s COMB\n", 
+                "", "i-j", "j-i", "i-i", "j-j");
+    }
+    /* loop over all i-j atom pairs and verify if 
+       sigma_ij = sigma_ji = sigma_comb and eps_ij = eps_ji = eps_comb */
+    for (i = 0; i < natoms; i++)
+    {
+        /* i-i */
+        c12 = C12(nbfp, natoms, i, i);
+        c6  = C6(nbfp,  natoms, i, i);
+        convert_c_12_6(c12, c6, &sigma_ii, &eps_ii);
+
+        for (j = 0; j < i; j++)
+        {
+            /* i-j */
+            c12 = C12(nbfp, natoms, i, j);
+            c6  = C6(nbfp,  natoms, i, j);
+            convert_c_12_6(c12, c6, &sigma_ij, &eps_ij);
+            /* j-i */
+            c12 = C12(nbfp, natoms, j, i);
+            c6  = C6(nbfp,  natoms, j, i);
+            convert_c_12_6(c12, c6, &sigma_ji, &eps_ji);
+            /* j-j */
+            c12 = C12(nbfp, natoms, j, j);
+            c6  = C6(nbfp,  natoms, j, j);
+            convert_c_12_6(c12, c6, &sigma_jj, &eps_jj);
+            /* OpenMM hardcoded combination rules */
+            sigma_comb = COMBRULE_SIGMA(sigma_ii, sigma_jj);
+            eps_comb = COMBRULE_EPS(eps_ii, eps_jj);
+  
+            if (debug)
+            {
+                fprintf(debug, "i=%-3d j=%-3d", i, j);
+                fprintf(debug, "%-11s", "sigma");
+                fprintf(debug, "%5.3f %5.3f %5.3f %5.3f %5.3f\n",  
+                        sigma_ij, sigma_ji, sigma_ii, sigma_jj, sigma_comb);
+                fprintf(debug, "%11s%-11s", "", "epsilon");
+                fprintf(debug, "%5.3f %5.3f %5.3f %5.3f %5.3f\n", 
+                        eps_ij, eps_ji, eps_ii, eps_jj, eps_comb);
+            }
+
+            /* check the values against the rule used by omm */
+            if((fabs(eps_ij) > COMBRULE_CHK_TOL && 
+                fabs(eps_ji) > COMBRULE_CHK_TOL) &&
+               (fabs(sigma_comb - sigma_ij) > COMBRULE_CHK_TOL ||
+               fabs(sigma_comb - sigma_ji) > COMBRULE_CHK_TOL ||
+               fabs(eps_comb - eps_ij) > COMBRULE_CHK_TOL ||
+               fabs(eps_comb - eps_ji) > COMBRULE_CHK_TOL ))
+            {
+                gmx_fatal(FARGS,
+                        "The combination rules of the used force-field do not "
+                        "match the one supported by OpenMM:  "
+                        "sigma_ij = (sigma_i + sigma_j)/2, eps_ij = sqrt(eps_i * eps_j). "
+                        "Switch to a force-field that uses these rules in order to "
+                        "simulate this system using OpenMM.\n");                        
+            }
+        }
+    }
+    if (debug) { fprintf(debug, ">><<\n\n"); }
+
+    /* if we got here, log that everything is fine */
+    if (debug)
+    {
+        fprintf(debug, ">> The combination rule of the used force matches the one used by OpenMM.\n");
+    }
+    fprintf(fplog, "The combination rule of the force used field matches the one used by OpenMM.\n");   
 
+    } /* if (are we checking the combination rules) ... */
 }
 
-/**
- * Initialize OpenMM, and return a pointer to the OpenMMData object containing the System, Integrator, and Context.
+
+/*!
+ * \brief Initialize OpenMM, run sanity/consistency checks, and return a pointer to 
+ * the OpenMMData.
+ * 
+ * Various gromacs data structures are passed that contain the parameters, state and 
+ * other porperties of the system to simulate. These serve as input for initializing 
+ * OpenMM. Besides, a set of misc action are taken:
+ *  - OpenMM plugins are loaded;
+ *  - platform options in \p platformOptStr are parsed and checked; 
+ *  - Gromacs parameters are checked for OpenMM support and consistency;
+ *  - after the OpenMM is initialized memtest executed in the same GPU context.
+ * 
+ * \param[in] fplog             Gromacs log file handler.
+ * \param[in] platformOptStr    Platform option string. 
+ * \param[in] ir                The Gromacs input parameters, see ::t_inputrec
+ * \param[in] top_global        Gromacs system toppology, \see ::gmx_mtop_t
+ * \param[in] top               Gromacs node local topology, \see gmx_localtop_t
+ * \param[in] mdatoms           Gromacs atom parameters, \see ::t_mdatoms
+ * \param[in] fr                \see ::t_forcerec
+ * \param[in] state             Gromacs systems state, \see ::t_state
+ * \returns                     Pointer to a 
+ * 
  */
 void* openmm_init(FILE *fplog, const char *platformOptStr,
-                    t_commrec *cr,t_inputrec *ir,
-                    gmx_mtop_t *top_global, gmx_localtop_t *top,
-                    t_mdatoms *mdatoms, t_forcerec *fr,t_state *state)
+                  t_inputrec *ir,
+                  gmx_mtop_t *top_global, gmx_localtop_t *top,
+                  t_mdatoms *mdatoms, t_forcerec *fr, t_state *state)
 {
 
     char warn_buf[STRLEN];
-
     static bool hasLoadedPlugins = false;
     string usedPluginDir;
+    int devId;
 
-    try {
-    if (!hasLoadedPlugins)
-    {
-        vector<string> loadedPlugins;
-    /*  Look for OpenMM plugins at various locations (listed in order of priority):
-        - on the path in OPENMM_PLUGIN_DIR environment variable if this is specified
-        - on the path in the OPENMM_PLUGIN_DIR macro that is set by the build script
-        - at the default location assumed by OpenMM
-    */
-        /* env var */
-        char *pluginDir = getenv("OPENMM_PLUGIN_DIR");
-        trim(pluginDir);
-        /* no env var or empty */
-        if (pluginDir != NULL && *pluginDir != '\0')
-        {
-            loadedPlugins = Platform::loadPluginsFromDirectory(pluginDir);
-            if (loadedPlugins.size() > 0)
-            {
-                hasLoadedPlugins = true;
-                usedPluginDir = pluginDir;
-            }
-            else
+    try
+    {
+        if (!hasLoadedPlugins)
+        {
+            vector<string> loadedPlugins;
+            /*  Look for OpenMM plugins at various locations (listed in order of priority):
+                - on the path in OPENMM_PLUGIN_DIR environment variable if this is specified
+                - on the path in the OPENMM_PLUGIN_DIR macro that is set by the build script
+                - at the default location assumed by OpenMM
+            */
+            /* env var */
+            char *pluginDir = getenv("OPENMM_PLUGIN_DIR");
+            trim(pluginDir);
+            /* no env var or empty */
+            if (pluginDir != NULL && *pluginDir != '\0')
             {
-                gmx_fatal(FARGS, "The directory provided in the OPENMM_PLUGIN_DIR environment variable "
-                    "(%s) does not contain valid OpenMM plugins. Check your OpenMM installation!", pluginDir);
+                loadedPlugins = Platform::loadPluginsFromDirectory(pluginDir);
+                if (loadedPlugins.size() > 0)
+                {
+                    hasLoadedPlugins = true;
+                    usedPluginDir = pluginDir;
+                }
+                else
+                {
+                    gmx_fatal(FARGS, "The directory provided in the OPENMM_PLUGIN_DIR environment variable "
+                              "(%s) does not contain valid OpenMM plugins. Check your OpenMM installation!", 
+                              pluginDir);
+                }
             }
-        }
 
-        /* macro set at build time  */
+            /* macro set at build time  */
 #ifdef OPENMM_PLUGIN_DIR
-        if (!hasLoadedPlugins)
-        {
-            loadedPlugins = Platform::loadPluginsFromDirectory(OPENMM_PLUGIN_DIR);
-            if (loadedPlugins.size() > 0)
+            if (!hasLoadedPlugins)
             {
-                hasLoadedPlugins = true;
-                usedPluginDir = OPENMM_PLUGIN_DIR;
+                loadedPlugins = Platform::loadPluginsFromDirectory(OPENMM_PLUGIN_DIR);
+                if (loadedPlugins.size() > 0)
+                {
+                    hasLoadedPlugins = true;
+                    usedPluginDir = OPENMM_PLUGIN_DIR;
+                }
             }
-        }
 #endif
-        /* default loocation */
-        if (!hasLoadedPlugins)
-        {
-            loadedPlugins = Platform::loadPluginsFromDirectory(Platform::getDefaultPluginsDirectory());
-            if (loadedPlugins.size() > 0)
+            /* default loocation */
+            if (!hasLoadedPlugins)
+            {
+                loadedPlugins = Platform::loadPluginsFromDirectory(Platform::getDefaultPluginsDirectory());
+                if (loadedPlugins.size() > 0)
+                {
+                    hasLoadedPlugins = true;
+                    usedPluginDir = Platform::getDefaultPluginsDirectory();
+                }
+            }
+
+            /* if there are still no plugins loaded there won't be any */
+            if (!hasLoadedPlugins)
+            {
+                gmx_fatal(FARGS, "No OpenMM plugins were found! You can provide the"
+                          " plugin directory in the OPENMM_PLUGIN_DIR environment variable.", pluginDir);
+            }
+
+            fprintf(fplog, "\nOpenMM plugins loaded from directory %s:\t", usedPluginDir.c_str());
+            for (int i = 0; i < (int)loadedPlugins.size(); i++)
             {
-                hasLoadedPlugins = true;
-                usedPluginDir = Platform::getDefaultPluginsDirectory();
+                fprintf(fplog, "%s, ", loadedPlugins[i].c_str());
             }
+            fprintf(fplog, "\n");
         }
 
-        /* if there are still no plugins loaded there won't be any */
-        if (!hasLoadedPlugins)
+        /* parse option string */
+        GmxOpenMMPlatformOptions *opt = new GmxOpenMMPlatformOptions(platformOptStr);
+        devId = atoi(opt->getOptionValue("deviceid").c_str());
+
+        if (debug)
         {
-            gmx_fatal(FARGS, "No OpenMM plugins were found! You can provide the"
-                " plugin directory in the OPENMM_PLUGIN_DIR environment variable.", pluginDir);
+            opt->print();
         }
 
-        fprintf(fplog, "\nPlugins loaded from directory %s:\t", usedPluginDir.c_str());
-        for (int i = 0; i < loadedPlugins.size(); i++)
+        /* check wheter Gromacs options compatibility with OpenMM */
+        checkGmxOptions(fplog, opt, ir, top, fr, state);
+
+        // Create the system.
+        const t_idef& idef = top->idef;
+        const int numAtoms = top_global->natoms;
+        const int numConstraints = idef.il[F_CONSTR].nr/3;
+        const int numSettle = idef.il[F_SETTLE].nr/2;
+        const int numBonds = idef.il[F_BONDS].nr/3;
+        const int numUB = idef.il[F_UREY_BRADLEY].nr/4;
+        const int numAngles = idef.il[F_ANGLES].nr/4;
+        const int numPeriodic = idef.il[F_PDIHS].nr/5;
+        const int numRB = idef.il[F_RBDIHS].nr/5;
+        const int num14 = idef.il[F_LJ14].nr/3;
+        System* sys = new System();
+        if (ir->nstcomm > 0)
+            sys->addForce(new CMMotionRemover(ir->nstcomm));
+
+        // Set bonded force field terms.
+        const int* bondAtoms = (int*) idef.il[F_BONDS].iatoms;
+        HarmonicBondForce* bondForce = new HarmonicBondForce();
+        sys->addForce(bondForce);
+        int offset = 0;
+        for (int i = 0; i < numBonds; ++i)
         {
-            fprintf(fplog, "%s, ", loadedPlugins[i].c_str());
+            int type = bondAtoms[offset++];
+            int atom1 = bondAtoms[offset++];
+            int atom2 = bondAtoms[offset++];
+            bondForce->addBond(atom1, atom2,
+                               idef.iparams[type].harmonic.rA, idef.iparams[type].harmonic.krA);
+        }
+        // Urey-Bradley includes both the angle and bond potential for 1-3 interactions
+        const int* ubAtoms = (int*) idef.il[F_UREY_BRADLEY].iatoms;
+        HarmonicBondForce* ubBondForce = new HarmonicBondForce();
+        HarmonicAngleForce* ubAngleForce = new HarmonicAngleForce();
+        sys->addForce(ubBondForce);
+        sys->addForce(ubAngleForce);
+        offset = 0;
+        for (int i = 0; i < numUB; ++i)
+        {
+            int type = ubAtoms[offset++];
+            int atom1 = ubAtoms[offset++];
+            int atom2 = ubAtoms[offset++];
+            int atom3 = ubAtoms[offset++];
+            ubBondForce->addBond(atom1, atom3,
+                               idef.iparams[type].u_b.r13, idef.iparams[type].u_b.kUB);
+            ubAngleForce->addAngle(atom1, atom2, atom3, 
+                    idef.iparams[type].u_b.theta*M_PI/180.0, idef.iparams[type].u_b.ktheta);
+        }
+        const int* angleAtoms = (int*) idef.il[F_ANGLES].iatoms;
+        HarmonicAngleForce* angleForce = new HarmonicAngleForce();
+        sys->addForce(angleForce);
+        offset = 0;
+        for (int i = 0; i < numAngles; ++i)
+        {
+            int type = angleAtoms[offset++];
+            int atom1 = angleAtoms[offset++];
+            int atom2 = angleAtoms[offset++];
+            int atom3 = angleAtoms[offset++];
+            angleForce->addAngle(atom1, atom2, atom3, 
+                    idef.iparams[type].harmonic.rA*M_PI/180.0, idef.iparams[type].harmonic.krA);
+        }
+        const int* periodicAtoms = (int*) idef.il[F_PDIHS].iatoms;
+        PeriodicTorsionForce* periodicForce = new PeriodicTorsionForce();
+        sys->addForce(periodicForce);
+        offset = 0;
+        for (int i = 0; i < numPeriodic; ++i)
+        {
+            int type = periodicAtoms[offset++];
+            int atom1 = periodicAtoms[offset++];
+            int atom2 = periodicAtoms[offset++];
+            int atom3 = periodicAtoms[offset++];
+            int atom4 = periodicAtoms[offset++];
+            periodicForce->addTorsion(atom1, atom2, atom3, atom4,
+                                      idef.iparams[type].pdihs.mult,
+                                      idef.iparams[type].pdihs.phiA*M_PI/180.0, 
+                                      idef.iparams[type].pdihs.cpA);
+        }
+        const int* rbAtoms = (int*) idef.il[F_RBDIHS].iatoms;
+        RBTorsionForce* rbForce = new RBTorsionForce();
+        sys->addForce(rbForce);
+        offset = 0;
+        for (int i = 0; i < numRB; ++i)
+        {
+            int type = rbAtoms[offset++];
+            int atom1 = rbAtoms[offset++];
+            int atom2 = rbAtoms[offset++];
+            int atom3 = rbAtoms[offset++];
+            int atom4 = rbAtoms[offset++];
+            rbForce->addTorsion(atom1, atom2, atom3, atom4,
+                                idef.iparams[type].rbdihs.rbcA[0], idef.iparams[type].rbdihs.rbcA[1],
+                                idef.iparams[type].rbdihs.rbcA[2], idef.iparams[type].rbdihs.rbcA[3],
+                                idef.iparams[type].rbdihs.rbcA[4], idef.iparams[type].rbdihs.rbcA[5]);
         }
-        fprintf(fplog, "\n");
-    }
 
-    /* parse option string */
-    GmxOpenMMPlatformOptions *opt = new GmxOpenMMPlatformOptions(platformOptStr);
-
-    /* check wheter Gromacs options compatibility with OpenMM */
-    checkGmxOptions(ir, top);
-
-    /* check GPU support */
-    char s[1000];
-    is_supported_cuda_gpu(atoi(opt->getOptionValue("deviceid").c_str()), s);
-
-    // Create the system.
-    const t_idef& idef = top->idef;
-    const int numAtoms = top_global->natoms;
-    const int numConstraints = idef.il[F_CONSTR].nr/3;
-    const int numSettle = idef.il[F_SETTLE].nr/2;
-    const int numBonds = idef.il[F_BONDS].nr/3;
-    const int numAngles = idef.il[F_ANGLES].nr/4;
-    const int numPeriodic = idef.il[F_PDIHS].nr/5;
-    const int numRB = idef.il[F_RBDIHS].nr/5;
-    const int num14 = idef.il[F_LJ14].nr/3;
-    System* sys = new System();
-    if (ir->nstcomm > 0)
-        sys->addForce(new CMMotionRemover(ir->nstcomm));
-
-    // Set bonded force field terms.
-    const int* bondAtoms = (int*) idef.il[F_BONDS].iatoms;
-    HarmonicBondForce* bondForce = new HarmonicBondForce();
-    sys->addForce(bondForce);
-    int offset = 0;
-    for (int i = 0; i < numBonds; ++i) {
-        int type = bondAtoms[offset++];
-        int atom1 = bondAtoms[offset++];
-        int atom2 = bondAtoms[offset++];
-        bondForce->addBond(atom1, atom2, idef.iparams[type].harmonic.rA, idef.iparams[type].harmonic.krA);
-    }
-    const int* angleAtoms = (int*) idef.il[F_ANGLES].iatoms;
-    HarmonicAngleForce* angleForce = new HarmonicAngleForce();
-    sys->addForce(angleForce);
-    offset = 0;
-    for (int i = 0; i < numAngles; ++i) {
-        int type = angleAtoms[offset++];
-        int atom1 = angleAtoms[offset++];
-        int atom2 = angleAtoms[offset++];
-        int atom3 = angleAtoms[offset++];
-        angleForce->addAngle(atom1, atom2, atom3, idef.iparams[type].harmonic.rA*M_PI/180.0, idef.iparams[type].harmonic.krA);
-    }
-    const int* periodicAtoms = (int*) idef.il[F_PDIHS].iatoms;
-    PeriodicTorsionForce* periodicForce = new PeriodicTorsionForce();
-    sys->addForce(periodicForce);
-    offset = 0;
-    for (int i = 0; i < numPeriodic; ++i) {
-        int type = periodicAtoms[offset++];
-        int atom1 = periodicAtoms[offset++];
-        int atom2 = periodicAtoms[offset++];
-        int atom3 = periodicAtoms[offset++];
-        int atom4 = periodicAtoms[offset++];
-        periodicForce->addTorsion(atom1, atom2, atom3, atom4, idef.iparams[type].pdihs.mult, idef.iparams[type].pdihs.phiA*M_PI/180.0, idef.iparams[type].pdihs.cpA);
-    }
-    const int* rbAtoms = (int*) idef.il[F_RBDIHS].iatoms;
-    RBTorsionForce* rbForce = new RBTorsionForce();
-    sys->addForce(rbForce);
-    offset = 0;
-    for (int i = 0; i < numRB; ++i) {
-        int type = rbAtoms[offset++];
-        int atom1 = rbAtoms[offset++];
-        int atom2 = rbAtoms[offset++];
-        int atom3 = rbAtoms[offset++];
-        int atom4 = rbAtoms[offset++];
-        rbForce->addTorsion(atom1, atom2, atom3, atom4, idef.iparams[type].rbdihs.rbcA[0], idef.iparams[type].rbdihs.rbcA[1],
-                idef.iparams[type].rbdihs.rbcA[2], idef.iparams[type].rbdihs.rbcA[3], idef.iparams[type].rbdihs.rbcA[4], idef.iparams[type].rbdihs.rbcA[5]);
-    }
+        // Set nonbonded parameters and masses.
+        int ntypes = fr->ntype;
+        int* types = mdatoms->typeA;
+        real* nbfp = fr->nbfp;
+        real* charges = mdatoms->chargeA;
+        real* masses = mdatoms->massT;
+        NonbondedForce* nonbondedForce = new NonbondedForce();
+        sys->addForce(nonbondedForce);
+        
+        switch (ir->ePBC)
+        {
+        case epbcNONE:
+            if (ir->rcoulomb == 0)
+            {
+                nonbondedForce->setNonbondedMethod(NonbondedForce::NoCutoff);
+            }
+            else
+            {
+                nonbondedForce->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic);
+            }
+            break;
+        case epbcXYZ:
+            switch (ir->coulombtype)
+            {
+            case eelRF:
+                nonbondedForce->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
+                break;
+
+            case eelEWALD:
+                nonbondedForce->setNonbondedMethod(NonbondedForce::Ewald);
+                break;
+
+            case eelPME:
+                nonbondedForce->setNonbondedMethod(NonbondedForce::PME);
+                break;
+
+            default:
+                gmx_fatal(FARGS,"Internal error: you should not see this message, it that the"
+                          "electrosatics option check failed. Please report this error!");
+            }        
+            sys->setPeriodicBoxVectors(Vec3(state->box[0][0], 0, 0),
+                                       Vec3(0, state->box[1][1], 0), Vec3(0, 0, state->box[2][2]));                    
+            nonbondedForce->setCutoffDistance(ir->rcoulomb);
+           
+            break;
+        default:            
+            gmx_fatal(FARGS,"OpenMM supports only full periodic boundary conditions "
+                              "(pbc = xyz), or none (pbc = no).");
+        }
 
-    // Set nonbonded parameters and masses.
-
-    int ntypes = fr->ntype;
-    int* types = mdatoms->typeA;
-    real* nbfp = fr->nbfp;
-    real* charges = mdatoms->chargeA;
-    real* masses = mdatoms->massT;
-    NonbondedForce* nonbondedForce = new NonbondedForce();
-    sys->addForce(nonbondedForce);
-
-    if (ir->rcoulomb == 0)
-            nonbondedForce->setNonbondedMethod(NonbondedForce::NoCutoff);
-
-    else {
-           switch (ir->coulombtype)
-           {
-               case eelRF: // TODO what is the correct condition?
-                   if (ir->ePBC == epbcXYZ) {
-                        nonbondedForce->setNonbondedMethod(NonbondedForce::CutoffPeriodic);
-                        sys->setPeriodicBoxVectors(Vec3(state->box[0][0], 0, 0), Vec3(0, state->box[1][1], 0), Vec3(0, 0, state->box[2][2]));
-                   }
-                   else if (ir->ePBC == epbcNONE)
-                       nonbondedForce->setNonbondedMethod(NonbondedForce::CutoffNonPeriodic);
-                   else
-                       gmx_fatal(FARGS,"OpenMM supports only full periodic boundary conditions (pbc = xyz), or none (pbc = no).\n");                       
-                    nonbondedForce->setCutoffDistance(ir->rcoulomb);
-                    break;
-
-            case eelEWALD:
-                    if (ir->ewald_geometry == eewg3DC)
-                        gmx_fatal(FARGS,"OpenMM supports only Ewald 3D geometry.\n");
-                    if (ir->epsilon_surface != 0)
-                        gmx_fatal(FARGS,"OpenMM does not support dipole correction in Ewald summation.\n");
-                    nonbondedForce->setNonbondedMethod(NonbondedForce::Ewald);
-                    nonbondedForce->setCutoffDistance(ir->rcoulomb);
-                    sys->setPeriodicBoxVectors(Vec3(state->box[0][0], 0, 0), Vec3(0, state->box[1][1], 0), Vec3(0, 0, state->box[2][2]));
-                    break;
-
-                case eelPME:
-                    nonbondedForce->setNonbondedMethod(NonbondedForce::PME);
-                    nonbondedForce->setCutoffDistance(ir->rcoulomb);
-                    sys->setPeriodicBoxVectors(Vec3(state->box[0][0], 0, 0), Vec3(0, state->box[1][1], 0), Vec3(0, 0, state->box[2][2]));
-                    break;
-
-                default:
-                    gmx_fatal(FARGS,"Internal error: you should not see this message, it that the"
-                    "electrosatics option check failed. Please report this error!");
-               }
-    }
 
-    for (int i = 0; i < numAtoms; ++i) {
-        real c6 = nbfp[types[i]*2*ntypes+types[i]*2];
-        real c12 = nbfp[types[i]*2*ntypes+types[i]*2+1];
-        if (c12 <= 0)
-            nonbondedForce->addParticle(charges[i], 1.0, 0.0);
-        else
-            nonbondedForce->addParticle(charges[i], pow(c12/c6, (real) (1.0/6.0)), c6*c6/(4.0*c12));
-        sys->addParticle(masses[i]);
-    }
+        /* Fix for PME and Ewald error tolerance 
+         *
+        *  OpenMM uses approximate formulas to calculate the Ewald parameter:
+        *  alpha = (1.0/cutoff)*sqrt(-log(2.0*tolerlance));
+        *  and the grid spacing for PME:
+        *  gridX = ceil(alpha*box[0][0]/pow(0.5*tol, 0.2));
+        *  gridY = ceil(alpha*box[1][1]/pow(0.5*tol, 0.2));
+        *  gridZ = ceil(alpha*box[2][2]/pow(0.5*tol, 0.2));
+         *
+        *  It overestimates the precision and setting it to 
+        *  (500 x ewald_rtol) seems to give a reasonable match to the GROMACS settings
+         *  
+         *  If the default ewald_rtol=1e-5 is used we silently adjust the value,
+         * otherwise a warning is issued about the action taken. 
+        */
+        double corr_ewald_rtol = 500.0 * ir->ewald_rtol;
+        if ((ir->ePBC == epbcXYZ) && 
+            (ir->coulombtype == eelEWALD || ir->coulombtype == eelPME))
+        {
+            if (debug)
+            {
+                fprintf(debug, ">> ewald_rtol = %e (corrected = %e) \n",
+                    ir->ewald_rtol, corr_ewald_rtol);
+            }
 
-    // Build a table of all exclusions.
+            if (fabs(ir->ewald_rtol - 1e-5) > 1e-10)
+            {
+                gmx_warning("OpenMM uses the ewald_rtol parameter with approximate formulas "
+                        "to calculate the alpha and grid spacing parameters of the Ewald "
+                        "and PME methods. This tolerance need to be corrected in order to get "
+                        "settings close to the ones used in GROMACS. Although the internal correction "
+                        "should work for any reasonable value of ewald_rtol, using values other than "
+                        "the default 1e-5 might cause incorrect behavior.");
+
+                if (corr_ewald_rtol > 1)
+                {
+                    gmx_fatal(FARGS, "The ewald_rtol accuracy term is >1 after the "
+                            "adjustment for OpenMM (%e)", corr_ewald_rtol);
+                }
+            }
+            nonbondedForce->setEwaldErrorTolerance(corr_ewald_rtol);
+        }
 
-    vector<set<int> > exclusions(numAtoms);
-    for (int i = 0; i < numAtoms; i++) {
-        int start = top->excls.index[i];
-        int end = top->excls.index[i+1];
-        for (int j = start; j < end; j++)
-            exclusions[i].insert(top->excls.a[j]);
-    }
+        for (int i = 0; i < numAtoms; ++i)
+        {
+            double c12 = nbfp[types[i]*2*ntypes+types[i]*2+1];
+            double c6 = nbfp[types[i]*2*ntypes+types[i]*2];
+            double sigma=0.0, epsilon=0.0;
+            convert_c_12_6(c12, c6, &sigma, &epsilon);
+            nonbondedForce->addParticle(charges[i], sigma, epsilon);
+            sys->addParticle(masses[i]);
+        }
 
-    // Record the 1-4 interactions, and remove them from the list of exclusions.
-
-    const int* nb14Atoms = (int*) idef.il[F_LJ14].iatoms;
-    offset = 0;
-    for (int i = 0; i < num14; ++i) {
-        int type = nb14Atoms[offset++];
-        int atom1 = nb14Atoms[offset++];
-        int atom2 = nb14Atoms[offset++];
-        real c6 = idef.iparams[type].lj14.c6A;
-        real c12 = idef.iparams[type].lj14.c12A;
-        real sigma, epsilon;
-        if (c12 <= 0) {
-            epsilon = (real) 0.0;
-            sigma = (real) 1.0;
-        }
-        else {
-            epsilon = (real) ((c6*c6)/(4.0*c12));
-            sigma = (real) pow(c12/c6, (real) (1.0/6.0));
-        }
-        nonbondedForce->addException(atom1, atom2, fr->fudgeQQ*charges[atom1]*charges[atom2], sigma, epsilon);
-        exclusions[atom1].erase(atom2);
-        exclusions[atom2].erase(atom1);
-    }
+        // Build a table of all exclusions.
+        vector<set<int> > exclusions(numAtoms);
+        for (int i = 0; i < numAtoms; i++)
+        {
+            int start = top->excls.index[i];
+            int end = top->excls.index[i+1];
+            for (int j = start; j < end; j++)
+                exclusions[i].insert(top->excls.a[j]);
+        }
 
-    // Record exclusions.
+        // Record the 1-4 interactions, and remove them from the list of exclusions.
+        const int* nb14Atoms = (int*) idef.il[F_LJ14].iatoms;
+        offset = 0;
+        for (int i = 0; i < num14; ++i)
+        {
+            int type = nb14Atoms[offset++];
+            int atom1 = nb14Atoms[offset++];
+            int atom2 = nb14Atoms[offset++];
+            double sigma=0, epsilon=0;
+            convert_c_12_6(idef.iparams[type].lj14.c12A, 
+                    idef.iparams[type].lj14.c6A,
+                    &sigma, &epsilon);
+            nonbondedForce->addException(atom1, atom2,
+                                         fr->fudgeQQ*charges[atom1]*charges[atom2], sigma, epsilon);
+            exclusions[atom1].erase(atom2);
+            exclusions[atom2].erase(atom1);
+        }
 
-    for (int i = 0; i < numAtoms; i++) {
-        for (set<int>::const_iterator iter = exclusions[i].begin(); iter != exclusions[i].end(); ++iter) {
-            if (i < *iter)
-                nonbondedForce->addException(i, *iter, 0.0, 1.0, 0.0);
+        // Record exclusions.
+        for (int i = 0; i < numAtoms; i++)
+        {
+            for (set<int>::const_iterator iter = exclusions[i].begin(); iter != exclusions[i].end(); ++iter)
+            {
+                if (i < *iter)
+                {
+                    nonbondedForce->addException(i, *iter, 0.0, 1.0, 0.0);
+                }
+            }
         }
-    }
 
-    // Add GBSA if needed.
-    t_atoms        atoms;
-    atoms    = gmx_mtop_global_atoms(top_global);
+        // Add GBSA if needed.
+        if (ir->implicit_solvent == eisGBSA)
+        {
+            gmx_warning("The OBC scale factors alpha, beta and gamma are hardcoded in OpenMM with the default Gromacs values.");
+            t_atoms atoms       = gmx_mtop_global_atoms(top_global);
+            GBSAOBCForce* gbsa  = new GBSAOBCForce();
 
-    if (ir->implicit_solvent == eisGBSA) {
-            GBSAOBCForce* gbsa = new GBSAOBCForce();
             sys->addForce(gbsa);
             gbsa->setSoluteDielectric(ir->epsilon_r);
             gbsa->setSolventDielectric(ir->gb_epsilon_solvent);
@@ -677,195 +1083,240 @@ void* openmm_init(FILE *fplog, const char *platformOptStr,
             else if (nonbondedForce->getNonbondedMethod() == NonbondedForce::CutoffPeriodic)
                 gbsa->setNonbondedMethod(GBSAOBCForce::CutoffPeriodic);
             else
-                       gmx_fatal(FARGS,"OpenMM supports only Reaction-Field electrostatics with OBC/GBSA.\n");
+                gmx_fatal(FARGS,"OpenMM supports only Reaction-Field electrostatics with OBC/GBSA.");
 
             for (int i = 0; i < numAtoms; ++i)
+            {
                 gbsa->addParticle(charges[i],
                                   top_global->atomtypes.gb_radius[atoms.atom[i].type],
                                   top_global->atomtypes.S_hct[atoms.atom[i].type]);
-    }
-
-    // Set constraints.
-
-    const int* constraintAtoms = (int*) idef.il[F_CONSTR].iatoms;
-    offset = 0;
-    for (int i = 0; i < numConstraints; ++i) {
-        int type = constraintAtoms[offset++];
-        int atom1 = constraintAtoms[offset++];
-        int atom2 = constraintAtoms[offset++];
-        sys->addConstraint(atom1, atom2, idef.iparams[type].constr.dA);
-    }
-    const int* settleAtoms = (int*) idef.il[F_SETTLE].iatoms;
-    offset = 0;
-    for (int i = 0; i < numSettle; ++i) {
-        int type = settleAtoms[offset++];
-        int oxygen = settleAtoms[offset++];
-        sys->addConstraint(oxygen, oxygen+1, idef.iparams[type].settle.doh);
-        sys->addConstraint(oxygen, oxygen+2, idef.iparams[type].settle.doh);
-        sys->addConstraint(oxygen+1, oxygen+2, idef.iparams[type].settle.dhh);
-    }
-
-    // Create an integrator for simulating the system.
+            }
+            free_t_atoms(&atoms, FALSE);
+        }
 
-    real friction = (ir->opts.tau_t[0] == 0.0 ? 0.0 : 1.0/ir->opts.tau_t[0]);
-    Integrator* integ;
-    if (ir->eI == eiMD || ir->eI == eiVV || ir->eI == eiVVAK) {
-        integ = new VerletIntegrator(ir->delta_t);
-        if ( ir->etc != etcNO) {
-           real collisionFreq = ir->opts.tau_t[0] / 1000; /* tau_t (ps) / 1000 = collisionFreq (fs^-1) */
-           AndersenThermostat* thermostat = new AndersenThermostat(ir->opts.ref_t[0], friction); /* TODO test this  */
-           sys->addForce(thermostat);
+        // Set constraints.
+        const int* constraintAtoms = (int*) idef.il[F_CONSTR].iatoms;
+        offset = 0;
+        for (int i = 0; i < numConstraints; ++i)
+        {
+            int type = constraintAtoms[offset++];
+            int atom1 = constraintAtoms[offset++];
+            int atom2 = constraintAtoms[offset++];
+            sys->addConstraint(atom1, atom2, idef.iparams[type].constr.dA);
+        }
+        const int* settleAtoms = (int*) idef.il[F_SETTLE].iatoms;
+        offset = 0;
+        for (int i = 0; i < numSettle; ++i)
+        {
+            int type = settleAtoms[offset++];
+            int oxygen = settleAtoms[offset++];
+            sys->addConstraint(oxygen, oxygen+1, idef.iparams[type].settle.doh);
+            sys->addConstraint(oxygen, oxygen+2, idef.iparams[type].settle.doh);
+            sys->addConstraint(oxygen+1, oxygen+2, idef.iparams[type].settle.dhh);
         }
-    }
 
-    else if (ir->eI == eiBD) {
-        integ = new BrownianIntegrator(ir->opts.ref_t[0], friction, ir->delta_t);
-        static_cast<BrownianIntegrator*>(integ)->setRandomNumberSeed(ir->ld_seed); /* TODO test this */
-    }
-    else if (EI_SD(ir->eI)) {
-        integ = new LangevinIntegrator(ir->opts.ref_t[0], friction, ir->delta_t);
-        static_cast<LangevinIntegrator*>(integ)->setRandomNumberSeed(ir->ld_seed); /* TODO test this */
-    }
-    else {
-        gmx_fatal(FARGS, "OpenMM supports only the following integrators: md-vv/md-vvak, sd/sd1, and bd.\n");
-    }
+        // Create an integrator for simulating the system.
+        double friction = (ir->opts.tau_t[0] == 0.0 ? 0.0 : 1.0/ir->opts.tau_t[0]);
+        Integrator* integ;
+        if (ir->eI == eiBD)
+        {
+            integ = new BrownianIntegrator(ir->opts.ref_t[0], friction, ir->delta_t);
+            static_cast<BrownianIntegrator*>(integ)->setRandomNumberSeed(ir->ld_seed); 
+        }
+        else if (EI_SD(ir->eI))
+        {
+            integ = new LangevinIntegrator(ir->opts.ref_t[0], friction, ir->delta_t);
+            static_cast<LangevinIntegrator*>(integ)->setRandomNumberSeed(ir->ld_seed); 
+        }
+        else 
+        {
+            integ = new VerletIntegrator(ir->delta_t);
+            if ( ir->etc != etcNO)
+            {
+                real collisionFreq = ir->opts.tau_t[0] / 1000; /* tau_t (ps) / 1000 = collisionFreq (fs^-1) */
+                AndersenThermostat* thermostat = new AndersenThermostat(ir->opts.ref_t[0], friction); 
+                sys->addForce(thermostat);
+            }           
+        }
+        integ->setConstraintTolerance(ir->shake_tol);
 
-    integ->setConstraintTolerance(ir->shake_tol);
+        // Create a context and initialize it.
+        Context* context = NULL;
 
-    // Create a context and initialize it.
-    Context* context = NULL;
-    if (platformOptStr == NULL || platformOptStr == "")
-    {
-        context = new Context(*sys, *integ);
-    }
-    else
-    {
-        // Find which platform is it.
-        for (int i = 0; i < Platform::getNumPlatforms() && context == NULL; i++)
+        /*      
+        OpenMM could automatically select the "best" GPU, however we're not't 
+        going to let it do that for now, as the current algorithm is very rudimentary
+        and we anyway support only CUDA.        
+        if (platformOptStr == NULL || platformOptStr == "")
         {
-            if (isStringEqNCase(opt->getOptionValue("platform"), Platform::getPlatform(i).getName()))
-            {
-                Platform& platform = Platform::getPlatform(i);
-                // set standard properties
-                platform.setPropertyDefaultValue("CudaDevice", opt->getOptionValue("deviceid"));
-                // TODO add extra properties
-                context = new Context(*sys, *integ, platform);
-            }
+            context = new Context(*sys, *integ);
         }
-        if (context == NULL)
+        else
+        */        
         {
-            gmx_fatal(FARGS, "The requested platform \"%s\" could not be found.\n", opt->getOptionValue("platform").c_str());
+            /* which platform should we use */
+            for (int i = 0; i < (int)Platform::getNumPlatforms() && context == NULL; i++)
+            {
+                if (isStringEqNCase(opt->getOptionValue("platform"), Platform::getPlatform(i).getName()))
+                {
+                    Platform& platform = Platform::getPlatform(i);
+                    // set standard properties
+                    platform.setPropertyDefaultValue("CudaDevice", opt->getOptionValue("deviceid"));
+                    // TODO add extra properties
+                    context = new Context(*sys, *integ, platform);
+                }
+            }
+            if (context == NULL)
+            {
+                gmx_fatal(FARGS, "The requested platform \"%s\" could not be found.", 
+                        opt->getOptionValue("platform").c_str());
+            }
         }
-    }
 
-    Platform& platform = context->getPlatform();
-    fprintf(fplog, "Gromacs will use the OpenMM platform: %s\n", platform.getName().c_str());
+        Platform& platform = context->getPlatform();
+        fprintf(fplog, "Gromacs will use the OpenMM platform: %s\n", platform.getName().c_str());
 
-    const vector<string>& properties = platform.getPropertyNames();
-    if (debug)
-    {
-        for (int i = 0; i < properties.size(); i++)
+        const vector<string>& properties = platform.getPropertyNames();
+        if (debug)
         {
-            printf(">> %s: %s\n", properties[i].c_str(), platform.getPropertyValue(*context, properties[i]).c_str());
-            fprintf(fplog, ">> %s: %s\n", properties[i].c_str(), platform.getPropertyValue(*context, properties[i]).c_str());
+            for (int i = 0; i < (int)properties.size(); i++)
+            {
+                fprintf(debug, ">> %s: %s\n", properties[i].c_str(), 
+                        platform.getPropertyValue(*context, properties[i]).c_str());
+            }
         }
-    }
 
-    int devId;
-    if (!from_string<int>(devId, platform.getPropertyValue(*context, "CudaDevice"), std::dec))
-    {
-        gmx_fatal(FARGS, "Internal error: couldn't determine the device selected by OpenMM");
-    }
+        /* only for CUDA */
+        if (isStringEqNCase(opt->getOptionValue("platform"), "CUDA"))
+        {
+            int tmp;
+            if (!from_string<int>(tmp, platform.getPropertyValue(*context, "CudaDevice"), std::dec))
+            {
+                gmx_fatal(FARGS, "Internal error: couldn't determine the device selected by OpenMM");
 
-    /* check GPU compatibility */
-    char gpuname[STRLEN];
-    if (!is_supported_cuda_gpu(-1, gpuname))
-    {
-        if (!gmx_strcasecmp(opt->getOptionValue("force-device").c_str(), "yes"))
+            }
+
+            /* For now this is just to double-check if OpenMM selected the GPU we wanted,
+            but when we'll let OpenMM select the GPU automatically, it will query the devideId.
+            */            
+            if (tmp != devId)
+            {
+                gmx_fatal(FARGS, "Internal error: OpenMM is using device #%d"
+                        "while initialized for device #%d", tmp, devId);
+            }        
+            cout << ">>>>> OpenMM devId=" << tmp << endl;
+            
+            /* check GPU compatibility */
+            char gpuname[STRLEN];
+            devId = atoi(opt->getOptionValue("deviceid").c_str());
+            if (!is_supported_cuda_gpu(-1, gpuname))
+            {
+                if (!gmx_strcasecmp(opt->getOptionValue("force-device").c_str(), "yes"))
+                {
+                    sprintf(warn_buf, "Non-supported GPU selected (#%d, %s), forced continuing."
+                            "Note, that the simulation can be slow or it migth even crash.", 
+                            devId, gpuname);
+                    fprintf(fplog, "%s\n", warn_buf);
+                    gmx_warning(warn_buf);
+                }
+                else
+                {
+                    gmx_fatal(FARGS, "The selected GPU (#%d, %s) is not supported by Gromacs! "
+                              "Most probably you have a low-end GPU which would not perform well, " 
+                              "or new hardware that has not been tested with the current release. "
+                              "If you still want to try using the device, use the force-device=yes option.", 
+                              devId, gpuname);
+                }
+            }
+            else
+            {
+                fprintf(fplog, "Gromacs will run on the GPU #%d (%s).\n", devId, gpuname);
+            }
+        }
+        
+        /* only for CUDA */
+        if (isStringEqNCase(opt->getOptionValue("platform"), "CUDA"))
         {
-            sprintf(warn_buf, "Non-supported GPU selected (#%d, %s), forced continuing.\n"
-                    "Note, that the simulation can be slow or it migth even crash.", devId, gpuname);
-            fprintf(fplog, "%s", warn_buf);
-            gmx_warning(warn_buf);
+            /* pre-simulation memtest */
+            runMemtest(fplog, -1, "Pre", opt);
         }
-        else
+
+        vector<Vec3> pos(numAtoms);
+        vector<Vec3> vel(numAtoms);
+        for (int i = 0; i < numAtoms; ++i)
         {
-            gmx_fatal(FARGS, "The selected GPU (#%d, %s) is not supported by Gromacs! "
-                    "Most probably you have a low-end GPU which would not perform well, or new hardware that"
-                    "has not been tested yet with Gromacs-OpenMM. If you still want to try using this "
-                    "device use the force=on option.", devId, gpuname);
+            pos[i] = Vec3(state->x[i][0], state->x[i][1], state->x[i][2]);
+            vel[i] = Vec3(state->v[i][0], state->v[i][1], state->v[i][2]);
         }
+        context->setPositions(pos);
+        context->setVelocities(vel);
+
+        // Return a structure containing the system, integrator, and context.
+        OpenMMData* data = new OpenMMData();
+        data->system = sys;
+        data->integrator = integ;
+        data->context = context;
+        data->removeCM = (ir->nstcomm > 0);
+        data->platformOpt = opt;
+        return data;
     }
-    else
+    catch (std::exception& e)
     {
-        fprintf(fplog, "Gromacs will run on the GPU #%d (%s).\n", devId, gpuname);
-    }
-
-    /* do the pre-simulation memtest */
-    run_memtest(fplog, -1, "Pre", opt);
-
-    vector<Vec3> pos(numAtoms);
-    vector<Vec3> vel(numAtoms);
-    for (int i = 0; i < numAtoms; ++i) {
-        pos[i] = Vec3(state->x[i][0], state->x[i][1], state->x[i][2]);
-        vel[i] = Vec3(state->v[i][0], state->v[i][1], state->v[i][2]);
-    }
-    context->setPositions(pos);
-    context->setVelocities(vel);
-
-    // Return a structure containing the system, integrator, and context.
-    OpenMMData* data = new OpenMMData();
-    data->system = sys;
-    data->integrator = integ;
-    data->context = context;
-    data->removeCM = (ir->nstcomm > 0);
-    data->platformOpt = opt;
-    return data;
-
-    } catch (std::exception& e) {
-        gmx_fatal(FARGS, "OpenMM exception caught while initializating: %s\n", e.what());
-    }
+        gmx_fatal(FARGS, "OpenMM exception caught while initializating: %s", e.what());
+    } 
+    return NULL; /* just to avoid warnings */
 }
 
-/**
- * Integrate one step.
+/*!
+ * \brief Integrate one step.
  *
- * @param data the OpenMMData object created by openmm_init().
+ * \param[in] data  OpenMMData object created by openmm_init().
  */
 void openmm_take_one_step(void* data)
 {
-    // static int step = 0; printf("----> taking step #%d\n", step++); 
-    try {
+    // static int step = 0; printf("----> taking step #%d\n", step++);
+    try
+    {
         static_cast<OpenMMData*>(data)->integrator->step(1);
-    } catch (std::exception& e) {
-        gmx_fatal(FARGS, "OpenMM exception caught while taking a step: %s\n", e.what());
+    }
+    catch (std::exception& e)
+    {
+        gmx_fatal(FARGS, "OpenMM exception caught while taking a step: %s", e.what());
     }
 }
 
-/**
- * Integrate n steps.
+/*!
+ * \brief Integrate n steps.
  *
- * @param data the OpenMMData object created by openmm_init().
+ * \param[in] data  OpenMMData object created by openmm_init().
  */
 void openmm_take_steps(void* data, int nstep)
 {
-    try {
+    try
+    {
         static_cast<OpenMMData*>(data)->integrator->step(nstep);
-    } catch (std::exception& e) {
-        gmx_fatal(FARGS, "OpenMM exception caught while taking a step: %s\n", e.what());
+    }
+    catch (std::exception& e)
+    {
+        gmx_fatal(FARGS, "OpenMM exception caught while taking a step: %s", e.what());
     }
 }
 
-/**
- * Clean up all the data structures used by OpenMM.
+/*!
+ * \brief Clean up the data structures cretead for OpenMM.
  *
- * @param log file pointer
- * @param data the OpenMMData object created by openmm_init().
+ * \param[in] log   Log file pointer.
+ * \param[in] data  OpenMMData object created by openmm_init().
  */
 void openmm_cleanup(FILE* fplog, void* data)
 {
     OpenMMData* d = static_cast<OpenMMData*>(data);
-    run_memtest(fplog, -1, "Post", d->platformOpt);
+    /* only for CUDA */
+    if (isStringEqNCase(d->platformOpt->getOptionValue("platform"), "CUDA"))
+    {
+        /* post-simulation memtest */
+        runMemtest(fplog, -1, "Post", d->platformOpt);
+    }
     delete d->system;
     delete d->integrator;
     delete d->context;
@@ -873,16 +1324,27 @@ void openmm_cleanup(FILE* fplog, void* data)
     delete d;
 }
 
-/**
- * Copy the current state information (positions, velocities, and forces) into the data structures used
- * by Gromacs.
+/*!
+ * \brief Copy the current state information from OpenMM into the Gromacs data structures.
+ * 
+ * This function results in the requested proprties to be copied from the 
+ * GPU to host. As this represents a bottleneck, the frequency of pulling data
+ * should be minimized. 
  *
- * @param data the OpenMMData object created by openmm_init().
+ * \param[in]   data        OpenMMData object created by openmm_init().
+ * \param[out]  time        Simulation time for which the state was created.
+ * \param[out]  state       State of the system: coordinates and velocities.
+ * \param[out]  f           Forces.
+ * \param[out]  enerd       Energies.
+ * \param[in]   includePos  True if coordinates are requested.
+ * \param[in]   includeVel  True if velocities are requested. 
+ * \param[in]   includeForce True if forces are requested. 
+ * \param[in]   includeEnergy True if energies are requested. 
  */
 void openmm_copy_state(void *data,
-                        t_state *state, double *time,
-                        rvec f[], gmx_enerdata_t *enerd,
-                        bool includePos, bool includeVel, bool includeForce, bool includeEnergy)
+                       t_state *state, double *time,
+                       rvec f[], gmx_enerdata_t *enerd,
+                       bool includePos, bool includeVel, bool includeForce, bool includeEnergy)
 {
     int types = 0;
     if (includePos)
@@ -895,34 +1357,42 @@ void openmm_copy_state(void *data,
         types += State::Energy;
     if (types == 0)
         return;
-    try {
+    try
+    {
         State currentState = static_cast<OpenMMData*>(data)->context->getState(types);
         int numAtoms =  static_cast<OpenMMData*>(data)->system->getNumParticles();
-        if (includePos) {
-            for (int i = 0; i < numAtoms; i++) {
+        if (includePos)
+        {
+            for (int i = 0; i < numAtoms; i++)
+            {
                 Vec3 x = currentState.getPositions()[i];
                 state->x[i][0] = x[0];
                 state->x[i][1] = x[1];
                 state->x[i][2] = x[2];
             }
         }
-        if (includeVel) {
-            for (int i = 0; i < numAtoms; i++) {
+        if (includeVel)
+        {
+            for (int i = 0; i < numAtoms; i++)
+            {
                 Vec3 v = currentState.getVelocities()[i];
                 state->v[i][0] = v[0];
                 state->v[i][1] = v[1];
                 state->v[i][2] = v[2];
             }
         }
-        if (includeForce) {
-            for (int i = 0; i < numAtoms; i++) {
+        if (includeForce)
+        {
+            for (int i = 0; i < numAtoms; i++)
+            {
                 Vec3 force = currentState.getForces()[i];
                 f[i][0] = force[0];
                 f[i][1] = force[1];
                 f[i][2] = force[2];
             }
         }
-        if (includeEnergy) {
+        if (includeEnergy)
+        {
             int numConstraints = static_cast<OpenMMData*>(data)->system->getNumConstraints();
             int dof = 3*numAtoms-numConstraints;
             if (static_cast<OpenMMData*>(data)->removeCM)
@@ -933,7 +1403,9 @@ void openmm_copy_state(void *data,
             enerd->term[F_TEMP] = 2.0*enerd->term[F_EKIN]/dof/BOLTZ;
         }
         *time = currentState.getTime();
-    } catch (std::exception& e) {
-        gmx_fatal(FARGS, "OpenMM exception caught while retrieving state information: %s\n", e.what());
+    }
+    catch (std::exception& e)
+    {
+        gmx_fatal(FARGS, "OpenMM exception caught while retrieving state information: %s", e.what());
     }
 }
index aed209ccd1e435b4e880b2d40308f8c06d09fbfc..359e5df2d4f0b895b2783186ddaa90c82d741366 100644 (file)
@@ -1,3 +1,38 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ *
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2010, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+
 #ifndef _OPENMM_WRAPPER_H_
 #define _OPENMM_WRAPPER_H_
 
@@ -8,9 +43,9 @@ extern "C"
 
 #ifdef GMX_OPENMM
 void* openmm_init(FILE *fplog, const char *platformOptStr,
-                    t_commrec *cr,t_inputrec *ir,
+                    t_inputrec *ir,
                     gmx_mtop_t *top_global, gmx_localtop_t *top,
-                    t_mdatoms *mdatoms, t_forcerec *fr,t_state *state);
+                    t_mdatoms *mdatoms, t_forcerec *fr, t_state *state);
 
 void openmm_take_one_step(void* data);
 
@@ -21,12 +56,12 @@ void openmm_copy_state(void *data,
 
 void openmm_cleanup(FILE *fplog, void* data);
 #else 
-/* dummy versions of the openmm wrapper functions to enable compilation of 
+/* dummy versions of the wrapper functions to enable compilation of 
    do_md_openmm even when OpenMM is not used */ 
 void* openmm_init(FILE *fplog, const char *platformOptStr,
-                    t_commrec *cr,t_inputrec *ir,
+                    t_inputrec *ir,
                     gmx_mtop_t *top_global, gmx_localtop_t *top,
-                    t_mdatoms *mdatoms, t_forcerec *fr,t_state *state){return NULL;}
+                    t_mdatoms *mdatoms, t_forcerec *fr, t_state *state){return NULL;}
 
 void openmm_take_one_step(void* data){}
 
@@ -37,7 +72,7 @@ void openmm_copy_state(void *data,
 
 void openmm_cleanup(FILE *fplog, void* data){}
 
-#endif //GMX_OPENMM
+#endif /*GMX_OPENMM*/
 
 
 #ifdef __cplusplus
index 34287fa2aa5f00d5cdb0f7f352a308335a601183..79da815d020071d6cd895d6174ac17f181d84135 100644 (file)
@@ -77,6 +77,7 @@ typedef struct {
   char main[6];
   char nter[6];
   char cter[6];
+  char bter[6];
 } rtprename_t;
 
 
@@ -155,7 +156,7 @@ static const char *get_glntp(int resnr,int nrr,const rtprename_t *rr)
 static const char *get_lystp(int resnr,int nrr,const rtprename_t *rr)
 {
   enum { elys, elysH, elysNR };
-  const  char *lh[elysNR] = { "LYS", "LYSH" };
+  const  char *lh[elysNR] = { "LYSN", "LYS" };
   const char *expl[elysNR] = {
     "Not protonated (charge 0)",
     "Protonated (charge +1)"
@@ -179,7 +180,7 @@ static const char *get_argtp(int resnr,int nrr,const rtprename_t *rr)
 static const char *get_cystp(int resnr,int nrr,const rtprename_t *rr)
 {
   enum { ecys, ecysH, ecysNR };
-  const char *lh[ecysNR] = { "CYS", "CYSH" };
+  const char *lh[ecysNR] = { "CYS2", "CYS" };
   const char *expl[ecysNR] = {
     "Cysteine in disulfide bridge",
     "Protonated"
@@ -215,11 +216,11 @@ static void read_rtprename(const char *fname,FILE *fp,
   ncol = 0;
   while(get_a_line(fp,line,STRLEN)) {
     srenew(rr,n+1);
-    nc = sscanf(line,"%s %s %s %s %s",
-               rr[n].gmx,rr[n].main,rr[n].nter,rr[n].cter,buf);
+    nc = sscanf(line,"%s %s %s %s %s %s",
+               rr[n].gmx,rr[n].main,rr[n].nter,rr[n].cter,rr[n].bter,buf);
     if (ncol == 0) {
-      if (nc != 2 && nc != 4) {
-       gmx_fatal(FARGS,"Residue renaming database '%s' has %d columns instead of %d or %d",fname,ncol,2,4);
+      if (nc != 2 && nc != 5) {
+       gmx_fatal(FARGS,"Residue renaming database '%s' has %d columns instead of %d or %d",fname,ncol,2,5);
       }
       ncol = nc;
     } else if (nc != ncol) {
@@ -230,6 +231,7 @@ static void read_rtprename(const char *fname,FILE *fp,
       /* This file does not have special termini names, copy them from main */
       strcpy(rr[n].nter,rr[n].main);
       strcpy(rr[n].cter,rr[n].main);
+      strcpy(rr[n].bter,rr[n].main);
     }
 
     n++;
@@ -268,7 +270,9 @@ static void rename_resrtp(t_atoms *pdba,int nterpairs,int *rN,int *rC,
          bC = TRUE;
        }
       }
-      if (bN) {
+      if (bN && bC) {
+       nn = rr[i].bter;
+      } else if (bN) {
        nn = rr[i].nter;
       } else if (bC) {
        nn = rr[i].cter;
@@ -447,10 +451,9 @@ static int read_pdball(const char *inf, const char *outf,char *title,
   rename_pdbres(atoms,"HOH",watres,FALSE,symtab);
   rename_pdbres(atoms,"SOL",watres,FALSE,symtab);
   rename_pdbres(atoms,"WAT",watres,FALSE,symtab);
-  
-  rename_pdbres(atoms,"HEM","HEME",FALSE,symtab);
 
-  rename_atoms("xlateat.dat",NULL,atoms,symtab,NULL,TRUE,aan,TRUE,bVerbose);
+  rename_atoms("xlateat.dat",NULL,FALSE,
+              atoms,symtab,NULL,TRUE,aan,TRUE,bVerbose);
   
   if (natom == 0)
     return 0;
@@ -478,8 +481,6 @@ void process_chain(t_atoms *pdba, rvec *x,
   if (bPheU) rename_bb(pdba,"PHE","PHEU",FALSE,symtab);
   if (bLysMan) 
     rename_bbint(pdba,"LYS",get_lystp,FALSE,symtab,nrr,rr);
-  else
-    rename_bb(pdba,"LYS","LYSH",FALSE,symtab);
   if (bArgMan) 
     rename_bbint(pdba,"ARG",get_argtp,FALSE,symtab,nrr,rr);
   if (bGlnMan) 
@@ -493,9 +494,13 @@ void process_chain(t_atoms *pdba, rvec *x,
   else
     rename_bb(pdba,"GLUH","GLU",FALSE,symtab);
 
-  if (bRenameCys)
-    /* Make sure we don't have things like CYS? */ 
+  if (bRenameCys) {
+    /* Make sure we don't have things like CYS?
+     * And rename CYS to CYSH, since that is the Gromacs standard
+     * unbound cysteine rtp entry name.
+     */ 
     rename_bb(pdba,"CYS","CYS",FALSE,symtab);
+  }
 
   if (!bHisMan)
     set_histp(pdba,x,angle,distance);
@@ -685,9 +690,9 @@ void find_nc_ter(t_atoms *pdba,int r0,int r1,int *rn,int *rc,t_aa_names *aan)
   *rc=-1;
 
   for(rnr=r0; rnr<r1; rnr++) {
-    if ((*rn == -1) && (is_protein(aan,*pdba->resinfo[rnr].name)))
+    if ((*rn == -1) && (is_residue(aan,*pdba->resinfo[rnr].name)))
        *rn=rnr;
-    if ((*rc != rnr) && (is_protein(aan,*pdba->resinfo[rnr].name)))
+    if ((*rc != rnr) && (is_residue(aan,*pdba->resinfo[rnr].name)))
       *rc=rnr;
   }
 
@@ -739,9 +744,13 @@ int main(int argc, char *argv[])
       
     "The corresponding data files can be found in the library directory",
     "in the subdirectory <forcefield>.ff.",
-    "Check chapter 5 of the manual for more",
-    "information about file formats. By default the forcefield selection",
-    "is interactive, but you can use the [TT]-ff[tt] option to specify",
+    "Note that pdb2gmx will also look for a [TT]forcefield.itp[tt] file",
+    "in such subdirectories in the current working directory.",
+    "After choosing a force field, all files will be read only from",
+    "the corresponding directory, unless the [TT]-cwd[tt] option is used.",
+    "Check chapter 5 of the manual for more information about file formats.",
+    "By default the forcefield selection is interactive,",
+    "but you can use the [TT]-ff[tt] option to specify",
     "one of the short names above on the command line instead. In that",
     "case pdb2gmx just looks for the corresponding file.[PAR]",
     
@@ -754,11 +763,11 @@ int main(int argc, char *argv[])
     "files, that allow it to make special bonds (Cys-Cys, Heme-His, etc.),",
     "if necessary this can be done manually. The program can prompt the",
     "user to select which kind of LYS, ASP, GLU, CYS or HIS residue she",
-    "wants. For LYS the choice is between LYS (two protons on NZ) or LYSH",
-    "(three protons, default), for ASP and GLU unprotonated (default) or",
-    "protonated, for HIS the proton can be either on ND1 (HISA), on NE2",
-    "(HISB) or on both (HISH). By default these selections are done",
-    "automatically. For His, this is based on an optimal hydrogen bonding",
+    "wants. For LYS the choice is between neutral (two protons on NZ) or",
+    "protonated (three protons, default), for ASP and GLU unprotonated",
+    "(default) or protonated, for HIS the proton can be either on ND1,",
+    "on NE2 or on both. By default these selections are done automatically.",
+    "For His, this is based on an optimal hydrogen bonding",
     "conformation. Hydrogen bonds are defined based on a simple geometric",
     "criterium, specified by the maximum hydrogen-donor-acceptor angle",
     "and donor-acceptor distance, which are set by [TT]-angle[tt] and",
@@ -769,7 +778,7 @@ int main(int argc, char *argv[])
     "with a disulfide brigde or intermolecular distance restraints.[PAR]",
     
     "pdb2gmx will also check the occupancy field of the pdb file.",
-    "If any of the occupanccies are not one, indicating that the atom is",
+    "If any of the occupancies are not one, indicating that the atom is",
     "not resolved well in the structure, a warning message is issued.",
     "When a pdb file does not originate from an X-Ray structure determination",
     "all occupancy fields may be zero. Either way, it is up to the user",
@@ -831,9 +840,10 @@ int main(int argc, char *argv[])
   t_aa_names *aan;
   const char *top_fn;
   char       fn[256],itp_fn[STRLEN],posre_fn[STRLEN],buf_fn[STRLEN];
-  char       molname[STRLEN],title[STRLEN],resname[STRLEN],quote[STRLEN];
+  char       molname[STRLEN],title[STRLEN],quote[STRLEN],generator[STRLEN];
   char       *c,forcefield[STRLEN],ffdir[STRLEN];
-  char       fff[STRLEN],suffix[STRLEN];
+  char       ffname[STRLEN],suffix[STRLEN];
+  char       *watermodel;
   const char *watres;
   int        nrtpf;
   char       **rtpf;
@@ -867,7 +877,7 @@ int main(int argc, char *argv[])
  
 
   /* Command line arguments must be static */
-  static bool bNewRTP=FALSE,bAllowOverrideRTP=FALSE,bMerge=FALSE;
+  static bool bNewRTP=FALSE,bAddCWD=FALSE,bAllowOverrideRTP=FALSE,bMerge=FALSE;
   static bool bInter=FALSE, bCysMan=FALSE; 
   static bool bLysMan=FALSE, bAspMan=FALSE, bGluMan=FALSE, bHisMan=FALSE;
   static bool bGlnMan=FALSE, bArgMan=FALSE;
@@ -879,12 +889,14 @@ int main(int argc, char *argv[])
   static real angle=135.0, distance=0.3,posre_fc=1000;
   static real long_bond_dist=0.25, short_bond_dist=0.05;
   static const char *vsitestr[] = { NULL, "none", "hydrogens", "aromatics", NULL };
-  static const char *watstr[] = { NULL, "spc", "spce", "tip3p", "tip4p", "tip5p", "f3c", NULL };
+  static const char *watstr[] = { NULL, "select", "none", "spc", "spce", "tip3p", "tip4p", "tip5p", NULL };
   static const char *ff = "select";
 
   t_pargs pa[] = {
     { "-newrtp", FALSE, etBOOL, {&bNewRTP},
       "HIDDENWrite the residue database in new format to 'new.rtp'"},
+    { "-cwd",    FALSE, etBOOL, {&bAddCWD},
+      "Also read force field files from the current working directory" },
     { "-rtpo",  FALSE, etBOOL,  {&bAllowOverrideRTP},
       "Allow an entry in a local rtp file to override a library rtp entry"},
     { "-lb",     FALSE, etREAL, {&long_bond_dist},
@@ -896,7 +908,7 @@ int main(int argc, char *argv[])
     { "-ff",     FALSE, etSTR,  {&ff},
       "Force field, interactive by default. Use -h for information." },
     { "-water",  FALSE, etENUM, {watstr},
-      "Water model to use: with GROMOS we recommend SPC, with OPLS, TIP4P" },
+      "Water model to use" },
     { "-inter",  FALSE, etBOOL, {&bInter},
       "Set the next 8 options to interactive"},
     { "-ss",     FALSE, etBOOL, {&bCysMan}, 
@@ -915,8 +927,8 @@ int main(int argc, char *argv[])
       "Interactive Glutamine selection, iso neutral" },
     { "-his",    FALSE, etBOOL, {&bHisMan},
       "Interactive Histidine selection, iso checking H-bonds" },
-    { "-cys",    FALSE, etBOOL, {&bRenameCys},
-      "HIDDENRename cysteines to cys" },
+    { "-cysh",    FALSE, etBOOL, {&bRenameCys},
+      "HIDDENUse rtp entry CYSH for cysteines" },
     { "-angle",  FALSE, etREAL, {&angle}, 
       "Minimum hydrogen-donor-acceptor angle for a H-bond (degrees)" },
     { "-dist",   FALSE, etREAL, {&distance},
@@ -960,14 +972,18 @@ int main(int argc, char *argv[])
            forcefield,sizeof(forcefield),
            ffdir,sizeof(ffdir));
 
-  if (strlen(forcefield) > 2)
-    strcpy(fff,&(forcefield[2]));
-  else
-    gmx_incons(forcefield);
+  if (strlen(forcefield) > 0) {
+    strcpy(ffname,forcefield);
+    ffname[0] = toupper(ffname[0]);
+  } else {
+    gmx_fatal(FARGS,"Empty forcefield string");
+  }
   
-  printf("\nUsing force field '%s' in directory '%s'\n\n",
-        forcefield,ffdir);
+  printf("\nUsing the %s force field in directory %s\n\n",
+        ffname,ffdir);
     
+  choose_watermodel(watstr[0],ffdir,&watermodel);
+
   if (bInter) {
     /* if anything changes here, also change description of -inter */
     bCysMan = TRUE;
@@ -1012,7 +1028,7 @@ int main(int argc, char *argv[])
   aan = get_aa_names();
   
   /* Read residue renaming database(s), if present */
-  nrrn = fflib_search_file_end(ffdir,".r2b",FALSE,&rrn);
+  nrrn = fflib_search_file_end(ffdir,bAddCWD,".r2b",FALSE,&rrn);
   nrtprename = 0;
   rtprename  = NULL;
   for(i=0; i<nrrn; i++) {
@@ -1023,21 +1039,16 @@ int main(int argc, char *argv[])
   }
   sfree(rrn);
 
-  /* Encad only works with the f3c water model */
-  if(strncmp(forcefield,"ffencad",7) == 0)
-  {
-      printf("Encad detected, switching to the F3C water model...\n");
-      watstr[0] = "f3c";
-      watres = "WAT";
-  }    
-
   clear_mat(box);
-  if (strcmp(watstr[0],"tip4p") == 0)
+  if (watermodel != NULL && (strstr(watermodel,"4p") ||
+                            strstr(watermodel,"4P"))) {
     watres = "HO4";
-  else if (strcmp(watstr[0],"tip5p") == 0)
+  } else if (watermodel != NULL && (strstr(watermodel,"5p") ||
+                                   strstr(watermodel,"5P"))) {
     watres = "HO5";
-  else
+  } else {
     watres = "HOH";
+  }
     
   aps = gmx_atomprop_init();
   natom = read_pdball(opt2fn("-f",NFILE,fnm),opt2fn_null("-q",NFILE,fnm),title,
@@ -1200,11 +1211,11 @@ int main(int argc, char *argv[])
   check_occupancy(&pdba_all,opt2fn("-f",NFILE,fnm),bVerbose);
   
   /* Read atomtypes... */
-  atype = read_atype(ffdir,&symtab);
+  atype = read_atype(ffdir,bAddCWD,&symtab);
   
   /* read residue database */
   printf("Reading residue database... (%s)\n",forcefield);
-  nrtpf = fflib_search_file_end(ffdir,".rtp",TRUE,&rtpf);
+  nrtpf = fflib_search_file_end(ffdir,bAddCWD,".rtp",TRUE,&rtpf);
   nrtp  = 0;
   restp = NULL;
   for(i=0; i<nrtpf; i++) {
@@ -1220,15 +1231,21 @@ int main(int argc, char *argv[])
   }
     
   /* read hydrogen database */
-  nah = read_h_db(ffdir,&ah);
+  nah = read_h_db(ffdir,bAddCWD,&ah);
   
   /* Read Termini database... */
-  nNtdb=read_ter_db(ffdir,'n',&ntdb,atype);
-  nCtdb=read_ter_db(ffdir,'c',&ctdb,atype);
+  nNtdb=read_ter_db(ffdir,bAddCWD,'n',&ntdb,atype);
+  nCtdb=read_ter_db(ffdir,bAddCWD,'c',&ctdb,atype);
   
   top_fn=ftp2fn(efTOP,NFILE,fnm);
   top_file=gmx_fio_fopen(top_fn,"w");
-  print_top_header(top_file,top_fn,title,FALSE,ffdir,mHmult);
+
+#ifdef PACKAGE_VERSION
+  sprintf(generator,"%s - version %s",ShortProgram(), PACKAGE_VERSION );
+#else
+  sprintf(generator,"%s - version %s",ShortProgram(), "unknown" );
+#endif
+  print_top_header(top_file,top_fn,generator,FALSE,ffdir,mHmult);
 
   nincl=0;
   nmol=0;
@@ -1269,9 +1286,7 @@ int main(int argc, char *argv[])
     }
 
     /* Check for disulphides and other special bonds */
-    rename_bb(pdba,"CYSH","CYS",TRUE,&symtab);
-    nssbonds=mk_specbonds(pdba,x,bCysMan,&ssbonds);
-    rename_bb(pdba,"CYS","CYSH",TRUE,&symtab);
+    nssbonds = mk_specbonds(pdba,x,bCysMan,&ssbonds,bVerbose);
 
     if (nrtprename > 0) {
       rename_resrtp(pdba,cc->nterpairs,cc->rN,cc->rC,nrtprename,rtprename,
@@ -1295,9 +1310,10 @@ int main(int argc, char *argv[])
        */
       /* First the N terminus */
       if (nNtdb > 0) {
-       strncpy(resname,*pdba->resinfo[cc->rN[i]].name,3);
-       resname[3] = '\0';
-       tdblist=filter_ter(nrtp,restp,nNtdb,ntdb,resname,&ntdblist);
+       tdblist = filter_ter(nrtp,restp,nNtdb,ntdb,
+                            *pdba->resinfo[cc->rN[i]].name,
+                            *pdba->resinfo[cc->rN[i]].rtp,
+                            &ntdblist);
        if(ntdblist==0)
          gmx_fatal(FARGS,"No suitable N-terminus found in database");
        
@@ -1313,8 +1329,10 @@ int main(int argc, char *argv[])
       
       /* And the C terminus */
       if (nCtdb > 0) {
-       strncpy(resname,*pdba->resinfo[cc->rC[i]].name,3);
-       tdblist=filter_ter(nrtp,restp,nCtdb,ctdb,resname,&ntdblist);
+       tdblist = filter_ter(nrtp,restp,nCtdb,ctdb,
+                            *pdba->resinfo[cc->rC[i]].name,
+                            *pdba->resinfo[cc->rC[i]].rtp,
+                            &ntdblist);
        if(ntdblist==0)
          gmx_fatal(FARGS,"No suitable C-terminus found in database");
        
@@ -1338,9 +1356,10 @@ int main(int argc, char *argv[])
      requires some re-thinking of code in gen_vsite.c, which I won't 
      do now :( AF 26-7-99 */
 
-    rename_atoms(NULL,ffdir,pdba,&symtab,restp_chain,FALSE,aan,FALSE,bVerbose);
+    rename_atoms(NULL,ffdir,bAddCWD,
+                pdba,&symtab,restp_chain,FALSE,aan,FALSE,bVerbose);
 
-    match_atomnames_with_rtp(restp_chain,hb_chain,pdba,bVerbose);
+    match_atomnames_with_rtp(restp_chain,hb_chain,pdba,x,bVerbose);
 
     if (bSort) {
       block = new_blocka();
@@ -1431,7 +1450,7 @@ int main(int argc, char *argv[])
     nmol++;
 
     if (bITP)
-      print_top_comment(itp_file,itp_fn,title,TRUE);
+      print_top_comment(itp_file,itp_fn,generator,TRUE);
 
     if (cc->bAllWat)
       top_file2=NULL;
@@ -1445,7 +1464,7 @@ int main(int argc, char *argv[])
            nrtp,restp,
            restp_chain,hb_chain,
            cc->nterpairs,cc->ntdb,cc->ctdb,cc->rN,cc->rC,bAllowMissing,
-           bVsites,bVsiteAromatics,forcefield,ffdir,
+           bVsites,bVsiteAromatics,forcefield,ffdir,bAddCWD,
            mHmult,nssbonds,ssbonds,
            long_bond_dist,short_bond_dist,bDeuterate,bChargeGroups,bCmap,
            bRenumRes,bRTPresname);
@@ -1469,20 +1488,22 @@ int main(int argc, char *argv[])
       write_sto_conf(fn,quote,pdba,x,NULL,ePBC,box);
     }
   }
-  
-  sprintf(buf_fn,"%s%c%s.itp",ffdir,DIR_SEPARATOR,watstr[0]);
-  if (!fflib_fexist(buf_fn)) {
+
+  if (watermodel == NULL) {
     for(chain=0; chain<nch; chain++) {
       if (chains[chain].bAllWat) {
-       gmx_fatal(FARGS,"The topology file '%s' for the selected water model '%s' can not be found in the force field directory. Select a different water model or remove the water from your input file.",
-                 buf_fn,watstr[0]);
+       gmx_fatal(FARGS,"You have chosen not to include a water model, but there is water in the input file. Select a water model or remove the water from your input file.");
       }
     }
-    /* Do not include the water topology file. */
-    watstr[0] = NULL;
+  } else {
+    sprintf(buf_fn,"%s%c%s.itp",ffdir,DIR_SEPARATOR,watermodel);
+    if (!fflib_fexist(buf_fn)) {
+      gmx_fatal(FARGS,"The topology file '%s' for the selected water model '%s' can not be found in the force field directory. Select a different water model.",
+               buf_fn,watermodel);
+    }
   }
 
-  print_top_mols(top_file,title,ffdir,watstr[0],nincl,incls,nmol,mols);
+  print_top_mols(top_file,title,ffdir,watermodel,nincl,incls,nmol,mols);
   gmx_fio_fclose(top_file);
 
   done_aa_names(&aan);
@@ -1537,12 +1558,15 @@ int main(int argc, char *argv[])
   write_sto_conf(ftp2fn(efSTO,NFILE,fnm),title,atoms,x,NULL,ePBC,box);
 
   printf("\t\t--------- PLEASE NOTE ------------\n");
-  printf("You have succesfully generated a topology from: %s.\n",
+  printf("You have successfully generated a topology from: %s.\n",
         opt2fn("-f",NFILE,fnm));
-  printf("The %s force field and the %s water model are used.\n",
-        fff,watstr[0]);
-  printf("Note that the default mechanism for selecting a force fields has\n"
-        "changed, starting from GROMACS version 3.2.0\n");
+  if (watstr[0] != NULL) {
+    printf("The %s force field and the %s water model are used.\n",
+          ffname,watstr[0]);
+  } else {
+    printf("The %s force field is used.\n",
+          ffname);
+  }
   printf("\t\t--------- ETON ESAELP ------------\n");
   
 
index 92e99f07f570745b55be835b4aac5f52e0705e46..0c35945d1bf3e70c85cefb312ef97d80e3b75abc 100644 (file)
@@ -46,6 +46,7 @@
 #include "macros.h"
 #include "symtab.h"
 #include "futil.h"
+#include "statutil.h"
 #include "gmx_fatal.h"
 #include "pdb2top.h"
 #include "gpp_nextnb.h"
@@ -68,7 +69,7 @@
 #include "strdb.h"
 
 /* this must correspond to enum in pdb2top.h */
-const char *hh[ehisNR]   = { "HISA", "HISB", "HISH", "HIS1" };
+const char *hh[ehisNR]   = { "HISD", "HISE", "HISH", "HIS1" };
 
 static int missing_atoms(t_restp *rp, int resind,t_atoms *at, int i0, int i)
 {
@@ -116,6 +117,15 @@ bool is_int(double x)
   return (fabs(x-ix) < tol);
 }
 
+static void swap_strings(char **s,int i,int j)
+{
+    char *tmp;
+
+    tmp  = s[i];
+    s[i] = s[j];
+    s[j] = tmp;
+}
+
 void
 choose_ff(const char *ffsel,
           char *forcefield, int ff_maxlen,
@@ -123,8 +133,8 @@ choose_ff(const char *ffsel,
 {
     int  nff;
     char **ffdirs,**ffs,*ptr;
-    int  i,sel;
-    char buf[STRLEN],*doc_dir;
+    int  i,j,sel;
+    char buf[STRLEN],**desc,*doc_dir;
     FILE *fp;
     char *pret;
 
@@ -173,7 +183,7 @@ choose_ff(const char *ffsel,
     }
     else if (nff > 1)
     {
-        printf("\nSelect the Force Field:\n");
+        snew(desc,nff);
         for(i=0; (i<nff); i++)
         {
             sprintf(buf,"%s%c%s",
@@ -183,23 +193,47 @@ choose_ff(const char *ffsel,
             {
                 /* We don't use fflib_open, because we don't want printf's */
                 fp = ffopen(doc_dir,"r");
-                get_a_line(fp,buf,STRLEN);
+                snew(desc[i],STRLEN);
+                get_a_line(fp,desc[i],STRLEN);
                 ffclose(fp);
                 sfree(doc_dir);
-                printf("%2d: %s\n",i,buf);
             }
             else
             {
-                printf("%2d: %s\n",i,ffs[i]);
+                desc[i] = strdup(ffs[i]);
+            }
+        }
+        for(i=0; (i<nff); i++)
+        {
+            for(j=i+1; (j<nff); j++)
+            {
+                if ((desc[i][0] == '[' && desc[j][0] != '[') ||
+                    ((desc[i][0] == '[' || desc[j][0] != '[') &&
+                     strcasecmp(desc[i],desc[j]) > 0))
+                {
+                    swap_strings(ffdirs,i,j);
+                    swap_strings(ffs   ,i,j);
+                    swap_strings(desc  ,i,j);
+                }
             }
         }
+
+        printf("\nSelect the Force Field:\n");
+        for(i=0; (i<nff); i++)
+        {
+            printf("%2d: %s\n",i+1,desc[i]);
+            sfree(desc[i]);
+        }
+        sfree(desc);
+
         do
         {
             pret = fgets(buf,STRLEN,stdin);
             
-            if(pret != NULL)
+            if (pret != NULL)
             {
                 sscanf(buf,"%d",&sel);
+                sel--;
             }
         }
         while ( pret==NULL || (sel < 0) || (sel >= nff));
@@ -209,14 +243,14 @@ choose_ff(const char *ffsel,
         sel = 0;
     }
 
-    if (strlen(ffs[sel]) >= ff_maxlen)
+    if (strlen(ffs[sel]) >= (size_t)ff_maxlen)
     {
         gmx_fatal(FARGS,"Length of force field name (%d) >= maxlen (%d)",
                   strlen(ffs[sel]),ff_maxlen);
     }
     strcpy(forcefield,ffs[sel]);
 
-    if (strlen(ffdirs[sel]) >= ffdir_maxlen)
+    if (strlen(ffdirs[sel]) >= (size_t)ffdir_maxlen)
     {
         gmx_fatal(FARGS,"Length of force field dir (%d) >= maxlen (%d)",
                   strlen(ffdirs[sel]),ffdir_maxlen);
@@ -232,6 +266,92 @@ choose_ff(const char *ffsel,
     sfree(ffs);
 }
 
+void choose_watermodel(const char *wmsel,const char *ffdir,
+                       char **watermodel)
+{
+    const char *fn_watermodels="watermodels.dat";
+    char fn_list[STRLEN];
+    FILE *fp;
+    char buf[STRLEN];
+    int  nwm,sel,i;
+    char **model;
+    char *pret;
+
+    if (strcmp(wmsel,"none") == 0)
+    {
+        *watermodel = NULL;
+        
+        return;
+    }
+    else if (strcmp(wmsel,"select") != 0)
+    {
+        *watermodel = strdup(wmsel);
+
+        return;
+    }
+
+    sprintf(fn_list,"%s%c%s",ffdir,DIR_SEPARATOR,fn_watermodels);
+    
+    if (!fflib_fexist(fn_list))
+    {
+        fprintf(stderr,"No file '%s' found, will not include a water model\n",
+                fn_watermodels);
+        *watermodel = NULL;
+        
+        return;
+    }
+
+    fp = fflib_open(fn_list);
+    printf("\nSelect the Water Model:\n");
+    nwm = 0;
+    model = NULL;
+    while (get_a_line(fp,buf,STRLEN))
+    {
+        srenew(model,nwm+1);
+        snew(model[nwm],STRLEN);
+        sscanf(buf,"%s%n",model[nwm],&i);
+        if (i > 0)
+        {
+            ltrim(buf+i);
+            fprintf(stderr,"%2d: %s\n",nwm+1,buf+i);
+            nwm++;
+        }
+        else
+        {
+            sfree(model[nwm]);
+        }
+    }
+    fclose(fp);
+    fprintf(stderr,"%2d: %s\n",nwm,"None");
+
+    do
+    {
+        pret = fgets(buf,STRLEN,stdin);
+        
+        if (pret != NULL)
+        {
+            sscanf(buf,"%d",&sel);
+            sel--;
+        }
+    }
+    while (pret == NULL || sel < 0 || sel > nwm);
+
+    if (sel == nwm)
+    {
+        *watermodel = NULL;
+    }
+    else
+    {
+        *watermodel = strdup(model[sel]);
+    }
+
+    for(i=0; i<nwm; i++)
+    {
+        sfree(model[i]);
+    }
+    sfree(model);
+}
+
 static int name2type(t_atoms *at, int **cgnr, gpp_atomtype_t atype, 
                     t_restp restp[])
 {
@@ -317,15 +437,16 @@ static void print_top_heavy_H(FILE *out, real mHmult)
            "in pdb2top\n",mHmult);
 }
 
-void print_top_comment(FILE *out,const char *filename,const char *title,bool bITP)
+void print_top_comment(FILE *out,const char *filename,
+                       const char *generator,bool bITP)
 {
   char tmp[256]; 
-  
+
   nice_header(out,filename);
   fprintf(out,";\tThis is your %stopology file\n",bITP ? "include " : "");
-  cool_quote(tmp,255,NULL);
-  fprintf(out,";\t%s\n",title[0]?title:tmp);
-  fprintf(out,";\n");
+  fprintf(out,";\tit was generated using program:\n;\t%s\n",
+          (NULL == generator) ? "unknown" : generator);
+  fprintf(out,";\twith command line:\n;\t%s\n;\n\n",command_line());
 }
 
 void print_top_header(FILE *out,const char *filename, 
@@ -883,7 +1004,7 @@ static bool atomname_cmp_nr(const char *anm,t_hack *hack,int *nr)
     }
 }
 
-static bool match_atomnames_with_rtp_atom(t_atoms *pdba,int atind,
+static bool match_atomnames_with_rtp_atom(t_atoms *pdba,rvec *x,int atind,
                                           t_restp *rptr,t_hackblock *hbr,
                                           bool bVerbose)
 {
@@ -1021,11 +1142,15 @@ static bool match_atomnames_with_rtp_atom(t_atoms *pdba,int atind,
                     printf("Deleting atom '%s' in residue '%s' %d\n",
                            oldnm,rptr->resname,resnr);
                 }
-                sfree(pdba->atomname[atind]);
+                /* We should free the atom name,
+                 * but it might be used multiple times in the symtab.
+                 * sfree(pdba->atomname[atind]);
+                 */
                 for(k=atind+1; k<pdba->nr; k++)
                 {
                     pdba->atom[k-1]     = pdba->atom[k];
                     pdba->atomname[k-1] = pdba->atomname[k];
+                    copy_rvec(x[k],x[k-1]);
                 }
                 pdba->nr--;
                 bDeleted = TRUE;
@@ -1037,7 +1162,7 @@ static bool match_atomnames_with_rtp_atom(t_atoms *pdba,int atind,
 }
     
 void match_atomnames_with_rtp(t_restp restp[],t_hackblock hb[],
-                              t_atoms *pdba,
+                              t_atoms *pdba,rvec *x,
                               bool bVerbose)
 {
     int  i,j,k;
@@ -1065,7 +1190,7 @@ void match_atomnames_with_rtp(t_restp restp[],t_hackblock hb[],
         if (j == rptr->natom)
         {
             /* Not found yet, check if we have to rename this atom */
-            if (match_atomnames_with_rtp_atom(pdba,i,
+            if (match_atomnames_with_rtp_atom(pdba,x,i,
                                               rptr,&(hb[pdba->atom[i].resind]),
                                               bVerbose))
             {
@@ -1145,7 +1270,8 @@ void pdb2top(FILE *top_file, char *posre_fn, char *molname,
              int nterpairs,t_hackblock **ntdb, t_hackblock **ctdb,
              int *rn, int *rc, bool bAllowMissing,
              bool bVsites, bool bVsiteAromatics,
-             const char *ff, const char *ffdir, real mHmult,
+             const char *ff, const char *ffdir, bool bAddCWD,
+             real mHmult,
              int nssbonds, t_ssbond *ssbonds,
              real long_bond_dist, real short_bond_dist,
              bool bDeuterate, bool bChargeGroups, bool bCmap,
@@ -1200,7 +1326,7 @@ void pdb2top(FILE *top_file, char *posre_fn, char *molname,
     /* determine which atoms will be vsites and add dummy masses 
        also renumber atom numbers in plist[0..F_NRE]! */
     do_vsites(nrtp, rtp, atype, atoms, tab, x, plist, 
-              &vsite_type, &cgnr, mHmult, bVsiteAromatics, ffdir);
+              &vsite_type, &cgnr, mHmult, bVsiteAromatics, ffdir, bAddCWD);
   }
   
   /* Make Angles and Dihedrals */
index 35040c56a3d5aa9ec3132a71ba36e469b83bc70c..7f78e3e44b72ec967c3517bb7f1c6c17823e73ff 100644 (file)
@@ -58,6 +58,13 @@ extern void choose_ff(const char *ffsel,
  * If ffsel==NULL: interactive selection.
  */
 
+extern void choose_watermodel(const char *wmsel,const char *ffdir,
+                             char **watermodel);
+/* Choose, possibly interactively, which water model to include,
+ * based on the wmsel command line option choice and watermodels.dat
+ * in ffdir.
+ */
+
 extern void get_hackblocks_rtp(t_hackblock **hb, t_restp **restp, 
                               int nrtp, t_restp rtp[],
                               int nres, t_resinfo *resinfo, 
@@ -69,7 +76,7 @@ extern void get_hackblocks_rtp(t_hackblock **hb, t_restp **restp,
  */
 
 extern void match_atomnames_with_rtp(t_restp restp[],t_hackblock hb[],
-                                    t_atoms *pdba,
+                                    t_atoms *pdba,rvec *x,
                                     bool bVerbose);
 /* Check if atom in pdba need to be deleted of renamed due to tdb or hdb.
  * If renaming involves atoms added wrt to the rtp database,
@@ -84,7 +91,8 @@ extern void pdb2top(FILE *top_file, char *posre_fn, char *molname,
                    int nterpairs, t_hackblock **ntdb, t_hackblock **ctdb,
                    int *rn, int *rc, bool bAllowMissing,
                    bool bVsites, bool bVsiteAromatics,
-                   const char *ff, const char *ffdir, real mHmult,
+                   const char *ff, const char *ffdir, bool bAddCWD,
+                   real mHmult,
                    int nssbonds, t_ssbond ssbonds[],
                    real long_bond_dist, real short_bond_dist,
                    bool bDeuterate, bool bChargeGroups, bool bCmap,
index 854302553e9da3a9cd2d5e09f2097d5e25ae38d8..45f7a4fbb8b26f1d446b8019a7fe5eddfacf9630 100644 (file)
@@ -90,6 +90,13 @@ static char efield_x[STRLEN],efield_xt[STRLEN],efield_y[STRLEN],
 enum { egrptpALL, egrptpALL_GENREST, egrptpPART, egrptpONE };
 
 
+/* Minimum number of time steps required for accurate coupling integration
+ * of first and second order thermo- and barostats:
+ */
+int nstcmin1 = 10;
+int nstcmin2 = 20;
+
+
 void init_ir(t_inputrec *ir, t_gromppopts *opts)
 {
   snew(opts->include,STRLEN); 
@@ -129,14 +136,15 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
               warninp_t wi)
 /* Check internal consistency */
 {
-  /* Strange macro: first one fills the err_buf, and then one can check 
-   * the condition, which will print the message and increase the error
-   * counter.
-   */
+    /* Strange macro: first one fills the err_buf, and then one can check 
+     * the condition, which will print the message and increase the error
+     * counter.
+     */
 #define CHECK(b) _low_check(b,err_buf,wi)
     char err_buf[256],warn_buf[STRLEN];
-  int  ns_type=0;
-  real dt_coupl=0;
+    int  ns_type=0;
+    real dt_coupl=0;
+    int  nstcmin;
 
   set_warning_line(wi,mdparin,-1);
 
@@ -164,36 +172,70 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
       warning_error(wi,"Can not have nstlist<=0 with twin-range interactions");
   }
 
-  /* GENERAL INTEGRATOR STUFF */
-  if (!(ir->eI == eiMD || EI_VV(ir->eI))) {
-    ir->etc = etcNO;
-  }
-  if (!EI_DYNAMICS(ir->eI)) {
-    ir->epc = epcNO;
-  }
-  if (EI_DYNAMICS(ir->eI)) {
-    if (ir->nstcalcenergy < 0) {
-      gmx_fatal(FARGS,"Can not have nstcalcenergy < 0");
-    }
-    if ((ir->etc != etcNO || ir->epc != epcNO) && ir->nstcalcenergy == 0) {
-      gmx_fatal(FARGS,"Can not have nstcalcenergy=0 with global T/P-coupling");
+    /* GENERAL INTEGRATOR STUFF */
+    if (!(ir->eI == eiMD || EI_VV(ir->eI)))
+    {
+        ir->etc = etcNO;
     }
-    if (IR_TWINRANGE(*ir)) {
-        check_nst("nstlist",ir->nstlist,"nstcalcenergy",&ir->nstcalcenergy,wi);
+    if (!EI_DYNAMICS(ir->eI))
+    {
+        ir->epc = epcNO;
     }
-    dt_coupl = ir->nstcalcenergy*ir->delta_t;
+    if (EI_DYNAMICS(ir->eI))
+    {
+        if (ir->nstcalcenergy < 0)
+        {
+            if (EI_VV(ir->eI))
+            {
+                /* VV coupling algorithms currently only support 1 */
+                ir->nstcalcenergy = 1;
+            }
+            else
+            {
+                if (ir->nstlist > 0)
+                {
+                    ir->nstcalcenergy = ir->nstlist;
+                }
+                else
+                {
+                    ir->nstcalcenergy = 10;
+                }
+            }
+        }
+        if (ir->etc != etcNO || ir->epc != epcNO)
+        {
+            if (ir->nstcalcenergy == 0)
+            {
+                gmx_fatal(FARGS,"Can not have nstcalcenergy=0 with global T/P-coupling");
+            }
+            if (EI_VV(ir->eI))
+            {
+                sprintf(err_buf,"T- and P-coupling with VV integrators currently only supports nstcalcenergy=1");
+                CHECK(ir->nstcalcenergy > 1);
+            }
+        }
+        if (IR_TWINRANGE(*ir))
+        {
+            check_nst("nstlist",ir->nstlist,
+                      "nstcalcenergy",&ir->nstcalcenergy,wi);
+        }
+        dt_coupl = ir->nstcalcenergy*ir->delta_t;
   
-    if (ir->nstcalcenergy > 1) {
-      /* Energy and log file writing trigger energy calculation,
-       * so we need some checks.
-       */
-        check_nst("nstcalcenergy",ir->nstcalcenergy,"nstenergy",&ir->nstenergy,wi);
-        check_nst("nstcalcenergy",ir->nstcalcenergy,"nstlog",&ir->nstlog,wi);
-      if (ir->efep != efepNO) {
-          check_nst("nstcalcenergy",ir->nstcalcenergy,"nstdhdl",&ir->nstdhdl,wi);
-      }
+        if (ir->nstcalcenergy > 1)
+        {
+            /* for storing exact averages nstenergy should be
+             * a multiple of nstcalcenergy
+             */
+            check_nst("nstcalcenergy",ir->nstcalcenergy,
+                      "nstenergy",&ir->nstenergy,wi);
+            if (ir->efep != efepNO)
+            {
+                /* nstdhdl should be a multiple of nstcalcenergy */
+                check_nst("nstcalcenergy",ir->nstcalcenergy,
+                          "nstdhdl",&ir->nstdhdl,wi);
+            }
+        }
     }
-  }
 
   /* LD STUFF */
   if ((EI_SD(ir->eI) || ir->eI == eiBD) &&
@@ -303,83 +345,105 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
   CHECK(((ir->rcoulomb > ir->rlist) || (ir->rvdw > ir->rlist)) 
        && (ir->ns_type == ensSIMPLE));
   
-  /* TEMPERATURE COUPLING */
-  if(ir->etc == etcYES) {
-    ir->etc = etcBERENDSEN;
-    warning_note(wi,"Old option for temperature coupling given: "
-                "changing \"yes\" to \"Berendsen\"\n");
-  }
-  if (ir->etc == etcNOSEHOOVER) {
-    if (ir->opts.nhchainlength < 1) 
-      {
-       sprintf(warn_buf,"number of Nose-Hoover chains (currently %d) cannot be less than 1,reset to 1\n",ir->opts.nhchainlength);
-       ir->opts.nhchainlength =1;
-       warning(wi,warn_buf);
-      }
-    
-    if (ir->etc==etcNOSEHOOVER && !EI_VV(ir->eI) && ir->opts.nhchainlength > 1) {
-        warning_note(wi,"leapfrog does not yet support Nose-Hoover chains, nhchainlength reset to 1");
-      ir->opts.nhchainlength = 1;
+    /* TEMPERATURE COUPLING */
+    if (ir->etc == etcYES)
+    {
+        ir->etc = etcBERENDSEN;
+        warning_note(wi,"Old option for temperature coupling given: "
+                     "changing \"yes\" to \"Berendsen\"\n");
     }
-  } else {
-    ir->opts.nhchainlength = 0;
-  }
-
-  if (ir->etc == etcBERENDSEN) {
-    sprintf(warn_buf,"The %s thermostat does not generate the correct kinetic energy distribution. You might want to consider using the %s thermostat.",
-           ETCOUPLTYPE(ir->etc),ETCOUPLTYPE(etcVRESCALE));
-    warning_note(wi,warn_buf);
-  }
   
-  if((ir->etc==etcNOSEHOOVER || ir->etc==etcANDERSEN || ir->etc==etcANDERSENINTERVAL ) 
-     && ir->epc==epcBERENDSEN) {
-    sprintf(warn_buf,"Using Berendsen pressure coupling invalidates the "
-           "true ensemble for the thermostat");
-    warning(wi,warn_buf);
-  }
+    if (ir->etc == etcNOSEHOOVER)
+    {
+        if (ir->opts.nhchainlength < 1) 
+        {
+            sprintf(warn_buf,"number of Nose-Hoover chains (currently %d) cannot be less than 1,reset to 1\n",ir->opts.nhchainlength);
+            ir->opts.nhchainlength =1;
+            warning(wi,warn_buf);
+        }
+        
+        if (ir->etc==etcNOSEHOOVER && !EI_VV(ir->eI) && ir->opts.nhchainlength > 1)
+        {
+            warning_note(wi,"leapfrog does not yet support Nose-Hoover chains, nhchainlength reset to 1");
+            ir->opts.nhchainlength = 1;
+        }
+    }
+    else
+    {
+        ir->opts.nhchainlength = 0;
+    }
 
-  /* PRESSURE COUPLING */
-  if (ir->epc == epcISOTROPIC) {
-    ir->epc = epcBERENDSEN;
-    warning_note(wi,"Old option for pressure coupling given: "
-                 "changing \"Isotropic\" to \"Berendsen\"\n"); 
-  }
+    if (ir->etc == etcBERENDSEN)
+    {
+        sprintf(warn_buf,"The %s thermostat does not generate the correct kinetic energy distribution. You might want to consider using the %s thermostat.",
+                ETCOUPLTYPE(ir->etc),ETCOUPLTYPE(etcVRESCALE));
+        warning_note(wi,warn_buf);
+    }
 
-  if (ir->epc != epcNO) {
-    sprintf(err_buf,"tau_p must be > 0 instead of %g\n",ir->tau_p);
-    CHECK(ir->tau_p <= 0);
+    if ((ir->etc==etcNOSEHOOVER || ir->etc==etcANDERSEN || ir->etc==etcANDERSENINTERVAL) 
+        && ir->epc==epcBERENDSEN)
+    {
+        sprintf(warn_buf,"Using Berendsen pressure coupling invalidates the "
+                "true ensemble for the thermostat");
+        warning(wi,warn_buf);
+    }
 
-    if (ir->tau_p < 100*dt_coupl) {
-      sprintf(warn_buf,"For proper barostat integration tau_p (%g) should be more than two orders of magnitude larger than nstcalcenergy*dt (%g)",
-             ir->tau_p,dt_coupl);
-      warning(wi,warn_buf);
-    }  
-       
-    sprintf(err_buf,"compressibility must be > 0 when using pressure" 
-           " coupling %s\n",EPCOUPLTYPE(ir->epc));
-    CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 || 
-         ir->compress[ZZ][ZZ] < 0 || 
-         (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 &&
-          ir->compress[ZZ][XX] <= 0 && ir->compress[ZZ][YY] <= 0));
-    
-    sprintf(err_buf,"pressure coupling with PPPM not implemented, use PME");
-    CHECK(ir->coulombtype == eelPPPM);
-     
-  } else if (ir->coulombtype == eelPPPM) {
-    sprintf(warn_buf,"The pressure with PPPM is incorrect, if you need the pressure use PME");
-    warning(wi,warn_buf);
-  }
+    /* PRESSURE COUPLING */
+    if (ir->epc == epcISOTROPIC)
+    {
+        ir->epc = epcBERENDSEN;
+        warning_note(wi,"Old option for pressure coupling given: "
+                     "changing \"Isotropic\" to \"Berendsen\"\n"); 
+    }
 
-  if (EI_VV(ir->eI)) {
-    if (ir->epc > epcNO) {
-      if (ir->epc!=epcMTTK) {
-          warning_error(wi,"NPT only defined for vv using Martyna-Tuckerman-Tobias-Klein equations");        
-      }
+    if (ir->epc != epcNO)
+    {
+        sprintf(err_buf,"tau_p must be > 0 instead of %g\n",ir->tau_p);
+        CHECK(ir->tau_p <= 0);
+        
+        nstcmin = (ir->epc == epcBERENDSEN ? nstcmin1 : nstcmin2);
+        if (ir->tau_p < nstcmin*dt_coupl)
+        {
+            sprintf(warn_buf,"For proper integration of the %s barostat, tau_p (%g) should be at least %d times larger than nstcalcenergy*dt (%g)",
+                    EPCOUPLTYPE(ir->epc),ir->tau_p,nstcmin,dt_coupl);
+            warning(wi,warn_buf);
+        }      
+        
+        sprintf(err_buf,"compressibility must be > 0 when using pressure" 
+                " coupling %s\n",EPCOUPLTYPE(ir->epc));
+        CHECK(ir->compress[XX][XX] < 0 || ir->compress[YY][YY] < 0 || 
+              ir->compress[ZZ][ZZ] < 0 || 
+              (trace(ir->compress) == 0 && ir->compress[YY][XX] <= 0 &&
+               ir->compress[ZZ][XX] <= 0 && ir->compress[ZZ][YY] <= 0));
+        
+        sprintf(err_buf,"pressure coupling with PPPM not implemented, use PME");
+        CHECK(ir->coulombtype == eelPPPM);
+        
+    }
+    else if (ir->coulombtype == eelPPPM)
+    {
+        sprintf(warn_buf,"The pressure with PPPM is incorrect, if you need the pressure use PME");
+        warning(wi,warn_buf);
+    }
+    
+    if (EI_VV(ir->eI))
+    {
+        if (ir->epc > epcNO)
+        {
+            if (ir->epc!=epcMTTK)
+            {
+                warning_error(wi,"NPT only defined for vv using Martyna-Tuckerman-Tobias-Klein equations");          
+            }
+        }
     }
-  }
 
   /* ELECTROSTATICS */
   /* More checks are in triple check (grompp.c) */
+    if (ir->coulombtype == eelPPPM)
+    {
+        warning_error(wi,"PPPM is not functional in the current version, we plan to implement PPPM through a small modification of the PME code");
+    }
+
   if (ir->coulombtype == eelSWITCH) {
     sprintf(warn_buf,"coulombtype = %s is only for testing purposes and can lead to serious artifacts, advice: use coulombtype = %s",
            eel_names[ir->coulombtype],
@@ -546,7 +610,8 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
             warning_note(wi,warn_buf);
         }
     }
-
+  
+  /* IMPLICIT SOLVENT */
   if(ir->coulombtype==eelGB_NOTUSED)
   {
     ir->coulombtype=eelCUT;
@@ -560,6 +625,24 @@ void check_ir(const char *mdparin,t_inputrec *ir, t_gromppopts *opts,
   {
       sprintf(err_buf,"With GBSA implicit solvent, rgbradii must be equal to rlist.");
       CHECK(ir->rgbradii != ir->rlist);
+         
+         if(ir->coulombtype!=eelCUT)
+         {
+                 sprintf(err_buf,"With GBSA, coulombtype must be equal to %s\n",eel_names[eelCUT]);
+                 CHECK(ir->coulombtype!=eelCUT);
+         }
+         if(ir->vdwtype!=evdwCUT)
+         {
+                 sprintf(err_buf,"With GBSA, vdw-type must be equal to %s\n",evdw_names[evdwCUT]);
+                 CHECK(ir->vdwtype!=evdwCUT);
+         }
+    
+    if(ir->nstgbradii<1)
+    {
+      sprintf(warn_buf,"Using GBSA with nstgbradii<1, setting nstgbradii=1");
+      warning_note(wi,warn_buf);
+      ir->nstgbradii=1;
+    }
   }
 }
 
@@ -705,10 +788,10 @@ void get_ir(const char *mdparin,const char *mdparout,
   ITYPE ("simulation_part", ir->simulation_part, 1);
   CTYPE ("mode for center of mass motion removal");
   CTYPE ("energy calculation and T/P-coupling frequency");
-  ITYPE ("nstcalcenergy",ir->nstcalcenergy,    1);
+  ITYPE ("nstcalcenergy",ir->nstcalcenergy,    -1);
   EETYPE("comm-mode",   ir->comm_mode,  ecm_names);
   CTYPE ("number of steps for center of mass motion removal");
-  ITYPE ("nstcomm",    ir->nstcomm,    1);
+  ITYPE ("nstcomm",    ir->nstcomm,    10);
   CTYPE ("group(s) for center of mass motion removal");
   STYPE ("comm-grps",   vcm,            NULL);
   
@@ -1599,6 +1682,7 @@ void do_index(const char* mdparin, const char *ndx,
   t_atoms atoms_all;
   char    warnbuf[STRLEN],**gnames;
   int     nr,ntcg,ntau_t,nref_t,nacc,nofg,nSA,nSA_points,nSA_time,nSA_temp;
+  int     nstcmin;
   int     nacg,nfreeze,nfrdim,nenergy,nvcm,nuser;
   char    *ptr1[MAXPTR],*ptr2[MAXPTR],*ptr3[MAXPTR];
   int     i,j,k,restnm;
@@ -1658,32 +1742,46 @@ void do_index(const char* mdparin, const char *ndx,
   if (ir->eI==eiBD && ir->bd_fric==0) {
     fprintf(stderr,"bd_fric=0, so tau_t will be used as the inverse friction constant(s)\n"); 
   }
-  if (bSetTCpar) {
-    if (nr != nref_t)
-      gmx_fatal(FARGS,"Not enough ref_t and tau_t values!");
-    for(i=0; (i<nr); i++) {
-      ir->opts.tau_t[i]=strtod(ptr1[i],NULL);
-      if (ir->opts.tau_t[i] < 0) {
-       gmx_fatal(FARGS,"tau_t for group %d negative",i);
-      }
-      /* We check the relative magnitude of the coupling time tau_t.
-       * V-rescale works correctly, even for tau_t=0.
-       */
-      if ((ir->etc == etcBERENDSEN || ir->etc == etcNOSEHOOVER) &&
-         ir->opts.tau_t[i] != 0 &&
-         ir->opts.tau_t[i] < 10*ir->nstcalcenergy*ir->delta_t) {
-       sprintf(warn_buf,"For proper thermostat integration tau_t (%g) should be more than an order of magnitude larger than nstcalcenergy*dt (%g)",
-               ir->opts.tau_t[i],ir->nstcalcenergy*ir->delta_t);
-       warning(wi,warn_buf);
-      }
-    }
-    for(i=0; (i<nr); i++) {
-      ir->opts.ref_t[i]=strtod(ptr2[i],NULL);
-      if (ir->opts.ref_t[i] < 0)
-       gmx_fatal(FARGS,"ref_t for group %d negative",i);
-    }
-  }
 
+    if (bSetTCpar)
+    {
+        if (nr != nref_t)
+        {
+            gmx_fatal(FARGS,"Not enough ref_t and tau_t values!");
+        }
+        nstcmin = (ir->etc == etcBERENDSEN ? nstcmin1 : nstcmin2);
+        
+        for(i=0; (i<nr); i++)
+        {
+            ir->opts.tau_t[i] = strtod(ptr1[i],NULL);
+            if (ir->opts.tau_t[i] < 0)
+            {
+                gmx_fatal(FARGS,"tau_t for group %d negative",i);
+            }
+            /* We check the relative magnitude of the coupling time tau_t.
+             * V-rescale works correctly, even for tau_t=0.
+             */
+            if ((ir->etc == etcBERENDSEN || ir->etc == etcNOSEHOOVER) &&
+                ir->opts.tau_t[i] != 0 &&
+                ir->opts.tau_t[i] < nstcmin*ir->nstcalcenergy*ir->delta_t)
+            {
+                sprintf(warn_buf,"For proper integration of the %s thermostat, tau_t (%g) should be at least %d times larger than nstcalcenergy*dt (%g)",
+                        ETCOUPLTYPE(ir->etc),
+                        ir->opts.tau_t[i],nstcmin,
+                        ir->nstcalcenergy*ir->delta_t);
+                warning(wi,warn_buf);
+            }
+        }
+        for(i=0; (i<nr); i++)
+        {
+            ir->opts.ref_t[i] = strtod(ptr2[i],NULL);
+            if (ir->opts.ref_t[i] < 0)
+            {
+                gmx_fatal(FARGS,"ref_t for group %d negative",i);
+            }
+        }
+    }
+    
   /* Simulated annealing for each group. There are nr groups */
   nSA = str_nelem(anneal,MAXPTR,ptr1);
   if (nSA == 1 && (ptr1[0][0]=='n' || ptr1[0][0]=='N'))
index 87f0c0c5ac11e540e26254afa6ce317e3b81ca1b..b5d2d6921affb5329069edfc2e3a6f9311bad9d4 100644 (file)
@@ -100,7 +100,7 @@ char **read_pullparams(int *ninp_p,t_inpfile **inp_p,
                       t_pull *pull,bool *bStart,
                       warninp_t wi) 
 {
-  int  ninp,nerror,i,nchar,ndim,nscan,m;
+  int  ninp,nerror=0,i,nchar,ndim,nscan,m;
   t_inpfile *inp;
   const char *tmp;
   char **grpbuf;
index b2101278a427aad88845db499186fd86fbc771d7..625fba5ed276888330eda9448312a8dc130a45db 100644 (file)
@@ -370,7 +370,6 @@ static void exchange_rvecs(const gmx_multisim_t *ms,int b,rvec *v,int n)
 
 static void exchange_state(const gmx_multisim_t *ms,int b,t_state *state)
 {
-
   /* When t_state changes, this code should be updated. */
   int ngtc,nnhpres;
   ngtc = state->ngtc * state->nhchainlength;
@@ -393,6 +392,53 @@ static void exchange_state(const gmx_multisim_t *ms,int b,t_state *state)
   exchange_rvecs(ms,b,state->sd_X,state->natoms);
 }
 
+static void copy_rvecs(rvec *s,rvec *d,int n)
+{
+    int i;
+
+    for(i=0; i<n; i++)
+    {
+        copy_rvec(s[i],d[i]);
+    }
+}
+
+static void copy_doubles(double *s,double *d,int n)
+{
+    int i;
+
+    for(i=0; i<n; i++)
+    {
+        d[i] = s[i];
+    }
+}
+
+#define scopy_rvecs(v,n)   copy_rvecs(state->v,state_local->v,n)
+#define scopy_doubles(v,n) copy_doubles(state->v,state_local->v,n)
+
+static void copy_state_nonatomdata(t_state *state,t_state *state_local)
+{
+  /* When t_state changes, this code should be updated. */
+  int ngtc,nnhpres;
+  ngtc = state->ngtc * state->nhchainlength;
+  nnhpres = state->nnhpres* state->nhchainlength;
+  scopy_rvecs(box,DIM);
+  scopy_rvecs(box_rel,DIM);
+  scopy_rvecs(boxv,DIM);
+  state_local->veta = state->veta;
+  state_local->vol0 = state->vol0;
+  scopy_rvecs(svir_prev,DIM);
+  scopy_rvecs(fvir_prev,DIM);
+  scopy_rvecs(pres_prev,DIM);
+  scopy_doubles(nosehoover_xi,ngtc);
+  scopy_doubles(nosehoover_vxi,ngtc);  
+  scopy_doubles(nhpres_xi,nnhpres);
+  scopy_doubles(nhpres_vxi,nnhpres);  
+  scopy_doubles(therm_integral,state->ngtc);
+  scopy_rvecs(x,state->natoms);
+  scopy_rvecs(v,state->natoms);
+  scopy_rvecs(sd_X,state->natoms);
+}
+
 static void scale_velocities(t_state *state,real fac)
 {
   int i;
@@ -574,46 +620,77 @@ static void write_debug_x(t_state *state)
 }
 
 bool replica_exchange(FILE *fplog,const t_commrec *cr,struct gmx_repl_ex *re,
-                     t_state *state,real *ener,
-                     t_state *state_local,
-                     int step,real time)
+                      t_state *state,real *ener,
+                      t_state *state_local,
+                      int step,real time)
 {
-  gmx_multisim_t *ms;
-  int  exchange=-1,shift;
-  bool bExchanged=FALSE;
-
-  ms = cr->ms;
-
-  if (MASTER(cr)) {
-    exchange = get_replica_exchange(fplog,ms,re,ener,det(state->box),
-                                   step,time);
-    bExchanged = (exchange >= 0);
-  }
-      
-  if (PAR(cr)) {
+    gmx_multisim_t *ms;
+    int  exchange=-1,shift;
+    bool bExchanged=FALSE;
+    
+    ms = cr->ms;
+  
+    if (MASTER(cr))
+    {
+        exchange = get_replica_exchange(fplog,ms,re,ener,det(state->box),
+                                        step,time);
+        bExchanged = (exchange >= 0);
+    }
+    
+    if (PAR(cr))
+    {
 #ifdef GMX_MPI
-    MPI_Bcast(&bExchanged,sizeof(bool),MPI_BYTE,MASTERRANK(cr),
-             cr->mpi_comm_mygroup);
+        MPI_Bcast(&bExchanged,sizeof(bool),MPI_BYTE,MASTERRANK(cr),
+                  cr->mpi_comm_mygroup);
 #endif
-  }
-  
-  if (bExchanged) {
-    if (PAR(cr)) {
-      if (DOMAINDECOMP(cr))
-       dd_collect_state(cr->dd,state_local,state);
-      else
-       pd_collect_state(cr,state);
     }
-    if (MASTER(cr)) {
-      if (debug)
-       fprintf(debug,"Exchanging %d with %d\n",ms->sim,exchange);
-      exchange_state(ms,exchange,state);
-      if (re->type == ereTEMP)
-       scale_velocities(state,sqrt(re->q[ms->sim]/re->q[exchange]));
+    
+    if (bExchanged)
+    {
+        /* Exchange the states */
+
+        if (PAR(cr))
+        {
+            /* Collect the global state on the master node */
+            if (DOMAINDECOMP(cr))
+            {
+                dd_collect_state(cr->dd,state_local,state);
+            }
+            else
+            {
+                pd_collect_state(cr,state);
+            }
+        }
+        
+        if (MASTER(cr))
+        {
+            /* Exchange the global states between the master nodes */
+            if (debug)
+            {
+                fprintf(debug,"Exchanging %d with %d\n",ms->sim,exchange);
+            }
+            exchange_state(ms,exchange,state);
+            
+            if (re->type == ereTEMP)
+            {
+                scale_velocities(state,sqrt(re->q[ms->sim]/re->q[exchange]));
+            }
+        }
+
+        /* With domain decomposition the global state is distributed later */
+        if (!DOMAINDECOMP(cr))
+        {
+            /* Copy the global state to the local state data structure */
+            copy_state_nonatomdata(state,state_local);
+            
+            if (PAR(cr))
+            {
+                bcast_state(cr,state,FALSE);
+            }
+        }
     }
-  }
-  
-  return bExchanged;
+        
+    return bExchanged;
 }
 
 void print_replica_exchange_statistics(FILE *fplog,struct gmx_repl_ex *re)
index 9461e9257dd3cc6e96631c3922f0b9627b01d7b8..16a5d83e2b3bb1e71b2e718407ce4f68cec02cfa 100644 (file)
@@ -57,8 +57,10 @@ extern bool replica_exchange(FILE *fplog,
 /* Attempts replica exchange, should be called on all nodes.
  * Returns TRUE if this state has been exchanged.
  * When running each replica in parallel,
- * this routine collects the state on the master node before exchange,
- * but it does not redistribute the state over the nodes after exchange.
+ * this routine collects the state on the master node before exchange.
+ * With particle the state is redistributed over the nodes after exchange.
+ * With domain decomposition the global state after exchanged in stored
+ * in state and still needs to be redistributed over the nodes.
  */
 
 extern void print_replica_exchange_statistics(FILE *fplog,gmx_repl_ex_t re);
index 62f2400882092320d3312d913e3eeb38009631ca..2ea28a360f663a345478d0c533a832b256eb4a0b 100644 (file)
@@ -50,7 +50,7 @@
 #include "pgutil.h"
 #include "fflibutil.h"
 
-gpp_atomtype_t read_atype(const char *ffdir,t_symtab *tab)
+gpp_atomtype_t read_atype(const char *ffdir,bool bAddCWD,t_symtab *tab)
 {
     int        nfile,f;
     char       **file;
@@ -62,7 +62,7 @@ gpp_atomtype_t read_atype(const char *ffdir,t_symtab *tab)
     t_atom     *a;
     t_param    *nb;
     
-    nfile = fflib_search_file_end(ffdir,".atp",TRUE,&file);
+    nfile = fflib_search_file_end(ffdir,bAddCWD,".atp",TRUE,&file);
     at = init_atomtype();
     snew(a,1);
     snew(nb,1);
@@ -481,14 +481,27 @@ void print_resall(FILE *out, int nrtp, t_restp rtp[],
  ***********************************************************/
 int neq_str(const char *a1,const char *a2)
 {
-  int j,l;
+    int j,l,l1,l2;;
   
-  l=min((int)strlen(a1),(int)strlen(a2));
-  j=0;
-  while ( (j<l) && (toupper(a1[j]) == toupper(a2[j])) )
-    j++;
-  
-  return j;
+    l1 = (int)strlen(a1);
+    l2 = (int)strlen(a2);
+    l = min(l1,l2);
+    
+    j=0;
+    while (j < l && toupper(a1[j]) == toupper(a2[j]))
+    {
+        j++;
+    }
+    if (j == l1 && j == l2)
+    {
+        /* Exact match */
+        return 1000;
+    }
+    else
+    {
+        /* Partial match */
+        return j;
+    }
 }
 
 t_restp *search_rtp(const char *key,int nrtp,t_restp rtp[])
index 7292b1d399a76a1f73deef110212828f16158b93..073cc26c8f1ed39e023d4417d477524b7184f102 100644 (file)
 #include "mvdata.h"
 #include "checkpoint.h"
 #include "mtop_util.h"
-#include "pull_rotation.h"
 #include "sighandler.h"
+#include "tpxio.h"
+#include "txtdump.h"
+#include "pull_rotation.h"
 #include "md_openmm.h"
 
 #ifdef GMX_LIB_MPI
@@ -141,6 +143,9 @@ struct mdrunner_arglist
 };
 
 
+/* The function used for spawning threads. Extracts the mdrunner() 
+   arguments from its one argument and calls mdrunner(), after making
+   a commrec. */
 static void mdrunner_start_fn(void *arg)
 {
     struct mdrunner_arglist *mda=(struct mdrunner_arglist*)arg;
@@ -150,112 +155,171 @@ static void mdrunner_start_fn(void *arg)
                                         but those are all const. */
     t_commrec *cr;  /* we need a local version of this */
     FILE *fplog=NULL;
-    t_filenm *fnm=dup_tfn(mc.nfile, mc.fnm);
+    t_filenm *fnm;
+
+    fnm = dup_tfn(mc.nfile, mc.fnm);
+
+    cr = init_par_threads(mc.cr);
 
-    cr=init_par_threads(mc.cr);
     if (MASTER(cr))
     {
         fplog=mc.fplog;
     }
 
-
-    mda->ret=mdrunner(fplog, cr, mc.nfile, mc.fnm, mc.oenv, mc.bVerbose,
-                      mc.bCompact, mc.nstglobalcomm, 
+    mda->ret=mdrunner(cr->nthreads, fplog, cr, mc.nfile, fnm, mc.oenv, 
+                      mc.bVerbose, mc.bCompact, mc.nstglobalcomm, 
                       mc.ddxyz, mc.dd_node_order, mc.rdd,
                       mc.rconstr, mc.dddlb_opt, mc.dlb_scale, 
-                      mc.ddcsx, mc.ddcsy, mc.ddcsz, mc.nstepout, mc.resetstep, mc.nmultisim,
-                      mc.repl_ex_nst, mc.repl_ex_seed, mc.pforce, 
+                      mc.ddcsx, mc.ddcsy, mc.ddcsz, mc.nstepout, mc.resetstep, 
+                      mc.nmultisim, mc.repl_ex_nst, mc.repl_ex_seed, mc.pforce, 
                       mc.cpt_period, mc.max_hours, mc.deviceOptions, mc.Flags);
 }
 
-#endif
-
-int mdrunner_threads(int nthreads, 
-                     FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
-                     const output_env_t oenv, bool bVerbose,bool bCompact,
-                     int nstglobalcomm,
-                     ivec ddxyz,int dd_node_order,real rdd,real rconstr,
-                     const char *dddlb_opt,real dlb_scale,
-                     const char *ddcsx,const char *ddcsy,const char *ddcsz,
-                     int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
-                     int repl_ex_seed, real pforce,real cpt_period,
-                     real max_hours, const char *deviceOptions, unsigned long Flags)
+/* called by mdrunner() to start a specific number of threads (including 
+   the main thread) for thread-parallel runs. This in turn calls mdrunner()
+   for each thread. 
+   All options besides nthreads are the same as for mdrunner(). */
+static t_commrec *mdrunner_start_threads(int nthreads, 
+              FILE *fplog,t_commrec *cr,int nfile, 
+              const t_filenm fnm[], const output_env_t oenv, bool bVerbose,
+              bool bCompact, int nstglobalcomm,
+              ivec ddxyz,int dd_node_order,real rdd,real rconstr,
+              const char *dddlb_opt,real dlb_scale,
+              const char *ddcsx,const char *ddcsy,const char *ddcsz,
+              int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
+              int repl_ex_seed, real pforce,real cpt_period, real max_hours, 
+              const char *deviceOptions, unsigned long Flags)
 {
     int ret;
+    struct mdrunner_arglist *mda;
+    t_commrec *crn; /* the new commrec */
+    t_filenm *fnmn;
+
     /* first check whether we even need to start tMPI */
-    if (nthreads < 2)
+    if (nthreads<2)
+        return cr;
+
+    /* a few small, one-time, almost unavoidable memory leaks: */
+    snew(mda,1);
+    fnmn=dup_tfn(nfile, fnm);
+
+    /* fill the data structure to pass as void pointer to thread start fn */
+    mda->fplog=fplog;
+    mda->cr=cr;
+    mda->nfile=nfile;
+    mda->fnm=fnmn;
+    mda->oenv=oenv;
+    mda->bVerbose=bVerbose;
+    mda->bCompact=bCompact;
+    mda->nstglobalcomm=nstglobalcomm;
+    mda->ddxyz[XX]=ddxyz[XX];
+    mda->ddxyz[YY]=ddxyz[YY];
+    mda->ddxyz[ZZ]=ddxyz[ZZ];
+    mda->dd_node_order=dd_node_order;
+    mda->rdd=rdd;
+    mda->rconstr=rconstr;
+    mda->dddlb_opt=dddlb_opt;
+    mda->dlb_scale=dlb_scale;
+    mda->ddcsx=ddcsx;
+    mda->ddcsy=ddcsy;
+    mda->ddcsz=ddcsz;
+    mda->nstepout=nstepout;
+    mda->resetstep=resetstep;
+    mda->nmultisim=nmultisim;
+    mda->repl_ex_nst=repl_ex_nst;
+    mda->repl_ex_seed=repl_ex_seed;
+    mda->pforce=pforce;
+    mda->cpt_period=cpt_period;
+    mda->max_hours=max_hours;
+    mda->deviceOptions=deviceOptions;
+    mda->Flags=Flags;
+
+    fprintf(stderr, "Starting %d threads\n",nthreads);
+    fflush(stderr);
+    /* now spawn new threads that start mdrunner_start_fn(), while 
+       the main thread returns */
+    ret=tMPI_Init_fn(TRUE, nthreads, mdrunner_start_fn, (void*)(mda) );
+    if (ret!=TMPI_SUCCESS)
+        return NULL;
+
+    /* make a new comm_rec to reflect the new situation */
+    crn=init_par_threads(cr);
+    return crn;
+}
+
+
+/* get the number of threads based on how many there were requested, 
+   which algorithms we're using, and how many particles there are. */
+static int get_nthreads(int nthreads_requested, t_inputrec *inputrec,
+                        gmx_mtop_t *mtop)
+{
+    int nthreads,nthreads_new;
+
+    nthreads = nthreads_requested;
+
+    /* determine # of hardware threads. */
+    if (nthreads_requested < 1)
     {
-        ret=mdrunner(fplog, cr, nfile, fnm, oenv, bVerbose, bCompact,
-                     nstglobalcomm,
-                     ddxyz, dd_node_order, rdd, rconstr, dddlb_opt, dlb_scale,
-                     ddcsx, ddcsy, ddcsz, nstepout, resetstep, nmultisim, repl_ex_nst, 
-                     repl_ex_seed, pforce, cpt_period, max_hours, deviceOptions, Flags);
+        nthreads = tMPI_Get_recommended_nthreads();
     }
-    else
+    /* Check if an algorithm does not support parallel simulation.  */
+    if (nthreads != 1 && 
+        ( inputrec->eI == eiLBFGS ||
+          inputrec->eI == eiNM ||
+          inputrec->coulombtype == eelEWALD) )
+    {
+        fprintf(stderr,"\nThe integration or electrostatics algorithm doesn't support parallel runs. Not starting any threads.\n");
+        nthreads = 1;
+    }
+    else if ((nthreads_requested < 1) &&
+             (mtop->natoms/nthreads < MIN_ATOMS_PER_THREAD) )
     {
-#ifdef GMX_THREADS
-        struct mdrunner_arglist mda;
-        /* fill the data structure to pass as void pointer to thread start fn */
-        mda.fplog=fplog;
-        mda.cr=cr;
-        mda.nfile=nfile;
-        mda.fnm=fnm;
-        mda.oenv=oenv;
-        mda.bVerbose=bVerbose;
-        mda.bCompact=bCompact;
-        mda.nstglobalcomm=nstglobalcomm;
-        mda.ddxyz[XX]=ddxyz[XX];
-        mda.ddxyz[YY]=ddxyz[YY];
-        mda.ddxyz[ZZ]=ddxyz[ZZ];
-        mda.dd_node_order=dd_node_order;
-        mda.rdd=rdd;
-        mda.rconstr=rconstr;
-        mda.dddlb_opt=dddlb_opt;
-        mda.dlb_scale=dlb_scale;
-        mda.ddcsx=ddcsx;
-        mda.ddcsy=ddcsy;
-        mda.ddcsz=ddcsz;
-        mda.nstepout=nstepout;
-        mda.resetstep=resetstep;
-        mda.nmultisim=nmultisim;
-        mda.repl_ex_nst=repl_ex_nst;
-        mda.repl_ex_seed=repl_ex_seed;
-        mda.pforce=pforce;
-        mda.cpt_period=cpt_period;
-        mda.max_hours=max_hours;
-        mda.deviceOptions=deviceOptions;
-        mda.Flags=Flags;
-
-        fprintf(stderr, "Starting %d threads\n",nthreads);
-        fflush(stderr);
-        tMPI_Init_fn(nthreads, mdrunner_start_fn, (void*)(&mda) );
-        ret=mda.ret;
-#else
-        ret=-1;
-        gmx_comm("Multiple threads requested but not compiled with threads");
-#endif
+        /* the thread number was chosen automatically, but there are too many
+           threads (too few atoms per thread) */
+        nthreads_new = max(1,mtop->natoms/MIN_ATOMS_PER_THREAD);
+
+        if (nthreads_new > 8 || (nthreads == 8 && nthreads_new > 4))
+        {
+            /* Use only multiples of 4 above 8 threads
+             * or with an 8-core processor
+             * (to avoid 6 threads on 8 core processors with 4 real cores).
+             */
+            nthreads_new = (nthreads_new/4)*4;
+        }
+        else if (nthreads_new > 4)
+        {
+            /* Avoid 5 or 7 threads */
+            nthreads_new = (nthreads_new/2)*2;
+        }
+
+        nthreads = nthreads_new;
+
+        fprintf(stderr,"\n");
+        fprintf(stderr,"NOTE: Parallelization is limited by the small number of atoms,\n");
+        fprintf(stderr,"      only starting %d threads.\n",nthreads);
+        fprintf(stderr,"      You can use the -nt option to optimize the number of threads.\n\n");
     }
-    return ret;
+    return nthreads;
 }
+#endif
 
 
-int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
-             const output_env_t oenv, bool bVerbose,bool bCompact,
-             int nstglobalcomm,
+int mdrunner(int nthreads_requested, FILE *fplog,t_commrec *cr,int nfile,
+             const t_filenm fnm[], const output_env_t oenv, bool bVerbose,
+             bool bCompact, int nstglobalcomm,
              ivec ddxyz,int dd_node_order,real rdd,real rconstr,
              const char *dddlb_opt,real dlb_scale,
              const char *ddcsx,const char *ddcsy,const char *ddcsz,
-             int nstepout,int resetstep,int nmultisim,int repl_ex_nst,int repl_ex_seed,
-             real pforce,real cpt_period,real max_hours,
-             const char *deviceOptions,
-             unsigned long Flags)
+             int nstepout,int resetstep,int nmultisim,int repl_ex_nst,
+             int repl_ex_seed, real pforce,real cpt_period,real max_hours,
+             const char *deviceOptions, unsigned long Flags)
 {
     double     nodetime=0,realtime;
     t_inputrec *inputrec;
     t_state    *state=NULL;
     matrix     box;
-    gmx_ddbox_t ddbox;
-    int        npme_major;
+    gmx_ddbox_t ddbox={0};
+    int        npme_major,npme_minor;
     real       tmpr1,tmpr2;
     t_nrnb     *nrnb;
     gmx_mtop_t *mtop=NULL;
@@ -274,35 +338,12 @@ int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     gmx_runtime_t runtime;
     int        rc;
     gmx_large_int_t reset_counters;
-    gmx_edsam_t ed;
-
-    /* A parallel command line option consistency check */
-    if (!PAR(cr) &&
-        (ddxyz[XX] > 1 || ddxyz[YY] > 1 || ddxyz[ZZ] > 1 || cr->npmenodes > 0))
-    {
-        gmx_fatal(FARGS,
-                  "The -dd or -npme option request a parallel simulation, "
-#ifndef GMX_MPI
-                  "but mdrun was compiled without threads or MPI enabled"
-#else
-#ifdef GMX_THREADS
-                  "but the number of threads (option -nt) is 1"
-#else
-                  "but mdrun was not started through mpirun/mpiexec or only one process was requested through mpirun/mpiexec" 
-#endif
-#endif
-            );
-    }
-
-    /* Essential dynamics */
-    if (opt2bSet("-ei",nfile,fnm)) 
-    {
-        /* Open input and output files, allocate space for ED data structure */
-        ed = ed_open(nfile,fnm,cr);
-    } 
-    else
-        ed=NULL;
+    gmx_edsam_t ed=NULL;
+    t_commrec   *cr_old=cr; 
+    int         nthreads=1;
 
+    /* CAUTION: threads may be started later on in this function, so
+       cr doesn't reflect the final parallel state right now */
     snew(inputrec,1);
     snew(mtop,1);
 
@@ -316,30 +357,76 @@ int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         fplog = NULL;
     }
 
-    if (PAR(cr))
+    snew(state,1);
+    if (MASTER(cr)) 
     {
-        /* The master thread on the master node reads from disk, 
-         * then distributes everything to the other processors.
-         */
+        /* Read (nearly) all data required for the simulation */
+        read_tpx_state(ftp2fn(efTPX,nfile,fnm),inputrec,state,NULL,mtop);
 
-        list = (SIMMASTER(cr) && !(Flags & MD_APPENDFILES)) ?  (LIST_SCALARS | LIST_INPUTREC) : 0;
+        /* NOW the threads will be started: */
+#ifdef GMX_THREADS
+        nthreads = get_nthreads(nthreads_requested, inputrec, mtop);
 
-        snew(state,1);
-        /* NOTE: if the run is thread-parallel but the integrator doesn't support this
-                 such as with LBGFS, this function may cancel the threads 
-                 through cancel_par_threads(), and make the commrec serial. The
-                 rest of the simulation is then only performed by the main thread,
-                 as if it were a serial run. */
-        init_parallel(fplog, opt2fn_master("-s",nfile,fnm,cr),cr,
-                      inputrec,mtop,state,list);
+        if (nthreads > 1)
+        {
+            /* now start the threads. */
+            cr=mdrunner_start_threads(nthreads, fplog, cr_old, nfile, fnm, 
+                                      oenv, bVerbose, bCompact, nstglobalcomm, 
+                                      ddxyz, dd_node_order, rdd, rconstr, 
+                                      dddlb_opt, dlb_scale, ddcsx, ddcsy, ddcsz,
+                                      nstepout, resetstep, nmultisim, 
+                                      repl_ex_nst, repl_ex_seed, pforce, 
+                                      cpt_period, max_hours, deviceOptions, 
+                                      Flags);
+            /* the main thread continues here with a new cr. We don't deallocate
+               the old cr because other threads may still be reading it. */
+            if (cr == NULL)
+            {
+                gmx_comm("Failed to spawn threads");
+            }
+        }
+#endif
+    }
+    /* END OF CAUTION: cr is now reliable */
 
+    /* now make sure the state is initialized and propagated */
+    set_state_entries(state,inputrec,cr->nnodes);
+    if (PAR(cr))
+    {
+        /* now broadcast everything to the non-master nodes/threads: */
+        init_parallel(fplog, cr, inputrec, mtop, state);
     }
-    else
+
+    if (fplog)
+    {
+        pr_inputrec(fplog,0,"Input Parameters",inputrec,FALSE);
+    }
+
+    /* A parallel command line option consistency check that we can
+       only do after any threads have started. */
+    if (!PAR(cr) &&
+        (ddxyz[XX] > 1 || ddxyz[YY] > 1 || ddxyz[ZZ] > 1 || cr->npmenodes > 0))
+    {
+        gmx_fatal(FARGS,
+                  "The -dd or -npme option request a parallel simulation, "
+#ifndef GMX_MPI
+                  "but mdrun was compiled without threads or MPI enabled"
+#else
+#ifdef GMX_THREADS
+                  "but the number of threads (option -nt) is 1"
+#else
+                  "but mdrun was not started through mpirun/mpiexec or only one process was requested through mpirun/mpiexec" 
+#endif
+#endif
+            );
+    }
+
+    if (can_use_allvsall(inputrec,mtop,TRUE,cr,fplog))
     {
-        /* Read a file for a single processor */
-        snew(state,1);
-        init_single(fplog,inputrec,ftp2fn(efTPX,nfile,fnm),mtop,state);
+        /* All-vs-all loops do not work with domain decomposition */
+        Flags |= MD_PARTDEC;
     }
+
     if (!EEL_PME(inputrec->coulombtype) || (Flags & MD_PARTDEC))
     {
         cr->npmenodes = 0;
@@ -441,6 +528,13 @@ int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         gmx_bcast(sizeof(box),box,cr);
     }
 
+    /* Essential dynamics */
+    if (opt2bSet("-ei",nfile,fnm))
+    {
+        /* Open input and output files, allocate space for ED data structure */
+        ed = ed_open(nfile,fnm,Flags,cr);
+    }
+
     if (bVerbose && SIMMASTER(cr))
     {
         fprintf(stderr,"Loaded with Money\n\n");
@@ -453,7 +547,7 @@ int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
                                            ddcsx,ddcsy,ddcsz,
                                            mtop,inputrec,
                                            box,state->x,
-                                           &ddbox,&npme_major);
+                                           &ddbox,&npme_major,&npme_minor);
 
         make_dd_communicators(fplog,cr,dd_node_order);
 
@@ -462,8 +556,11 @@ int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     }
     else
     {
+        /* PME, if used, is done on all nodes with 1D decomposition */
+        cr->npmenodes = 0;
         cr->duty = (DUTY_PP | DUTY_PME);
         npme_major = cr->nnodes;
+        npme_minor = 1;
         
         if (inputrec->ePBC == epbcSCREW)
         {
@@ -623,7 +720,7 @@ int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         }
         if (cr->duty & DUTY_PME)
         {
-            status = gmx_pme_init(pmedata,cr,npme_major,inputrec,
+            status = gmx_pme_init(pmedata,cr,npme_major,npme_minor,inputrec,
                                   mtop ? mtop->natoms : 0,nChargePerturbed,
                                   (Flags & MD_REPRODUCIBLE));
             if (status != 0) 
@@ -710,7 +807,7 @@ int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
     if (EI_DYNAMICS(inputrec->eI) || EI_TPI(inputrec->eI))
     {
         /* Some timing stats */  
-        if (MASTER(cr))
+        if (SIMMASTER(cr))
         {
             if (runtime.proc == 0)
             {
@@ -741,18 +838,17 @@ int mdrunner(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
         gmx_log_close(fplog);
     }  
 
-    if(bGotStopNextStepSignal)
-    {
-        rc = 1;
-    }
-    else if(bGotStopNextNSStepSignal)
-    {
-        rc = 2;
-    }
-    else
+    rc=(int)gmx_get_stop_condition();
+
+#ifdef GMX_THREADS
+    /* we need to join all threads. The sub-threads join when they
+       exit this function, but the master thread needs to be told to 
+       wait for that. */
+    if (nthreads>1 && MASTERTHREAD(cr) )
     {
-        rc = 0;
+        tMPI_Finalize();
     }
+#endif
 
     return rc;
 }
index 56c7a4653b1797d3b02545eb7132862fc7c7906e..f72a6dd7c32e233fcad80fda0c15ee82a4d4cc7f 100644 (file)
@@ -94,7 +94,7 @@ t_specbond *get_specbonds(int *nspecbond)
   }
   if (nlines > 0)
     sfree(lines);
-  fprintf(stderr,"%d out of %d lines of %s converted succesfully\n",
+  fprintf(stderr,"%d out of %d lines of %s converted successfully\n",
          n,nlines,sbfile);
          
   *nspecbond = n;
@@ -173,19 +173,21 @@ static bool is_bond(int nsb,t_specbond sb[],t_atoms *pdba,int a1,int a2,
   return FALSE;
 }
 
-static void rename_1res(t_atoms *pdba,int resind,char *newres)
+static void rename_1res(t_atoms *pdba,int resind,char *newres,bool bVerbose)
 {
-  if(debug) fprintf(stderr,"Renaming %s-%d to %s\n", 
-                   *pdba->resinfo[resind].name,
-                   pdba->resinfo[resind].nr,
-                   newres);
+  if (bVerbose) {
+    printf("Using rtp entry %s for %s %d\n",
+          newres,
+          *pdba->resinfo[resind].name,
+          pdba->resinfo[resind].nr);
+  }
   /* this used to free *resname, which fucks up the symtab! */
-  snew(pdba->resinfo[resind].name,1);
-  *pdba->resinfo[resind].name = strdup(newres);
+  snew(pdba->resinfo[resind].rtp,1);
+  *pdba->resinfo[resind].rtp = strdup(newres);
 }
 
 int mk_specbonds(t_atoms *pdba,rvec x[],bool bInteractive,
-                t_ssbond **specbonds)
+                t_ssbond **specbonds,bool bVerbose)
 {
   t_specbond *sb=NULL;
   t_ssbond   *bonds=NULL;
@@ -289,12 +291,12 @@ int mk_specbonds(t_atoms *pdba,rvec x[],bool bInteractive,
            bonds[nbonds].a2   = strdup(*pdba->atomname[aj]);
            /* rename residues */
            if (bSwap) {
-             rename_1res(pdba,specp[i],sb[index_sb].newres2);
-             rename_1res(pdba,specp[j],sb[index_sb].newres1);
+             rename_1res(pdba,specp[i],sb[index_sb].newres2,bVerbose);
+             rename_1res(pdba,specp[j],sb[index_sb].newres1,bVerbose);
            }
            else {
-             rename_1res(pdba,specp[i],sb[index_sb].newres1);
-             rename_1res(pdba,specp[j],sb[index_sb].newres2);
+             rename_1res(pdba,specp[i],sb[index_sb].newres1,bVerbose);
+             rename_1res(pdba,specp[j],sb[index_sb].newres2,bVerbose);
            }
            nbonds++;
          }
index 80ad9303aa53908e4eb9810857efb3b8e322702b..8253c8b4871ba19ae2ac43372de208cf000d96df 100644 (file)
@@ -39,7 +39,7 @@
 #include "pdb2top.h"
 
 extern int mk_specbonds(t_atoms *pdba,rvec x[],bool bInteractive,
-                       t_ssbond **specbonds);
+                       t_ssbond **specbonds,bool bVerbose);
 
 extern bool yesno(void);
 
index e61a413d16d7ab0577b63a42eca2348cb441ab68..e6dc0596e5b1183f2fe75202d32185737109568c 100644 (file)
@@ -128,7 +128,7 @@ static void print_atom(FILE *out,t_atom *a,gpp_atomtype_t atype,char *newnm)
          get_atomtype_name(a->type,atype),a->m,a->q);
 }
 
-static void print_ter_db(char *ff,char C,int nb,t_hackblock tb[],
+static void print_ter_db(const char *ff,char C,int nb,t_hackblock tb[],
                         gpp_atomtype_t atype) 
 {
   FILE *out;
@@ -313,7 +313,7 @@ static void read_ter_db_file(char *fn,
   *tbptr  = tb;
 }
 
-int read_ter_db(const char *ffdir,char ter,
+int read_ter_db(const char *ffdir,bool bAddCWD,char ter,
                t_hackblock **tbptr,gpp_atomtype_t atype)
 {
   char ext[STRLEN];
@@ -326,7 +326,7 @@ int read_ter_db(const char *ffdir,char ter,
   /* Search for termini database files.
    * Do not generate an error when none are found.
    */
-  ntdbf = fflib_search_file_end(ffdir,ext,FALSE,&tdbf);
+  ntdbf = fflib_search_file_end(ffdir,bAddCWD,ext,FALSE,&tdbf);
   ntb    = 0;
   *tbptr = NULL;
   for(f=0; f<ntdbf; f++) {
@@ -345,6 +345,7 @@ int read_ter_db(const char *ffdir,char ter,
 t_hackblock **filter_ter(int nrtp,t_restp rtp[],
                         int nb,t_hackblock tb[],
                         const char *resname,
+                        const char *rtpname,
                         int *nret)
 {
   /* Since some force fields (e.g. OPLS) needs different
@@ -374,7 +375,7 @@ t_hackblock **filter_ter(int nrtp,t_restp rtp[],
   char *s,*s2,*c;
   t_hackblock **list;
 
-  restp = search_rtp(resname,nrtp,rtp);
+  restp = search_rtp(rtpname,nrtp,rtp);
   
   n=0;
   list=NULL;
index 3531543cc800f7d15eb98ecc93f0d5aa44ea8f1d..38447f3ae724ffc98e1610dd9131a3e91a86b60f 100644 (file)
 #include "hackblock.h"
 #include "grompp.h"
 
-extern int read_ter_db(const char *ffdir,char ter,
+extern int read_ter_db(const char *ffdir,bool bAddCWD,char ter,
                       t_hackblock **tbptr,gpp_atomtype_t atype);
 /* Read database for N&C terminal hacking */
 
 extern t_hackblock **filter_ter(int nrtp,t_restp rtp[],
                                int nb,t_hackblock tb[],
                                const char *resname,
+                               const char *rtpname,
                                int *nret);
 /* Return a list of pointers to blocks that match residue name */
 
index 508a7317d1dc97075cc52009a6d2de0923398e78..d978e4dd670fe539605b2de8a8bfac820927eff1 100644 (file)
@@ -91,7 +91,7 @@ int ifunc_index(directive d,int type)
       return F_UREY_BRADLEY;
     case 6:
       return F_QUARTIC_ANGLES;
-    case 7:
+    case 8:
       return F_TABANGLES;
     default:
       gmx_fatal(FARGS,"Invalid angle type %d",type);
index 237fbae64fbd61fbb202273ebf2d9396a37cc165..d56242e65c17138225521118d4459192f335f058 100644 (file)
@@ -201,13 +201,25 @@ double check_mol(gmx_mtop_t *mtop,warninp_t wi)
 
 static void sum_q(t_atoms *atoms,int n,double *qt,double *qBt)
 {
-  int     i;
+    double qmolA,qmolB;
+    int     i;
 
-  /* sum charge */
-  for (i=0; (i<atoms->nr); i++) {
-    *qt  += n*atoms->atom[i].q;
-    *qBt += n*atoms->atom[i].qB;
-  }
+    /* sum charge */
+    qmolA = 0;
+    qmolB = 0;
+    for (i=0; i<atoms->nr; i++)
+    {
+        qmolA += atoms->atom[i].q;
+        qmolB += atoms->atom[i].qB;
+    }
+    /* Unfortunately an absolute comparison,
+     * but this avoids unnecessary warnings and gmx-users mails.
+     */
+    if (fabs(qmolA) >= 1e-6 || fabs(qmolB) >= 1e-6)
+    {
+        *qt  += n*qmolA;
+        *qBt += n*qmolB;
+    }
 }
 
 static void get_nbparm(char *nb_str,char *comb_str,int *nb,int *comb,
index 44119d723b046d81df30c878185dc0c9a9e61208..41cb4ba67c6d19707312c40def20a5193ccfa911 100644 (file)
@@ -882,7 +882,7 @@ push_gb_params (gpp_atomtype_t at, char *line,
                 warninp_t wi)
 {
     int nfield;
-    int i,n,k,found,gfound;
+    int atype;
     double radius,vol,surftens,gb_radius,S_hct;
     char atypename[STRLEN];
     char errbuf[STRLEN];
@@ -894,24 +894,15 @@ push_gb_params (gpp_atomtype_t at, char *line,
     }
     
     /* Search for atomtype */
-    found = 0;
-    gfound = -1;
-    for(i=0;i<get_atomtype_ntypes(at) && !found;i++)
-    {
-        if(gmx_strncasecmp(atypename,get_atomtype_name(i,at),STRLEN-1)==0)
-        {
-            found = i;
-                       gfound = i;
-               }
-    }
+    atype = get_atomtype_type(atypename,at);
        
-       if (gfound==-1)
+       if (atype == NOTSET)
     {
                printf("Couldn't find topology match for atomtype %s\n",atypename);
                abort();
     }
     
-       set_atomtype_gbparam(at,found,radius,vol,surftens,gb_radius,S_hct);
+       set_atomtype_gbparam(at,atype,radius,vol,surftens,gb_radius,S_hct);
 }
 
 void 
index 9b4a2e67631edae5cc3f973a67b0aae4de73f5fa..d110c66685fbc8421fdcbfcc0569d6cc20b56c2b 100644 (file)
@@ -415,7 +415,7 @@ void print_atoms(FILE *out,gpp_atomtype_t atype,t_atoms *at,int *cgnr,
     /* if the information is present... */
     for (i=0; (i < at->nr); i++) {
       ri = at->atom[i].resind;
-      if (i == 0 || ri != at->atom[i-1].resind &&
+      if ((i == 0 || ri != at->atom[i-1].resind) &&
          at->resinfo[ri].rtp != NULL) {
        qres = get_residue_charge(at,i);
        fprintf(out,"; residue %3d %-3s rtp %-4s q ",
index eeaa9ca7aaf9fdd9189fab6ba28e71060117d972..f7aa0563274b1bffe0696d321dfcf34483e7cc08 100644 (file)
@@ -732,7 +732,7 @@ void comp_trx(const output_env_t oenv,const char *fn1, const char *fn2,
   int i;
   const char *fn[2];
   t_trxframe fr[2];
-  int status[2];
+  t_trxstatus *status[2];
   bool b[2];
   
   fn[0]=fn1;
@@ -856,7 +856,7 @@ void comp_enx(const char *fn1,const char *fn2,real ftol,real abstol,const char *
     else if (!b1 && b2) 
       fprintf(stdout,"\nEnd of file on %s but not on %s\n",fn1,fn2);
     else if (!b1 && !b2)
-      fprintf(stdout,"\nFiles read succesfully\n");
+      fprintf(stdout,"\nFiles read successfully\n");
     else {
       cmp_real(stdout,"t",-1,fr1->t,fr2->t,ftol,abstol);
       cmp_int(stdout,"step",-1,fr1->step,fr2->step);
index 1e473ed8bb5644dfd0c33bc0ba1a7452bcde07a3..b6c3ae0160b4b831eb8007514324763ee76af72f 100644 (file)
@@ -292,10 +292,11 @@ static void zeroq(int n,atom_id index[],gmx_mtop_t *mtop)
 int main (int argc, char *argv[])
 {
   const char *desc[] = {
-    "tpbconv can edit run input files in four ways.[PAR]"
+    "tpbconv can edit run input files in four ways.[PAR]",
     "[BB]1st.[bb] by modifying the number of steps in a run input file",
-    "with option [TT]-nsteps[tt] or option [TT]-runtime[tt].[PAR]",
-    "[BB]2st.[bb] (OBSOLETE) by creating a run input file",
+    "with options [TT]-extend[tt], [TT]-until[tt] or [TT]-nsteps[tt]",
+    "(nsteps=-1 means unlimited number of steps)[PAR]",
+    "[BB]2nd.[bb] (OBSOLETE) by creating a run input file",
     "for a continuation run when your simulation has crashed due to e.g.",
     "a full disk, or by making a continuation run input file.",
     "This option is obsolete, since mdrun now writes and reads",
@@ -304,17 +305,17 @@ int main (int argc, char *argv[])
     "When pressure and/or Nose-Hoover temperature coupling is used",
     "an energy file can be supplied to get an exact continuation",
     "of the original run.[PAR]",
-    "[BB]3nd.[bb] by creating a tpx file for a subset of your original",
+    "[BB]3rd.[bb] by creating a tpx file for a subset of your original",
     "tpx file, which is useful when you want to remove the solvent from",
     "your tpx file, or when you want to make e.g. a pure Ca tpx file.",
     "[BB]WARNING: this tpx file is not fully functional[bb].",
-    "[BB]4rd.[bb] by setting the charges of a specified group",
+    "[BB]4th.[bb] by setting the charges of a specified group",
     "to zero. This is useful when doing free energy estimates",
     "using the LIE (Linear Interaction Energy) method."
   };
 
   const char   *top_fn,*frame_fn;
-  int          fp;
+  t_fileio     *fp;
   ener_file_t  fp_ener=NULL;
   t_trnheader head;
   int          i;
@@ -347,21 +348,18 @@ int main (int argc, char *argv[])
 #define NFILE asize(fnm)
 
   /* Command line options */
-  static int  nsteps_req_int = -1;
-  static real runtime_req = -1;
+  static int  nsteps_req_int = 0;
   static real start_t = -1.0, extend_t = 0.0, until_t = 0.0;
   static bool bContinuation = TRUE,bZeroQ = FALSE,bVel=TRUE;
   static t_pargs pa[] = {
-    { "-nsteps",        FALSE, etINT,  {&nsteps_req_int},
-      "Change the number of steps" },
-    { "-runtime",       FALSE, etREAL, {&runtime_req},
-      "Set the run time (ps)" },
-    { "-time",          FALSE, etREAL, {&start_t}, 
-      "Continue from frame at this time (ps) instead of the last frame" },
     { "-extend",        FALSE, etREAL, {&extend_t}, 
       "Extend runtime by this amount (ps)" },
     { "-until",         FALSE, etREAL, {&until_t}, 
       "Extend runtime until this ending time (ps)" },
+    { "-nsteps",        FALSE, etINT,  {&nsteps_req_int},
+      "Change the number of steps" },
+    { "-time",          FALSE, etREAL, {&start_t}, 
+      "Continue from frame at this time (ps) instead of the last frame" },
     { "-zeroq",         FALSE, etBOOL, {&bZeroQ},
       "Set the charges of a group (from the index) to zero" },
     { "-vel",           FALSE, etBOOL, {&bVel},
@@ -379,14 +377,14 @@ int main (int argc, char *argv[])
 
   /* Convert int to gmx_large_int_t */
   nsteps_req = nsteps_req_int;
-  bNsteps = (nsteps_req >= 0 || runtime_req >= 0);
+  bNsteps = opt2parg_bSet("-nsteps",asize(pa),pa);
   bExtend = opt2parg_bSet("-extend",asize(pa),pa);
   bUntil  = opt2parg_bSet("-until",asize(pa),pa);
   bTime   = opt2parg_bSet("-time",asize(pa),pa);
   bTraj   = (opt2bSet("-f",NFILE,fnm) || bTime);
 
   top_fn = ftp2fn(efTPX,NFILE,fnm);
-  fprintf(stderr,"Reading toplogy and shit from %s\n",top_fn);
+  fprintf(stderr,"Reading toplogy and stuff from %s\n",top_fn);
   
   snew(ir,1);
   read_tpx_state(top_fn,ir,&state,NULL,&mtop);
@@ -523,13 +521,6 @@ int main (int argc, char *argv[])
   }
 
   if (bNsteps) {
-    if (nsteps_req < 0) {
-      if (!EI_DYNAMICS(ir->eI)) {
-       gmx_fatal(FARGS,"Can not set the run time with integrator '%s'",
-                 EI(ir->eI));
-      }
-      nsteps_req = (int)(runtime_req/ir->delta_t + 0.5);
-    }
     fprintf(stderr,"Setting nsteps to %s\n",gmx_step_str(nsteps_req,buf));
     ir->nsteps = nsteps_req;
   } else {
index a52e7f9ee7a08c89de0bdf80a12e3eef673d49fb..ec6646d280de6cf1b276a748cdd0719d82160d2b 100644 (file)
@@ -49,6 +49,7 @@
 #include "fflibutil.h"
 #include "hackblock.h"
 #include "gmx_fatal.h"
+#include "xlate.h"
 
 typedef struct {
     char *filebase;
@@ -132,7 +133,7 @@ static void done_xlatom(int nxlate,t_xlate_atom *xlatom)
     sfree(xlatom);
 }
 
-void rename_atoms(const char *xlfile,const char *ffdir,
+void rename_atoms(const char *xlfile,const char *ffdir,bool bAddCWD,
                   t_atoms *atoms,t_symtab *symtab,const t_restp *restp,
                   bool bResname,t_aa_names *aan,bool bReorderNum,
                   bool bVerbose)
@@ -155,7 +156,7 @@ void rename_atoms(const char *xlfile,const char *ffdir,
     }
     else
     {
-        nf = fflib_search_file_end(ffdir,".arn",FALSE,&f);
+        nf = fflib_search_file_end(ffdir,bAddCWD,".arn",FALSE,&f);
         for(i=0; i<nf; i++)
         {
             fp = fflib_open(f[i]);
index c846557013d4a5637ecca40fe88f08706a5b0a41..8f0dba672de35a173dd625cd96da51d73c36e46a 100644 (file)
@@ -41,7 +41,7 @@
 /* If bResname is true renames atoms based on residue names,
  * otherwise renames atoms based on rtp entry names.
  */
-extern void rename_atoms(const char *xlfile,const char *ffdir,
+extern void rename_atoms(const char *xlfile,const char *ffdir,bool bAddCWD,
                         t_atoms *atoms,t_symtab *symtab,const t_restp *restp,
                         bool bResname,t_aa_names *aan,bool bReorderNum,
                         bool bVerbose);
index 1192d9a56b5162a2c6748dc768f41bbd643b34e3..29dbeb4cdd4a7d81dc8c09da8ec0b2ea0a4a4f98 100644 (file)
@@ -19,7 +19,7 @@ libmd@LIBSUFFIX@_la_SOURCES = \
        domdec.c        domdec_box.c    domdec_con.c    \
        domdec_network.c domdec_setup.c domdec_top.c    \
        ebin.c          \
-       edsam.c         ewald.c         fftgrid.c       \
+       edsam.c         ewald.c         \
        force.c         forcerec.c      \
        ghat.c          init.c          \
        mdatom.c        mdebin.c        minimize.c      \
@@ -45,10 +45,11 @@ libmd@LIBSUFFIX@_la_SOURCES = \
        wall.c          wnblist.c       \
        csettle.c       clincs.c        \
        qmmm.c          gmx_fft.c       gmx_parallel_3dfft.c    \
-       gmx_wallcycle.c \
+       fft5d.c         fft5d.h         \
+       gmx_wallcycle.c \
        qm_gaussian.c   qm_mopac.c      qm_gamess.c             \
        gmx_fft_fftw2.c gmx_fft_fftw3.c gmx_fft_fftpack.c       \
-       gmx_fft_mkl.c   
+       gmx_fft_mkl.c   qm_orca.c
 
 LDADD = ../mdlib/libmd@LIBSUFFIX@.la ../gmxlib/libgmx@LIBSUFFIX@.la 
 
index dfa6b001463eed047d1bbcef77cf903155976272..4d2dcb84e3203f7fab0d649106de37d7b4710846 100644 (file)
@@ -403,10 +403,9 @@ bool constrain(FILE *fplog,bool bLog,bool bEner,
             {
                 char buf[256];
                 sprintf(buf,
-                        "\nt = %.3f ps: Water molecule starting at atom %d can not be "
-                        "settled.\nCheck for bad contacts and/or reduce the timestep.\n",
-                        ir->init_t+step*ir->delta_t,
-                        ddglatnr(cr->dd,settle->iatoms[error*2+1]));
+                        "\nstep " gmx_large_int_pfmt ": Water molecule starting at atom %d can not be "
+                        "settled.\nCheck for bad contacts and/or reduce the timestep if appropriate.\n",
+                        step,ddglatnr(cr->dd,settle->iatoms[error*2+1]));
                 if (fplog)
                 {
                     fprintf(fplog,"%s",buf);
index b2c75c7477490666149ffea89e8e450bdfc4e266..88ed5919f7d2c32df384692b7fff9c92b9ee102c 100644 (file)
 #include "txtdump.h"
 #include "nrnb.h"
 #include "gmx_random.h"
+#include "update.h"
+#include "mdrun.h"
 
 #define NTROTTERCALLS 5
 #define NTROTTERPARTS 3
 
-/* these integration routines are only references inside this file */
+/* these integration routines are only referenced inside this file */
 static void NHC_trotter(t_grpopts *opts,int nvar, gmx_ekindata_t *ekind,real dtfull,
                         double xi[],double vxi[], double scalefac[], real *veta, t_extmass *MassQ, bool bEkinAveVel)
 
@@ -631,7 +633,7 @@ void destroy_bufstate(t_state *state)
     sfree(state);
 }  
 
-void trotter_update(t_inputrec *ir,gmx_ekindata_t *ekind, 
+void trotter_update(t_inputrec *ir,gmx_large_int_t step, gmx_ekindata_t *ekind, 
                     gmx_enerdata_t *enerd, t_state *state, 
                     tensor vir, t_mdatoms *md, 
                     t_extmass *MassQ, int *trotter_seq) 
@@ -643,14 +645,20 @@ void trotter_update(t_inputrec *ir,gmx_ekindata_t *ekind,
     real ecorr,pcorr,dvdlcorr;
     real bmass,qmass,reft,kT,dt,nd;
     tensor dumpres,dumvir;
-    double *scalefac;
+    double *scalefac,dtc;
     rvec sumv,consk;
+    bool bCouple;
 
+    bCouple = (ir->nstcalcenergy == 1 ||
+               do_per_step(step+ir->nstcalcenergy,ir->nstcalcenergy));
+    
     /* signal we are returning if nothing is going to be done in this routine */
-    if (trotter_seq[0] == etrtSKIPALL) 
+    if ((trotter_seq[0] == etrtSKIPALL)  || !(bCouple))
     {
         return;
     }
+
+    dtc = ir->nstcalcenergy*ir->delta_t;
     opts = &(ir->opts); /* just for ease of referencing */
     ngtc = opts->ngtc;
     snew(scalefac,opts->ngtc);
@@ -664,13 +672,13 @@ void trotter_update(t_inputrec *ir,gmx_ekindata_t *ekind,
         /* allow for doubled intgrators by doubling dt instead of making 2 calls */
         if ((trotter_seq[i] == etrtBAROV2) || (trotter_seq[i] == etrtBARONHC2) || (trotter_seq[i] == etrtNHC2))
         {
-            dt = 2 * ir->delta_t;
+            dt = 2 * dtc;
         }
         else 
         {
-            dt = ir->delta_t;
+            dt = dtc;
         }
-            
+
         switch (trotter_seq[i])
         {
         case etrtBAROV:
@@ -1018,9 +1026,12 @@ real NPT_energy(t_inputrec *ir, t_state *state, t_extmass *MassQ)
         
             for (j=0;j<nh;j++) 
             {
-                ener_npt += 0.5*sqr(ivxi[j])/iQinv[j];
-                /* contribution from the thermal variable of the NH chain */
-                ener_npt += ixi[j]*kT;
+                if (iQinv[j] > 0)
+                {
+                    ener_npt += 0.5*sqr(ivxi[j])/iQinv[j];
+                    /* contribution from the thermal variable of the NH chain */
+                    ener_npt += ixi[j]*kT;
+                }
                 if (debug) 
                 {
                     fprintf(debug,"P-T-group: %10d Chain %4d ThermV: %15.8f ThermX: %15.8f",i,j,ivxi[j],ixi[j]);
@@ -1048,16 +1059,18 @@ real NPT_energy(t_inputrec *ir, t_state *state, t_extmass *MassQ)
                     /* contribution from the thermal momenta of the NH chain */
                     for (j=0;j<nh;j++) 
                     {
-                        ener_npt += 0.5*sqr(ivxi[j])/iQinv[j];
-                        /* contribution from the thermal variable of the NH chain */
-                        if (j==0) {
-                            ndj = nd;
-                        } 
-                        else 
-                        {
-                            ndj = 1;
-                        } 
-                        ener_npt += ndj*ixi[j]*kT;
+                        if (iQinv[j] > 0) {
+                            ener_npt += 0.5*sqr(ivxi[j])/iQinv[j];
+                            /* contribution from the thermal variable of the NH chain */
+                            if (j==0) {
+                                ndj = nd;
+                            } 
+                            else 
+                            {
+                                ndj = 1;
+                            } 
+                            ener_npt += ndj*ixi[j]*kT;
+                        }
                     }
                 }
                 else  /* Other non Trotter temperature NH control  -- no chains yet. */
index 413d7ea8dccefa4ddd6b54001342b94636f1c572..53634854c9b9556aaadcf7c1c76ca4d6c5b43d1a 100644 (file)
@@ -48,6 +48,7 @@
 #include "mtop_util.h"
 #include "gmxfio.h"
 #include "gmx_ga2la.h"
+#include "gmx_sort.h"
 
 #ifdef GMX_LIB_MPI
 #include <mpi.h>
@@ -162,7 +163,7 @@ const char *edlb_names[edlbNR] = { "auto", "no", "yes" };
 
 typedef struct
 {
-    int  dimind;   /* The dimension index                                    */
+    int  dim;      /* The dimension                                          */
     int  nslab;    /* The number of PME slabs in this dimension              */
     real *slb_dim_f; /* Cell sizes for determining the PME comm. with SLB    */
     int  *pp_min;  /* The minimum pp node location, size nslab               */
@@ -191,6 +192,7 @@ typedef struct gmx_domdec_comm
     /* The number of nodes doing PME (PP/PME or only PME) */
     int  npmenodes;
     int  npmenodes_major;
+    int  npmenodes_minor;
     /* The communication setup including the PME only nodes */
     bool bCartesianPP_PME;
     ivec ntot;
@@ -2664,33 +2666,27 @@ static float dd_force_load(gmx_domdec_comm_t *comm)
     return load;
 }
 
-static void set_slb_pme_dim_f(gmx_domdec_t *dd,int dimind,real **dim_f)
+static void set_slb_pme_dim_f(gmx_domdec_t *dd,int dim,real **dim_f)
 {
     gmx_domdec_comm_t *comm;
     int i;
     
     comm = dd->comm;
     
-    if (dd->dim[dimind] != dimind)
-    {
-        *dim_f = NULL;
-        return;
-    }
-    
-    snew(*dim_f,dd->nc[dimind]+1);
+    snew(*dim_f,dd->nc[dim]+1);
     (*dim_f)[0] = 0;
-    for(i=1; i<dd->nc[dimind]; i++)
+    for(i=1; i<dd->nc[dim]; i++)
     {
-        if (comm->slb_frac[dimind])
+        if (comm->slb_frac[dim])
         {
-            (*dim_f)[i] = (*dim_f)[i-1] + comm->slb_frac[dimind][i-1];
+            (*dim_f)[i] = (*dim_f)[i-1] + comm->slb_frac[dim][i-1];
         }
         else
         {
-            (*dim_f)[i] = (real)i/(real)dd->nc[dimind];
+            (*dim_f)[i] = (real)i/(real)dd->nc[dim];
         }
     }
-    (*dim_f)[dd->nc[dimind]] = 1;
+    (*dim_f)[dd->nc[dim]] = 1;
 }
 
 static void init_ddpme(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
@@ -2699,8 +2695,8 @@ static void init_ddpme(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
     int         pmeindex,slab,nso,i;
     ivec xyz;
     
-    ddpme->dimind = dimind;
-    ddpme->nslab  = nslab;
+    ddpme->dim   = dd->dim[dimind];
+    ddpme->nslab = nslab;
 
     if (nslab <= 1)
     {
@@ -2708,7 +2704,7 @@ static void init_ddpme(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
     }
 
     nso = dd->comm->npmenodes/nslab;
-    /* Determine for each PME slab the PP locacation range for dimension dim */
+    /* Determine for each PME slab the PP location range for dimension dim */
     snew(ddpme->pp_min,nslab);
     snew(ddpme->pp_max,nslab);
     for(slab=0; slab<nslab; slab++) {
@@ -2720,7 +2716,7 @@ static void init_ddpme(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
         /* For y only use our y/z slab.
          * This assumes that the PME x grid size matches the DD grid size.
          */
-        if (dimind == 0 || xyz[YY] == dd->ci[YY]) {
+        if (dimind == 0 || xyz[XX] == dd->ci[XX]) {
             pmeindex = ddindex2pmeindex(dd,i);
             if (dimind == 0) {
                 slab = pmeindex/nso;
@@ -2732,7 +2728,7 @@ static void init_ddpme(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
         }
     }
 
-    set_slb_pme_dim_f(dd,ddpme->dimind,&ddpme->slb_dim_f);
+    set_slb_pme_dim_f(dd,ddpme->dim,&ddpme->slb_dim_f);
 }
 
 int dd_pme_maxshift0(gmx_domdec_t *dd)
@@ -2742,24 +2738,33 @@ int dd_pme_maxshift0(gmx_domdec_t *dd)
 
 int dd_pme_maxshift1(gmx_domdec_t *dd)
 {
-    return dd->comm->ddpme[1].maxshift;
+    /* This should return the maxshift for dim Y,
+     * where comm indexes ddpme with dimind.
+     */
+    if (dd->comm->npmedecompdim == 1 && dd->dim[0] == YY)
+    {
+        return dd->comm->ddpme[0].maxshift;
+    }
+    else
+    {
+        return dd->comm->ddpme[1].maxshift;
+    }
 }
 
 static void set_pme_maxshift(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
                              bool bUniform,gmx_ddbox_t *ddbox,real *cell_f)
 {
     gmx_domdec_comm_t *comm;
-    int  dim,nc,ns,s;
+    int  nc,ns,s;
     int  *xmin,*xmax;
     real range,pme_boundary;
     int  sh;
     
     comm = dd->comm;
-    dim = ddpme->dimind;
-    nc  = dd->nc[dim];
+    nc  = dd->nc[ddpme->dim];
     ns  = ddpme->nslab;
     
-    if (dd->dim[dim] != dim)
+    if (nc == 1)
     {
         /* PP decomposition is not along dim: the worst situation */
         sh = ns/2;
@@ -2776,12 +2781,13 @@ static void set_pme_maxshift(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
          */
         xmin = ddpme->pp_min;
         xmax = ddpme->pp_max;
-        /* Allow for atoms to be maximally half the cell size or cut-off
-         * out of their DD cell.
+        /* Allow for atoms to be maximally 2/3 times the cut-off
+         * out of their DD cell. This is a reasonable balance between
+         * between performance and support for most charge-group/cut-off
+         * combinations.
          */
-        range  = 0.5*min(comm->cellsize_min[dim],comm->cutoff);
-        range /= ddbox->skew_fac[dim]*ddbox->box_size[dim];
-        /* Avoid unlucky rounding at exactly 0.5 */
+        range  = 2.0/3.0*comm->cutoff/ddbox->box_size[ddpme->dim];
+        /* Avoid extra communication when we are exactly at a boundary */
         range *= 0.999;
         
         sh = 1;
@@ -2813,8 +2819,8 @@ static void set_pme_maxshift(gmx_domdec_t *dd,gmx_ddpme_t *ddpme,
     
     if (debug)
     {
-        fprintf(debug,"PME slab communication range for dimind %d is %d\n",
-                ddpme->dimind,ddpme->maxshift);
+        fprintf(debug,"PME slab communication range for dim %d is %d\n",
+                ddpme->dim,ddpme->maxshift);
     }
 }
 
@@ -2915,7 +2921,7 @@ static void set_dd_cell_sizes_slb(gmx_domdec_t *dd,gmx_ddbox_t *ddbox,
         if (d < ddbox->npbcdim &&
             dd->nc[d] > 1 && npulse[d] >= dd->nc[d])
         {
-            gmx_fatal_collective(FARGS,DDMASTER(dd),
+            gmx_fatal_collective(FARGS,NULL,dd,
                                  "The box size in direction %c (%f) times the triclinic skew factor (%f) is too small for a cut-off of %f with %d domain decomposition cells, use 1 or more than %d %s or increase the box size in this direction",
                                  dim2char(d),ddbox->box_size[d],ddbox->skew_fac[d],
                                  comm->cutoff,
@@ -4040,7 +4046,7 @@ static void clear_and_mark_ind(int ncg,int *move,
 static void print_cg_move(FILE *fplog,
                           gmx_domdec_t *dd,
                           gmx_large_int_t step,int cg,int dim,int dir,
-                          real limitd,
+                          bool bHaveLimitdAndCMOld,real limitd,
                           rvec cm_old,rvec cm_new,real pos_d)
 {
     gmx_domdec_comm_t *comm;
@@ -4049,12 +4055,23 @@ static void print_cg_move(FILE *fplog,
     comm = dd->comm;
 
     fprintf(fplog,"\nStep %s:\n",gmx_step_str(step,buf));
-    fprintf(fplog,"The charge group starting at atom %d moved than the distance allowed by the domain decomposition (%f) in direction %c\n",
-            ddglatnr(dd,dd->cgindex[cg]),limitd,dim2char(dim));
+    if (bHaveLimitdAndCMOld)
+    {
+        fprintf(fplog,"The charge group starting at atom %d moved than the distance allowed by the domain decomposition (%f) in direction %c\n",
+                ddglatnr(dd,dd->cgindex[cg]),limitd,dim2char(dim));
+    }
+    else
+    {
+        fprintf(fplog,"The charge group starting at atom %d moved than the distance allowed by the domain decomposition in direction %c\n",
+                ddglatnr(dd,dd->cgindex[cg]),dim2char(dim));
+    }
     fprintf(fplog,"distance out of cell %f\n",
             dir==1 ? pos_d - comm->cell_x1[dim] : pos_d - comm->cell_x0[dim]);
-    fprintf(fplog,"Old coordinates: %8.3f %8.3f %8.3f\n",
-            cm_old[XX],cm_old[YY],cm_old[ZZ]);
+    if (bHaveLimitdAndCMOld)
+    {
+        fprintf(fplog,"Old coordinates: %8.3f %8.3f %8.3f\n",
+                cm_old[XX],cm_old[YY],cm_old[ZZ]);
+    }
     fprintf(fplog,"New coordinates: %8.3f %8.3f %8.3f\n",
             cm_new[XX],cm_new[YY],cm_new[ZZ]);
     fprintf(fplog,"Old cell boundaries in direction %c: %8.3f %8.3f\n",
@@ -4068,14 +4085,16 @@ static void print_cg_move(FILE *fplog,
 static void cg_move_error(FILE *fplog,
                           gmx_domdec_t *dd,
                           gmx_large_int_t step,int cg,int dim,int dir,
-                          real limitd,
+                          bool bHaveLimitdAndCMOld,real limitd,
                           rvec cm_old,rvec cm_new,real pos_d)
 {
     if (fplog)
     {
-        print_cg_move(fplog, dd,step,cg,dim,dir,limitd,cm_old,cm_new,pos_d);
+        print_cg_move(fplog, dd,step,cg,dim,dir,
+                      bHaveLimitdAndCMOld,limitd,cm_old,cm_new,pos_d);
     }
-    print_cg_move(stderr,dd,step,cg,dim,dir,limitd,cm_old,cm_new,pos_d);
+    print_cg_move(stderr,dd,step,cg,dim,dir,
+                  bHaveLimitdAndCMOld,limitd,cm_old,cm_new,pos_d);
     gmx_fatal(FARGS,
               "A charge group moved too far between two domain decomposition steps\n"
               "This usually means that your system is not well equilibrated");
@@ -4211,8 +4230,19 @@ static int dd_redistribute_cg(FILE *fplog,gmx_large_int_t step,
         {
             cell_x1[d] = comm->cell_x1[d];
         }
-        limit0[d] = comm->old_cell_x0[d] - limitd[d];
-        limit1[d] = comm->old_cell_x1[d] + limitd[d];
+        if (d < npbcdim)
+        {
+            limit0[d] = comm->old_cell_x0[d] - limitd[d];
+            limit1[d] = comm->old_cell_x1[d] + limitd[d];
+        }
+        else
+        {
+            /* We check after communication if a charge group moved
+             * more than one cell. Set the pre-comm check limit to float_max.
+             */
+            limit0[d] = -GMX_FLOAT_MAX;
+            limit1[d] =  GMX_FLOAT_MAX;
+        }
     }
     
     make_tric_corr_matrix(npbcdim,state->box,tcm);
@@ -4267,7 +4297,7 @@ static int dd_redistribute_cg(FILE *fplog,gmx_large_int_t step,
                 {
                     if (pos_d >= limit1[d])
                     {
-                        cg_move_error(fplog,dd,step,cg,d,1,limitd[d],
+                        cg_move_error(fplog,dd,step,cg,d,1,TRUE,limitd[d],
                                       cg_cm[cg],cm_new,pos_d);
                     }
                     dev[d] = 1;
@@ -4293,7 +4323,7 @@ static int dd_redistribute_cg(FILE *fplog,gmx_large_int_t step,
                 {
                     if (pos_d < limit0[d])
                     {
-                        cg_move_error(fplog,dd,step,cg,d,-1,limitd[d],
+                        cg_move_error(fplog,dd,step,cg,d,-1,TRUE,limitd[d],
                                       cg_cm[cg],cm_new,pos_d);
                     }
                     dev[d] = -1;
@@ -4509,6 +4539,26 @@ static int dd_redistribute_cg(FILE *fplog,gmx_large_int_t step,
         for(cg=0; cg<ncg_recv; cg++)
         {
             flag = comm->buf_int[cg*DD_CGIBS+1];
+
+            if (dim >= npbcdim && dd->nc[dim] > 2)
+            {
+                /* No pbc in this dim and more than one domain boundary.
+                 * We to a separate check if a charge did not move too far.
+                 */
+                if (((flag & DD_FLAG_FW(d)) &&
+                     comm->vbuf.v[buf_pos][d] > cell_x1[dim]) ||
+                    ((flag & DD_FLAG_BW(d)) &&
+                     comm->vbuf.v[buf_pos][d] < cell_x0[dim]))
+                {
+                    cg_move_error(fplog,dd,step,cg,d,
+                                  (flag & DD_FLAG_FW(d)) ? 1 : 0,
+                                   FALSE,0,
+                                   comm->vbuf.v[buf_pos],
+                                   comm->vbuf.v[buf_pos],
+                                   comm->vbuf.v[buf_pos][d]);
+                }
+            }
+
             mc = -1;
             if (d < dd->ndim-1)
             {
@@ -5577,7 +5627,7 @@ static gmx_domdec_master_t *init_gmx_domdec_master_t(gmx_domdec_t *dd,
 }
 
 static void split_communicator(FILE *fplog,t_commrec *cr,int dd_node_order,
-                              int reorder)
+                               int reorder)
 {
     gmx_domdec_t *dd;
     gmx_domdec_comm_t *comm;
@@ -5600,18 +5650,22 @@ static void split_communicator(FILE *fplog,t_commrec *cr,int dd_node_order,
         if (bDiv[YY] || bDiv[ZZ])
         {
             comm->bCartesianPP_PME = TRUE;
-            /* We choose the direction that provides the thinnest slab
+            /* If we have 2D PME decomposition, which is always in x+y,
+             * we stack the PME only nodes in z.
+             * Otherwise we choose the direction that provides the thinnest slab
              * of PME only nodes as this will have the least effect
              * on the PP communication.
              * But for the PME communication the opposite might be better.
              */
-            if (bDiv[YY] && (!bDiv[ZZ] || dd->nc[YY] <= dd->nc[ZZ]))
+            if (bDiv[ZZ] && (comm->npmenodes_minor > 1 ||
+                             !bDiv[YY] ||
+                             dd->nc[YY] > dd->nc[ZZ]))
             {
-                comm->cartpmedim = YY;
+                comm->cartpmedim = ZZ;
             }
             else
             {
-                comm->cartpmedim = ZZ;
+                comm->cartpmedim = YY;
             }
             comm->ntot[comm->cartpmedim]
                 += (cr->npmenodes*dd->nc[comm->cartpmedim])/dd->nnodes;
@@ -6093,7 +6147,7 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog,t_commrec *cr,
                                         gmx_mtop_t *mtop,t_inputrec *ir,
                                         matrix box,rvec *x,
                                         gmx_ddbox_t *ddbox,
-                                        int *npme_major)
+                                        int *npme_x,int *npme_y)
 {
     gmx_domdec_t *dd;
     gmx_domdec_comm_t *comm;
@@ -6110,6 +6164,7 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog,t_commrec *cr,
     }
     
     snew(dd,1);
+
     dd->comm = init_dd_comm();
     comm = dd->comm;
     snew(comm->cggl_flag,DIM*2);
@@ -6328,7 +6383,7 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog,t_commrec *cr,
             {
                 fprintf(fplog,"ERROR: The initial cell size (%f) is smaller than the cell size limit (%f)\n",acs,comm->cellsize_limit);
             }
-            gmx_fatal_collective(FARGS,MASTER(cr),
+            gmx_fatal_collective(FARGS,cr,NULL,
                                  "The initial cell size (%f) is smaller than the cell size limit (%f), change options -dd, -rdd or -rcon, see the log file for details",
                                  acs,comm->cellsize_limit);
         }
@@ -6351,7 +6406,7 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog,t_commrec *cr,
                     comm->eDLB!=edlbNO ? " or -dds" : "",
                     bC ? " or your LINCS settings" : "");
 
-            gmx_fatal_collective(FARGS,MASTER(cr),
+            gmx_fatal_collective(FARGS,cr,NULL,
                                  "There is no domain decomposition for %d nodes that is compatible with the given box and a minimum cell size of %g nm\n"
                                  "%s\n"
                                  "Look in the log file for details on the domain decomposition",
@@ -6370,12 +6425,14 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog,t_commrec *cr,
     dd->nnodes = dd->nc[XX]*dd->nc[YY]*dd->nc[ZZ];
     if (cr->nnodes - dd->nnodes != cr->npmenodes)
     {
-        gmx_fatal(FARGS,"The size of the domain decomposition grid (%d) does not match the number of nodes (%d). The total number of nodes is %d",
-                  dd->nnodes,cr->nnodes - cr->npmenodes,cr->nnodes);
+        gmx_fatal_collective(FARGS,cr,NULL,
+                             "The size of the domain decomposition grid (%d) does not match the number of nodes (%d). The total number of nodes is %d",
+                             dd->nnodes,cr->nnodes - cr->npmenodes,cr->nnodes);
     }
     if (cr->npmenodes > dd->nnodes)
     {
-        gmx_fatal(FARGS,"The number of separate PME node (%d) is larger than the number of PP nodes (%d), this is not supported.",cr->npmenodes,dd->nnodes);
+        gmx_fatal_collective(FARGS,cr,NULL,
+                             "The number of separate PME node (%d) is larger than the number of PP nodes (%d), this is not supported.",cr->npmenodes,dd->nnodes);
     }
     if (cr->npmenodes > 0)
     {
@@ -6388,23 +6445,46 @@ gmx_domdec_t *init_domain_decomposition(FILE *fplog,t_commrec *cr,
 
     if (EEL_PME(ir->coulombtype))
     {
-        if (FALSE && dd->nc[XX] > cr->npmenodes && cr->npmenodes % dd->nc[XX] == 0)
+        if (dd->nc[XX] > 1 && dd->nc[YY] > 1 &&
+            comm->npmenodes > dd->nc[XX] && comm->npmenodes % dd->nc[XX] == 0 &&
+            getenv("GMX_PMEONEDD") == NULL)
         {
             comm->npmedecompdim   = 2;
             comm->npmenodes_major = dd->nc[XX];
+            comm->npmenodes_minor = comm->npmenodes/comm->npmenodes_major;
         }
         else
         {
             comm->npmedecompdim   = 1;
             comm->npmenodes_major = comm->npmenodes;
+            comm->npmenodes_minor = comm->npmenodes/comm->npmenodes_major;
+        }
+        if (fplog)
+        {
+            fprintf(fplog,"PME domain decomposition: %d x %d x %d\n",
+                    comm->npmenodes_major,comm->npmenodes_minor,1);
         }
     }
     else
     {
         comm->npmedecompdim   = 0;
         comm->npmenodes_major = 0;
+        comm->npmenodes_minor = 0;
+    }
+    
+    /* Technically we don't need both of these,
+     * but it simplifies code not having to recalculate it.
+     */
+    if (comm->npmedecompdim == 1 && dd->dim[0] == YY)
+    {
+        *npme_x = 1;
+        *npme_y = comm->npmenodes;
+    }
+    else
+    {
+        *npme_x = comm->npmenodes_major;
+        *npme_y = comm->npmenodes_minor;
     }
-    *npme_major = comm->npmenodes_major;
         
     snew(comm->slb_frac,DIM);
     if (comm->eDLB == edlbNO)
@@ -6742,7 +6822,8 @@ void set_dd_parameters(FILE *fplog,gmx_domdec_t *dd,real dlb_scale,
         comm->npmenodes = 0;
         if (dd->pme_nodeid >= 0)
         {
-            gmx_fatal(FARGS,"Can not have separate PME nodes without PME electrostatics");
+            gmx_fatal_collective(FARGS,NULL,dd,
+                                 "Can not have separate PME nodes without PME electrostatics");
         }
     }
     
@@ -6868,7 +6949,15 @@ void set_dd_parameters(FILE *fplog,gmx_domdec_t *dd,real dlb_scale,
         print_dd_settings(fplog,dd,ir,TRUE,dlb_scale,ddbox);
     }
 
-    vol_frac = 1/(real)dd->nnodes + comm_box_frac(dd->nc,comm->cutoff,ddbox);
+    if (ir->ePBC == epbcNONE)
+    {
+        vol_frac = 1;
+    }
+    else
+    {
+        vol_frac =
+            1/(real)dd->nnodes + comm_box_frac(dd->nc,comm->cutoff,ddbox);
+    }
     if (debug)
     {
         fprintf(debug,"Volume fraction for all DD zones: %f\n",vol_frac);
@@ -7735,7 +7824,7 @@ static void ordered_sort(int nsort2,gmx_cgsort_t *sort2,
     int i1,i2,i_new;
     
     /* The new indices are not very ordered, so we qsort them */
-    qsort(sort_new,nsort_new,sizeof(sort_new[0]),comp_cgsort);
+    qsort_threadsafe(sort_new,nsort_new,sizeof(sort_new[0]),comp_cgsort);
     
     /* sort2 is already ordered, so now we can merge the two arrays */
     i1 = 0;
@@ -7851,7 +7940,7 @@ static void dd_sort_state(gmx_domdec_t *dd,int ePBC,
             fprintf(debug,"qsort cgs: %d new home %d\n",dd->ncg_home,ncg_new);
         }
         /* Determine the order of the charge groups using qsort */
-        qsort(cgsort,dd->ncg_home,sizeof(cgsort[0]),comp_cgsort);
+        qsort_threadsafe(cgsort,dd->ncg_home,sizeof(cgsort[0]),comp_cgsort);
     }
     cgsort = sort->sort1;
     
@@ -8045,7 +8134,7 @@ void dd_partition_system(FILE            *fplog,
 {
     gmx_domdec_t *dd;
     gmx_domdec_comm_t *comm;
-    gmx_ddbox_t ddbox;
+    gmx_ddbox_t ddbox={0};
     t_block *cgs_gl;
     gmx_large_int_t step_pcoupl;
     rvec cell_ns_x0,cell_ns_x1;
index 9deef392320cbf714bb8c517b39397ae5d2ecb45..f431f93bb56c279fd03e666d139ce79855fa32f2 100644 (file)
@@ -241,6 +241,13 @@ void dd_scatterv(gmx_domdec_t *dd,
                  int rcount,void *rbuf)
 {
 #ifdef GMX_MPI
+    int dum;
+
+    if (rcount == 0)
+    {
+        /* MPI does not allow NULL pointers */
+        rbuf = &dum;
+    }
     MPI_Scatterv(sbuf,scounts,disps,MPI_BYTE,
                  rbuf,rcount,MPI_BYTE,
                  DDMASTERRANK(dd),dd->mpi_comm_all);
@@ -252,6 +259,13 @@ void dd_gatherv(gmx_domdec_t *dd,
                 int *rcounts,int *disps,void *rbuf)
 {
 #ifdef GMX_MPI
+    int dum;
+
+    if (scount == 0)
+    {
+        /* MPI does not allow NULL pointers */
+        sbuf = &dum;
+    }
     MPI_Gatherv(sbuf,scount,MPI_BYTE,
                 rbuf,rcounts,disps,MPI_BYTE,
                 DDMASTERRANK(dd),dd->mpi_comm_all);
index 69ef8a2a23d4e61ae855ea444ee9255278c16f6e..896d9328208f8b800b2c5a5141378b3b69fe04a0 100644 (file)
@@ -25,7 +25,6 @@
 #include "network.h"
 #include "perf_est.h"
 #include "physics.h"
-#include "pme.h"
 #include "smalloc.h"
 #include "typedefs.h"
 #include "vec.h"
@@ -86,8 +85,7 @@ static bool fits_pp_pme_perf(FILE *fplog,
     }
 
     /* Does this division gives a reasonable PME load? */
-    return (fits_pme_ratio(nnodes,npme,ratio) &&
-                       pme_inconvenient_nnodes(ir->nkx,ir->nky,npme) <= 1);
+    return fits_pme_ratio(nnodes,npme,ratio);
 }
 
 static int guess_npme(FILE *fplog,gmx_mtop_t *mtop,t_inputrec *ir,matrix box,
@@ -193,6 +191,11 @@ static int lcd(int n1,int n2)
   return d;
 }
 
+static int div_up(int n,int f)
+{
+    return (n + f - 1)/f;
+}
+
 real comm_box_frac(ivec dd_nc,real cutoff,gmx_ddbox_t *ddbox)
 {
     int  i,j,k,npp;
@@ -229,8 +232,6 @@ real comm_box_frac(ivec dd_nc,real cutoff,gmx_ddbox_t *ddbox)
             }
         }
     }
-    /* Normalize by the number of PP nodes */
-    comm_vol /= npp;
    
     return comm_vol;
 }
@@ -242,13 +243,15 @@ static bool inhomogeneous_z(const t_inputrec *ir)
 }
 
 static float comm_cost_est(gmx_domdec_t *dd,real limit,real cutoff,
-                           matrix box,gmx_ddbox_t *ddbox,t_inputrec *ir,
+                           matrix box,gmx_ddbox_t *ddbox,
+                           int natoms,t_inputrec *ir,
                            float pbcdxr,
-                           int npme,ivec nc)
+                           int npme_tot,ivec nc)
 {
-    int  i,j,k,npp;
+    ivec npme={1,1,1};
+    int  i,j,k,nk,overlap;
     rvec bt;
-    float comm_vol,comm_vol_pme,cost_pbcdx;
+    float comm_vol,comm_vol_xf,comm_pme,cost_pbcdx;
     /* This is the cost of a pbc_dx call relative to the cost
      * of communicating the coordinate and force of an atom.
      * This will be machine dependent.
@@ -285,10 +288,8 @@ static float comm_cost_est(gmx_domdec_t *dd,real limit,real cutoff,
         }
     }
     
-    npp = 1;
     for(i=0; i<DIM; i++)
     {
-        npp *= nc[i];
         bt[i] = ddbox->box_size[i]*ddbox->skew_fac[i];
         
         /* Without PBC there are no cell size limits with 2 cells */
@@ -297,6 +298,13 @@ static float comm_cost_est(gmx_domdec_t *dd,real limit,real cutoff,
             return -1;
         }
     }
+
+    if (npme_tot > 1)
+    {
+        /* Will we use 1D or 2D PME decomposition? */
+        npme[XX] = (npme_tot % nc[XX] == 0) ? nc[XX] : npme_tot;
+        npme[YY] = npme_tot/npme[XX];
+    }
     
     /* When two dimensions are (nearly) equal, use more cells
      * for the smallest index, so the decomposition does not
@@ -304,35 +312,64 @@ static float comm_cost_est(gmx_domdec_t *dd,real limit,real cutoff,
      */
     for(i=0; i<DIM; i++)
     {
-        if (npme == 0 || i != XX)
+        for(j=i+1; j<DIM; j++)
         {
-            for(j=i+1; j<DIM; j++)
+            /* Check if dimension i and j are equivalent,
+             * both for PME and for the box size.
+             * The XX/YY check is a bit compact. If nc[YY]==npme[YY]
+             * this means the swapped nc has nc[XX]=npme[XX],
+             * and we can also swap X and Y for PME.
+             */
+            if (!((i == XX && j == YY && npme[YY] > 1 && nc[YY] != npme[YY]) ||
+                  (i == YY && j == ZZ && npme[YY] > 1)) &&
+                fabs(bt[j] - bt[i]) < 0.01*bt[i] && nc[j] > nc[i])
             {
-                if (fabs(bt[j] - bt[i]) < 0.01*bt[i] && nc[j] > nc[i])
-                {
-                    return -1;
-                }
+                return -1;
             }
         }
     }
+
+    /* This function determines only half of the communication cost.
+     * All PP, PME and PP-PME communication is symmetric
+     * and the "back"-communication cost is identical to the forward cost.
+     */
     
     comm_vol = comm_box_frac(nc,cutoff,ddbox);
 
-    /* Determine the largest volume that a PME only needs to communicate */
-    comm_vol_pme = 0;
-    if ((npme > 0) && (nc[XX] % npme != 0))
+    comm_pme = 0;
+    for(i=0; i<2; i++)
     {
-        if (nc[XX] > npme)
+        /* Determine the largest volume for PME x/f redistribution */
+        if (nc[i] % npme[i] != 0)
         {
-            comm_vol_pme = (npme==2 ? 1.0/3.0 : 0.5);
+            if (nc[i] > npme[i])
+            {
+                comm_vol_xf = (npme[i]==2 ? 1.0/3.0 : 0.5);
+            }
+            else
+            {
+                comm_vol_xf = 1.0 - lcd(nc[i],npme[i])/(double)npme[i];
+            }
+            comm_pme += 3*natoms*comm_vol_xf;
         }
-        else
+
+        /* Grid overlap communication */
+        if (npme[i] > 1)
         {
-            comm_vol_pme = 1.0 - lcd(nc[XX],npme)/(double)npme;
+            nk = (i==0 ? ir->nkx : ir->nky);
+            overlap = (nk % npme[i] == 0 ? ir->pme_order-1 : ir->pme_order);
+            comm_pme += npme[i]*overlap*ir->nkx*ir->nky*ir->nkz/nk;
         }
-        /* Normalize by the number of PME only nodes */
-        comm_vol_pme /= npme;
     }
+
+    /* PME FFT communication volume.
+     * This only takes the communication into account and not imbalance
+     * in the calculation. But the imbalance in communication and calculation
+     * are similar and therefore these formulas also prefer load balance
+     * in the FFT and pme_solve calculation.
+     */
+    comm_pme += (npme[YY] - 1)*npme[YY]*div_up(ir->nky,npme[YY])*div_up(ir->nkz,npme[YY])*ir->nkx;
+    comm_pme += (npme[XX] - 1)*npme[XX]*div_up(ir->nkx,npme[XX])*div_up(ir->nky,npme[XX])*ir->nkz;
     
     /* Add cost of pbc_dx for bondeds */
     cost_pbcdx = 0;
@@ -341,29 +378,30 @@ static float comm_cost_est(gmx_domdec_t *dd,real limit,real cutoff,
         if ((ddbox->tric_dir[XX] && nc[XX] == 1) ||
             (ddbox->tric_dir[YY] && nc[YY] == 1))
         {
-            cost_pbcdx = pbcdxr*pbcdx_tric_fac/npp;
+            cost_pbcdx = pbcdxr*pbcdx_tric_fac;
         }
         else
         {
-            cost_pbcdx = pbcdxr*pbcdx_rect_fac/npp;
+            cost_pbcdx = pbcdxr*pbcdx_rect_fac;
         }
     }
     
     if (debug)
     {
         fprintf(debug,
-                "nc %2d %2d %2d vol pp %6.4f pbcdx %6.4f pme %6.4f tot %6.4f\n",
-                nc[XX],nc[YY],nc[ZZ],
-                comm_vol,cost_pbcdx,comm_vol_pme,
-                comm_vol + cost_pbcdx + comm_vol_pme);
+                "nc %2d %2d %2d %2d %2d vol pp %6.4f pbcdx %6.4f pme %9.3e tot %9.3e\n",
+                nc[XX],nc[YY],nc[ZZ],npme[XX],npme[YY],
+                comm_vol,cost_pbcdx,comm_pme,
+                3*natoms*(comm_vol + cost_pbcdx) + comm_pme);
     }
     
-    return comm_vol + cost_pbcdx + comm_vol_pme;
+    return 3*natoms*(comm_vol + cost_pbcdx) + comm_pme;
 }
 
 static void assign_factors(gmx_domdec_t *dd,
                            real limit,real cutoff,
-                           matrix box,gmx_ddbox_t *ddbox,t_inputrec *ir,
+                           matrix box,gmx_ddbox_t *ddbox,
+                           int natoms,t_inputrec *ir,
                            float pbcdxr,int npme,
                            int ndiv,int *div,int *mdiv,ivec ir_try,ivec opt)
 {
@@ -372,9 +410,11 @@ static void assign_factors(gmx_domdec_t *dd,
     
     if (ndiv == 0)
     {
-        ce = comm_cost_est(dd,limit,cutoff,box,ddbox,ir,pbcdxr,npme,ir_try);
+        ce = comm_cost_est(dd,limit,cutoff,box,ddbox,
+                           natoms,ir,pbcdxr,npme,ir_try);
         if (ce >= 0 && (opt[XX] == 0 ||
-                        ce < comm_cost_est(dd,limit,cutoff,box,ddbox,ir,pbcdxr,
+                        ce < comm_cost_est(dd,limit,cutoff,box,ddbox,
+                                           natoms,ir,pbcdxr,
                                            npme,opt)))
         {
             copy_ivec(ir_try,opt);
@@ -401,7 +441,7 @@ static void assign_factors(gmx_domdec_t *dd,
             }
             
             /* recurse */
-            assign_factors(dd,limit,cutoff,box,ddbox,ir,pbcdxr,npme,
+            assign_factors(dd,limit,cutoff,box,ddbox,natoms,ir,pbcdxr,npme,
                            ndiv-1,div+1,mdiv+1,ir_try,opt);
             
             for(i=0; i<mdiv[0]-x-y; i++)
@@ -527,7 +567,7 @@ static real optimize_ncells(FILE *fplog,
     itry[YY] = 1;
     itry[ZZ] = 1;
     clear_ivec(nc);
-    assign_factors(dd,limit,cutoff,box,ddbox,ir,pbcdxr,
+    assign_factors(dd,limit,cutoff,box,ddbox,mtop->natoms,ir,pbcdxr,
                    npme,ndiv,div,mdiv,itry,nc);
     
     sfree(div);
@@ -560,8 +600,7 @@ real dd_choose_grid(FILE *fplog,
             }
             else
             {
-                if (cr->nnodes < 12 &&
-                    pme_inconvenient_nnodes(ir->nkx,ir->nky,cr->nnodes) == 0)
+                if (cr->nnodes <= 10)
                 {
                     cr->npmenodes = 0;
                 }
index 95e34abb80517e056d5ba84b2372d90b4416eaed..d3f974d067c91bee3a88ae4fc425b11981b37333 100644 (file)
@@ -728,9 +728,9 @@ static void add_posres(int mol,int a_mol,gmx_molblock_t *molb,
      * so it's index is the current number of position restraints.
      */
     n = idef->il[F_POSRES].nr/2;
-    if (n >= idef->iparams_posres_nalloc)
+    if (n+1 > idef->iparams_posres_nalloc)
     {
-        idef->iparams_posres_nalloc = over_alloc_dd(n);
+        idef->iparams_posres_nalloc = over_alloc_dd(n+1);
         srenew(idef->iparams_posres,idef->iparams_posres_nalloc);
     }
     ip = &idef->iparams_posres[n];
index 4b7f5902a37777ec5b64b3ba56dc71c508f21174..d0ea82f1f6dd25820889285f471d7188f6f8d0d5 100644 (file)
@@ -177,6 +177,7 @@ typedef struct gmx_edsam
     FILE          *edo;           /* output file pointer                  */
     t_edpar       *edpar;
     bool          bFirst;
+    bool          bStartFromCpt;
 } t_gmx_edsam;
 
 
@@ -288,8 +289,8 @@ static void project_to_eigvectors(rvec       *x,    /* The positions to project
 static void project(rvec      *x,     /* positions to project */ 
                     t_edpar   *edi)   /* edi data set */
 {
-    /* It is not more work to subtract the average position in every s
-     * ubroutine again, because these routines are rarely used simultanely */
+    /* It is not more work to subtract the average position in every
+     * subroutine again, because these routines are rarely used simultanely */
     project_to_eigvectors(x, &edi->vecs.mon   , edi);
     project_to_eigvectors(x, &edi->vecs.linfix, edi);
     project_to_eigvectors(x, &edi->vecs.linacc, edi);
@@ -678,7 +679,6 @@ static void write_edo_flood(t_edpar *edi, FILE *fp, int step)
         fprintf(fp," %f",edi->flood.vecs.fproj[i]);
     
     fprintf(fp,"\n");
-    fflush(fp);
 }
 
 
@@ -748,7 +748,7 @@ static void flood_blowup(t_edpar *edi, rvec *forces_cart)
      for every atom we add all the contributions to this atom from all the different eigenvectors.
 
      NOTE: one could add directly to the forcefield forces, would mean we wouldn't have to clear the 
-     field forces_cart prior the computation, but momentarily we want to compute the forces seperately 
+     field forces_cart prior the computation, but momentarily we want to compute the forces separately 
      to have them accessible for diagnostics
      */
     int  j,eig;
@@ -963,7 +963,7 @@ static void get_flood_energies(t_edpar *edi, real Vfl[],int nnames)
 #endif
 
 
-gmx_edsam_t ed_open(int nfile,const t_filenm fnm[],t_commrec *cr)
+gmx_edsam_t ed_open(int nfile,const t_filenm fnm[],unsigned long Flags,t_commrec *cr)
 {   
     gmx_edsam_t ed;
     
@@ -981,7 +981,8 @@ gmx_edsam_t ed_open(int nfile,const t_filenm fnm[],t_commrec *cr)
         /* The master opens the .edo output file */
         fprintf(stderr,"ED sampling will be performed!\n");        
         ed->edonam = ftp2fn(efEDO,nfile,fnm);
-        ed->edo    = gmx_fio_fopen(ed->edonam,"w");
+        ed->edo    = gmx_fio_fopen(ed->edonam,(Flags & MD_APPENDFILES)? "a+" : "w+");
+        ed->bStartFromCpt = Flags & MD_STARTFROMCPT;
     }
     return ed;
 }
@@ -1861,7 +1862,7 @@ static void do_radcon(rvec *xcoll, t_edpar *edi, t_commrec *cr)
 }
 
 
-static void ed_apply_constraints(rvec *xcoll, t_edpar *edi, int step, t_commrec *cr)
+static void ed_apply_constraints(rvec *xcoll, t_edpar *edi, gmx_large_int_t step, t_commrec *cr)
 {
     int i;
 
@@ -2131,7 +2132,7 @@ void init_edsam(gmx_mtop_t  *mtop,   /* global topology                    */
             rad_project(edi, xstart, &edi->vecs.linfix, cr);
 
             /* Output to file, set the step to -1 so that write_edo knows it was called from init_edsam */
-            if (ed->edo)
+            if (ed->edo && !(ed->bStartFromCpt))
                 write_edo(nr_edi, edi, ed, -1, 0);
 
             /* Prepare for the next edi data set: */
@@ -2235,7 +2236,7 @@ void init_edsam(gmx_mtop_t  *mtop,   /* global topology                    */
 
 
 void do_edsam(t_inputrec  *ir,
-              int         step,
+              gmx_large_int_t step,
               t_mdatoms   *md,
               t_commrec   *cr,
               rvec        xs[],   /* The local current positions on this processor */
@@ -2333,7 +2334,7 @@ void do_edsam(t_inputrec  *ir,
             }
 
             /* update radsam references, when required */
-            if (do_per_step(step,edi->maxedsteps) && step > edi->presteps)
+            if (do_per_step(step,edi->maxedsteps) && step >= edi->presteps)
             {
                 project(buf->xcoll, edi);
                 rad_project(edi, buf->xcoll, &edi->vecs.radacc, cr);
@@ -2342,7 +2343,7 @@ void do_edsam(t_inputrec  *ir,
             }
 
             /* update radacc references, when required */
-            if (do_per_step(step,iupdate) && step > edi->presteps)
+            if (do_per_step(step,iupdate) && step >= edi->presteps)
             {
                 edi->vecs.radacc.radius = calc_radius(&edi->vecs.radacc);
                 if (edi->vecs.radacc.radius - buf->oldrad < edi->slope)
@@ -2355,8 +2356,12 @@ void do_edsam(t_inputrec  *ir,
             }
 
             /* apply the constraints */
-            if (step > edi->presteps && ed_constraints(ed->eEDtype, edi))
-                ed_apply_constraints(buf->xcoll, edi, step, cr);
+            if (step >= edi->presteps && ed_constraints(ed->eEDtype, edi))
+            {
+                /* ED constraints should be applied already in the first MD step
+                 * (which is step 0), therfore we pass step+1 to the routine */
+                ed_apply_constraints(buf->xcoll, edi, step+1 - ir->init_step, cr);
+            }
 
             /* write to edo, when required */
             if (do_per_step(step,edi->outfrq))
index a00885fe6d4a8c5fe7cdc2e8f7ec38521976ab5a..192a9d93573114982c352f8f01cc891c266f7858 100644 (file)
@@ -43,7 +43,6 @@
 #include "gmxcomplex.h"
 #include "smalloc.h"
 #include "futil.h"
-#include "fftgrid.h"
 #include "gmx_fatal.h"
 #include "physics.h"
 #include "coulomb.h"
@@ -131,7 +130,7 @@ real do_ewald(FILE *log,       bool bVerbose,
               ewald_tab_t et)
 {
   real factor=-1.0/(4*ewaldcoeff*ewaldcoeff);
-  real scaleRecip =4.0*M_PI/(box[XX]*box[YY]*box[ZZ])*ONE_4PI_EPS0/ir->epsilon_r; // 1/(Vol*e0) //
+  real scaleRecip =4.0*M_PI/(box[XX]*box[YY]*box[ZZ])*ONE_4PI_EPS0/ir->epsilon_r; /* 1/(Vol*e0) */
   real *charge,energy_AB[2],energy;
   rvec lll;
   int  lowiy,lowiz,ix,iy,iz,n,q;
diff --git a/src/mdlib/fft5d.c b/src/mdlib/fft5d.c
new file mode 100644 (file)
index 0000000..3734625
--- /dev/null
@@ -0,0 +1,975 @@
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef NOGMX
+#define GMX_PARALLEL_ENV_INITIALIZED 1
+#else 
+#include "main.h"
+#define GMX_PARALLEL_ENV_INITIALIZED gmx_parallel_env_initialized()
+#endif
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+#ifdef FFT5D_THREADS
+#include <omp.h>
+#endif
+
+#include "fft5d.h"
+#include <float.h>
+#include <math.h>
+#include <assert.h>
+
+#ifndef __FLT_EPSILON__
+#define __FLT_EPSILON__ FLT_EPSILON
+#define __DBL_EPSILON__ DBL_EPSILON
+#endif
+
+#ifdef NOGMX
+FILE* debug=0;
+#endif
+
+#include "gmx_fatal.h"
+
+
+#ifdef GMX_FFT_FFTW3 
+#ifdef GMX_THREADS
+/* none of the fftw3 calls, except execute(), are thread-safe, so 
+   we need to serialize them with this mutex. */
+static tMPI_Thread_mutex_t big_fftw_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
+
+#define FFTW_LOCK tMPI_Thread_mutex_lock(&big_fftw_mutex);
+#define FFTW_UNLOCK tMPI_Thread_mutex_unlock(&big_fftw_mutex);
+#else /* GMX_THREADS */
+#define FFTW_LOCK 
+#define FFTW_UNLOCK 
+#endif /* GMX_THREADS */
+#endif /* GMX_FFT_FFTW3 */
+
+static double fft5d_fmax(double a, double b){
+       return (a>b)?a:b;
+}
+
+/* largest factor smaller than sqrt */
+static int lfactor(int z) {  
+       int i;
+       for (i=sqrt(z);;i--)
+               if (z%i==0) return i;
+}
+
+/* largest factor */
+static int l2factor(int z) {  
+       int i;
+       if (z==1) return 1;
+       for (i=z/2;;i--)
+               if (z%i==0) return i;
+}
+
+/* largest prime factor: WARNING: slow recursion, only use for small numbers */
+static int lpfactor(int z) {
+       int f = l2factor(z);
+       if (f==1) return z;
+       return fft5d_fmax(lpfactor(f),lpfactor(z/f));
+}
+
+#ifndef GMX_MPI
+#ifdef HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+double MPI_Wtime() {
+    struct timeval tv;
+    gettimeofday(&tv,0);
+    return tv.tv_sec+tv.tv_usec*1e-6;
+}
+#else
+double MPI_Wtime() {
+    return 0.0;
+}
+#endif
+#endif
+
+static int vmax(int* a, int s) {
+    int i,max=0;
+    for (i=0;i<s;i++) 
+    {
+        if (a[i]>max) max=a[i];
+    }
+    return max;
+} 
+
+/*
+copied here from fftgrid, because:
+1. function there not publically available
+2. not sure whether we keep fftgrid
+3. less dependencies for fft5d
+
+Only used for non-fftw case
+*/
+static void *
+gmx_calloc_aligned(size_t size)
+{
+    void *p0,*p;
+    
+    /*We initialize by zero for Valgrind
+      For non-divisible case we communicate more than the data.
+      If we don't initialize the data we communicate uninitialized data*/
+    p0 = calloc(size+32,1);  
+    
+    if(p0 == NULL)
+    {
+        gmx_fatal(FARGS,"Failed to allocated %u bytes of aligned memory.",size+32);
+    }
+    
+    p = (void *) (((size_t) p0 + 32) & (~((size_t) 31)));
+    
+    /* Yeah, yeah, we cannot free this pointer, but who cares... */
+    return p;
+}
+
+
+/* NxMxK the size of the data
+ * comm communicator to use for fft5d
+ * P0 number of processor in 1st axes (can be null for automatic)
+ * lin is allocated by fft5d because size of array is only known after planning phase */
+fft5d_plan fft5d_plan_3d(int NG, int MG, int KG, MPI_Comm comm[2], int flags, t_complex** rlin, t_complex** rlout)
+{
+
+    int P[2],bMaster,prank[2],i;
+    int rNG,rMG,rKG;
+    int *N0=0, *N1=0, *M0=0, *M1=0, *K0=0, *K1=0, *oN0=0, *oN1=0, *oM0=0, *oM1=0, *oK0=0, *oK1=0;
+    int N[3],M[3],K[3],pN[3],pM[3],pK[3],oM[3],oK[3],*iNin[3]={0},*oNin[3]={0},*iNout[3]={0},*oNout[3]={0};
+    int C[3],rC[3],nP[2];
+    int lsize;
+    t_complex *lin=0,*lout=0;
+    fft5d_plan plan;
+    int s;
+
+    /* comm, prank and P are in the order of the decomposition (plan->cart is in the order of transposes) */
+#ifdef GMX_MPI
+    if (GMX_PARALLEL_ENV_INITIALIZED && comm[0] != 0)
+    {
+        MPI_Comm_size(comm[0],&P[0]);
+        MPI_Comm_rank(comm[0],&prank[0]);
+    }
+    else
+#endif
+    {
+        P[0] = 1;
+        prank[0] = 0;
+    }
+#ifdef GMX_MPI
+    if (GMX_PARALLEL_ENV_INITIALIZED && comm[1] != 0)
+    {
+        MPI_Comm_size(comm[1],&P[1]);
+        MPI_Comm_rank(comm[1],&prank[1]);
+    }
+    else
+#endif
+    {
+        P[1] = 1;
+        prank[1] = 0;
+    }
+   
+    bMaster=(prank[0]==0&&prank[1]==0);
+   
+    
+    if (debug)
+    {
+        fprintf(debug,"FFT5D: Using %dx%d processor grid, rank %d,%d\n",
+                P[0],P[1],prank[0],prank[1]);
+    }
+    
+    if (bMaster) {
+        if (debug) 
+            fprintf(debug,"FFT5D: N: %d, M: %d, K: %d, P: %dx%d, real2complex: %d, backward: %d, order yz: %d, debug %d\n",
+                NG,MG,KG,P[0],P[1],(flags&FFT5D_REALCOMPLEX)>0,(flags&FFT5D_BACKWARD)>0,(flags&FFT5D_ORDER_YZ)>0,(flags&FFT5D_DEBUG)>0);
+        /* The check below is not correct, one prime factor 11 or 13 is ok.
+        if (fft5d_fmax(fft5d_fmax(lpfactor(NG),lpfactor(MG)),lpfactor(KG))>7) {
+            printf("WARNING: FFT very slow with prime factors larger 7\n");
+            printf("Change FFT size or in case you cannot change it look at\n");
+            printf("http://www.fftw.org/fftw3_doc/Generating-your-own-code.html\n");
+        }
+        */
+    }
+    
+    if (NG==0 || MG==0 || KG==0) {
+        if (bMaster) printf("FFT5D: FATAL: Datasize cannot be zero in any dimension\n");
+        return 0;
+    }
+
+    rNG=NG;rMG=MG;rKG=KG;
+    
+    if (flags&FFT5D_REALCOMPLEX) {
+        if (!(flags&FFT5D_BACKWARD)) NG = NG/2+1;
+        else {
+            if (!(flags&FFT5D_ORDER_YZ)) MG=MG/2+1;
+            else KG=KG/2+1;
+        }
+    }
+    
+    
+    /*for transpose we need to know the size for each processor not only our own size*/
+
+    N0 = (int*)malloc(P[0]*sizeof(int)); N1 = (int*)malloc(P[1]*sizeof(int)); 
+    M0 = (int*)malloc(P[0]*sizeof(int)); M1 = (int*)malloc(P[1]*sizeof(int));
+    K0 = (int*)malloc(P[0]*sizeof(int)); K1 = (int*)malloc(P[1]*sizeof(int));
+    oN0 = (int*)malloc(P[0]*sizeof(int));oN1 = (int*)malloc(P[1]*sizeof(int));
+    oM0 = (int*)malloc(P[0]*sizeof(int));oM1 = (int*)malloc(P[1]*sizeof(int));
+    oK0 = (int*)malloc(P[0]*sizeof(int));oK1 = (int*)malloc(P[1]*sizeof(int));
+    
+    for (i=0;i<P[0];i++) 
+    {
+        #define EVENDIST
+        #ifndef EVENDIST
+        oN0[i]=i*ceil((double)NG/P[0]);
+        oM0[i]=i*ceil((double)MG/P[0]);
+        oK0[i]=i*ceil((double)KG/P[0]);
+        #else
+        oN0[i]=(NG*i)/P[0];
+        oM0[i]=(MG*i)/P[0];
+        oK0[i]=(KG*i)/P[0];
+        #endif
+    }
+    for (i=0;i<P[1];i++) 
+    {
+        #ifndef EVENDIST
+        oN1[i]=i*ceil((double)NG/P[1]); 
+        oM1[i]=i*ceil((double)MG/P[1]); 
+        oK1[i]=i*ceil((double)KG/P[1]); 
+        #else
+        oN1[i]=(NG*i)/P[1]; 
+        oM1[i]=(MG*i)/P[1]; 
+        oK1[i]=(KG*i)/P[1]; 
+        #endif
+    }
+    for (i=0;i<P[0]-1;i++) 
+    {
+        N0[i]=oN0[i+1]-oN0[i];
+        M0[i]=oM0[i+1]-oM0[i];
+        K0[i]=oK0[i+1]-oK0[i];
+    }
+    N0[P[0]-1]=NG-oN0[P[0]-1];
+    M0[P[0]-1]=MG-oM0[P[0]-1];
+    K0[P[0]-1]=KG-oK0[P[0]-1];
+    for (i=0;i<P[1]-1;i++) 
+    {
+        N1[i]=oN1[i+1]-oN1[i];
+        M1[i]=oM1[i+1]-oM1[i];
+        K1[i]=oK1[i+1]-oK1[i];
+    }
+    N1[P[1]-1]=NG-oN1[P[1]-1];
+    M1[P[1]-1]=MG-oM1[P[1]-1];
+    K1[P[1]-1]=KG-oK1[P[1]-1];
+
+    /* for step 1-3 the local N,M,K sizes of the transposed system
+       C: contiguous dimension, and nP: number of processor in subcommunicator 
+       for that step */
+    
+    
+    pM[0] = M0[prank[0]];
+    oM[0] = oM0[prank[0]];
+    pK[0] = K1[prank[1]];
+    oK[0] = oK1[prank[1]];
+    C[0] = NG;
+    rC[0] = rNG;
+    if (!(flags&FFT5D_ORDER_YZ)) {
+        N[0] = vmax(N1,P[1]);
+        M[0] = M0[prank[0]];
+        K[0] = vmax(K1,P[1]);
+        pN[0] = N1[prank[1]];
+        iNout[0] = N1;
+        oNout[0] = oN1;
+        nP[0] = P[1];
+        C[1] = KG;
+        rC[1] =rKG;
+        N[1] = vmax(K0,P[0]);
+        pN[1] = K0[prank[0]];
+        iNin[1] = K1;
+        oNin[1] = oK1; 
+        iNout[1] = K0;
+        oNout[1] = oK0;
+        M[1] = vmax(M0,P[0]);
+        pM[1] = M0[prank[0]];
+        oM[1] = oM0[prank[0]];
+        K[1] = N1[prank[1]];
+        pK[1] = N1[prank[1]];
+        oK[1] = oN1[prank[1]];
+        nP[1] = P[0];
+        C[2] = MG;
+        rC[2] = rMG;
+        iNin[2] = M0;
+        oNin[2] = oM0;
+        M[2] = vmax(K0,P[0]);
+        pM[2] = K0[prank[0]];
+        oM[2] = oK0[prank[0]];
+        K[2] = vmax(N1,P[1]);
+        pK[2] = N1[prank[1]];
+        oK[2] = oN1[prank[1]];
+        free(N0); free(oN0); /*these are not used for this order*/
+        free(M1); free(oM1); /*the rest is freed in destroy*/
+    } else {
+        N[0] = vmax(N0,P[0]);
+        M[0] = vmax(M0,P[0]);
+        K[0] = K1[prank[1]];
+        pN[0] = N0[prank[0]];
+        iNout[0] = N0;
+        oNout[0] = oN0;
+        nP[0] = P[0];
+        C[1] = MG;
+        rC[1] =rMG;
+        N[1] = vmax(M1,P[1]);
+        pN[1] = M1[prank[1]];
+        iNin[1] = M0;
+        oNin[1] = oM0;
+        iNout[1] = M1;
+        oNout[1] = oM1;
+        M[1] = N0[prank[0]];
+        pM[1] = N0[prank[0]];
+        oM[1] = oN0[prank[0]];
+        K[1] = vmax(K1,P[1]);
+        pK[1] = K1[prank[1]];
+        oK[1] = oK1[prank[1]];
+        nP[1] = P[1];
+        C[2] = KG;
+        rC[2] = rKG;
+        iNin[2] = K1;
+        oNin[2] = oK1;
+        M[2] = vmax(N0,P[0]);
+        pM[2] = N0[prank[0]];
+        oM[2] = oN0[prank[0]];
+        K[2] = vmax(M1,P[1]);
+        pK[2] = M1[prank[1]];
+        oK[2] = oM1[prank[1]];
+        free(N1); free(oN1); /*these are not used for this order*/
+        free(K0); free(oK0); /*the rest is freed in destroy*/
+    }
+    
+    /*
+      Difference between x-y-z regarding 2d decomposition is whether they are 
+      distributed along axis 1, 2 or both 
+    */
+    
+    /* int lsize = fmax(N[0]*M[0]*K[0]*nP[0],N[1]*M[1]*K[1]*nP[1]); */
+    lsize = fft5d_fmax(N[0]*M[0]*K[0]*nP[0],fft5d_fmax(N[1]*M[1]*K[1]*nP[1],C[2]*M[2]*K[2])); 
+    /* int lsize = fmax(C[0]*M[0]*K[0],fmax(C[1]*M[1]*K[1],C[2]*M[2]*K[2])); */
+    if (!(flags&FFT5D_NOMALLOC)) { 
+        lin = (t_complex*)gmx_calloc_aligned(sizeof(t_complex) * lsize);   
+        lout = (t_complex*)gmx_calloc_aligned(sizeof(t_complex) * lsize); 
+    } else {
+        lin = *rlin;
+        lout = *rlout;
+    }
+
+    plan = (fft5d_plan)calloc(1,sizeof(struct fft5d_plan_t));
+
+    
+#ifdef FFT5D_THREADS   /*requires fftw with openmp and openmp*/
+    FFTW(init_threads)();
+    int nthreads;
+    #pragma omp parallel
+    {
+        #pragma omp master
+        {
+            nthreads = omp_get_num_threads();
+        }
+    }
+    printf("Running on %d threads\n",nthreads);        
+    FFTW(plan_with_nthreads)(nthreads);
+
+#endif    
+
+#ifdef GMX_FFT_FFTW3  /*if not FFTW - then we don't do a 3d plan but insead only 1D plans */
+    if ((!(flags&FFT5D_INPLACE)) && (!(P[0]>1 || P[1]>1))) {  /*don't do 3d plan in parallel or if in_place requested */  
+            int fftwflags=FFTW_DESTROY_INPUT;
+            fftw_iodim dims[3];
+            int inNG=NG,outMG=MG,outKG=KG;
+
+            FFTW_LOCK;
+            if (!(flags&FFT5D_NOMEASURE)) fftwflags|=FFTW_MEASURE;
+            if (flags&FFT5D_REALCOMPLEX) {
+                if (!(flags&FFT5D_BACKWARD)) {  /*input pointer is not complex*/
+                    inNG*=2; 
+                } else {                        /*output pointer is not complex*/
+                    if (!(flags&FFT5D_ORDER_YZ)) outMG*=2;
+                    else outKG*=2;
+                }
+            }
+
+            if (!(flags&FFT5D_BACKWARD)) {
+                dims[0].n  = KG;
+                dims[1].n  = MG;
+                dims[2].n  = rNG;
+                
+                dims[0].is = inNG*MG;     /*N M K*/
+                dims[1].is = inNG;
+                dims[2].is = 1;
+                if (!(flags&FFT5D_ORDER_YZ)) {
+                    dims[0].os = MG;       /*M K N*/
+                    dims[1].os = 1;
+                    dims[2].os = MG*KG;
+                } else  {
+                    dims[0].os = 1;       /*K N M*/
+                    dims[1].os = KG*NG;
+                    dims[2].os = KG;
+                }
+            } else {
+                if (!(flags&FFT5D_ORDER_YZ)) {
+                    dims[0].n  = NG;   
+                    dims[1].n  = KG;   
+                    dims[2].n  = rMG;  
+                    
+                    dims[0].is = 1;     
+                    dims[1].is = NG*MG;
+                    dims[2].is = NG;
+
+                    dims[0].os = outMG*KG;       
+                    dims[1].os = outMG;
+                    dims[2].os = 1;                  
+                } else {
+                    dims[0].n  = MG;
+                    dims[1].n  = NG;
+                    dims[2].n  = rKG;
+                    
+                    dims[0].is = NG;     
+                    dims[1].is = 1;
+                    dims[2].is = NG*MG;
+
+                    dims[0].os = outKG*NG;       
+                    dims[1].os = outKG;
+                    dims[2].os = 1;                  
+                }           
+            }
+            if ((flags&FFT5D_REALCOMPLEX) && !(flags&FFT5D_BACKWARD)) {
+                plan->p3d = FFTW(plan_guru_dft_r2c)(/*rank*/ 3, dims,
+                                     /*howmany*/ 0, /*howmany_dims*/0 ,
+                                     (real*)lin, (FFTW(complex) *)lout,
+                                     /*flags*/ fftwflags);              
+            } else if ((flags&FFT5D_REALCOMPLEX) && (flags&FFT5D_BACKWARD)) {
+                plan->p3d = FFTW(plan_guru_dft_c2r)(/*rank*/ 3, dims,
+                                     /*howmany*/ 0, /*howmany_dims*/0 ,
+                                     (FFTW(complex) *)lin, (real*)lout,
+                                     /*flags*/ fftwflags);              
+            } else {
+                plan->p3d = FFTW(plan_guru_dft)(/*rank*/ 3, dims,
+                                     /*howmany*/ 0, /*howmany_dims*/0 ,
+                                     (FFTW(complex) *)lin, (FFTW(complex) *)lout,
+                                     /*sign*/ (flags&FFT5D_BACKWARD)?1:-1, /*flags*/ fftwflags);
+            }
+            FFTW_UNLOCK;
+    }
+    if (!plan->p3d) {  /* for decomposition and if 3d plan did not work */
+#endif /* GMX_FFT_FFTW3 */
+        for (s=0;s<3;s++) {
+            if (debug)
+            {
+                fprintf(debug,"FFT5D: Plan s %d rC %d M %d pK %d C %d lsize %d\n",
+                        s,rC[s],M[s],pK[s],C[s],lsize);
+            }
+            if ((flags&FFT5D_REALCOMPLEX) && ((!(flags&FFT5D_BACKWARD) && s==0) || ((flags&FFT5D_BACKWARD) && s==2))) {
+                gmx_fft_init_many_1d_real( &plan->p1d[s], rC[s], pM[s]*pK[s], (flags&FFT5D_NOMEASURE)?GMX_FFT_FLAG_CONSERVATIVE:0 );
+            } else {
+                gmx_fft_init_many_1d     ( &plan->p1d[s],  C[s], pM[s]*pK[s], (flags&FFT5D_NOMEASURE)?GMX_FFT_FLAG_CONSERVATIVE:0 );
+            }
+        }
+#ifdef GMX_FFT_FFTW3 
+    }
+#endif
+    if ((flags&FFT5D_ORDER_YZ)) { /*plan->cart is in the order of transposes */
+        plan->cart[0]=comm[0]; plan->cart[1]=comm[1];
+    } else {
+        plan->cart[1]=comm[0]; plan->cart[0]=comm[1];
+    }
+#ifdef FFT5D_MPI_TRANSPOSE
+    FFTW_LOCK
+    for (s=0;s<2;s++) {
+        if ((s==0 && !(flags&FFT5D_ORDER_YZ)) || (s==1 && (flags&FFT5D_ORDER_YZ))) 
+            plan->mpip[s] = FFTW(mpi_plan_many_transpose)(nP[s], nP[s], N[s]*K[s]*pM[s]*2, 1, 1, (real*)lin, (real*)lout, plan->cart[s], FFTW_PATIENT);
+        else
+            plan->mpip[s] = FFTW(mpi_plan_many_transpose)(nP[s], nP[s], N[s]*pK[s]*M[s]*2, 1, 1, (real*)lin, (real*)lout, plan->cart[s], FFTW_PATIENT);
+    }
+    FFTW_UNLOCK
+#endif 
+
+    
+    plan->lin=lin;
+    plan->lout=lout;
+    
+    plan->NG=NG;plan->MG=MG;plan->KG=KG;
+    
+    for (s=0;s<3;s++) {
+        plan->N[s]=N[s];plan->M[s]=M[s];plan->K[s]=K[s];plan->pN[s]=pN[s];plan->pM[s]=pM[s];plan->pK[s]=pK[s];
+        plan->oM[s]=oM[s];plan->oK[s]=oK[s];
+        plan->C[s]=C[s];plan->rC[s]=rC[s];
+        plan->iNin[s]=iNin[s];plan->oNin[s]=oNin[s];plan->iNout[s]=iNout[s];plan->oNout[s]=oNout[s];
+    }
+    for (s=0;s<2;s++) {
+        plan->P[s]=nP[s];plan->coor[s]=prank[s];
+    }
+    
+/*    plan->fftorder=fftorder;
+    plan->direction=direction;    
+    plan->realcomplex=realcomplex;
+*/
+    plan->flags=flags;
+    *rlin=lin;
+    *rlout=lout;
+    return plan;
+}
+
+
+enum order {
+    XYZ,
+    XZY,
+    YXZ,
+    YZX,
+    ZXY,
+    ZYX
+};
+
+
+
+/*here x,y,z and N,M,K is in rotated coordinate system!!
+  x (and N) is mayor (consecutive) dimension, y (M) middle and z (K) major
+  maxN,maxM,maxK is max size of local data
+  pN, pM, pK is local size specific to current processor (only different to max if not divisible)
+  NG, MG, KG is size of global data*/
+static void splitaxes(t_complex* lout,const t_complex* lin,
+                      int maxN,int maxM,int maxK, int pN, int pM, int pK,
+                      int P,int NG,int *N, int* oN) {
+    int x,y,z,i;
+    int in_i,out_i,in_z,out_z,in_y,out_y;
+
+    for (i=0;i<P;i++) { /*index cube along long axis*/
+        in_i  = i*maxN*maxM*maxK;
+        out_i = oN[i];
+        for (z=0;z<pK;z++) { /*3. z l*/ 
+            in_z  = in_i  + z*maxN*maxM;
+            out_z = out_i + z*NG*pM;
+            for (y=0;y<pM;y++) { /*2. y k*/
+                in_y  = in_z  + y*maxN;
+                out_y = out_z + y*NG;
+                for (x=0;x<N[i];x++) { /*1. x j*/
+                    lout[in_y+x] = lin[out_y+x];
+                    /*after split important that each processor chunk i has size maxN*maxM*maxK and thus being the same size*/
+                    /*before split data contiguos - thus if different processor get different amount oN is different*/
+                }
+            }
+        }
+    }
+}
+
+/*make axis contiguous again (after AllToAll) and also do local transpose*/
+/*transpose mayor and major dimension
+  variables see above
+  the major, middle, minor order is only correct for x,y,z (N,M,K) for the input
+  N,M,K local dimensions
+  KG global size*/
+static void joinAxesTrans13(t_complex* lin,const t_complex* lout,
+                            int maxN,int maxM,int maxK,int pN, int pM, int pK, 
+                            int P,int KG, int* K, int* oK)
+{
+    int i,x,y,z;
+    int in_i,out_i,in_x,out_x,in_z,out_z;
+
+    for (i=0;i<P;i++) { /*index cube along long axis*/
+        in_i  = oK[i];
+        out_i = i*maxM*maxN*maxK;
+        for (x=0;x<pN;x++) { /*1.j*/
+            in_x  = in_i  + x*KG*pM;
+            out_x = out_i + x;
+            for (z=0;z<K[i];z++) { /*3.l*/
+                in_z  = in_x  + z;
+                out_z = out_x + z*maxM*maxN;
+                for (y=0;y<pM;y++) { /*2.k*/
+                    lin[in_z+y*KG] = lout[out_z+y*maxN];
+                }
+            }
+        }
+    }
+}
+
+/*make axis contiguous again (after AllToAll) and also do local transpose
+  tranpose mayor and middle dimension
+  variables see above
+  the minor, middle, major order is only correct for x,y,z (N,M,K) for the input
+  N,M,K local size
+  MG, global size*/
+static void joinAxesTrans12(t_complex* lin,const t_complex* lout,int maxN,int maxM,int maxK,int pN, int pM, int pK,
+                int P,int MG, int* M, int* oM) {
+    int i,z,y,x;
+    int in_i,out_i,in_z,out_z,in_x,out_x;
+
+    for (i=0;i<P;i++) { /*index cube along long axis*/
+        in_i  = oM[i];
+        out_i = i*maxM*maxN*maxK;
+        for (z=0;z<pK;z++) { 
+            in_z  = in_i  + z*MG*pN;
+            out_z = out_i + z*maxM*maxN;
+            for (x=0;x<pN;x++) {
+                in_x  = in_z  + x*MG;
+                out_x = out_z + x;
+                for (y=0;y<M[i];y++) {
+                    lin[in_x+y] = lout[out_x+y*maxN];
+                }
+            }
+        }
+    }
+}
+
+
+static void rotate(int x[]) {
+    int t=x[0];
+/*    x[0]=x[2];
+    x[2]=x[1];
+    x[1]=t;*/
+    x[0]=x[1];
+    x[1]=x[2];
+    x[2]=t;
+}
+
+/*compute the offset to compare or print transposed local data in original input coordinates
+  xs matrix dimension size, xl dimension length, xc decomposition offset 
+  s: step in computation = number of transposes*/
+static void compute_offsets(fft5d_plan plan, int xs[], int xl[], int xc[], int NG[], int s) {
+/*    int direction = plan->direction;
+    int fftorder = plan->fftorder;*/
+    
+    int o;
+    int pos[3],i;
+    int *pM=plan->pM, *pK=plan->pK, *oM=plan->oM, *oK=plan->oK,
+        *C=plan->C, *rC=plan->rC;
+
+    NG[0]=plan->NG;NG[1]=plan->MG;NG[2]=plan->KG;
+
+    if (!(plan->flags&FFT5D_ORDER_YZ)) {
+        switch (s) {
+        case 0: o=XYZ; break;
+        case 1: o=ZYX; break;
+        case 2: o=YZX; break;
+        default: assert(0);
+        }
+    } else {
+        switch (s) {
+        case 0: o=XYZ; break;
+        case 1: o=YXZ; break;
+        case 2: o=ZXY; break;
+        default: assert(0);
+        }
+    }
+    switch (o) {
+        case XYZ:pos[0]=1;pos[1]=2;pos[2]=3;break;
+        case XZY:pos[0]=1;pos[1]=3;pos[2]=2;break;
+        case YXZ:pos[0]=2;pos[1]=1;pos[2]=3;break;
+        case YZX:pos[0]=3;pos[1]=1;pos[2]=2;break;
+        case ZXY:pos[0]=2;pos[1]=3;pos[2]=1;break;
+        case ZYX:pos[0]=3;pos[1]=2;pos[2]=1;break;
+    }
+    /*if (debug) printf("pos: %d %d %d\n",pos[0],pos[1],pos[2]);*/
+        
+    /*xs, xl give dimension size and data length in local transposed coordinate system
+      for 0(/1/2): x(/y/z) in original coordinate system*/
+    for (i=0;i<3;i++) {
+        switch (pos[i]) {
+        case 1: xs[i]=1;         xc[i]=0;     xl[i]=C[s];break;
+        case 2: xs[i]=C[s];      xc[i]=oM[s]; xl[i]=pM[s];break;
+        case 3: xs[i]=C[s]*pM[s];xc[i]=oK[s]; xl[i]=pK[s];break;
+        }
+    }
+    /*input order is different for test program to match FFTW order 
+      (important for complex to real)*/
+    if (plan->flags&FFT5D_BACKWARD) {
+        rotate(xs);
+        rotate(xl);
+        rotate(xc);
+        rotate(NG);
+        if (plan->flags&FFT5D_ORDER_YZ) {
+            rotate(xs);
+            rotate(xl);
+            rotate(xc);
+            rotate(NG);            
+        }
+    }
+    if (plan->flags&FFT5D_REALCOMPLEX && ((!(plan->flags&FFT5D_BACKWARD) && s==0) || (plan->flags&FFT5D_BACKWARD && s==2))) {
+        xl[0] = rC[s];
+    }
+}
+
+static void print_localdata(const t_complex* lin, const char* txt, int s, fft5d_plan plan) {
+    int x,y,z,l;
+    int *coor = plan->coor;
+    int xs[3],xl[3],xc[3],NG[3];        
+    int ll=(plan->flags&FFT5D_REALCOMPLEX)?1:2;
+    compute_offsets(plan,xs,xl,xc,NG,s);
+    fprintf(debug,txt,coor[0],coor[1],s);
+    /*printf("xs: %d %d %d, xl: %d %d %d\n",xs[0],xs[1],xs[2],xl[0],xl[1],xl[2]);*/
+    for(z=0;z<xl[2];z++) {
+        for(y=0;y<xl[1];y++) {
+            fprintf(debug,"%d %d: ",coor[0],coor[1]);
+            for (x=0;x<xl[0];x++) {
+                for (l=0;l<ll;l++) {
+                    fprintf(debug,"%f ",((real*)lin)[(z*xs[2]+y*xs[1])*2+(x*xs[0])*ll+l]);
+                }
+                fprintf(debug,",");
+            }
+            fprintf(debug,"\n");
+        }
+    }
+}
+
+void fft5d_execute(fft5d_plan plan,fft5d_time times) {
+    t_complex *lin = plan->lin;
+    t_complex *lout = plan->lout;
+
+    gmx_fft_t *p1d=plan->p1d;
+#ifdef FFT5D_MPI_TRANSPOSE
+    FFTW(plan) *mpip=plan->mpip;
+#endif
+#ifdef GMX_MPI
+    MPI_Comm *cart=plan->cart;
+#endif
+
+    double time_fft=0,time_local=0,time_mpi[2]={0},time=0;    
+    int *N=plan->N,*M=plan->M,*K=plan->K,*pN=plan->pN,*pM=plan->pM,*pK=plan->pK,
+        *C=plan->C,*P=plan->P,**iNin=plan->iNin,**oNin=plan->oNin,**iNout=plan->iNout,**oNout=plan->oNout;
+    int s=0;
+    
+    
+#ifdef GMX_FFT_FFTW3 
+    if (plan->p3d) {
+        if (times!=0)
+            time=MPI_Wtime();
+        FFTW(execute)(plan->p3d); 
+        if (times!=0)
+            times->fft+=MPI_Wtime()-time;
+        return;
+    }
+#endif
+
+    /*lin: x,y,z*/
+    if (plan->flags&FFT5D_DEBUG) print_localdata(lin, "%d %d: copy in lin\n", s, plan);
+    for (s=0;s<2;s++) {
+        if (times!=0)
+            time=MPI_Wtime();
+        
+        if ((plan->flags&FFT5D_REALCOMPLEX) && !(plan->flags&FFT5D_BACKWARD) && s==0) {
+            gmx_fft_many_1d_real(p1d[s],(plan->flags&FFT5D_BACKWARD)?GMX_FFT_COMPLEX_TO_REAL:GMX_FFT_REAL_TO_COMPLEX,lin,lout);
+        } else {
+            gmx_fft_many_1d(     p1d[s],(plan->flags&FFT5D_BACKWARD)?GMX_FFT_BACKWARD:GMX_FFT_FORWARD,               lin,lout);
+        }
+        if (times!=0)
+            time_fft+=MPI_Wtime()-time;
+    
+        if (plan->flags&FFT5D_DEBUG) print_localdata(lout, "%d %d: FFT %d\n", s, plan);
+        
+#ifdef GMX_MPI
+        if (GMX_PARALLEL_ENV_INITIALIZED && cart[s] !=0 && P[s]>1 )
+        {
+            if (times!=0)
+                time=MPI_Wtime(); 
+            /*prepare for AllToAll
+              1. (most outer) axes (x) is split into P[s] parts of size N[s] 
+              for sending*/
+            splitaxes(lin,lout,N[s],M[s],K[s], pN[s],pM[s],pK[s],P[s],C[s],iNout[s],oNout[s]);
+
+            if (times!=0)
+            {
+                time_local+=MPI_Wtime()-time;
+            
+                /*send, recv*/
+                time=MPI_Wtime();
+            }
+
+#ifdef FFT5D_MPI_TRANSPOSE
+            FFTW(execute)(mpip[s]);  
+#else
+            if ((s==0 && !(plan->flags&FFT5D_ORDER_YZ)) || (s==1 && (plan->flags&FFT5D_ORDER_YZ))) 
+                MPI_Alltoall(lin,N[s]*pM[s]*K[s]*sizeof(t_complex)/sizeof(real),GMX_MPI_REAL,lout,N[s]*pM[s]*K[s]*sizeof(t_complex)/sizeof(real),GMX_MPI_REAL,cart[s]);
+            else
+                MPI_Alltoall(lin,N[s]*M[s]*pK[s]*sizeof(t_complex)/sizeof(real),GMX_MPI_REAL,lout,N[s]*M[s]*pK[s]*sizeof(t_complex)/sizeof(real),GMX_MPI_REAL,cart[s]);
+#endif /*FFT5D_MPI_TRANSPOSE*/
+            if (times!=0)
+                time_mpi[s]=MPI_Wtime()-time;
+        }
+#endif /*GMX_MPI*/
+
+    
+        if (times!=0)
+            time=MPI_Wtime();
+        /*bring back in matrix form 
+          thus make  new 1. axes contiguos
+          also local transpose 1 and 2/3 */
+        if ((s==0 && !(plan->flags&FFT5D_ORDER_YZ)) || (s==1 && (plan->flags&FFT5D_ORDER_YZ))) 
+            joinAxesTrans13(lin,lout,N[s],pM[s],K[s],pN[s],pM[s],pK[s],P[s],C[s+1],iNin[s+1],oNin[s+1]);
+        else 
+            joinAxesTrans12(lin,lout,N[s],M[s],pK[s],pN[s],pM[s],pK[s],P[s],C[s+1],iNin[s+1],oNin[s+1]);    
+        if (times!=0)
+            time_local+=MPI_Wtime()-time;
+    
+        if (plan->flags&FFT5D_DEBUG) print_localdata(lin, "%d %d: tranposed %d\n", s+1, plan);
+                
+        /*if (debug) print_localdata(lin, "%d %d: transposed x-z\n", N1, M0, K, ZYX, coor);*/
+    }    
+    
+    if (times!=0)
+        time=MPI_Wtime();
+    if (plan->flags&FFT5D_INPLACE) lout=lin;
+    if ((plan->flags&FFT5D_REALCOMPLEX) && (plan->flags&FFT5D_BACKWARD)) {
+        gmx_fft_many_1d_real(p1d[s],(plan->flags&FFT5D_BACKWARD)?GMX_FFT_COMPLEX_TO_REAL:GMX_FFT_REAL_TO_COMPLEX,lin,lout);
+    } else {
+        gmx_fft_many_1d(     p1d[s],(plan->flags&FFT5D_BACKWARD)?GMX_FFT_BACKWARD:GMX_FFT_FORWARD,               lin,lout);
+    }
+
+    if (times!=0)
+        time_fft+=MPI_Wtime()-time;
+    if (plan->flags&FFT5D_DEBUG) print_localdata(lout, "%d %d: FFT %d\n", s, plan);
+    /*if (debug) print_localdata(lout, "%d %d: FFT in y\n", N1, M, K0, YZX, coor);*/
+    
+    if (times!=0) {
+        times->fft+=time_fft;
+        times->local+=time_local;
+        times->mpi2+=time_mpi[1];
+        times->mpi1+=time_mpi[0];
+    }
+}
+
+void fft5d_destroy(fft5d_plan plan) {
+    int s;
+    for (s=0;s<3;s++) {
+        gmx_many_fft_destroy(plan->p1d[s]);
+        if (plan->iNin[s]) {
+            free(plan->iNin[s]);
+            plan->iNin[s]=0;
+        }
+        if (plan->oNin[s]) {
+            free(plan->oNin[s]);
+            plan->oNin[s]=0;
+        }
+        if (plan->iNout[s]) {
+            free(plan->iNout[s]);
+            plan->iNout[s]=0;
+        }
+        if (plan->oNout[s]) {
+            free(plan->oNout[s]);
+            plan->oNout[s]=0;
+        }
+    }
+#ifdef GMX_FFT_FFTW3 
+    FFTW_LOCK;
+#ifdef FFT5D_MPI_TRANSPOS
+    for (s=0;s<2;s++)    
+        FFTW(destroy_plan)(plan->mpip[s]);
+#endif /* FFT5D_MPI_TRANSPOS */
+#endif /* GMX_FFT_FFTW3 */
+
+    /*We can't free lin/lout here - is allocated by gmx_calloc_aligned which can't be freed*/
+
+    
+#ifdef FFT5D_THREADS
+    FFTW(cleanup_threads)();
+#endif
+
+    free(plan);
+}
+
+/*Is this better than direct access of plan? enough data?
+  here 0,1 reference divided by which processor grid dimension (not FFT step!)*/
+void fft5d_local_size(fft5d_plan plan,int* N1,int* M0,int* K0,int* K1,int** coor) {
+    *N1=plan->N[0];
+    *M0=plan->M[0];
+    *K1=plan->K[0];
+    *K0=plan->N[1];
+    
+    *coor=plan->coor;
+}
+
+
+/*same as fft5d_plan_3d but with cartesian coordinator and automatic splitting 
+  of processor dimensions*/
+fft5d_plan fft5d_plan_3d_cart(int NG, int MG, int KG, MPI_Comm comm, int P0, int flags, t_complex** rlin, t_complex** rlout) {
+    MPI_Comm cart[2]={0};
+#ifdef GMX_MPI
+    int size=1,prank=0;
+    int P[2];
+    int coor[2];
+    int wrap[]={0,0};
+    MPI_Comm gcart;
+    int rdim1[] = {0,1}, rdim2[] = {1,0};
+
+    MPI_Comm_size(comm,&size);
+    MPI_Comm_rank(comm,&prank);
+
+    if (P0==0) P0 = lfactor(size);
+    if (size%P0!=0) {
+        if (prank==0) printf("FFT5D: WARNING: Number of processors %d not evenly dividable by %d\n",size,P0);
+        P0 = lfactor(size);
+    }
+        
+    P[0] = P0; P[1]=size/P0; /*number of processors in the two dimensions*/
+    
+    /*Difference between x-y-z regarding 2d decomposition is whether they are 
+      distributed along axis 1, 2 or both*/
+    
+    MPI_Cart_create(comm,2,P,wrap,1,&gcart); /*parameter 4: value 1: reorder*/
+    MPI_Cart_get(gcart,2,P,wrap,coor); 
+    MPI_Cart_sub(gcart, rdim1 , &cart[0]);
+    MPI_Cart_sub(gcart, rdim2 , &cart[1]);
+#endif
+    return fft5d_plan_3d(NG, MG, KG, cart, flags, rlin, rlout); 
+}
+
+
+
+/*prints in original coordinate system of data (as the input to FFT)*/
+void fft5d_compare_data(const t_complex* lin, const t_complex* in, fft5d_plan plan, int bothLocal, int normalize) {
+    int xs[3],xl[3],xc[3],NG[3];
+    int x,y,z,l;
+    int *coor = plan->coor;
+    int ll=2; /*compare ll values per element (has to be 2 for complex)*/
+    if (plan->flags&FFT5D_REALCOMPLEX && plan->flags&FFT5D_BACKWARD) 
+    {
+        ll=1;
+    }
+
+    compute_offsets(plan,xs,xl,xc,NG,2);
+    if (plan->flags&FFT5D_DEBUG) printf("Compare2\n");
+    for (z=0;z<xl[2];z++) {
+        for(y=0;y<xl[1];y++) {
+            if (plan->flags&FFT5D_DEBUG) printf("%d %d: ",coor[0],coor[1]);
+            for (x=0;x<xl[0];x++) {
+                for (l=0;l<ll;l++) { /*loop over real/complex parts*/
+                    real a,b;
+                    a=((real*)lin)[(z*xs[2]+y*xs[1])*2+x*xs[0]*ll+l];
+                    if (normalize) a/=plan->rC[0]*plan->rC[1]*plan->rC[2];
+                    if (!bothLocal) 
+                        b=((real*)in)[((z+xc[2])*NG[0]*NG[1]+(y+xc[1])*NG[0])*2+(x+xc[0])*ll+l];
+                    else 
+                        b=((real*)in)[(z*xs[2]+y*xs[1])*2+x*xs[0]*ll+l];
+                    if (plan->flags&FFT5D_DEBUG) {
+                        printf("%f %f, ",a,b);
+                    } else {
+                        if (fabs(a-b)>2*NG[0]*NG[1]*NG[2]*GMX_REAL_EPS) {
+                            printf("result incorrect on %d,%d at %d,%d,%d: FFT5D:%f reference:%f\n",coor[0],coor[1],x,y,z,a,b);
+                        }
+/*                        assert(fabs(a-b)<2*NG[0]*NG[1]*NG[2]*GMX_REAL_EPS);*/
+                    }
+                }
+                if (plan->flags&FFT5D_DEBUG) printf(",");
+            }
+            if (plan->flags&FFT5D_DEBUG) printf("\n");
+        }
+    }
+    
+}
+
diff --git a/src/mdlib/fft5d.h b/src/mdlib/fft5d.h
new file mode 100644 (file)
index 0000000..d4444f2
--- /dev/null
@@ -0,0 +1,85 @@
+#ifndef FFT5D_H_     
+#define FFT5D_H_
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef NOGMX
+/*#define GMX_MPI*/
+/*#define GMX_FFT_FFTW3*/
+FILE* debug;
+#endif
+
+#include <types/commrec.h>
+#include "gmxcomplex.h"
+#include "gmx_fft.h"
+
+#ifndef GMX_LIB_MPI
+double MPI_Wtime();
+#endif
+
+/*currently only special optimization for FFTE*/
+#ifdef GMX_FFT_FFTW3
+#include <fftw3.h>
+#endif
+
+#ifndef GMX_DOUBLE
+#define FFTW(x) fftwf_##x
+#else
+#define FFTW(x) fftw_##x
+#endif
+
+struct fft5d_time_t {
+       double fft,local,mpi1,mpi2;
+};
+typedef struct fft5d_time_t *fft5d_time;
+
+typedef enum fft5d_flags_t {
+       FFT5D_ORDER_YZ=1,
+       FFT5D_BACKWARD=2,
+       FFT5D_REALCOMPLEX=4,
+       FFT5D_DEBUG=8,
+       FFT5D_NOMEASURE=16,
+       FFT5D_INPLACE=32,
+       FFT5D_NOMALLOC=64
+} fft5d_flags;
+
+struct fft5d_plan_t {
+       t_complex *lin;
+       t_complex *lout;
+        gmx_fft_t p1d[3];   /*1D plans*/
+#ifdef GMX_FFT_FFTW3 
+        FFTW(plan) p2d;  /*2D plan: used for 1D decomposition if FFT supports transposed output*/
+        FFTW(plan) p3d;  /*3D plan: used for 0D decomposition if FFT supports transposed output*/
+       FFTW(plan) mpip[2];
+#endif
+       MPI_Comm cart[2];
+
+    int N[3],M[3],K[3]; /*local length in transposed coordinate system (if not divisisable max)*/
+    int pN[3],pM[3], pK[3]; /*local length - not max but length for this processor*/
+    int oM[3],oK[3]; /*offset for current processor*/
+    int *iNin[3],*oNin[3],*iNout[3],*oNout[3]; /*size for each processor (if divisisable=max) for out(=split) 
+                                                and in (=join) and offsets in transposed coordinate system*/
+    int C[3],rC[3]; /*global length (of the one global axes) */
+    /* C!=rC for real<->complex. then C=rC/2 but with potential padding*/
+    int P[2]; /*size of processor grid*/
+/*     int fftorder;*/
+/*     int direction;*/
+/*     int realcomplex;*/
+       int flags;
+    /*int N0,N1,M0,M1,K0,K1;*/
+       int NG,MG,KG;
+    /*int P[2];*/
+       int coor[2];
+}; 
+
+typedef struct fft5d_plan_t *fft5d_plan;
+
+void fft5d_execute(fft5d_plan plan,fft5d_time times);
+fft5d_plan fft5d_plan_3d(int N, int M, int K, MPI_Comm comm[2], int flags, t_complex** lin, t_complex** lin2);
+void fft5d_local_size(fft5d_plan plan,int* N1,int* M0,int* K0,int* K1,int** coor);
+void fft5d_destroy(fft5d_plan plan);
+fft5d_plan fft5d_plan_3d_cart(int N, int M, int K, MPI_Comm comm, int P0, int flags, t_complex** lin, t_complex** lin2);
+void fft5d_compare_data(const t_complex* lin, const t_complex* in, fft5d_plan plan, int bothLocal, int normarlize);
+#endif /*FFTLIB_H_*/
diff --git a/src/mdlib/fftgrid.c b/src/mdlib/fftgrid.c
deleted file mode 100644 (file)
index 9e0c3b7..0000000
+++ /dev/null
@@ -1,491 +0,0 @@
-/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
- *
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * GROwing Monsters And Cloning Shrimps
- */
-/* This file is completely threadsafe - keep it that way! */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "typedefs.h"
-#include "futil.h"
-#include "smalloc.h"
-#include "futil.h"
-#include "macros.h"
-#include "network.h"
-#include "fftgrid.h"
-#include "gmx_fft.h"
-#include "gmx_parallel_3dfft.h"
-#include "gmxfio.h"
-
-
-#ifdef GMX_MPI
-static void print_parfft(FILE *fp,char *title,t_parfft *pfft)
-{
-  fprintf(fp,"PARALLEL FFT DATA:\n"
-         "   local_nx:                 %3d  local_x_start:                 %3d\n"
-         "   local_ny_after_transpose: %3d  local_y_start_after_transpose  %3d\n",
-         pfft->local_nx,pfft->local_x_start,pfft->local_ny_after_transpose,
-         pfft->local_y_start_after_transpose);
-}
-#endif
-
-
-void *
-gmx_alloc_aligned(size_t size)
-{
-    void *p0,*p;
-    
-    p0 = malloc(size+32);
-    
-    if(p0 == NULL)
-    {
-        gmx_fatal(FARGS,"Failed to allocated %u bytes of aligned memory.",size+32);
-    }
-    
-    p = (void *) (((size_t) p0 + 32) & (~((size_t) 31)));
-    
-    /* Yeah, yeah, we cannot free this pointer, but who cares... */
-    return p;
-}
-
-t_fftgrid *mk_fftgrid(int          nx,
-                      int          ny,
-                      int          nz,
-                      int          *node2slab,
-                      int          *slab2grid_x,
-                      t_commrec *  cr,
-                      bool         bReproducible)
-{
-/* parallel runs with non-parallel ffts haven't been tested yet */
-    int           nnodes;
-    int           x1,y1,maxlocalsize;
-    t_fftgrid *   grid;
-    int           flags;
-    
-    nnodes = 1;
-#ifdef GMX_MPI
-    if (cr && cr->nnodes > 1) {
-        MPI_Comm_size(cr->mpi_comm_mygroup,&nnodes);
-    }
-#endif
-    
-    snew(grid,1);
-    grid->nx   = nx;
-    grid->ny   = ny;
-    grid->nz   = nz;
-    grid->nxyz = nx*ny*nz;
-    grid->bParallel = (nnodes > 1);
-    
-    if (grid->bParallel)
-    {
-        grid->la2r = (nz/2+1)*2;
-    }
-    else
-    {
-        grid->la2r = nz;  
-    }
-    
-    grid->la2c = (nz/2+1);    
-    
-    grid->la12r = ny*grid->la2r;
-    
-    if (grid->bParallel)
-    {
-        grid->la12c = nx*grid->la2c;
-    }
-    else
-    {
-        grid->la12c = ny*grid->la2c;
-    }
-    
-    /* This code assumes that the when the grid is not divisble by nnodes,
-     * the maximum difference in local grid sizes is 1.
-     */
-    x1 = (nx % nnodes == 0 ? 0 : 1);
-    y1 = (ny % nnodes == 0 ? 0 : 1);
-    
-    grid->nptr = (nx + x1)*(ny + y1)*grid->la2c*2;
-    
-    if (grid->bParallel) 
-    {
-#ifdef GMX_MPI
-        gmx_parallel_3dfft_init(&grid->mpi_fft_setup,nx,ny,nz,
-                                node2slab,slab2grid_x,cr->mpi_comm_mygroup,
-                                bReproducible);
-        
-        gmx_parallel_3dfft_limits(grid->mpi_fft_setup,
-                                  &(grid->pfft.local_x_start),
-                                  &(grid->pfft.local_nx),
-                                  &(grid->pfft.local_y_start_after_transpose),
-                                  &(grid->pfft.local_ny_after_transpose));
-#else
-        gmx_fatal(FARGS,"Parallel FFT supported with MPI only!");
-#endif
-    }
-    else 
-    {
-        gmx_fft_init_3d_real(&grid->fft_setup,nx,ny,nz,bReproducible ? GMX_FFT_FLAG_CONSERVATIVE : GMX_FFT_FLAG_NONE);
-    }
-    grid->ptr = (real *)gmx_alloc_aligned(grid->nptr*sizeof(*(grid->ptr)));
-    
-#ifdef GMX_MPI
-    if (grid->bParallel && debug) 
-    {
-        print_parfft(debug,"Plan", &grid->pfft);
-    }
-    if (grid->bParallel)
-    {
-        maxlocalsize = max((nx/nnodes + x1)*ny*grid->la2c*2,
-                           (ny/nnodes + y1)*nx*grid->la2c*2);
-        grid->workspace = (real *)
-            gmx_alloc_aligned(maxlocalsize*sizeof(*(grid->workspace)));
-    }
-    else
-    {
-        grid->workspace =
-            (real*)gmx_alloc_aligned(grid->nptr*sizeof(*(grid->workspace)));
-    }
-#else /* no MPI */
-    grid->workspace = (real *)gmx_alloc_aligned(grid->nptr*sizeof(*(grid->workspace)));
-#endif
-
-    return grid;
-}
-
-void 
-pr_fftgrid(FILE *fp,char *title,t_fftgrid *grid)
-{
-  int     i,j,k,index_x,index_xy,ntot=0;
-  int     nx,ny,nz,nx2,ny2,nz2,la12,la2;
-  real *  ptr;
-
-  /* Unpack structure */
-  unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
-  for(i=0; (i<nx); i++) {
-    index_x = la12*i;
-    for(j=0; (j<ny); j++) {
-      index_xy = index_x + la2*j;
-      for(k=0; (k<nz); k++) {
-       if (ptr[index_xy+k] != 0) {
-         fprintf(fp,"%-12s  %5d  %5d  %5d  %12.5e\n",
-                 title,i,j,k,ptr[index_xy+k]);
-         ntot++;
-       }
-      }
-    }
-  }
-  fprintf(fp,"%d non zero elements in %s\n",ntot,title);
-}
-
-void done_fftgrid(t_fftgrid *grid)
-{
-  /* memory can't be freed because it is allocated by gmx_alloc_aligned */
-  if (grid->ptr) {
-    /* sfree(grid->ptr); */
-    grid->ptr = NULL;
-  }
-  if (grid->workspace) {
-    /* sfree(grid->workspace); */
-    grid->workspace=NULL;
-  }
-}
-
-
-void gmxfft3D(t_fftgrid *grid,enum gmx_fft_direction dir,t_commrec *cr)
-{
-  real *tmp;
-
-  if (grid->bParallel) 
-  {
-#ifdef GMX_MPI
-    if( dir == GMX_FFT_REAL_TO_COMPLEX || dir == GMX_FFT_COMPLEX_TO_REAL )
-    {
-      gmx_parallel_3dfft(grid->mpi_fft_setup,dir,grid->ptr,grid->ptr);
-    }
-    else
-    {
-        gmx_fatal(FARGS,"Invalid direction for FFT: %d",dir);
-    }
-#else
-    gmx_fatal(FARGS,"Parallel FFT supported with MPI only!");   
-#endif
-  }
-  else
-  {
-    if( dir == GMX_FFT_REAL_TO_COMPLEX || dir == GMX_FFT_COMPLEX_TO_REAL)
-    {
-        gmx_fft_3d_real(grid->fft_setup,dir,grid->ptr,grid->workspace);
-        tmp = grid->ptr;
-        grid->ptr = grid->workspace;
-        grid->workspace = tmp;        
-    }
-    else
-    {
-      gmx_fatal(FARGS,"Invalid direction for FFT: %d",dir);
-    }
-  }
-}
-
-void clear_fftgrid(t_fftgrid *grid)
-{
-    /* clears the whole grid */
-  int      i,ngrid;
-  real *   ptr;
-  
-  ngrid = grid->nptr;
-  ptr   = grid->ptr;
-  
-  for (i=0; (i<ngrid); i++) {
-    ptr[i] = 0;
-  }
-}
-
-void unpack_fftgrid(t_fftgrid *grid,int *nx,int *ny,int *nz,
-                    int *nx2,int *ny2,int *nz2,
-                    int *la2,int *la12,bool bReal,real **ptr)
-{
-  *nx  = grid->nx;
-  *ny  = grid->ny;
-  *nz  = grid->nz;
-  *nx2 = 2*grid->nx;
-  *ny2 = 2*grid->ny;
-  *nz2 = 2*grid->nz;
-  if(bReal) {
-    *la2 = grid->la2r;
-    *la12= grid->la12r;
-  } 
-  else {
-    *la2 = grid->la2c;
-    *la12= grid->la12c;
-  }
-  *ptr = grid->ptr;
-}
-
-
-
-/*****************************************************************
- * 
- * For backward compatibility (for testing the ewald code vs. PPPM etc)
- * some old grid routines are retained here.
- *
- ************************************************************************/
-
-real ***mk_rgrid(int nx,int ny,int nz)
-{
-  real *ptr1;
-  real **ptr2;
-  real ***ptr3;
-  int  i,j,n2,n3;
-  
-  snew(ptr1,nx*ny*nz);
-  snew(ptr2,nx*ny);
-  snew(ptr3,nx);
-  
-  n2=n3=0;
-  for(i=0; (i<nx); i++) {
-    ptr3[i]=&(ptr2[n2]);
-    for(j=0; (j<ny); j++,n2++) { 
-      ptr2[n2] = &(ptr1[n3]);
-      n3 += nz;
-    }
-  }
-  return ptr3;
-}
-
-void free_rgrid(real ***grid,int nx,int ny)
-{
-  int i;
-
-  sfree(grid[0][0]);  
-  for(i=0; (i<nx); i++) {
-    sfree(grid[i]);
-  }
-  sfree(grid);
-}
-
-real print_rgrid(FILE *fp,char *title,int nx,int ny,int nz,real ***grid)
-{
-  int  ix,iy,iz;
-  real g,gtot;
-  
-  gtot=0;
-  if (fp)
-    fprintf(fp,"Printing all non-zero real elements of %s\n",title);
-  for(ix=0; (ix<nx); ix++)
-    for(iy=0; (iy<ny); iy++)
-      for(iz=0; (iz<nz); iz++) {
-       g=grid[ix][iy][iz];
-       if (fp && (g != 0))
-         fprintf(fp,"%s[%2d][%2d][%2d] = %12.5e\n",title,ix,iy,iz,g);
-       gtot+=g;
-      }
-  return gtot;
-}
-
-void print_rgrid_pdb(char *fn,int nx,int ny,int nz,real ***grid)
-{
-  FILE *fp;
-  int  ix,iy,iz,n,ig;
-  real x,y,z,g;
-
-  n=1;
-  fp=gmx_fio_fopen(fn,"w");  
-  for(ix=0; (ix<nx); ix++) {
-    for(iy=0; (iy<ny); iy++) {
-      for(iz=0; (iz<nz); iz++) {
-       g=grid[ix][iy][iz];
-       ig=g;
-       if ((ig != 0) || (1)) {
-         x = 4*ix;
-         y = 4*iy;
-         z = 4*iz;
-         fprintf(fp,"ATOM  %5d  Na   Na     1    %8.3f%8.3f%8.3f%6.2f%6.2f\n",
-                 n++,x,y,z,0.0,g);
-       }
-      }
-    }
-  }
-  gmx_fio_fclose(fp);
-}
-
-void clear_rgrid(int nx,int ny,int nz,real ***grid)
-{
-  int i,j,k;
-  
-  for(i=0; (i<nx); i++)
-    for(j=0; (j<ny); j++)
-      for(k=0; (k<nz); k++)
-       grid[i][j][k] = 0;
-}
-
-void clear_cgrid(int nx,int ny,int nz,t_complex ***grid)
-{
-  int i,j,k;
-  
-  for(i=0; (i<nx); i++)
-    for(j=0; (j<ny); j++)
-      for(k=0; (k<nz); k++)
-       grid[i][j][k] = cnul;
-}
-
-t_complex ***mk_cgrid(int nx,int ny,int nz)
-{
-  t_complex *ptr1;
-  t_complex **ptr2;
-  t_complex ***ptr3;
-  int  i,j,n2,n3;
-  
-  snew(ptr1,nx*ny*nz);
-  snew(ptr2,nx*ny);
-  snew(ptr3,nx);
-  
-  n2=n3=0;
-  for(i=0; (i<nx); i++) {
-    ptr3[i]=&(ptr2[n2]);
-    for(j=0; (j<ny); j++,n2++) { 
-      ptr2[n2] = &(ptr1[n3]);
-      n3 += nz;
-    }
-  }
-  return ptr3;
-}
-
-void free_cgrid(t_complex ***grid,int nx,int ny)
-{
-  int i;
-
-  sfree(grid[0][0]);
-  for(i=0; (i<nx); i++) 
-    sfree(grid[i]);
-  sfree(grid);
-}
-
-t_complex print_cgrid(FILE *fp,char *title,int nx,int ny,int nz,
-                      t_complex ***grid)
-{
-  int     ix,iy,iz;
-  t_complex g,gtot;
-  
-  gtot=cnul;
-  if (fp)
-    fprintf(fp,"Printing all non-zero complex elements of %s\n",title);
-  for(ix=0; (ix<nx); ix++)
-    for(iy=0; (iy<ny); iy++)
-      for(iz=0; (iz<nz); iz++) {
-       g=grid[ix][iy][iz];
-       if (fp  && ((g.re != 0) || (g.im != 0)))
-         fprintf(fp,"%s[%2d][%2d][%2d] = %12.5e + i %12.5e\n",
-                 title,ix,iy,iz,g.re,g.im);
-       gtot = cadd(gtot,g);
-      }
-  return gtot;
-}
-
-void print_cgrid_pdb(char *fn,int nx,int ny,int nz,t_complex ***grid)
-{
-  FILE *fp;
-  int  ix,iy,iz,n;
-  real x,y,z,g;
-
-  n=1;
-  fp=gmx_fio_fopen(fn,"w");  
-  for(ix=0; (ix<nx); ix++) {
-    for(iy=0; (iy<ny); iy++) {
-      for(iz=0; (iz<nz); iz++) {
-       g=grid[ix][iy][iz].re;
-       if (g != 0) {
-         x = 4*ix;
-         y = 4*iy;
-         z = 4*iz;
-         fprintf(fp,"ATOM  %5d  Na   Na     1    %8.3f%8.3f%8.3f%6.2f%6.2f\n",
-                 n++,x,y,z,0.0,g);
-       }
-      }
-    }
-  }
-  gmx_fio_fclose(fp);
-}
-
-
-
-
-
-
-
-
index 258f69157a5e8e7a788c6cbd60d1a456b6a88887..d512b7402e9e7abd412281f8636ad81fbdb7b7c0 100644 (file)
@@ -453,6 +453,10 @@ void do_force_lowlevel(FILE       *fplog,   gmx_large_int_t step,
                     {
                         pme_flags |= GMX_PME_CALC_F;
                     }
+                    if (flags & GMX_FORCE_VIRIAL)
+                    {
+                        pme_flags |= GMX_PME_CALC_ENER_VIR;
+                    }
                     wallcycle_start(wcycle,ewcPMEMESH);
                     status = gmx_pme_do(fr->pmedata,
                                         md->start,md->homenr - fr->n_tpi,
index b8775b9efac9ee43a0e1a26c53f4259bd1dc4029..0872800b5ceb78d05f79044a5bd9a5e98bf55a77 100644 (file)
@@ -1162,6 +1162,56 @@ static real cutoff_inf(real cutoff)
     return cutoff;
 }
 
+bool can_use_allvsall(const t_inputrec *ir, const gmx_mtop_t *mtop,
+                      bool bPrintNote,t_commrec *cr,FILE *fp)
+{
+    bool bAllvsAll;
+
+#ifdef GMX_DOUBLE
+    /* double not done yet */
+    bAllvsAll = FALSE;
+#else
+    bAllvsAll =
+        (
+         /* disable for very small systems (bug 416) */
+         mtop->natoms > 64       &&
+         ir->rlist==0            &&
+         ir->rcoulomb==0         &&
+         ir->rvdw==0             &&
+         ir->ePBC==epbcNONE      &&
+         ir->vdwtype==evdwCUT    &&
+         ir->coulombtype==eelCUT &&
+         ir->efep==efepNO        &&
+         (ir->implicit_solvent == eisNO || 
+          (ir->implicit_solvent==eisGBSA && (ir->gb_algorithm==egbSTILL || 
+                                             ir->gb_algorithm==egbHCT   || 
+                                             ir->gb_algorithm==egbOBC))) &&
+         getenv("GMX_NO_ALLVSALL") == NULL
+            );
+
+    if (bAllvsAll && ir->opts.ngener > 1)
+    {
+        const char *note="NOTE: Can not use all-vs-all force loops, because there are multiple energy monitor groups; you might get significantly higher performance when using only a single energy monitor group.\n";
+
+        if (bPrintNote)
+        {
+            if (MASTER(cr))
+            {
+                fprintf(stderr,"\n%s\n",note);
+            }
+            if (fp != NULL)
+            {
+                fprintf(fp,"\n%s\n",note);
+            }
+        }
+        bAllvsAll = FALSE;
+    }
+#endif
+
+    return bAllvsAll;
+}
+
+
 void init_forcerec(FILE *fp,
                    const output_env_t oenv,
                    t_forcerec *fr,
@@ -1229,36 +1279,7 @@ void init_forcerec(FILE *fp,
     fr->sc_sigma6  = pow(ir->sc_sigma,6);
     
     /* Check if we can/should do all-vs-all kernels */
-#ifdef GMX_DOUBLE
-    /* double not done yet */
-    fr->bAllvsAll = FALSE;
-#else
-    fr->bAllvsAll = (ir->rlist==0            &&
-                     ir->rcoulomb==0         &&
-                     ir->rvdw==0             &&
-                     ir->ePBC==epbcNONE      &&
-                     ir->vdwtype==evdwCUT    &&
-                     ir->coulombtype==eelCUT &&
-                     ir->efep==efepNO        &&
-                     (ir->implicit_solvent == eisNO || 
-                      (ir->implicit_solvent==eisGBSA && (ir->gb_algorithm==egbSTILL || 
-                                                         ir->gb_algorithm==egbHCT   || 
-                                                         ir->gb_algorithm==egbOBC)))
-                     );
-    if (fr->bAllvsAll && ir->opts.ngener > 1)
-    {
-        const char *note="NOTE: Can not use all-vs-all force loops, because there are multiple energy monitor groups; you might get significantly higher performance when using only a single energy monitor group.\n";
-        if (MASTER(cr))
-        {
-            fprintf(stderr,"\n%s\n",note);
-        }
-        if (fp != NULL)
-        {
-            fprintf(fp,"\n%s\n",note);
-        }
-        fr->bAllvsAll = FALSE;
-    }
-#endif
+    fr->bAllvsAll       = can_use_allvsall(ir,mtop,FALSE,NULL,NULL);
     fr->AllvsAll_work   = NULL;
     fr->AllvsAll_workgb = NULL;
 
index 0d85f0a768430a405169aeea484c6d954ab9e031..c4b325bf342cecad7c635b8c0c63e4256b90940c 100644 (file)
 #include "tmpi.h"
 #endif
 
-#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_SSE2) )
 #ifdef GMX_DOUBLE
+#if ( defined(GMX_IA32_SSE2) || defined(GMX_X86_64_SSE2) || defined(GMX_SSE2) )
 #include "genborn_sse2_double.h"
+#endif
 #else
+#if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_SSE2) )
 #include "genborn_sse2_single.h"
 #include "genborn_allvsall_sse2_single.h"
-#endif /* GMX_DOUBLE */
 #endif /* GMX_SSE */
+#endif /* GMX_DOUBLE */
 
 #include "genborn_allvsall.h"
 
-    //#define DISABLE_SSE
+/*#define DISABLE_SSE*/
 
 typedef struct {
     int shift;
@@ -1173,7 +1175,7 @@ int calc_gb_rad(t_commrec *cr, t_forcerec *fr, t_inputrec *ir,gmx_localtop_t *to
         }
     }
 
-#ifndef DOUBLE
+#ifndef GMX_DOUBLE
     if(fr->bAllvsAll)
     {
         cnt = md->homenr*(md->nr/2+1);
@@ -1252,7 +1254,7 @@ int calc_gb_rad(t_commrec *cr, t_forcerec *fr, t_inputrec *ir,gmx_localtop_t *to
     switch(ir->gb_algorithm)
     {
         case egbSTILL:
-            calc_gb_rad_still_sse(cr,fr,born->nr,top, atype, x[0], nl, born, md);
+            calc_gb_rad_still_sse(cr,fr,born->nr,top, atype, x[0], nl, born);
             break;
         case egbHCT:
         case egbOBC:
@@ -1559,8 +1561,8 @@ real calc_gb_chainrule(int natoms, t_nblist *nl, real *dadx, real *dvda, rvec x[
     {
         ai   = nl->iinr[i];
         
-        nj0     = nl->jindex[ai];
-        nj1  = nl->jindex[ai+1];
+        nj0  = nl->jindex[i];
+        nj1  = nl->jindex[i+1];
         
         /* Load shifts for this list */
         shift   = nl->shift[i];
@@ -1679,7 +1681,7 @@ real calc_gb_forces(t_commrec *cr, t_mdatoms *md, gmx_genborn_t *born, gmx_local
         dd_atom_spread_real(cr->dd,fr->dvda);
     }
 
-#ifndef DOUBLE
+#ifndef GMX_DOUBLE
     if(fr->bAllvsAll)
     {
 #if ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_SSE2) )
@@ -1712,7 +1714,7 @@ real calc_gb_forces(t_commrec *cr, t_mdatoms *md, gmx_genborn_t *born, gmx_local
     /* x86 or x86-64 with GCC inline assembly and/or SSE intrinsics */
     calc_gb_chainrule_sse(born->nr, &(fr->gblist), fr->dadx, fr->dvda, 
                           x[0], f[0], fr->fshift[0], fr->shift_vec[0], 
-                          gb_algorithm, born, md);    
+                          gb_algorithm, born, md);
 #else
     /* Calculate the forces due to chain rule terms with non sse code */
     calc_gb_chainrule(born->nr, &(fr->gblist), fr->dadx, fr->dvda, 
index ebd5c62f1014d24cd4b19162c199f2fc28cd583e..4be1567e82411bcff97e8cd6f74f0cc2da9ebbf8 100644 (file)
@@ -32,6 +32,8 @@
 #include <xmmintrin.h>
 #include <emmintrin.h>
 
+#include "genborn_sse2_double.h"
+
 #if (defined (_MSC_VER) || defined(__INTEL_COMPILER))
 #define gmx_castsi128_pd(a) _mm_castsi128_pd(a)
 #define gmx_castpd_si128(a) _mm_castpd_si128(a)
@@ -69,8 +71,8 @@ sincos_sse2double(__m128d x, __m128d *sinval, __m128d *cosval)
     const __m128d sincosd_sc4 = {0.00833333333331908278,0.00833333333331908278};
     const __m128d sincosd_sc5 = {-0.16666666666666612594,-0.16666666666666612594};
     
-    __m128d signbit           = (__m128d) _mm_set1_epi64x(0x8000000000000000ULL);
-    __m128d tiny              = (__m128d) _mm_set1_epi64x(0x3e40000000000000ULL);
+    __m128d signbit           = gmx_castsi128_pd(_mm_set1_epi64x(0x8000000000000000ULL));
+    __m128d tiny              = gmx_castsi128_pd(_mm_set1_epi64x(0x3e40000000000000ULL));
     
     __m128d xl,xl2,xl3,qd,absxl,p1,cx,sx,ts,tc,tsn,tcn;
     __m128i q;
@@ -142,18 +144,18 @@ sincos_sse2double(__m128d x, __m128d *sinval, __m128d *cosval)
     sx     = _mm_or_pd( _mm_and_pd(isTiny,xl) , _mm_andnot_pd(isTiny,sx) );
     cx     = _mm_or_pd( _mm_and_pd(isTiny,one) , _mm_andnot_pd(isTiny,cx) );
        
-    sinMask = (__m128d) _mm_cmpeq_epi32( _mm_and_si128(offsetSin,ione), izero);
-    cosMask = (__m128d) _mm_cmpeq_epi32( _mm_and_si128(offsetCos,ione), izero);
+    sinMask = gmx_castsi128_pd(_mm_cmpeq_epi32( _mm_and_si128(offsetSin,ione), izero));
+    cosMask = gmx_castsi128_pd(_mm_cmpeq_epi32( _mm_and_si128(offsetCos,ione), izero));
     
     ts     = _mm_or_pd( _mm_and_pd(sinMask,sx) , _mm_andnot_pd(sinMask,cx) );
     tc     = _mm_or_pd( _mm_and_pd(cosMask,sx) , _mm_andnot_pd(cosMask,cx) );
        
     /* Flip the sign of the result when (offset mod 4) = 1 or 2 */
-    sinMask = (__m128d) _mm_cmpeq_epi32( _mm_and_si128(offsetSin,itwo), izero);
+    sinMask = gmx_castsi128_pd(_mm_cmpeq_epi32( _mm_and_si128(offsetSin,itwo), izero));
     tsn    = _mm_xor_pd(signbit,ts);
     ts     = _mm_or_pd( _mm_and_pd(sinMask,ts) , _mm_andnot_pd(sinMask,tsn) );
        
-    cosMask = (__m128d) _mm_cmpeq_epi32( _mm_and_si128(offsetCos,itwo), izero);
+    cosMask = gmx_castsi128_pd(_mm_cmpeq_epi32( _mm_and_si128(offsetCos,itwo), izero));
     tcn    = _mm_xor_pd(signbit,tc);
     tc     = _mm_or_pd( _mm_and_pd(cosMask,tc) , _mm_andnot_pd(cosMask,tcn) );
        
@@ -590,7 +592,7 @@ calc_gb_rad_still_sse2_double(t_commrec *cr, t_forcerec *fr,int natoms, gmx_loca
                _mm_store_sd(born->gpol_still_work+ai,gpi);
        }
        
-       /* Parallell summations */
+       /* Parallel summations */
        if(PARTDECOMP(cr))
        {
                gmx_sum(natoms,born->gpol_still_work, cr);
@@ -609,7 +611,7 @@ calc_gb_rad_still_sse2_double(t_commrec *cr, t_forcerec *fr,int natoms, gmx_loca
                        gpi2   = gpi_ai*gpi_ai;
                        
                        born->bRad[i]=factor*gmx_invsqrt(gpi2);
-                       fr->invsqrta[i]=gmx_invsqrt(born->bRad[ai]);
+                       fr->invsqrta[i]=gmx_invsqrt(born->bRad[i]);
                }
        }
        
@@ -1828,7 +1830,7 @@ calc_gb_rad_obc_sse2_double(t_commrec *cr, t_forcerec * fr, int natoms, gmx_loca
                        born->bRad[i] = rr_inv - tsum*rr_inv2;
                        born->bRad[i] = 1.0 / born->bRad[i];
                        
-                       fr->invsqrta[ai]=gmx_invsqrt(born->bRad[ai]);
+                       fr->invsqrta[i] = gmx_invsqrt(born->bRad[i]);
                        
                        tchain  = rr * (born->obc_alpha-2*born->obc_beta*sum+3*born->obc_gamma*sum2);
                        born->drobc[i] = (1.0-tsum*tsum)*tchain*rr_inv2;
index 57cece8b60682e29522b02c940de4ef837446c90..1dba21578623d9076b4abdb1c540eaec9378137c 100644 (file)
@@ -1,5 +1,39 @@
+/*
+ * 
+ *                This source code is part of
+ * 
+ *                 G   R   O   M   A   C   S
+ * 
+ *          GROningen MAchine for Chemical Simulations
+ * 
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2008, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ * 
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ * 
+ * For more info, check our website at http://www.gromacs.org
+ * 
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
 #ifndef _genborn_sse2_double_h
 #define _genborn_sse2_double_h
+
 #ifdef HAVE_CONFIG_H
 #include <config.h>
 #endif
index 8176a0ed867f671eb08ddefa11a0b516c5893bb7..017574d191192fd48bf5e6340e4852c97d59a0c3 100644 (file)
 #include <xmmintrin.h>
 #include <emmintrin.h>
 
+#include "genborn_sse2_single.h"
+
 
 int 
-calc_gb_rad_still_sse(t_commrec *cr, t_forcerec *fr,int natoms, gmx_localtop_t *top,
-                                         const t_atomtypes *atype, float *x, t_nblist *nl, gmx_genborn_t *born, t_mdatoms *md)
+calc_gb_rad_still_sse(t_commrec *cr, t_forcerec *fr,
+                     int natoms, gmx_localtop_t *top,
+                     const t_atomtypes *atype, float *x, t_nblist *nl,
+                     gmx_genborn_t *born)
 {
        int i,k,n,ii,is3,ii3,nj0,nj1,offset;
-    int n0,n1;
        int jnrA,jnrB,jnrC,jnrD,j3A,j3B,j3C,j3D;
        int jnrE,jnrF,jnrG,jnrH,j3E,j3F,j3G,j3H;
        int shift;
@@ -137,9 +140,6 @@ calc_gb_rad_still_sse(t_commrec *cr, t_forcerec *fr,int natoms, gmx_localtop_t *
     
        n = 0;
     
-    n0 = md->start;
-    n1 = md->start+md->homenr+natoms/2+1;
-               
        for(i=0;i<natoms;i++)
        {
                work[i]=0;
@@ -1684,9 +1684,9 @@ float gb_bonds_analytic(real *x, real *f, real *charge, real *bRad, real *dvda,
                        xmm3 = _mm_shuffle_ps(xmm3,xmm4,_MM_SHUFFLE(0,0,0,0)); 
                        isaj  = _mm_shuffle_ps(xmm1,xmm3,_MM_SHUFFLE(2,0,2,0));
                        
-                       isaprod = _mm_mul_ps(isai,isaj); // rb2 in tinker
+                       isaprod = _mm_mul_ps(isai,isaj); /* rb2 in tinker */
                        inv_isaprod = _mm_mul_ps(isaprod,isaprod);
-                       inv_isaprod = gmx_mm_inv_ps(inv_isaprod); //1/rb2 in tinker
+                       inv_isaprod = gmx_mm_inv_ps(inv_isaprod); /* 1/rb2 in tinker*/
                        
                        /* Load charges for ai's and aj's */
                        xmm1 = _mm_load_ss(charge+ai1); 
index eca0e23c46347db42b4e7092858b619b7a4b94b2..923b9109080b63186e29ff573cf4643d766c7b68 100644 (file)
 
 float 
 calc_gb_chainrule_sse(int natoms, t_nblist *nl, float *dadx, float *dvda, 
-                                         float *xd, float *f, float *fshift, float *shift_vec, int gb_algorithm, gmx_genborn_t *born, t_mdatoms *md);                                          
-
+                     float *xd, float *f, float *fshift, float *shift_vec,
+                     int gb_algorithm, gmx_genborn_t *born, t_mdatoms *md);
 
 int 
 calc_gb_rad_still_sse(t_commrec *cr, t_forcerec *fr,int natoms, gmx_localtop_t *top,
-                                         const t_atomtypes *atype, float *x, t_nblist *nl, gmx_genborn_t *born, t_mdatoms *md);
+                                         const t_atomtypes *atype, float *x, t_nblist *nl, gmx_genborn_t *born);
 
 int 
 calc_gb_rad_hct_obc_sse(t_commrec *cr, t_forcerec * fr, int natoms, gmx_localtop_t *top,
index ccd36d1441c05b4addc4f86b6eb9e700e48575ce..6ebca5eae460092cf82caca6d80bb06cd4756b5b 100644 (file)
@@ -45,9 +45,9 @@
 #include "coulomb.h"
 #include "pppm.h"
 #include "xvgr.h"
-#include "fftgrid.h"
 #include "gmxfio.h"
 #include "pppm.h"
+#include "smalloc.h"
 
 static void calc_k(rvec lll,int ix,int iy,int iz,int nx,int ny,int nz,rvec k)
 {
@@ -218,6 +218,28 @@ void pr_scalar_gk(const char *fn,const output_env_t oenv,int nx,int ny,int nz,
   gmx_fio_fclose(fp);
 }
 
+static real ***mk_rgrid(int nx,int ny,int nz)
+{
+  real *ptr1;
+  real **ptr2;
+  real ***ptr3;
+  int  i,j,n2,n3;
+
+  snew(ptr1,nx*ny*nz);
+  snew(ptr2,nx*ny);
+  snew(ptr3,nx);
+
+  n2=n3=0;
+  for(i=0; (i<nx); i++) {
+    ptr3[i]=&(ptr2[n2]);
+    for(j=0; (j<ny); j++,n2++) {
+      ptr2[n2] = &(ptr1[n3]);
+      n3 += nz;
+    }
+  }
+  return ptr3;
+}
+
 real ***rd_ghat(FILE *log,const output_env_t oenv,char *fn,ivec igrid,
                 rvec gridspace, rvec beta,int *porder,real *r1,real *rc)
 {
index 41e9007394e663b3c69399df15feef3ddcf5d278..c07a0c3f836c09394f847b94c0fc77be37fe4748 100644 (file)
  * files like gmx_fft_fftw3.c or gmx_fft_intel_mkl.c for that.
  */
 
+#ifndef GMX_FFT_FFTW3
+
+ struct gmx_many_fft {
+     int howmany;
+     int dist;
+     gmx_fft_t fft;
+ };
+
+typedef struct gmx_many_fft* gmx_many_fft_t ;
+
+int
+gmx_fft_init_many_1d(gmx_fft_t *        pfft,
+                    int                nx,
+                    int                howmany,
+                    gmx_fft_flag       flags) 
+{
+    gmx_many_fft_t fft;
+    if(pfft==NULL)
+    {
+        gmx_fatal(FARGS,"Invalid opaque FFT datatype pointer.");
+        return EINVAL;
+    }
+    *pfft = NULL;
+    
+    if( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
+    {
+        return ENOMEM;
+    }
+
+    gmx_fft_init_1d(&fft->fft,nx,flags);
+    fft->howmany = howmany;
+    fft->dist = 2*nx;
+
+    *pfft = (gmx_fft_t)fft;
+    return 0;
+}
+
+int
+gmx_fft_init_many_1d_real(gmx_fft_t *        pfft,
+                    int                nx,
+                    int                howmany,
+                    gmx_fft_flag       flags) 
+{
+    gmx_many_fft_t fft;
+    if(pfft==NULL)
+    {
+        gmx_fatal(FARGS,"Invalid opaque FFT datatype pointer.");
+        return EINVAL;
+    }
+    *pfft = NULL;
+    
+    if( (fft = (gmx_many_fft_t)malloc(sizeof(struct gmx_many_fft))) == NULL)
+    {
+        return ENOMEM;
+    }
+
+    gmx_fft_init_1d_real(&fft->fft,nx,flags);
+    fft->howmany = howmany;
+    fft->dist = 2*(nx/2+1);
+
+    *pfft = (gmx_fft_t)fft;
+    return 0;
+}
+
+int
+gmx_fft_many_1d     (gmx_fft_t                  fft,
+                     enum gmx_fft_direction     dir,
+                     void *                     in_data,
+                     void *                     out_data)
+{
+    gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
+    int i,ret;
+    for (i=0;i<mfft->howmany;i++) 
+    {
+        ret=gmx_fft_1d(mfft->fft,dir,in_data,out_data);
+        if (ret!=0) return ret;
+        in_data=(real*)in_data+mfft->dist;
+        out_data=(real*)out_data+mfft->dist;
+    }
+    return 0;
+}
+
+int
+gmx_fft_many_1d_real     (gmx_fft_t                  fft,
+                          enum gmx_fft_direction     dir,
+                          void *                     in_data,
+                          void *                     out_data)
+{
+    gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
+    int i,ret;
+    for (i=0;i<mfft->howmany;i++) 
+    {
+        ret=gmx_fft_1d_real(mfft->fft,dir,in_data,out_data);
+        if (ret!=0) return ret;
+        in_data=(real*)in_data+mfft->dist;
+        out_data=(real*)out_data+mfft->dist;
+    }
+    return 0;
+}
+
+
+void
+gmx_many_fft_destroy(gmx_fft_t    fft)
+{
+    gmx_many_fft_t mfft = (gmx_many_fft_t)fft;
+    if (mfft!=NULL) 
+    {
+        if (mfft->fft!=NULL) 
+        {
+            gmx_fft_destroy(mfft->fft);
+        }
+        free(mfft);
+    }
+}
+
+#endif
+
 int gmx_fft_transpose_2d(t_complex *          in_data,
                          t_complex *          out_data,
                          int                  nx,
index add9b1da419b418690c6f6aac1992838987c390d..8fd8b6afabfbce817f8d69d5c4bf8319b6162ba2 100644 (file)
@@ -69,6 +69,16 @@ int
 gmx_fft_init_1d(gmx_fft_t *        pfft,
                 int                nx,
                 gmx_fft_flag       flags) 
+{
+    return gmx_fft_init_many_1d(pfft,nx,1,flags);
+}
+
+
+int
+gmx_fft_init_many_1d(gmx_fft_t *        pfft,
+                    int                nx,
+                    int                howmany,
+                    gmx_fft_flag       flags) 
 {
     gmx_fft_t              fft;
     FFTWPREFIX(complex)   *p1,*p2,*up1,*up2;
@@ -97,7 +107,7 @@ gmx_fft_init_1d(gmx_fft_t *        pfft,
     }    
     
     /* allocate aligned, and extra memory to make it unaligned */
-    p1  = (FFTWPREFIX(complex) *) FFTWPREFIX(malloc)(sizeof(FFTWPREFIX(complex))*(nx+2));
+    p1  = (FFTWPREFIX(complex) *) FFTWPREFIX(malloc)(sizeof(FFTWPREFIX(complex))*(nx+2)*howmany);
     if(p1==NULL)
     {
         FFTWPREFIX(free)(fft);
@@ -105,7 +115,7 @@ gmx_fft_init_1d(gmx_fft_t *        pfft,
         return ENOMEM;
     }
     
-    p2  = (FFTWPREFIX(complex) *) FFTWPREFIX(malloc)(sizeof(FFTWPREFIX(complex))*(nx+2));
+    p2  = (FFTWPREFIX(complex) *) FFTWPREFIX(malloc)(sizeof(FFTWPREFIX(complex))*(nx+2)*howmany);
     if(p2==NULL)
     {
         FFTWPREFIX(free)(p1);
@@ -126,15 +136,20 @@ gmx_fft_init_1d(gmx_fft_t *        pfft,
     pc += 8; 
     up2 = (FFTWPREFIX(complex) *)pc;
     
-    fft->plan[0][0][0] = FFTWPREFIX(plan_dft_1d)(nx,up1,up2,FFTW_BACKWARD,fftw_flags); 
-    fft->plan[0][0][1] = FFTWPREFIX(plan_dft_1d)(nx,up1,up2,FFTW_FORWARD,fftw_flags); 
-    fft->plan[0][1][0] = FFTWPREFIX(plan_dft_1d)(nx,up1,up1,FFTW_BACKWARD,fftw_flags);  
-    fft->plan[0][1][1] = FFTWPREFIX(plan_dft_1d)(nx,up1,up1,FFTW_FORWARD,fftw_flags);  
-    fft->plan[1][0][0] = FFTWPREFIX(plan_dft_1d)(nx,p1,p2,FFTW_BACKWARD,fftw_flags); 
-    fft->plan[1][0][1] = FFTWPREFIX(plan_dft_1d)(nx,p1,p2,FFTW_FORWARD,fftw_flags); 
-    fft->plan[1][1][0] = FFTWPREFIX(plan_dft_1d)(nx,p1,p1,FFTW_BACKWARD,fftw_flags); 
-    fft->plan[1][1][1] = FFTWPREFIX(plan_dft_1d)(nx,p1,p1,FFTW_FORWARD,fftw_flags); 
-
+    /*                            int rank, const int *n, int howmany,
+                                  fftw_complex *in, const int *inembed,
+                                  int istride, int idist,
+                                  fftw_complex *out, const int *onembed,
+                                  int ostride, int odist,
+                                  int sign, unsigned flags */
+    fft->plan[0][0][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up2,&nx,1,nx,FFTW_BACKWARD,fftw_flags); 
+    fft->plan[0][0][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up2,&nx,1,nx,FFTW_FORWARD,fftw_flags); 
+    fft->plan[0][1][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up1,&nx,1,nx,FFTW_BACKWARD,fftw_flags); 
+    fft->plan[0][1][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,up1,&nx,1,nx,up1,&nx,1,nx,FFTW_FORWARD,fftw_flags); 
+    fft->plan[1][0][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p2,&nx,1,nx,FFTW_BACKWARD,fftw_flags); 
+    fft->plan[1][0][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p2,&nx,1,nx,FFTW_FORWARD,fftw_flags); 
+    fft->plan[1][1][0] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p1,&nx,1,nx,FFTW_BACKWARD,fftw_flags); 
+    fft->plan[1][1][1] = FFTWPREFIX(plan_many_dft)(1,&nx,howmany,p1,&nx,1,nx,p1,&nx,1,nx,FFTW_FORWARD,fftw_flags); 
 
     for(i=0;i<2;i++)
     {
@@ -169,11 +184,19 @@ gmx_fft_init_1d(gmx_fft_t *        pfft,
 }
 
 
-
 int
 gmx_fft_init_1d_real(gmx_fft_t *        pfft,
                      int                nx,
                      gmx_fft_flag       flags) 
+{
+    return gmx_fft_init_many_1d_real(pfft, nx, 1, flags);
+}
+
+int
+gmx_fft_init_many_1d_real(gmx_fft_t *        pfft,
+                     int                nx,
+                     int                howmany,
+                     gmx_fft_flag       flags) 
 {
     gmx_fft_t              fft;
     real            *p1,*p2,*up1,*up2;
@@ -202,7 +225,7 @@ gmx_fft_init_1d_real(gmx_fft_t *        pfft,
     }    
     
     /* allocate aligned, and extra memory to make it unaligned */
-    p1  = (real *) FFTWPREFIX(malloc)(sizeof(real)*(nx+2));
+    p1  = (real *) FFTWPREFIX(malloc)(sizeof(real)*(nx/2+1)*2*howmany + 8);
     if(p1==NULL)
     {
         FFTWPREFIX(free)(fft);
@@ -210,7 +233,7 @@ gmx_fft_init_1d_real(gmx_fft_t *        pfft,
         return ENOMEM;
     }
     
-    p2  = (real *) FFTWPREFIX(malloc)(sizeof(real)*(nx+2));
+    p2  = (real *) FFTWPREFIX(malloc)(sizeof(real)*(nx/2+1)*2*howmany + 8);
     if(p2==NULL)
     {
         FFTWPREFIX(free)(p1);
@@ -231,17 +254,21 @@ gmx_fft_init_1d_real(gmx_fft_t *        pfft,
     pc += 8; 
     up2 = (real *)pc;
     
-    
-    fft->plan[0][0][0] = FFTWPREFIX(plan_dft_c2r_1d)(nx,(FFTWPREFIX(complex) *)up1,up2,fftw_flags); 
-    fft->plan[0][0][1] = FFTWPREFIX(plan_dft_r2c_1d)(nx,up1,(FFTWPREFIX(complex) *)up2,fftw_flags); 
-    fft->plan[0][1][0] = FFTWPREFIX(plan_dft_c2r_1d)(nx,(FFTWPREFIX(complex) *)up1,up1,fftw_flags);  
-    fft->plan[0][1][1] = FFTWPREFIX(plan_dft_r2c_1d)(nx,up1,(FFTWPREFIX(complex) *)up1,fftw_flags);  
-
-    fft->plan[1][0][0] = FFTWPREFIX(plan_dft_c2r_1d)(nx,(FFTWPREFIX(complex) *)p1,p2,fftw_flags); 
-    fft->plan[1][0][1] = FFTWPREFIX(plan_dft_r2c_1d)(nx,p1,(FFTWPREFIX(complex) *)p2,fftw_flags); 
-    fft->plan[1][1][0] = FFTWPREFIX(plan_dft_c2r_1d)(nx,(FFTWPREFIX(complex) *)p1,p1,fftw_flags); 
-    fft->plan[1][1][1] = FFTWPREFIX(plan_dft_r2c_1d)(nx,p1,(FFTWPREFIX(complex) *)p1,fftw_flags); 
-
+    /*                                int rank, const int *n, int howmany,
+                                      double *in, const int *inembed,
+                                      int istride, int idist,
+                                      fftw_complex *out, const int *onembed,
+                                      int ostride, int odist,
+                                      unsigned flag    */
+    fft->plan[0][0][1] = FFTWPREFIX(plan_many_dft_r2c)(1,&nx,howmany,up1,0,1,(nx/2+1)*2,(FFTWPREFIX(complex) *)up2,0,1,(nx/2+1),fftw_flags); 
+    fft->plan[0][1][1] = FFTWPREFIX(plan_many_dft_r2c)(1,&nx,howmany,up1,0,1,(nx/2+1)*2,(FFTWPREFIX(complex) *)up1,0,1,(nx/2+1),fftw_flags);
+    fft->plan[1][0][1] = FFTWPREFIX(plan_many_dft_r2c)(1,&nx,howmany, p1,0,1,(nx/2+1)*2,(FFTWPREFIX(complex) *)p2 ,0,1,(nx/2+1),fftw_flags);
+    fft->plan[1][1][1] = FFTWPREFIX(plan_many_dft_r2c)(1,&nx,howmany, p1,0,1,(nx/2+1)*2,(FFTWPREFIX(complex) *)p1 ,0,1,(nx/2+1),fftw_flags);
+
+    fft->plan[0][0][0] = FFTWPREFIX(plan_many_dft_c2r)(1,&nx,howmany,(FFTWPREFIX(complex) *)up1,0,1,(nx/2+1),up2,0,1,(nx/2+1)*2,fftw_flags); 
+    fft->plan[0][1][0] = FFTWPREFIX(plan_many_dft_c2r)(1,&nx,howmany,(FFTWPREFIX(complex) *)up1,0,1,(nx/2+1),up1,0,1,(nx/2+1)*2,fftw_flags); 
+    fft->plan[1][0][0] = FFTWPREFIX(plan_many_dft_c2r)(1,&nx,howmany,(FFTWPREFIX(complex) *) p1,0,1,(nx/2+1), p2,0,1,(nx/2+1)*2,fftw_flags); 
+    fft->plan[1][1][0] = FFTWPREFIX(plan_many_dft_c2r)(1,&nx,howmany,(FFTWPREFIX(complex) *) p1,0,1,(nx/2+1), p1,0,1,(nx/2+1)*2,fftw_flags); 
 
     for(i=0;i<2;i++)
     {
@@ -735,6 +762,14 @@ gmx_fft_1d               (gmx_fft_t                  fft,
     return 0;
 }
 
+int
+gmx_fft_many_1d               (gmx_fft_t                  fft,
+                              enum gmx_fft_direction     dir,
+                              void *                     in_data,
+                              void *                     out_data)
+{
+    return gmx_fft_1d(fft,dir,in_data,out_data);
+}
 
 int 
 gmx_fft_1d_real          (gmx_fft_t                  fft,
@@ -768,6 +803,14 @@ gmx_fft_1d_real          (gmx_fft_t                  fft,
     return 0;
 }
 
+int 
+gmx_fft_many_1d_real     (gmx_fft_t                  fft,
+                          enum gmx_fft_direction     dir,
+                          void *                     in_data,
+                          void *                     out_data)
+{
+    return gmx_fft_1d_real(fft,dir,in_data,out_data);
+}
 
 int 
 gmx_fft_2d               (gmx_fft_t                  fft,
@@ -923,6 +966,12 @@ gmx_fft_destroy(gmx_fft_t      fft)
 
 }
 
+void
+gmx_many_fft_destroy(gmx_fft_t    fft)
+{
+    gmx_fft_destroy(fft);
+}
+
 #else
 int
 gmx_fft_fftw2_empty;
index d0d2ed154ee8f44a8b3ef9cc07427c4f5b4ef88e..e94bb24acd67f35149e27c24607c96e257c64011 100644 (file)
@@ -23,8 +23,6 @@
 #include <string.h>
 #include <errno.h>
 
-#ifdef GMX_MPI
-
 #ifdef GMX_LIB_MPI 
 #include <mpi.h>
 #endif
 #include "tmpi.h"
 #endif
 
-
+#include "smalloc.h"
 #include "gmx_parallel_3dfft.h"
 #include "gmx_fft.h"
 #include "gmxcomplex.h"
 #include "gmx_fatal.h"
 
-typedef struct {
-    int             *sdisps;
-    int             *scounts;
-    int             *rdisps;
-    int             *rcounts;
-} alltoallv_t;
+#include "fft5d.h"
 
-struct gmx_parallel_3dfft 
-{
-    int             nx;
-    int             ny;
-    int             nz;
-    int             nzc;
-    int             local_slab;
-    int             nnodes;
-    gmx_fft_t       fft_yz;
-    gmx_fft_t       fft_x;
-    void *          work_rawptr;
-       void *          work2_rawptr;
-    t_complex *     work;
-    t_complex *     work2;
-    int             *node2slab;
-    int             *slab2grid_x;
-    int             *slab2grid_y;
-    alltoallv_t     *aav;
-    MPI_Comm        comm;
+struct gmx_parallel_3dfft  { 
+    fft5d_plan p1,p2;    
 };
 
+
 static int *copy_int_array(int n,int *src)
 {
     int *dest,i;
@@ -92,450 +69,131 @@ static int *make_slab2grid(int nnodes,int ngrid)
 
 int
 gmx_parallel_3dfft_init   (gmx_parallel_3dfft_t *    pfft_setup,
-                           int                       ngridx,
-                           int                       ngridy,
-                           int                       ngridz,
-                           int                       *node2slab,
-                           int                       *slab2grid_x,
-                           MPI_Comm                  comm,
+                           ivec                      ndata,
+                                                  real **                   real_data,
+                                                  t_complex **              complex_data,
+                           MPI_Comm                  comm[2],
+                           int *                     slab2index_major,
+                           int *                     slab2index_minor,
                            bool                      bReproducible)
 {
-    gmx_parallel_3dfft_t p;
-    int  nxy_n;
-    void *p0;
-    int  flags;
-    
-    flags = bReproducible ? GMX_FFT_FLAG_CONSERVATIVE : 0;
+    int rN=ndata[2],M=ndata[1],K=ndata[0];
+    int flags = FFT5D_REALCOMPLEX | FFT5D_ORDER_YZ; /* FFT5D_DEBUG */
+    MPI_Comm rcomm[]={comm[1],comm[0]};
+    int Nb,Mb,Kb; /* dimension for backtransform (in starting order) */
     
-    p = (gmx_parallel_3dfft_t)malloc(sizeof(struct gmx_parallel_3dfft));
+    snew(*pfft_setup,1);
+    if (bReproducible) flags |= FFT5D_NOMEASURE; 
     
-    if(p==NULL)
-        return ENOMEM;
-    
-    p->nx  = ngridx;
-    p->ny  = ngridy;
-    p->nz  = ngridz;
-    p->nzc = ngridz/2 + 1;
-
-    MPI_Comm_rank( comm , &(p->local_slab) );
-    
-    MPI_Comm_dup( comm , &(p->comm) );
-
-    MPI_Comm_size( p->comm , &p->nnodes);
-
-    if (node2slab)
-        p->node2slab = copy_int_array(p->nnodes,node2slab);
-    else
-        p->node2slab = NULL;
-
-    if (p->node2slab)
-        p->local_slab = p->node2slab[p->local_slab];
-        
-    MPI_Comm_dup( comm , &(p->comm) );
-
-    MPI_Comm_size( p->comm , &p->nnodes);
-
-    if (slab2grid_x)
-        p->slab2grid_x = copy_int_array(p->nnodes+1,slab2grid_x);
-    else
-        p->slab2grid_x = make_slab2grid(p->nnodes,p->nx);
-    p->slab2grid_y     = make_slab2grid(p->nnodes,p->ny);
-
-    if (node2slab || p->nx % p->nnodes || p->ny % p->nnodes) {
-        p->aav = (alltoallv_t*)malloc(sizeof(alltoallv_t));
-        p->aav->sdisps  = (int*)malloc(p->nnodes*sizeof(int));
-        p->aav->scounts = (int*)malloc(p->nnodes*sizeof(int));
-        p->aav->rdisps  = (int*)malloc(p->nnodes*sizeof(int));
-        p->aav->rcounts = (int*)malloc(p->nnodes*sizeof(int));
+    if (!(flags&FFT5D_ORDER_YZ)) { 
+        Nb=M;Mb=K;Kb=rN;               
     } else {
-        p->aav  = NULL;
+        Nb=K;Mb=rN;Kb=M;  /* currently always true because ORDER_YZ always set */
     }
-
-    /* initialize transforms */
-    if ( ( gmx_fft_init_1d(&(p->fft_x),ngridx,flags) != 0 ) ||
-         ( gmx_fft_init_2d_real(&(p->fft_yz),ngridy,ngridz,flags) != 0))
-    {
-        free(p);
-        return -1;
-    }
-
-    /* Round up */
-    nxy_n = p->nnodes*((p->nx + p->nnodes - 1)/p->nnodes)*
-                      ((p->ny + p->nnodes - 1)/p->nnodes);
-
     
-    p0               = (real*)malloc(sizeof(real)*2*(p->nzc)*nxy_n + 32);
-    p->work_rawptr   = p0;
-    p->work          = (t_complex*) ((void *) (((size_t) p0 + 32) & 
-                                                (~((size_t) 31))));
-
-    p0               = (real*)malloc(sizeof(real)*2*(p->nzc)*nxy_n);
-    p->work2_rawptr  = p0;
-    p->work2         = (t_complex*) ((void *) (((size_t) p0 + 32) & 
-                                                (~((size_t) 31))));
+    (*pfft_setup)->p1 = fft5d_plan_3d(rN,M,K,rcomm, flags, (t_complex**)real_data, complex_data);
     
-    if(p->work == NULL || p->work2 == NULL)
-    {
-        if(p->work_rawptr != NULL)
-            free(p->work_rawptr);
-        if(p->work2_rawptr != NULL)
-            free(p->work2_rawptr);
-        free(p);
-        return ENOMEM;
-    }
-
-    *pfft_setup = p;
-    
-    return 0;
-}
-
-
-
-
-int
-gmx_parallel_3dfft_limits(gmx_parallel_3dfft_t      pfft_setup,
-                          int *                     local_x_start,
-                          int *                     local_nx,
-                          int *                     local_y_start,
-                          int *                     local_ny)
-{
-    int slab;
-
-    slab = pfft_setup->local_slab;
-
-    *local_x_start = pfft_setup->slab2grid_x[slab];
-    *local_y_start = pfft_setup->slab2grid_y[slab];
-
-    *local_nx = pfft_setup->slab2grid_x[slab+1] - (*local_x_start);
-    *local_ny = pfft_setup->slab2grid_y[slab+1] - (*local_y_start);
+    (*pfft_setup)->p2 = fft5d_plan_3d(Nb,Mb,Kb,rcomm,
+                                      (flags|FFT5D_BACKWARD|FFT5D_NOMALLOC)^FFT5D_ORDER_YZ, complex_data, (t_complex**)real_data);
     
-    return 0;
+    return (*pfft_setup)->p1 != 0 && (*pfft_setup)->p2 !=0;
 }
 
 
-                   
-int
-gmx_parallel_transpose_xy(t_complex *   data,
-                          t_complex *   work,
-                          int           nx,
-                          int           ny,
-                          int           local_slab,
-                          int           *s2x,
-                          int           *s2y,
-                          int           nzc,
-                          int           nnodes,
-                          int           *node2slab,
-                          alltoallv_t   *aav,
-                          MPI_Comm      comm)
+static int
+fft5d_limits(fft5d_plan p, 
+             ivec                      local_ndata,
+             ivec                      local_offset,
+             ivec                      local_size) 
 {
-    int     i,j;
-    int     local_nx,local_ny,blocksize,slab;
+    int N1,M0,K0,K1,*coor;
+    fft5d_local_size(p,&N1,&M0,&K0,&K1,&coor);  /* M0=MG/P[0], K1=KG/P[1], NG,MG,KG global sizes */
     
-    local_nx = s2x[local_slab+1] - s2x[local_slab];
-    local_ny = s2y[local_slab+1] - s2y[local_slab];
+    local_offset[2]=0;
+    local_offset[1]=p->oM[0];  /*=p->coor[0]*p->MG/p->P[0]; */
+    local_offset[0]=p->oK[0];  /*=p->coor[1]*p->KG/p->P[1]; */
     
-    /* A: Do a local transpose to get data continuous for communication.
-    *     We can use NULL for the workarray since we do it out-of-place.
-    */
-    gmx_fft_transpose_2d_nelem(data,work,local_nx,ny,nzc,NULL);
+    local_ndata[2]=p->rC[0];
+    local_ndata[1]=p->pM[0]; 
+    local_ndata[0]=p->pK[0]; 
     
-    /* B: Parallel communication, exchange data blocks. */
-    if (aav == NULL) {
-        blocksize = local_nx*local_ny*nzc*2;
-        MPI_Alltoall(work,
-                     blocksize,
-                     GMX_MPI_REAL,
-                     data,
-                     blocksize,
-                     GMX_MPI_REAL,
-                     comm);
+    if ((!(p->flags&FFT5D_BACKWARD)) && (p->flags&FFT5D_REALCOMPLEX)) {
+        local_size[2]=p->C[0]*2;
     } else {
-        for(i=0; i<nnodes; i++) {
-            slab = (node2slab ? node2slab[i] : i);
-            aav->sdisps [i] =                s2y[slab] *local_nx*nzc*2;
-            aav->scounts[i] = (s2y[slab+1] - s2y[slab])*local_nx*nzc*2;
-            aav->rdisps [i] = local_ny*               s2x[slab] *nzc*2;
-            aav->rcounts[i] = local_ny*(s2x[slab+1] - s2x[slab])*nzc*2;
-        }
-        MPI_Alltoallv(work,
-                      aav->scounts,aav->sdisps,
-                      GMX_MPI_REAL,
-                      data,
-                      aav->rcounts,aav->rdisps,
-                      GMX_MPI_REAL,
-                      comm);
-    }
-        
-    /* C: Copy entire blocks into place, so we have YXZ. */
-    for(j=0;j<local_ny;j++)
-    {
-        for(i=0;i<nnodes;i++)
-        {
-            memcpy(work + j*nx*nzc + s2x[i]*nzc,
-                   data + s2x[i]*local_ny*nzc + j*(s2x[i+1] - s2x[i])*nzc,
-                   (s2x[i+1] - s2x[i])*nzc*sizeof(t_complex));
-        }
+        local_size[2]=p->C[0];
     }
+    local_size[1]=p->pM[0]; 
+    local_size[0]=p->pK[0]; 
     return 0;
 }
 
-                       
 int
-gmx_parallel_3dfft(gmx_parallel_3dfft_t    pfft_setup,
-                   enum gmx_fft_direction  dir,
-                   void *                  in_data,
-                   void *                  out_data)
-{
-    int          i,j,k;
-    int          nx,ny,nz,nzc,nzr;
-    int          local_x_start,local_nx;
-    int          local_y_start,local_ny;    
-    t_complex *  work;
-    real *       rdata;
-    t_complex *  cdata;
-    t_complex *  ctmp;
-    
-    work    = pfft_setup->work;
-    
-    /* When we do in-place FFTs the data need to be embedded in the z-dimension,
-     * so there is room for the complex data. This means the direct space
-     * _grid_ (not data) dimensions will be nx*ny*(nzc*2), where nzc=nz/2+1.
-     * If we do out-of-place transforms the direct space dimensions are simply
-     * nx*ny*nz, and no embedding is used.
-     * The complex dimensions are always ny*nx*nzc (note the transpose).
-     *
-     * The direct space _grid_ dimension is nzr.
-     */
-    
-    nx  = pfft_setup->nx;
-    ny  = pfft_setup->ny;
-    nz  = pfft_setup->nz;
-    nzc = pfft_setup->nzc;
-    
-    if(in_data == out_data)
-    {
-        nzr = 2*nzc;
-    }
-    else
-    {
-        nzr = nz;
-    }
-
-    gmx_parallel_3dfft_limits(pfft_setup,
-                              &local_x_start,
-                              &local_nx,
-                              &local_y_start,
-                              &local_ny);
-
-    if(dir == GMX_FFT_REAL_TO_COMPLEX)
-    {
-        rdata =      (real *)in_data  + local_x_start*ny*nzr;
-        cdata = (t_complex *)out_data + local_x_start*ny*nzc;
-        
-        /* Perform nx local 2D real-to-complex FFTs in the yz slices.
-         * When the input data is "embedded" for 3D-in-place transforms, this
-         * must also be done in-place to get the data embedding right.
-         * 
-         * Note that rdata==cdata when we work in-place. 
-         */
-        for(i=0;i<local_nx;i++)
-        {
-            gmx_fft_2d_real(pfft_setup->fft_yz,
-                            GMX_FFT_REAL_TO_COMPLEX,
-                            rdata + i*ny*nzr,
-                            cdata + i*ny*nzc);
-        }
-        
-        /* Transpose to temporary work array */
-        gmx_parallel_transpose_xy(cdata,
-                                  work,
-                                  nx,
-                                  ny,
-                                  pfft_setup->local_slab,
-                                  pfft_setup->slab2grid_x,
-                                  pfft_setup->slab2grid_y,
-                                  nzc,
-                                  pfft_setup->nnodes,
-                                  pfft_setup->node2slab,
-                                  pfft_setup->aav,
-                                  pfft_setup->comm);
-
-        /* Transpose from temporary work array in order YXZ to
-         * the output array in order YZX. 
-         */ 
-        /* output cdata changes when nx or ny not divisible by nnodes */
-        cdata = (t_complex *)out_data + local_y_start*nx*nzc;
-        for(j=0;j<local_ny;j++)
-        {
-            gmx_fft_transpose_2d(work  + j*nzc*nx,
-                                 cdata + j*nzc*nx,
-                                 nx,
-                                 nzc);
-        }
-
-        /* Perform local_ny*nzc complex FFTs along the x dimension */
-        for(i=0;i<local_ny*nzc;i++)
-        {
-            gmx_fft_1d(pfft_setup->fft_x,
-                       GMX_FFT_FORWARD,
-                       cdata + i*nx,
-                       work  + i*nx);
-        }    
-    
-        /* Transpose back from YZX to YXZ. */
-        for(j=0;j<local_ny;j++)
-        {
-            gmx_fft_transpose_2d(work  + j*nzc*nx,
-                                 cdata + j*nzc*nx,
-                                 nzc,
-                                 nx);
-        }
-    }
-    else if(dir == GMX_FFT_COMPLEX_TO_REAL)
-    {
-        cdata = (t_complex *)in_data  + local_y_start*nx*nzc;
-        rdata =      (real *)out_data + local_x_start*ny*nzr;
-        
-        /* If we are working in-place it doesn't matter that we destroy
-         * input data. Otherwise we use an extra temporary workspace array.
-         */
-        if(in_data == out_data)
-        {
-            ctmp = cdata;
-        }
-        else
-        {
-            ctmp = pfft_setup->work2;
-        }
-                
-        /* Transpose from YXZ to YZX. */
-        for(j=0;j<local_ny;j++)
-        {
-            gmx_fft_transpose_2d(cdata + j*nzc*nx,
-                                 work  + j*nzc*nx,
-                                 nx,
-                                 nzc);
-        }
-        
-        /* Perform local_ny*nzc complex FFTs along the x dimension */
-        for(i=0;i<local_ny*nzc;i++)
-        {
-            gmx_fft_1d(pfft_setup->fft_x,
-                       GMX_FFT_BACKWARD,
-                       work + i*nx,
-                       ctmp + i*nx);
-        }    
-        
-        /* Transpose from YZX to YXZ. */
-        for(j=0;j<local_ny;j++)
-        {
-            gmx_fft_transpose_2d(ctmp + j*nzc*nx,
-                                 work + j*nzc*nx,
-                                 nzc,
-                                 nx);
-        }
-        
-        if(in_data == out_data)
-        {
-            /* output cdata changes when nx or ny not divisible by nnodes */
-           ctmp = (t_complex *)in_data + local_x_start*ny*nzc;
-        }
-        gmx_parallel_transpose_xy(work,
-                                  ctmp,
-                                  ny,
-                                  nx,
-                                  pfft_setup->local_slab,
-                                  pfft_setup->slab2grid_y,
-                                  pfft_setup->slab2grid_x,
-                                  nzc,
-                                  pfft_setup->nnodes,
-                                  pfft_setup->node2slab,
-                                  pfft_setup->aav,
-                                  pfft_setup->comm);
-        
-        
-        /* Perform nx local 2D complex-to-real FFTs in the yz slices.
-         * The 3D FFT is done in-place, so we need to do this in-place too in order
-         * to get the data organization right.
-         */
-        for(i=0;i<local_nx;i++)
-        {
-            gmx_fft_2d_real(pfft_setup->fft_yz,
-                            GMX_FFT_COMPLEX_TO_REAL,
-                            ctmp  + i*ny*nzc,
-                            rdata + i*ny*nzr);
-        }
-    }
-    else
-    {
-        gmx_fatal(FARGS,"Incorrect FFT direction.");
-    }
-    
-    /* Skip the YX backtranspose to save communication! Grid is now YXZ */
-    return 0;
+gmx_parallel_3dfft_real_limits(gmx_parallel_3dfft_t      pfft_setup,
+                               ivec                      local_ndata,
+                               ivec                      local_offset,
+                               ivec                      local_size) {
+    return fft5d_limits(pfft_setup->p1,local_ndata,local_offset,local_size);
 }
 
+static void reorder_ivec_yzx(ivec v)
+{
+    real tmp;
 
-
+    tmp   = v[0];
+    v[XX] = v[2];
+    v[ZZ] = v[1];
+    v[YY] = tmp;
+}
 
 int
-gmx_parallel_3dfft_complex2real(gmx_parallel_3dfft_t    pfft_setup,
-                                void *                  data)
+gmx_parallel_3dfft_complex_limits(gmx_parallel_3dfft_t      pfft_setup,
+                                  ivec                      complex_order,
+                                  ivec                      local_ndata,
+                                  ivec                      local_offset,
+                                  ivec                      local_size) 
 {
-    int          i,j,k;
-    int          nx,ny,nzc;
-    int          local_x_start,local_nx;
-    int          local_y_start,local_ny;    
-    t_complex *  work;
-    t_complex *  cdata;
-    
-    work    = pfft_setup->work;
-    cdata   = (t_complex*)data;
+    int ret;
 
-    nx  = pfft_setup->nx;
-    ny  = pfft_setup->ny;
-    nzc = pfft_setup->nzc;
-    
-    gmx_parallel_3dfft_limits(pfft_setup,
-                              &local_x_start,
-                              &local_nx,
-                              &local_y_start,
-                              &local_ny);
+    /* For now everything is in-order, but prepare to save communication by avoiding transposes */
+    complex_order[0] = 0;
+    complex_order[1] = 1;
+    complex_order[2] = 2;
 
-    
-    
-    return 0;    
-}
+    ret = fft5d_limits(pfft_setup->p2,local_ndata,local_offset,local_size);
 
+    reorder_ivec_yzx(local_ndata);
+    reorder_ivec_yzx(local_offset);
+    reorder_ivec_yzx(local_size);
 
+    return ret;
+}
 
-int
-gmx_parallel_3dfft_destroy(gmx_parallel_3dfft_t    pfft_setup)
-{
-    gmx_fft_destroy(pfft_setup->fft_x);
-    gmx_fft_destroy(pfft_setup->fft_yz);
 
-    free(pfft_setup->slab2grid_x);
-    free(pfft_setup->slab2grid_y);
-    if (pfft_setup->aav) {
-        free(pfft_setup->aav->sdisps);
-        free(pfft_setup->aav->scounts);
-        free(pfft_setup->aav->rdisps);
-        free(pfft_setup->aav->rcounts);
-        free(pfft_setup->aav);
+int
+gmx_parallel_3dfft_execute(gmx_parallel_3dfft_t    pfft_setup,
+                           enum gmx_fft_direction  dir,
+                           void *                  in_data,
+                           void *                  out_data) {
+    if ((!(pfft_setup->p1->flags&FFT5D_REALCOMPLEX)) ^ (dir==GMX_FFT_FORWARD ||dir==GMX_FFT_BACKWARD)) { 
+        gmx_fatal(FARGS,"Invalid transform. Plan and execution don't match regarding reel/complex");
+    }
+    if (dir==GMX_FFT_FORWARD || dir==GMX_FFT_REAL_TO_COMPLEX) {
+        fft5d_execute(pfft_setup->p1,0);
+    } else {
+        fft5d_execute(pfft_setup->p2,0);
     }
-    free(pfft_setup->work_rawptr);
-    free(pfft_setup->work2_rawptr);
-
     return 0;
 }
 
-#else
-/* Dummy function to avoid warnings without MPI enabled */
-void
-gmx_parallel_3dfft_dummy()
-{
+int
+gmx_parallel_3dfft_destroy(gmx_parallel_3dfft_t    pfft_setup) {
+    fft5d_destroy(pfft_setup->p2);
+    fft5d_destroy(pfft_setup->p1);
+    sfree(pfft_setup);
+    return 0;
 }
 
-#endif /* GMX_MPI */
+
+
+
 
index ae5f2eafa554c8ea1179ee8e2cd56d9a48882681..5dd96582509bfa3903cc9904be5a061298288dbb 100644 (file)
@@ -11,15 +11,15 @@ typedef struct{
        
 typedef struct gmx_qhop_db_t *gmx_qhop_db;
 
-/* Return database if succesfull, or NULL on failure */
+/* Return database if successful, or NULL on failure */
 extern gmx_qhop_db gmx_qhop_db_read(char *forcefield);
  
-/* Write the database to a filename. Return 1 on succes, or 0 for
+/* Write the database to a filename. Return 1 on success, or 0 for
    failure */
 extern int gmx_qhop_db_write(char *fn,gmx_qhop_db qdb);
 
 /* Destroy the internal datastructures to free memory. Return 1 on
-   succes, 0 for failure */
+   success, 0 for failure */
 extern int gmx_qhop_db_done(gmx_qhop_db qdb);
 
 /* Return the number of states in the database for a given residue
index 90c13ac65df1b3aebec63718099bbf61123ed9b3..7c45738132a1e6ea354c42a58da31729de45602d 100644 (file)
@@ -68,7 +68,7 @@ static char *int_title(const char *title,int nodeid,char buf[], int size)
   return buf;
 }
 
-static void set_state_entries(t_state *state,t_inputrec *ir,int nnodes)
+void set_state_entries(t_state *state,t_inputrec *ir,int nnodes)
 {
   int nnhpres;
 
@@ -93,9 +93,15 @@ static void set_state_entries(t_state *state,t_inputrec *ir,int nnodes)
       snew(state->sd_X,state->nalloc);
     }
   }
-  if (ir->eI == eiCG) {
-    state->flags |= (1<<estCGP);
-  }
+    if (ir->eI == eiCG)
+    {
+        state->flags |= (1<<estCGP);
+        if (state->cg_p == NULL)
+        {
+            /* cg_p is not stored in the tpx file, so we need to allocate it */
+            snew(state->cg_p,state->nalloc);
+        }
+    }
   if (EI_SD(ir->eI) || ir->eI == eiBD || ir->etc == etcVRESCALE) {
     state->nrng  = gmx_rng_n();
     state->nrngi = 1;
@@ -149,74 +155,17 @@ static void set_state_entries(t_state *state,t_inputrec *ir,int nnodes)
   init_energyhistory(&state->enerhist);
 }
 
-void init_single(FILE *fplog,t_inputrec *inputrec,
-                const char *tpxfile,gmx_mtop_t *mtop, 
-                 t_state *state)
-{
-  read_tpx_state(tpxfile,inputrec,state,NULL,mtop);
-  set_state_entries(state,inputrec,1);
-
-  if (fplog)
-    pr_inputrec(fplog,0,"Input Parameters",inputrec,FALSE);
-}
 
-void init_parallel(FILE *log,const char *tpxfile,t_commrec *cr,
-                  t_inputrec *inputrec,gmx_mtop_t *mtop,
-                  t_state *state,
-                  int list)
+void init_parallel(FILE *log, t_commrec *cr, t_inputrec *inputrec,
+                   gmx_mtop_t *mtop, t_state *state)
 {
-  char buf[256];
-  
-  if (MASTER(cr)) {
-    init_inputrec(inputrec);
-    read_tpx_state(tpxfile,inputrec,state,NULL,mtop);
-    /* When we will be doing domain decomposition with separate PME nodes
-     * the rng entries will be too large, we correct for this later.
-     */
-    set_state_entries(state,inputrec,cr->nnodes);
-  }
   bcast_ir_mtop(cr,inputrec,mtop);
 
-#ifdef GMX_THREADS
-    /* Check if we did not automatically start multiple threads,
-     * while an algorithm does not support parallel simulation.
-     */
-    if (inputrec->eI == eiLBFGS ||
-        inputrec->eI == eiNM ||
-        inputrec->coulombtype == eelEWALD)
-    {
-        if (cr->nnodes > 1 && MASTERTHREAD(cr))
-        {
-            fprintf(stderr,"\nThe integration or electrostatics algorithm doesn't support parallel runs.\n");
-        }
-        cancel_par_threads(cr); 
-    }
-#endif
 
   if (inputrec->eI == eiBD || EI_SD(inputrec->eI)) {
     /* Make sure the random seeds are different on each node */
     inputrec->ld_seed += cr->nodeid;
   }
-  
-  /* Printing */
-  if (list!=0 && log!=NULL) 
-  {
-         if (list&LIST_INPUTREC)
-                 pr_inputrec(log,0,"parameters of the run",inputrec,FALSE);
-         if (list&LIST_X)
-                 pr_rvecs(log,0,"box",state->box,DIM);
-         if (list&LIST_X)
-                 pr_rvecs(log,0,"box_rel",state->box_rel,DIM);
-         if (list&LIST_V)
-                 pr_rvecs(log,0,"boxv",state->boxv,DIM);
-         if (list&LIST_X)
-                 pr_rvecs(log,0,int_title("x",0,buf,255),state->x,state->natoms);
-         if (list&LIST_V)
-                 pr_rvecs(log,0,int_title("v",0,buf,255),state->v,state->natoms);
-         if (list&LIST_TOP)
-                 pr_mtop(log,0,int_title("topology",cr->nodeid,buf,255),mtop,TRUE);
-         fflush(log);
-  }
 }
 
 
index d5e0a650c3e87ba2f02d1adcfbf20723e67ff705..54c4f291e6a684e99d18d8250510c73607f794ec 100644 (file)
@@ -533,7 +533,16 @@ FILE *open_dhdl(const char *filename,const t_inputrec *ir,
     fp = gmx_fio_fopen(filename,"w+");
     xvgr_header(fp,title,label_x,label_y,exvggtXNY,oenv);
 
-    sprintf(buf,"T = %g (K)",ir->opts.ref_t[0]);
+    if (ir->delta_lambda == 0)
+    {
+        sprintf(buf,"T = %g (K), %s = %g",
+                ir->opts.ref_t[0],lambda,ir->init_lambda);
+    }
+    else
+    {
+        sprintf(buf,"T = %g (K)",
+                ir->opts.ref_t[0]);
+    }
     xvgr_subtitle(fp,buf,oenv);
 
     if (ir->n_flambda > 0)
index cea66f574c9070524fc7d124d2c49a3caf9a40e1..8524632f216f1dd3b30986871ebeed3a54d25a3b 100644 (file)
@@ -101,18 +101,28 @@ static void sp_header(FILE *out,const char *minimizer,real ftol,int nsteps)
   fprintf(out,"   Number of steps    = %12d\n",nsteps);
 }
 
-static void warn_step(FILE *fp,real ftol,bool bConstrain)
+static void warn_step(FILE *fp,real ftol,bool bLastStep,bool bConstrain)
 {
-  fprintf(fp,"\nStepsize too small, or no change in energy.\n"
-         "Converged to machine precision,\n"
-         "but not to the requested precision Fmax < %g\n",
-         ftol);
-  if (sizeof(real)<sizeof(double))
-      fprintf(fp,"\nDouble precision normally gives you higher accuracy.\n");
-       
-  if (bConstrain)
-    fprintf(fp,"You might need to increase your constraint accuracy, or turn\n"
-           "off constraints alltogether (set constraints = none in mdp file)\n");
+    if (bLastStep)
+    {
+        fprintf(fp,"\nReached the maximum number of steps before reaching Fmax < %g\n",ftol);
+    }
+    else
+    {
+        fprintf(fp,"\nStepsize too small, or no change in energy.\n"
+                "Converged to machine precision,\n"
+                "but not to the requested precision Fmax < %g\n",
+                ftol);
+        if (sizeof(real)<sizeof(double))
+        {
+            fprintf(fp,"\nDouble precision normally gives you higher accuracy.\n");
+        }
+        if (bConstrain)
+        {
+            fprintf(fp,"You might need to increase your constraint accuracy, or turn\n"
+                    "off constraints alltogether (set constraints = none in mdp file)\n");
+        }
+    }
 }
 
 
@@ -244,11 +254,6 @@ void init_em(FILE *fplog,const char *title,
     }
     
     state_global->ngtc = 0;
-    if (ir->eI == eiCG)
-    {
-        state_global->flags |= (1<<estCGP);
-        snew(state_global->cg_p,state_global->nalloc);
-    }
     
     /* Initiate some variables */
     if (ir->efep != efepNO)
@@ -323,54 +328,67 @@ void init_em(FILE *fplog,const char *title,
         {
             *graph = NULL;
         }
-    }
-
-  clear_rvec(mu_tot);
-  calc_shifts(ems->s.box,fr->shift_vec);
-
-  if (PARTDECOMP(cr)) {
-    pd_at_range(cr,&start,&homenr);
-    homenr -= start;
-  } else {
-    start  = 0;
-    homenr = top_global->natoms;
-  }
-  atoms2md(top_global,ir,0,NULL,start,homenr,mdatoms);
-  update_mdatoms(mdatoms,state_global->lambda);
-
-  if (vsite && !DOMAINDECOMP(cr)) {
-    set_vsite_top(vsite,*top,mdatoms,cr);
-  }
 
-  if (constr) {
-    if (ir->eConstrAlg == econtSHAKE &&
-       gmx_mtop_ftype_count(top_global,F_CONSTR) > 0) {
-      gmx_fatal(FARGS,"Can not do energy minimization with %s, use %s\n",
-               econstr_names[econtSHAKE],econstr_names[econtLINCS]);
+        if (PARTDECOMP(cr))
+        {
+            pd_at_range(cr,&start,&homenr);
+            homenr -= start;
+        }
+        else
+        {
+            start  = 0;
+            homenr = top_global->natoms;
+        }
+        atoms2md(top_global,ir,0,NULL,start,homenr,mdatoms);
+        update_mdatoms(mdatoms,state_global->lambda);
+    
+        if (vsite)
+        {
+            set_vsite_top(vsite,*top,mdatoms,cr);
+        }
     }
+    
+    if (constr)
+    {
+        if (ir->eConstrAlg == econtSHAKE &&
+            gmx_mtop_ftype_count(top_global,F_CONSTR) > 0)
+        {
+            gmx_fatal(FARGS,"Can not do energy minimization with %s, use %s\n",
+                      econstr_names[econtSHAKE],econstr_names[econtLINCS]);
+        }
+        
+        if (!DOMAINDECOMP(cr))
+        {
+            set_constraints(constr,*top,ir,mdatoms,cr);
+        }
 
-    if (!DOMAINDECOMP(cr))
-               set_constraints(constr,*top,ir,mdatoms,cr);
-
-    /* Constrain the starting coordinates */
-    dvdlambda=0;
-    constrain(PAR(cr) ? NULL : fplog,TRUE,TRUE,constr,&(*top)->idef,
-              ir,NULL,cr,-1,0,mdatoms,
-              ems->s.x,ems->s.x,NULL,ems->s.box,ems->s.lambda,&dvdlambda,
-              NULL,NULL,nrnb,econqCoord,FALSE,0,0);
-  }
-
-  if (PAR(cr)) {
-    *gstat = global_stat_init(ir);
-  }
+        if (!ir->bContinuation)
+        {
+            /* Constrain the starting coordinates */
+            dvdlambda=0;
+            constrain(PAR(cr) ? NULL : fplog,TRUE,TRUE,constr,&(*top)->idef,
+                      ir,NULL,cr,-1,0,mdatoms,
+                      ems->s.x,ems->s.x,NULL,ems->s.box,
+                      ems->s.lambda,&dvdlambda,
+                      NULL,NULL,nrnb,econqCoord,FALSE,0,0);
+        }
+    }
+    
+    if (PAR(cr))
+    {
+        *gstat = global_stat_init(ir);
+    }
+    
+    *outf = init_mdoutf(nfile,fnm,0,cr,ir,NULL);
 
-  *outf = init_mdoutf(nfile,fnm,FALSE,cr,ir,NULL);
+    snew(*enerd,1);
+    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,*enerd);
 
-  snew(*enerd,1);
-  init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,*enerd);
+    /* Init bin for energy stuff */
+    *mdebin = init_mdebin((*outf)->fp_ene,top_global,ir); 
 
-  /* Init bin for energy stuff */
-  *mdebin = init_mdebin((*outf)->fp_ene,top_global,ir); 
+    clear_rvec(mu_tot);
+    calc_shifts(ems->s.box,fr->shift_vec);
 }
 
 static void finish_em(FILE *fplog,t_commrec *cr,gmx_mdoutf_t *outf)
@@ -927,7 +945,8 @@ double do_cg(FILE *fplog,t_commrec *cr,
    * Each successful step is counted, and we continue until
    * we either converge or reach the max number of steps.
    */
-  for(step=0,converged=FALSE;( step<=number_steps || number_steps==0) && !converged;step++) {
+  converged = FALSE;
+  for(step=0; (number_steps<0 || (number_steps>=0 && step<=number_steps)) && !converged;step++) {
     
     /* start taking steps in a new direction 
      * First time we enter the routine, beta=0, and the direction is 
@@ -1271,13 +1290,15 @@ double do_cg(FILE *fplog,t_commrec *cr,
   if (converged)       
     step--; /* we never took that last step in this case */
   
-  if (s_min->fmax > inputrec->em_tol) {
-    if (MASTER(cr)) {
-      warn_step(stderr,inputrec->em_tol,FALSE);
-      warn_step(fplog,inputrec->em_tol,FALSE);
+    if (s_min->fmax > inputrec->em_tol)
+    {
+        if (MASTER(cr))
+        {
+            warn_step(stderr,inputrec->em_tol,step-1==number_steps,FALSE);
+            warn_step(fplog ,inputrec->em_tol,step-1==number_steps,FALSE);
+        }
+        converged = FALSE; 
     }
-    converged = FALSE; 
-  }
   
   if (MASTER(cr)) {
     /* If we printed energy and/or logfile last step (which was the last step)
@@ -1530,7 +1551,8 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
   ncorr=0;
 
   /* Set the gradient from the force */
-  for(step=0,converged=FALSE;( step<=number_steps || number_steps==0) && !converged;step++) {
+  converged = FALSE;
+  for(step=0; (number_steps<0 || (number_steps>=0 && step<=number_steps)) && !converged; step++) {
     
     /* Write coordinates if necessary */
     do_x = do_per_step(step,inputrec->nstxout);
@@ -1913,13 +1935,15 @@ double do_lbfgs(FILE *fplog,t_commrec *cr,
   if(converged)        
     step--; /* we never took that last step in this case */
   
-  if(fmax>inputrec->em_tol) {
-    if (MASTER(cr)) {
-      warn_step(stderr,inputrec->em_tol,FALSE);
-      warn_step(fplog,inputrec->em_tol,FALSE);
+    if(fmax>inputrec->em_tol)
+    {
+        if (MASTER(cr))
+        {
+            warn_step(stderr,inputrec->em_tol,step-1==number_steps,FALSE);
+            warn_step(fplog ,inputrec->em_tol,step-1==number_steps,FALSE);
+        }
+        converged = FALSE; 
     }
-    converged = FALSE; 
-  }
   
   /* If we printed energy and/or logfile last step (which was the last step)
    * we don't have to do it again, but otherwise print the final values.
@@ -2044,7 +2068,7 @@ double do_steep(FILE *fplog,t_commrec *cr,
   bDone  = FALSE;
   bAbort = FALSE;
   while( !bDone && !bAbort ) {
-    bAbort = (nsteps > 0) && (count==nsteps);
+    bAbort = (nsteps >= 0) && (count == nsteps);
     
     /* set new coordinates, except for first step */
     if (count > 0) {
@@ -2128,17 +2152,18 @@ double do_steep(FILE *fplog,t_commrec *cr,
     
     /* Check if stepsize is too small, with 1 nm as a characteristic length */
 #ifdef GMX_DOUBLE
-    if (ustep < 1e-12)
+        if (count == nsteps || ustep < 1e-12)
 #else
-    if (ustep < 1e-6)
+        if (count == nsteps || ustep < 1e-6)
 #endif
-      {
-       if (MASTER(cr)) {
-         warn_step(stderr,inputrec->em_tol,constr!=NULL);
-         warn_step(fplog,inputrec->em_tol,constr!=NULL);
-       }
-       bAbort=TRUE;
-      }
+        {
+            if (MASTER(cr))
+            {
+                warn_step(stderr,inputrec->em_tol,count==nsteps,constr!=NULL);
+                warn_step(fplog ,inputrec->em_tol,count==nsteps,constr!=NULL);
+            }
+            bAbort=TRUE;
+        }
     
     count++;
   } /* End of the loop  */
@@ -2214,9 +2239,15 @@ double do_nm(FILE *fplog,t_commrec *cr,
     /* added with respect to mdrun */
     int        idum,jdum,kdum,row,col;
     real       der_range=10.0*sqrt(GMX_REAL_EPS);
+    real       x_min;
     real       fnorm,fmax;
     real       dfdx;
     
+    if (constr != NULL)
+    {
+        gmx_fatal(FARGS,"Constraints present with Normal Mode Analysis, this combination is not supported");
+    }
+
     state_work = init_em_state();
     
     /* Init em and store the local state in state_minimum */
@@ -2330,47 +2361,52 @@ double do_nm(FILE *fplog,t_commrec *cr,
         
         for (idum=0; (idum<DIM); idum++) 
         {
-         row = DIM*step+idum;
+            row = DIM*step+idum;
          
-         state_work->s.x[step][idum] -= der_range;
+            x_min = state_work->s.x[step][idum];
+
+            state_work->s.x[step][idum] = x_min - der_range;
           
-         evaluate_energy(fplog,bVerbose,cr,
-                         state_global,top_global,state_work,top,
-                         inputrec,nrnb,wcycle,gstat,
-                         vsite,constr,fcd,graph,mdatoms,fr,
-                         mu_tot,enerd,vir,pres,count,count==0);
-         count++;
+            evaluate_energy(fplog,bVerbose,cr,
+                            state_global,top_global,state_work,top,
+                            inputrec,nrnb,wcycle,gstat,
+                            vsite,constr,fcd,graph,mdatoms,fr,
+                            mu_tot,enerd,vir,pres,count,count==0);
+            count++;
                        
-         for ( i=0 ; i < top_global->natoms ; i++ )
-           {
-             copy_rvec ( state_work->f[i] , fneg[i] );
-           }
-         
-         state_work->s.x[step][idum] += 2*der_range;
-          
-         evaluate_energy(fplog,bVerbose,cr,
-                         state_global,top_global,state_work,top,
-                         inputrec,nrnb,wcycle,gstat,
-                         vsite,constr,fcd,graph,mdatoms,fr,
-                         mu_tot,enerd,vir,pres,count,count==0);
-         count++;
-         
-         for ( i=0 ; i < top_global->natoms ; i++ )
-           {
-             copy_rvec ( state_work->f[i] , fpos[i] );
-           }
-         
-         for (jdum=0; (jdum<top_global->natoms); jdum++) 
+            for ( i=0 ; i < top_global->natoms ; i++ )
+            {
+                copy_rvec ( state_work->f[i] , fneg[i] );
+            }
+            
+            state_work->s.x[step][idum] = x_min + der_range;
+            
+            evaluate_energy(fplog,bVerbose,cr,
+                            state_global,top_global,state_work,top,
+                            inputrec,nrnb,wcycle,gstat,
+                            vsite,constr,fcd,graph,mdatoms,fr,
+                            mu_tot,enerd,vir,pres,count,count==0);
+            count++;
+            
+            for ( i=0 ; i < top_global->natoms ; i++ )
+            {
+                copy_rvec ( state_work->f[i] , fpos[i] );
+            }
+            
+            for (jdum=0; (jdum<top_global->natoms); jdum++) 
             {
                 for (kdum=0; (kdum<DIM); kdum++) 
                 {
-                    dfdx=-(fpos[jdum][kdum]-fneg[jdum][kdum])/(2*der_range);
-                    col = DIM*jdum+kdum;
+                    dfdx = -(fpos[jdum][kdum] - fneg[jdum][kdum])/(2*der_range);
+                    col  = DIM*jdum+kdum;
                     
-                    if(bSparse)
+                    if (bSparse)
                     {
-                        if(col>=row && dfdx!=0.0)
-                            gmx_sparsematrix_increment_value(sparse_matrix,row,col,dfdx);
+                        if (col>=row && dfdx!=0.0)
+                        {
+                            gmx_sparsematrix_increment_value(sparse_matrix,
+                                                             row,col,dfdx);
+                        }
                     }
                     else
                     {
@@ -2380,10 +2416,12 @@ double do_nm(FILE *fplog,t_commrec *cr,
             }
             
             /* x is restored to original */
-                       state_work->s.x[step][idum] -= der_range;
+            state_work->s.x[step][idum] = x_min;
             
             if (bVerbose && fplog)
+            {
                 fflush(fplog);            
+            }
         }
         /* write progress */
         if (MASTER(cr) && bVerbose) 
index f16475cc9a2ff07a38e97c2f921a17acdb77c379..c1b1291b3cb7e592d60d81f71228ae17a9289d50 100644 (file)
@@ -420,7 +420,7 @@ void done_grid(t_grid *grid)
   grid->dc_nalloc = 0;
 
   if (debug) 
-    fprintf(debug,"Succesfully freed memory for grid pointers.");
+    fprintf(debug,"Successfully freed memory for grid pointers.");
 }
 
 int xyz2ci_(int nry,int nrz,int x,int y,int z)
index db8630421ded66033f7371b67455def532a3d410..5f4cdb6b5ebc798dea0f677dcb223db841c7fdf0 100644 (file)
@@ -35,6 +35,8 @@
 #include <config.h>
 #endif
 
+#include <math.h>
+
 #include "perf_est.h"
 #include "physics.h"
 #include "vec.h"
@@ -84,8 +86,9 @@ float pme_load_estimate(gmx_mtop_t *mtop,t_inputrec *ir,matrix box)
   t_atom *atom;
   int  mb,nmol,atnr,cg,a,a0,ncqlj,ncq,nclj;
   bool bBHAM,bLJcut,bChargePerturbed,bWater,bQ,bLJ;
-  double nw,nqlj,nq,nlj,cost_bond,cost_pp,cost_spread,cost_fft;
-  float fq,fqlj,flj,fljtab,fqljw,fqw,fqspread,ffft,fbond;
+  double nw,nqlj,nq,nlj;
+  double cost_bond,cost_pp,cost_spread,cost_fft,cost_solve,cost_pme;
+  float fq,fqlj,flj,fljtab,fqljw,fqw,fqspread,ffft,fsolve,fbond;
   float ratio;
   t_iparams *iparams;
   gmx_moltype_t *molt;
@@ -94,24 +97,26 @@ float pme_load_estimate(gmx_mtop_t *mtop,t_inputrec *ir,matrix box)
 
   bLJcut = ((ir->vdwtype == evdwCUT) && !bBHAM);
 
-  /* Computational cost relative to a tabulated q-q interaction.
+  /* Computational cost of bonded, non-bonded and PME calculations.
    * This will be machine dependent.
    * The numbers here are accurate for Intel Core2 and AMD Athlon 64
    * in single precision. In double precision PME mesh is slightly cheaper,
    * although not so much that the numbers need to be adjusted.
    */
-  fq    = 1.0;
+  fq    = 1.5;
   fqlj  = (bLJcut ? 1.5  : 2.0 );
-  flj   = (bLJcut ? 0.5  : 1.5 );
+  flj   = (bLJcut ? 1.0  : 1.75);
   /* Cost of 1 water with one Q/LJ atom */
-  fqljw = (bLJcut ? 1.75 : 2.25);
+  fqljw = (bLJcut ? 2.0  : 2.25);
   /* Cost of 1 water with one Q atom or with 1/3 water (LJ negligible) */
-  fqw   = 1.5;
-  /* Cost of q spreading and force interpolation per charge */
-  fqspread = 25.0;
-  /* Cost of fft's + pme_solve, will be multiplied with N log(N) */
-  ffft     =  0.4;
-  /* Cost of a bonded interaction divided by the number of (pbc_)dx required */
+  fqw   = 1.75;
+  /* Cost of q spreading and force interpolation per charge (mainly memory) */
+  fqspread = 0.55;
+  /* Cost of fft's, will be multiplied with N log(N) */
+  ffft     = 0.20;
+  /* Cost of pme_solve, will be multiplied with N */
+  fsolve   = 0.80;
+  /* Cost of a bonded interaction divided by the number of (pbc_)dx nrequired */
   fbond = 5.0;
 
   iparams = mtop->ffparams.iparams;
@@ -179,25 +184,29 @@ float pme_load_estimate(gmx_mtop_t *mtop,t_inputrec *ir,matrix box)
                 flj  *nlj*(nw + nqlj + nlj))
     *4/3*M_PI*ir->rlist*ir->rlist*ir->rlist/det(box);
   
-  cost_spread = fqspread*(3*nw + nqlj + nq);
+  cost_spread = fqspread*(3*nw + nqlj + nq)*pow(ir->pme_order,3);
   cost_fft    = ffft*ir->nkx*ir->nky*ir->nkz*log(ir->nkx*ir->nky*ir->nkz);
+  cost_solve  = fsolve*ir->nkx*ir->nky*ir->nkz;
 
   if (ir->efep != efepNO && bChargePerturbed) {
     /* All PME work, except the spline coefficient calculation, doubles */
     cost_spread *= 2;
     cost_fft    *= 2;
+    cost_solve  *= 2;
   }
 
-  ratio =
-    (cost_spread + cost_fft)/(cost_bond + cost_pp + cost_spread + cost_fft);
+  cost_pme = cost_spread + cost_fft + cost_solve;
+
+  ratio = cost_pme/(cost_bond + cost_pp + cost_pme);
 
   if (debug) {
     fprintf(debug,
            "cost_bond   %f\n"
            "cost_pp     %f\n"
            "cost_spread %f\n"
-           "cost_fft    %f\n",
-           cost_bond,cost_pp,cost_spread,cost_fft);
+           "cost_fft    %f\n"
+           "cost_solve  %f\n",
+           cost_bond,cost_pp,cost_spread,cost_fft,cost_solve);
 
     fprintf(debug,"Estimate for relative PME load: %.3f\n",ratio);
   }
index cd7aca40390f53213c05929c93f330908462b06a..d7f527d1ceaca60f78eb8793c69511d0e40bbd3f 100644 (file)
@@ -78,7 +78,6 @@
 #include "smalloc.h"
 #include "futil.h"
 #include "coulomb.h"
-#include "fftgrid.h"
 #include "gmx_fatal.h"
 #include "pme.h"
 #include "network.h"
 #include "nrnb.h"
 #include "copyrite.h"
 #include "gmx_wallcycle.h"
-#include "sighandler.h"
+#include "gmx_parallel_3dfft.h"
+#include "pdbio.h"
 
+#if ( !defined(GMX_DOUBLE) && ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) ) )
+#include "gmx_sse2_single.h"
+#endif
 
 #include "mpelogging.h"
 
 
 /* Internal datastructures */
 typedef struct {
-    int snd0;
-    int snds;
-    int rcv0;
-    int rcvs;
+    int send_index0;
+    int send_nindex;
+    int recv_index0;
+    int recv_nindex;
 } pme_grid_comm_t;
 
 typedef struct {
 #ifdef GMX_MPI
     MPI_Comm mpi_comm;
 #endif
-    int  nslab;
-    int  *s2g;
-    int  nleftbnd,nrightbnd;  /* The number of nodes to communicate with */
-    int  nodeid,*leftid,*rightid;
-    pme_grid_comm_t *leftc,*rightc;
+    int  nnodes,nodeid;
+    int  ndata;
+    int  *s2g0;
+    int  *s2g1;
+    int  noverlap_nodes;
+    int  *send_id,*recv_id;
+    pme_grid_comm_t *comm_data;
 } pme_overlap_t;
 
 typedef struct {
@@ -159,10 +164,15 @@ typedef struct {
 typedef struct gmx_pme {
     int  ndecompdim;         /* The number of decomposition dimensions */
     int  nodeid;             /* Our nodeid in mpi->mpi_comm */
+    int  nodeid_major;
+    int  nodeid_minor;
     int  nnodes;             /* The number of nodes doing PME */
-#ifdef GMX_MPI
+    int  nnodes_major;
+    int  nnodes_minor;
+
     MPI_Comm mpi_comm;
-    MPI_Comm mpi_comm_d[2];
+    MPI_Comm mpi_comm_d[2];  /* Indexed on dimension, 0=x, 1=y */
+#ifdef GMX_MPI
     MPI_Datatype  rvec_mpi;  /* the pme vector's MPI type */
 #endif
 
@@ -171,14 +181,35 @@ typedef struct gmx_pme {
     int nkx,nky,nkz;         /* Grid dimensions */
     int pme_order;
     real epsilon_r;           
-    t_fftgrid *gridA,*gridB;
+    
+    real *  pmegridA;  /* Grids on which we do spreading/interpolation, includes overlap */
+    real *  pmegridB;
+    int     pmegrid_nx,pmegrid_ny,pmegrid_nz;
+    int     pmegrid_start_ix,pmegrid_start_iy,pmegrid_start_iz;    
+    
+    real *  pmegrid_sendbuf;
+    real *  pmegrid_recvbuf;
+    
+    real *fftgridA;             /* Grids for FFT. With 1D FFT decomposition this can be a pointer */
+    real *fftgridB;             /* inside the interpolation grid, but separate for 2D PME decomp. */
+    int   fftgrid_nx,fftgrid_ny,fftgrid_nz;
+    
+    t_complex *cfftgridA;             /* Grids for complex FFT data */
+    t_complex *cfftgridB;            
+    int   cfftgrid_nx,cfftgrid_ny,cfftgrid_nz;
+    
+    gmx_parallel_3dfft_t  pfft_setupA;
+    gmx_parallel_3dfft_t  pfft_setupB;
+    
     int  *nnx,*nny,*nnz;
+    real *fshx,*fshy,*fshz;
     
-    pme_atomcomm_t atc[2];
+    pme_atomcomm_t atc[2];  /* Indexed on decomposition index */
     matrix    recipbox;
     splinevec bsp_mod;
     
-    pme_overlap_t overlap[2];
+    pme_overlap_t overlap[2]; /* Indexed on dimension, 0=x, 1=y */
+
 
     pme_atomcomm_t atc_energy; /* Only for gmx_pme_calc_energy */
     
@@ -187,10 +218,13 @@ typedef struct gmx_pme {
     int  buf_nalloc;        /* The communication buffer size */
 
     /* work data for solve_pme */
-    int      maxkz;
+    int      work_nalloc;
+    real *   work_mhx;
+    real *   work_mhy;
     real *   work_mhz;
     real *   work_m2;
     real *   work_denom;
+    real *   work_tmp1_alloc;
     real *   work_tmp1;
     real *   work_m2inv;
 
@@ -210,69 +244,23 @@ typedef struct gmx_pme {
     real *   sum_qgrid_dd_tmp;
 } t_gmx_pme;
 
-/* #define SORTPME */
-
-static void pr_grid_dist(FILE *fp,char *title,t_fftgrid *grid)
-{
-  int     i,j,k,l,ntoti,ntot=0;
-  int     nx,ny,nz,nx2,ny2,nz2,la12,la2;
-  real *  ptr;
-
-  /* Unpack structure */
-  unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
-  for(i=0; (i<nx); i++) {
-    ntoti=0;
-    for(j=0; (j<ny); j++)
-      for(k=0; (k<nz); k++) {
-        l= INDEX(i,j,k);
-        if (ptr[l] != 0) {
-          ntoti++;
-          ntot++;
-        }
-      }
-          fprintf(fp,"%-12s  %5d  %5d\n",title,i,ntoti);
-  }
-  fprintf(fp,"%d non zero elements in %s\n",ntot,title);
-}
-/* test */
-
-static void calc_recipbox(matrix box,matrix recipbox)
-{
-  /* Save some time by assuming upper right part is zero */
-
-  real tmp=1.0/(box[XX][XX]*box[YY][YY]*box[ZZ][ZZ]);
-
-  recipbox[XX][XX]=box[YY][YY]*box[ZZ][ZZ]*tmp;
-  recipbox[XX][YY]=0;
-  recipbox[XX][ZZ]=0;
-  recipbox[YY][XX]=-box[YY][XX]*box[ZZ][ZZ]*tmp;
-  recipbox[YY][YY]=box[XX][XX]*box[ZZ][ZZ]*tmp;
-  recipbox[YY][ZZ]=0;
-  recipbox[ZZ][XX]=(box[YY][XX]*box[ZZ][YY]-box[YY][YY]*box[ZZ][XX])*tmp;
-  recipbox[ZZ][YY]=-box[ZZ][YY]*box[XX][XX]*tmp;
-  recipbox[ZZ][ZZ]=box[XX][XX]*box[YY][YY]*tmp;
-}
 
-static void calc_idx(gmx_pme_t pme,pme_atomcomm_t *atc)
+static void calc_interpolation_idx(gmx_pme_t pme,pme_atomcomm_t *atc)
 {
     int  i;
     int  *idxptr,tix,tiy,tiz;
     real *xptr,*fptr,tx,ty,tz;
     real rxx,ryx,ryy,rzx,rzy,rzz;
-    int  nx,ny,nz,nx2,ny2,nz2,la12,la2;
-    real *ptr;
-
-#if (defined __GNUC__ && (defined i386 || defined __386__) && !defined GMX_DOUBLE && defined GMX_X86TRUNC)
-    int x86_cw,x86_cwsave;
-
-    asm("fnstcw %0" : "=m" (*&x86_cwsave));
-    x86_cw = x86_cwsave | 3072;
-    asm("fldcw %0" : : "m" (*&x86_cw));
-#define x86trunc(a,b) asm("fld %1\nfistpl %0\n" : "=m" (*&b) : "f" (a));
-#endif
-    /* Unpack structure */
-    unpack_fftgrid(pme->gridA,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
+    int  nx,ny,nz;
+    int  start_ix,start_iy,start_iz;
+    
+    nx  = pme->nkx;
+    ny  = pme->nky;
+    nz  = pme->nkz;
+    
+    start_ix = pme->pmegrid_start_ix;
+    start_iy = pme->pmegrid_start_iy;
+    start_iz = pme->pmegrid_start_iz;
     
     rxx = pme->recipbox[XX][XX];
     ryx = pme->recipbox[YY][XX];
@@ -286,63 +274,58 @@ static void calc_idx(gmx_pme_t pme,pme_atomcomm_t *atc)
         idxptr = atc->idx[i];
         fptr   = atc->fractx[i];
         
-        /* Fractional coordinates along box vectors */
-        tx = nx2 + nx * ( xptr[XX] * rxx + xptr[YY] * ryx + xptr[ZZ] * rzx );
-        ty = ny2 + ny * (                  xptr[YY] * ryy + xptr[ZZ] * rzy );
-        tz = nz2 + nz * (                                   xptr[ZZ] * rzz );
+        /* Fractional coordinates along box vectors, add 2.0 to make 100% sure we are positive for triclinic boxes */
+        tx = nx * ( xptr[XX] * rxx + xptr[YY] * ryx + xptr[ZZ] * rzx + 2.0 );
+        ty = ny * (                  xptr[YY] * ryy + xptr[ZZ] * rzy + 2.0 );
+        tz = nz * (                                   xptr[ZZ] * rzz + 2.0 );
         
-#if (defined __GNUC__ && (defined i386 || defined __386__) && !defined GMX_DOUBLE && defined GMX_X86TRUNC)
-        x86trunc(tx,tix);
-        x86trunc(ty,tiy);
-        x86trunc(tz,tiz);
-#else
         tix = (int)(tx);
         tiy = (int)(ty);
         tiz = (int)(tz);
-#endif
         
-        fptr[XX] = tx - tix;
-        fptr[YY] = ty - tiy;
+        /* Because decomposition only occurs in x and y,
+         * we never have a fraction correction in z.
+         */
+        fptr[XX] = tx - tix + pme->fshx[tix];
+        fptr[YY] = ty - tiy + pme->fshy[tiy];
         fptr[ZZ] = tz - tiz;   
-        
+
         idxptr[XX] = pme->nnx[tix];
         idxptr[YY] = pme->nny[tiy];
         idxptr[ZZ] = pme->nnz[tiz];
 
 #ifdef DEBUG
-        range_check(idxptr[XX],0,nx);
-        range_check(idxptr[YY],0,ny);
-        range_check(idxptr[ZZ],0,nz);
+        range_check(idxptr[XX],0,pme->pmegrid_nx);
+        range_check(idxptr[YY],0,pme->pmegrid_ny);
+        range_check(idxptr[ZZ],0,pme->pmegrid_nz);
 #endif
   }  
-#if (defined __GNUC__ && (defined i386 || defined __386__) && !defined GMX_DOUBLE && defined GMX_X86TRUNC)  
-    asm("fldcw %0" : : "m" (*&x86_cwsave));
-#endif
 }
 
-static void pme_calc_pidx(int natoms,matrix box, rvec x[],
+static void pme_calc_pidx(int natoms, matrix recipbox, rvec x[],
                           pme_atomcomm_t *atc)
 {
     int  nslab,i;
     int  si;
     real *xptr,s;
     real rxx,ryx,rzx,ryy,rzy;
-    matrix recipbox;
-    
+    int *pd,*count;
+
     /* Calculate PME task index (pidx) for each grid index.
      * Here we always assign equally sized slabs to each node
      * for load balancing reasons (the PME grid spacing is not used).
      */
     
     nslab = atc->nslab;
+    pd    = atc->pd;
+    count = atc->count;
 
     /* Reset the count */
     for(i=0; i<nslab; i++)
     {
-        atc->count[i] = 0;
+        count[i] = 0;
     }
     
-    calc_recipbox(box,recipbox);
     if (atc->dimind == 0)
     {
         rxx = recipbox[XX][XX];
@@ -354,17 +337,9 @@ static void pme_calc_pidx(int natoms,matrix box, rvec x[],
             xptr   = x[i];
             /* Fractional coordinates along box vectors */
             s = nslab*(xptr[XX]*rxx + xptr[YY]*ryx + xptr[ZZ]*rzx);
-            si = (int)(s + nslab) - nslab;
-            if (si < 0)
-            {
-                si += nslab;
-            }
-            else if (si >= nslab)
-            {
-                si -= nslab;
-            }
-            atc->pd[i] = si;
-            atc->count[si]++;
+            si = (int)(s + 2*nslab) % nslab;
+            pd[i] = si;
+            count[si]++;
         }
     }
     else
@@ -377,32 +352,29 @@ static void pme_calc_pidx(int natoms,matrix box, rvec x[],
             xptr   = x[i];
             /* Fractional coordinates along box vectors */
             s = nslab*(xptr[YY]*ryy + xptr[ZZ]*rzy);
-            si = (int)(s + nslab) - nslab;
-            if (si < 0)
-            {
-                si += nslab;
-            }
-            else if (si >= nslab)
-            {
-                si -= nslab;
-            }
-            atc->pd[i] = si;
-            atc->count[si]++;
+            si = (int)(s + 2*nslab) % nslab;
+            pd[i] = si;
+            count[si]++;
         }
     }
 }
 
 static void pme_realloc_atomcomm_things(pme_atomcomm_t *atc)
 {
-    int i;
+    int nalloc_old,i;
     
     if (atc->n > atc->nalloc) {
+        nalloc_old = atc->nalloc;
         atc->nalloc = over_alloc_dd(atc->n);
         
         if (atc->nslab > 1) {
             srenew(atc->x,atc->nalloc);
             srenew(atc->q,atc->nalloc);
             srenew(atc->f,atc->nalloc);
+            for(i=nalloc_old; i<atc->nalloc; i++)
+            {
+                clear_rvec(atc->f[i]);
+            }
         }
         if (atc->bSpread) {
             for(i=0;i<DIM;i++) {
@@ -415,9 +387,9 @@ static void pme_realloc_atomcomm_things(pme_atomcomm_t *atc)
     }
 }
 
-static void pmeredist(gmx_pme_t pme, bool forw,
-                      int n, bool bXF, rvec *x_f, real *charge,
-                      pme_atomcomm_t *atc)
+static void pmeredist_pd(gmx_pme_t pme, bool forw,
+                         int n, bool bXF, rvec *x_f, real *charge,
+                         pme_atomcomm_t *atc)
 /* Redistribute particle data for PME calculation */
 /* domain decomposition by x coordinate           */
 {
@@ -560,7 +532,8 @@ static void dd_pmeredist_x_q(gmx_pme_t pme,
     }
     if (bX) {
         if (atc->count[atc->nodeid] + nsend != n)
-            gmx_fatal(FARGS,"%d particles communicated to PME node %d are more than a cell length out of the domain decomposition cell of their charge group in dimension %c",
+            gmx_fatal(FARGS,"%d particles communicated to PME node %d are more than 2/3 times the cut-off out of the domain decomposition cell of their charge group in dimension %c.\n"
+                      "This usually means that your system is not well equilibrated.",
                       n - (atc->count[atc->nodeid] + nsend),
                       pme->nodeid,'x'+atc->dimind);
         
@@ -696,323 +669,532 @@ static void dd_pmeredist_f(gmx_pme_t pme, pme_atomcomm_t *atc,
     }
 }
 
-static void gmx_sum_qgrid_dd(gmx_pme_t pme, pme_overlap_t *ol,t_fftgrid *grid,
-                             int direction)
-{
-    int b,i;
-    int la12r,localsize;
-    pme_grid_comm_t *pgc;
-    real *from, *to;
-    real *tmp;
 #ifdef GMX_MPI
+static void 
+gmx_sum_qgrid_dd(gmx_pme_t pme, real *grid, int direction)
+{
+    pme_overlap_t *overlap;
+    int send_index0,send_nindex;
+    int recv_index0,recv_nindex;
     MPI_Status stat;
-#endif
+    int i,j,k,ix,iy,iz,icnt;
+    int ipulse,send_id,recv_id,datasize;
+    real *p;
+    real *sendptr,*recvptr;
     
-    GMX_MPE_LOG(ev_sum_qgrid_start);
-    
-#ifdef GMX_MPI
+    /* Start with minor-rank communication. This is a bit of a pain since it is not contiguous */
+    overlap = &pme->overlap[1];
     
-    la12r      = grid->la12r;
-    localsize  = la12r*grid->pfft.local_nx;
-    
-    if (grid->workspace) {
-        tmp = grid->workspace;
-    } else {
-        if (pme->sum_qgrid_dd_tmp == NULL) {
-            snew(pme->sum_qgrid_dd_tmp,localsize);
+    for(ipulse=0;ipulse<overlap->noverlap_nodes;ipulse++)
+    {
+        /* Since we have already (un)wrapped the overlap in the z-dimension,
+         * we only have to communicate 0 to nkz (not pmegrid_nz).
+         */
+        if (direction==GMX_SUM_QGRID_FORWARD)
+        {
+            send_id = overlap->send_id[ipulse];
+            recv_id = overlap->recv_id[ipulse];
+            send_index0   = overlap->comm_data[ipulse].send_index0;
+            send_nindex   = overlap->comm_data[ipulse].send_nindex;
+            recv_index0   = overlap->comm_data[ipulse].recv_index0;
+            recv_nindex   = overlap->comm_data[ipulse].recv_nindex;
         }
-        tmp = pme->sum_qgrid_dd_tmp;
-    }
-    
-    if (direction == GMX_SUM_QGRID_FORWARD) { 
-        /* sum contributions to local grid */
-        /* Send left boundaries */
-        for(b=0; b<ol->nleftbnd; b++) {
-            pgc = &ol->leftc[b];
-            from = grid->ptr + la12r*pgc->snd0;
-            to   = grid->ptr + la12r*pgc->rcv0;
-            MPI_Sendrecv(from,la12r*pgc->snds,mpi_type,
-                         ol->leftid[b], ol->nodeid,
-                         tmp, la12r*pgc->rcvs,mpi_type,
-                         ol->rightid[b],ol->rightid[b],
-                         ol->mpi_comm,&stat);
-            GMX_MPE_LOG(ev_test_start); 
-            for(i=0; (i<la12r*pgc->rcvs); i++) {
-                to[i] += tmp[i];
+        else
+        {
+            send_id = overlap->recv_id[ipulse];
+            recv_id = overlap->send_id[ipulse];
+            send_index0   = overlap->comm_data[ipulse].recv_index0;
+            send_nindex   = overlap->comm_data[ipulse].recv_nindex;            
+            recv_index0   = overlap->comm_data[ipulse].send_index0;
+            recv_nindex   = overlap->comm_data[ipulse].send_nindex;
+        }
+
+        /* Copy data to contiguous send buffer */
+        if (debug)
+        {
+            fprintf(debug,"PME send node %d %d -> %d grid start %d Communicating %d to %d\n",
+                    pme->nodeid,overlap->nodeid,send_id,
+                    pme->pmegrid_start_iy,
+                    send_index0-pme->pmegrid_start_iy,
+                    send_index0-pme->pmegrid_start_iy+send_nindex);
+        }
+        icnt = 0;
+        for(i=0;i<pme->pmegrid_nx;i++)
+        {
+            ix = i;
+            for(j=0;j<send_nindex;j++)
+            {
+                iy = j + send_index0 - pme->pmegrid_start_iy;
+                for(k=0;k<pme->nkz;k++)
+                {
+                    iz = k;
+                    pme->pmegrid_sendbuf[icnt++] = grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz];
+                }
             }
         }
-        GMX_MPE_LOG(ev_test_finish);
-        /* Send right boundaries */
-        for(b=0; b<ol->nrightbnd; b++) {
-            pgc = &ol->rightc[b];
-            from = grid->ptr + la12r*pgc->snd0;
-            to   = grid->ptr + la12r*pgc->rcv0;
-            MPI_Sendrecv(from,la12r*pgc->snds,mpi_type,
-                         ol->rightid[b],ol->nodeid,
-                         tmp, la12r*pgc->rcvs,mpi_type,
-                         ol->leftid[b], ol->leftid[b],
-                         ol->mpi_comm,&stat);
-            GMX_MPE_LOG(ev_test_start); 
-            for(i=0; (i<la12r*pgc->rcvs); i++) {
-                to[i] += tmp[i];
+            
+        datasize      = pme->pmegrid_nx * pme->nkz;
+        
+        MPI_Sendrecv(pme->pmegrid_sendbuf,send_nindex*datasize,GMX_MPI_REAL,
+                     send_id,ipulse,
+                     pme->pmegrid_recvbuf,recv_nindex*datasize,GMX_MPI_REAL,
+                     recv_id,ipulse,
+                     overlap->mpi_comm,&stat);
+        
+        /* Get data from contiguous recv buffer */
+        if (debug)
+        {
+            fprintf(debug,"PME recv node %d %d <- %d grid start %d Communicating %d to %d\n",
+                    pme->nodeid,overlap->nodeid,recv_id,
+                    pme->pmegrid_start_iy,
+                    recv_index0-pme->pmegrid_start_iy,
+                    recv_index0-pme->pmegrid_start_iy+recv_nindex);
+        }
+        icnt = 0;
+        for(i=0;i<pme->pmegrid_nx;i++)
+        {
+            ix = i;
+            for(j=0;j<recv_nindex;j++)
+            {
+                iy = j + recv_index0 - pme->pmegrid_start_iy;
+                for(k=0;k<pme->nkz;k++)
+                {
+                    iz = k;
+                    if(direction==GMX_SUM_QGRID_FORWARD)
+                    {
+                        grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz] += pme->pmegrid_recvbuf[icnt++];
+                    }
+                    else
+                    {
+                        grid[ix*(pme->pmegrid_ny*pme->pmegrid_nz)+iy*(pme->pmegrid_nz)+iz]  = pme->pmegrid_recvbuf[icnt++];
+                    }
+                }
             }
         }
-        GMX_MPE_LOG(ev_test_finish);
-    }
-    else if (direction  == GMX_SUM_QGRID_BACKWARD) { 
-        /* distribute local grid to all processors */
-        /* Send right boundaries */
-        for(b=0; b<ol->nrightbnd; b++) {
-            pgc = &ol->rightc[b];
-            from = grid->ptr + la12r*pgc->rcv0;
-            to   = grid->ptr + la12r*pgc->snd0;
-            MPI_Sendrecv(from,la12r*pgc->rcvs,mpi_type,
-                         ol->leftid[b], ol->nodeid,
-                         to,  la12r*pgc->snds,mpi_type,
-                         ol->rightid[b],ol->rightid[b],
-                         ol->mpi_comm,&stat);
+    }
+    
+    /* Major dimension is easier, no copying required,
+     * but we might have to sum to separate array.
+     * Since we don't copy, we have to communicate up to pmegrid_nz,
+     * not nkz as for the minor direction.
+     */
+    overlap = &pme->overlap[0];
+    
+    for(ipulse=0;ipulse<overlap->noverlap_nodes;ipulse++)
+    {
+        if(direction==GMX_SUM_QGRID_FORWARD)
+        {
+            send_id = overlap->send_id[ipulse];
+            recv_id = overlap->recv_id[ipulse];
+            send_index0   = overlap->comm_data[ipulse].send_index0;
+            send_nindex   = overlap->comm_data[ipulse].send_nindex;
+            recv_index0   = overlap->comm_data[ipulse].recv_index0;
+            recv_nindex   = overlap->comm_data[ipulse].recv_nindex;
+            recvptr   = pme->pmegrid_recvbuf;
+        }
+        else
+        {
+            send_id = overlap->recv_id[ipulse];
+            recv_id = overlap->send_id[ipulse];
+            send_index0   = overlap->comm_data[ipulse].recv_index0;
+            send_nindex   = overlap->comm_data[ipulse].recv_nindex;            
+            recv_index0   = overlap->comm_data[ipulse].send_index0;
+            recv_nindex   = overlap->comm_data[ipulse].send_nindex;
+            recvptr   = grid + (recv_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
+        }
+                
+        sendptr       = grid + (send_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
+        datasize      = pme->pmegrid_ny * pme->pmegrid_nz;
+
+        if (debug)
+        {
+            fprintf(debug,"PME send node %d %d -> %d grid start %d Communicating %d to %d\n",
+                    pme->nodeid,overlap->nodeid,send_id,
+                    pme->pmegrid_start_ix,
+                    send_index0-pme->pmegrid_start_ix,
+                    send_index0-pme->pmegrid_start_ix+send_nindex);
+            fprintf(debug,"PME recv node %d %d <- %d grid start %d Communicating %d to %d\n",
+                    pme->nodeid,overlap->nodeid,recv_id,
+                    pme->pmegrid_start_ix,
+                    recv_index0-pme->pmegrid_start_ix,
+                    recv_index0-pme->pmegrid_start_ix+recv_nindex);
         }
-        /* Send left boundaries */
-        for(b=0; b<ol->nleftbnd; b++) {
-            pgc = &ol->leftc[b];
-            from = grid->ptr + la12r*pgc->rcv0;
-            to   = grid->ptr + la12r*pgc->snd0;
-            MPI_Sendrecv(from,la12r*pgc->rcvs,mpi_type,
-                         ol->rightid[b],ol->nodeid,
-                         to,  la12r*pgc->snds,mpi_type,
-                         ol->leftid[b], ol->leftid[b],
-                         ol->mpi_comm,&stat);
+
+        MPI_Sendrecv(sendptr,send_nindex*datasize,GMX_MPI_REAL,
+                     send_id,ipulse,
+                     recvptr,recv_nindex*datasize,GMX_MPI_REAL,
+                     recv_id,ipulse,
+                     overlap->mpi_comm,&stat);
+        
+        /* ADD data from contiguous recv buffer */
+        if(direction==GMX_SUM_QGRID_FORWARD)
+        {        
+            p = grid + (recv_index0-pme->pmegrid_start_ix)*(pme->pmegrid_ny*pme->pmegrid_nz);
+            for(i=0;i<recv_nindex*datasize;i++)
+            {
+                p[i] += pme->pmegrid_recvbuf[i];
+            }
         }
     }
-    else {
-        gmx_fatal(FARGS,"Invalid direction %d for summing qgrid",direction);
+}
+#endif
+
+
+static int
+copy_pmegrid_to_fftgrid(gmx_pme_t pme, real *pmegrid, real *fftgrid)
+{
+    ivec    local_fft_ndata,local_fft_offset,local_fft_size;
+    ivec    local_pme_size;
+    int     i,ix,iy,iz;
+    int     pmeidx,fftidx;
+
+    /* Dimensions should be identical for A/B grid, so we just use A here */
+    gmx_parallel_3dfft_real_limits(pme->pfft_setupA,
+                                   local_fft_ndata,
+                                   local_fft_offset,
+                                   local_fft_size);
+    
+    local_pme_size[0] = pme->pmegrid_nx;
+    local_pme_size[1] = pme->pmegrid_ny;
+    local_pme_size[2] = pme->pmegrid_nz;
+    
+    /* The fftgrid is always 'justified' to the lower-left corner of the PME grid, 
+     the offset is identical, and the PME grid always has more data (due to overlap)
+     */
+    {
+#ifdef DEBUG_PME
+        FILE *fp,*fp2;
+        char fn[STRLEN],format[STRLEN];
+        real val;
+        sprintf(fn,"pmegrid%d.pdb",pme->nodeid);
+        fp = ffopen(fn,"w");
+        sprintf(fn,"pmegrid%d.txt",pme->nodeid);
+        fp2 = ffopen(fn,"w");
+     sprintf(format,"%s%s\n",pdbformat,"%6.2f%6.2f");
+#endif
+    for(ix=0;ix<local_fft_ndata[XX];ix++)
+    {
+        for(iy=0;iy<local_fft_ndata[YY];iy++)
+        {
+            for(iz=0;iz<local_fft_ndata[ZZ];iz++)
+            {
+                pmeidx = ix*(local_pme_size[YY]*local_pme_size[ZZ])+iy*(local_pme_size[ZZ])+iz;
+                fftidx = ix*(local_fft_size[YY]*local_fft_size[ZZ])+iy*(local_fft_size[ZZ])+iz;
+                fftgrid[fftidx] = pmegrid[pmeidx];
+#ifdef DEBUG_PME
+                val = 100*pmegrid[pmeidx];
+                if (pmegrid[pmeidx] != 0)
+                fprintf(fp,format,"ATOM",pmeidx,"CA","GLY",' ',pmeidx,' ',
+                        5.0*ix,5.0*iy,5.0*iz,1.0,val);
+                if (pmegrid[pmeidx] != 0)
+                    fprintf(fp2,"%-12s  %5d  %5d  %5d  %12.5e\n",
+                            "qgrid",
+                            pme->pmegrid_start_ix + ix,
+                            pme->pmegrid_start_iy + iy,
+                            pme->pmegrid_start_iz + iz,
+                            pmegrid[pmeidx]);
+#endif
+            }
+        }
     }
-    
-#else
-    gmx_fatal(FARGS,"Parallel grid summation requires MPI and FFTW.\n");    
+#ifdef DEBUG_PME
+    fclose(fp);
+    fclose(fp2);
 #endif
-    GMX_MPE_LOG(ev_sum_qgrid_finish);
+    }
+    return 0;
 }
 
-void gmx_sum_qgrid(gmx_pme_t pme,t_commrec *cr,t_fftgrid *grid,int direction)
+
+static int
+copy_fftgrid_to_pmegrid(gmx_pme_t pme, real *fftgrid, real *pmegrid)
 {
-    int i;
-    int localsize;
-    int maxproc;
-    real *tmp;
-    
-#ifdef GMX_MPI
-    localsize=grid->la12r*grid->pfft.local_nx;
-    maxproc=grid->nx/grid->pfft.local_nx;
+    ivec    local_fft_ndata,local_fft_offset,local_fft_size;
+    ivec    local_pme_size;
+    int     i,ix,iy,iz;
+    int     pmeidx,fftidx;
+    
+    /* Dimensions should be identical for A/B grid, so we just use A here */
+    gmx_parallel_3dfft_real_limits(pme->pfft_setupA,
+                                   local_fft_ndata,
+                                   local_fft_offset,
+                                   local_fft_size);
+
+    local_pme_size[0] = pme->pmegrid_nx;
+    local_pme_size[1] = pme->pmegrid_ny;
+    local_pme_size[2] = pme->pmegrid_nz;
+    
+    /* The fftgrid is always 'justified' to the lower-left corner of the PME grid, 
+     the offset is identical, and the PME grid always has more data (due to overlap)
+     */
+    for(ix=0;ix<local_fft_ndata[XX];ix++)
+    {
+        for(iy=0;iy<local_fft_ndata[YY];iy++)
+        {
+            for(iz=0;iz<local_fft_ndata[ZZ];iz++)
+            {
+                pmeidx = ix*(local_pme_size[YY]*local_pme_size[ZZ])+iy*(local_pme_size[ZZ])+iz;
+                fftidx = ix*(local_fft_size[YY]*local_fft_size[ZZ])+iy*(local_fft_size[ZZ])+iz;
+                pmegrid[pmeidx] = fftgrid[fftidx];
+            }
+        }
+    }   
+    return 0;
+}
+
+
+static void
+wrap_periodic_pmegrid(gmx_pme_t pme, real *pmegrid)
+{
+    int     nx,ny,nz,pnx,pny,pnz,ny_x,overlap,ix,iy,iz;
+
+    nx = pme->nkx;
+    ny = pme->nky;
+    nz = pme->nkz;
+
+    pnx = pme->pmegrid_nx;
+    pny = pme->pmegrid_ny;
+    pnz = pme->pmegrid_nz;
+
+    overlap = pme->pme_order - 1;
 
-    if(grid->workspace!=NULL)
+    /* Add periodic overlap in z */
+    for(ix=0; ix<pnx; ix++)
     {
-        tmp = grid->workspace;
+        for(iy=0; iy<pny; iy++)
+        {
+            for(iz=0; iz<overlap; iz++)
+            {
+                pmegrid[(ix*pny+iy)*pnz+iz] +=
+                    pmegrid[(ix*pny+iy)*pnz+nz+iz];
+            }
+        }
+    }
+
+    if (pme->nnodes_minor == 1)
+    {
+       for(ix=0; ix<pnx; ix++)
+       {
+           for(iy=0; iy<overlap; iy++)
+           {
+               for(iz=0; iz<nz; iz++)
+               {
+                   pmegrid[(ix*pny+iy)*pnz+iz] +=
+                       pmegrid[(ix*pny+ny+iy)*pnz+iz];
+               }
+           }
+       }
     }
-    else 
+     
+    if (pme->nnodes_major == 1)
     {
-        if(pme->sum_qgrid_tmp==NULL)
+        ny_x = (pme->nnodes_minor == 1 ? ny : pny);
+
+        for(ix=0; ix<overlap; ix++)
         {
-            snew(pme->sum_qgrid_tmp,localsize);
+            for(iy=0; iy<ny_x; iy++)
+            {
+                for(iz=0; iz<nz; iz++)
+                {
+                    pmegrid[(ix*pny+iy)*pnz+iz] +=
+                        pmegrid[((nx+ix)*pny+iy)*pnz+iz];
+                }
+            }
         }
-        tmp = pme->sum_qgrid_tmp;
     }
+}
 
-    /* NOTE: FFTW doesnt necessarily use all processors for the fft;
-     * above I assume that the ones that do have equal amounts of data.
-     * this is bad since its not guaranteed by fftw, but works for now...
-     * This will be fixed in the next release.
-     */
-    if (direction == GMX_SUM_QGRID_FORWARD) { 
-        /* sum contributions to local grid */
-        
-        GMX_BARRIER(cr->mpi_comm_mygroup);
-        GMX_MPE_LOG(ev_reduce_start);
-        for(i=0;i<maxproc;i++) {
-            MPI_Reduce(grid->ptr+i*localsize, /*ptr arithm.     */
-                       tmp,localsize,      
-                       GMX_MPI_REAL,MPI_SUM,i,cr->mpi_comm_mygroup);
-        }
-        GMX_MPE_LOG(ev_reduce_finish);
-        
-        if(cr->nodeid<maxproc) {
-            memcpy(grid->ptr+cr->nodeid*localsize,tmp,localsize*sizeof(real));
+
+static void
+unwrap_periodic_pmegrid(gmx_pme_t pme, real *pmegrid)
+{
+    int     nx,ny,nz,pnx,pny,pnz,ny_x,overlap,ix,iy,iz;
+
+    nx = pme->nkx;
+    ny = pme->nky;
+    nz = pme->nkz;
+
+    pnx = pme->pmegrid_nx;
+    pny = pme->pmegrid_ny;
+    pnz = pme->pmegrid_nz;
+
+    overlap = pme->pme_order - 1;
+
+    if (pme->nnodes_major == 1)
+    {
+        ny_x = (pme->nnodes_minor == 1 ? ny : pny);
+
+        for(ix=0; ix<overlap; ix++)
+        {
+            for(iy=0; iy<ny_x; iy++)
+            {
+                for(iz=0; iz<nz; iz++)
+                {
+                    pmegrid[((nx+ix)*pny+iy)*pnz+iz] =
+                        pmegrid[(ix*pny+iy)*pnz+iz];
+                }
+            }
         }
     }
-    else if (direction == GMX_SUM_QGRID_BACKWARD) { 
-    /* distribute local grid to all processors */
-        for(i=0;i<maxproc;i++)
-            MPI_Bcast(grid->ptr+i*localsize, /* ptr arithm     */
-                      localsize,       
-                      GMX_MPI_REAL,i,cr->mpi_comm_mygroup);
+
+    if (pme->nnodes_minor == 1)
+    {
+       for(ix=0; ix<pnx; ix++)
+       {
+           for(iy=0; iy<overlap; iy++)
+           {
+               for(iz=0; iz<nz; iz++)
+               {
+                   pmegrid[(ix*pny+ny+iy)*pnz+iz] =
+                       pmegrid[(ix*pny+iy)*pnz+iz];
+               }
+           }
+       }
     }
-    else {
-        gmx_fatal(FARGS,"Invalid direction %d for summing qgrid",direction);
+
+    /* Copy periodic overlap in z */
+    for(ix=0; ix<pnx; ix++)
+    {
+        for(iy=0; iy<pny; iy++)
+        {
+            for(iz=0; iz<overlap; iz++)
+            {
+                pmegrid[(ix*pny+iy)*pnz+nz+iz] =
+                    pmegrid[(ix*pny+iy)*pnz+iz];
+            }
+        }
     }
-    
-#else
-    gmx_fatal(FARGS,"Parallel grid summation requires MPI and FFTW.\n");    
-#endif
 }
 
+
 /* This has to be a macro to enable full compiler optimization with xlC (and probably others too) */
 #define DO_BSPLINE(order)                            \
 for(ithx=0; (ithx<order); ithx++)                    \
 {                                                    \
-    index_x = la12*i0[ithx];                         \
+    index_x = (i0+ithx)*pny*pnz;                     \
     valx    = qn*thx[ithx];                          \
                                                      \
     for(ithy=0; (ithy<order); ithy++)                \
     {                                                \
         valxy    = valx*thy[ithy];                   \
-        index_xy = index_x+la2*j0[ithy];             \
+        index_xy = index_x+(j0+ithy)*pnz;            \
                                                      \
         for(ithz=0; (ithz<order); ithz++)            \
         {                                            \
-            index_xyz       = index_xy+k0[ithz];     \
-            ptr[index_xyz] += valxy*thz[ithz];       \
+            index_xyz        = index_xy+(k0+ithz);   \
+            grid[index_xyz] += valxy*thz[ithz];      \
         }                                            \
     }                                                \
 }
 
 
-
 static void spread_q_bsplines(gmx_pme_t pme, pme_atomcomm_t *atc, 
-                              t_fftgrid *grid)
+                              real *grid)
 {
-  /* spread charges from home atoms to local grid */
-    real     *ptr;
+
+    /* spread charges from home atoms to local grid */
     pme_overlap_t *ol;
-    int      b,i,nn,n,*i0,*j0,*k0,*ii0,*jj0,*kk0,ithx,ithy,ithz;
-    int      nx,ny,nz,nx2,ny2,nz2,la2,la12;
-    int      order,norder,*idxptr,index_x,index_xy,index_xyz;
+    int      b,i,nn,n,ithx,ithy,ithz,i0,j0,k0;
+    int *    idxptr;
+    int      order,norder,index_x,index_xy,index_xyz;
     real     valx,valxy,qn;
     real     *thx,*thy,*thz;
-    int localsize, bndsize;
+    int      localsize, bndsize;
   
-    if (pme->ndecompdim == 0) {
-        clear_fftgrid(grid); 
-#ifdef GMX_MPI
-    } else {
-        localsize = grid->la12r*grid->pfft.local_nx;
-        ptr = grid->ptr + grid->la12r*grid->pfft.local_x_start;
-        for (i=0; (i<localsize); i++) {
-            ptr[i] = 0;
-        }
-        ol = &pme->overlap[0];
-        /* clear left boundary area */
-        for(b=0; b<ol->nleftbnd; b++) {
-            ptr     = grid->ptr + ol->leftc[b].snd0*grid->la12r;
-            bndsize =             ol->leftc[b].snds*grid->la12r;
-            for (i=0; (i<bndsize); i++) {
-                ptr[i] = 0;
-            }
-        }
-        /* clear right boundary area */
-        for(b=0; b<ol->nrightbnd; b++) {
-            ptr     = grid->ptr + ol->rightc[b].snd0*grid->la12r;
-            bndsize =             ol->rightc[b].snds*grid->la12r;
-            for (i=0; (i<bndsize); i++) {
-                ptr[i] = 0;
-            }
-        }
-#endif
+    int      pnx,pny,pnz,ndatatot;
+  
+    pnx = pme->pmegrid_nx;
+    pny = pme->pmegrid_ny;
+    pnz = pme->pmegrid_nz;
+    ndatatot = pnx*pny*pnz;
+    
+    for(i=0;i<ndatatot;i++)
+    {
+        grid[i] = 0;
     }
 
-    unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
-
     order = pme->pme_order;
 
-    ii0   = pme->nnx + nx2 + 1 - order/2;
-    jj0   = pme->nny + ny2 + 1 - order/2;
-    kk0   = pme->nnz + nz2 + 1 - order/2;
-    
-    switch (order) 
-       {
-               case 4:
-                       for(nn=0; (nn<atc->n);nn++) 
-                       {
-                               n      = nn;
-                               qn     = atc->q[n];
-                               idxptr = atc->idx[n];
-
-                               if(qn != 0) 
-                               {
-                                       norder = n*4;
-                                       
-                                       /* Pointer arithmetic alert, next six statements */
-                                       i0  = ii0 + idxptr[XX]; 
-                                       j0  = jj0 + idxptr[YY];
-                                       k0  = kk0 + idxptr[ZZ];
-                                       thx = atc->theta[XX] + norder;
-                                       thy = atc->theta[YY] + norder;
-                                       thz = atc->theta[ZZ] + norder;
-                                       
-#if ((defined __IBMC__ || defined __IBMCPP__) && defined _IBMSMP)
-                                       /* Magic optimization pragma proposed by Mathias Puetz */
-#pragma ibm independent_loop
-#endif
-                                       DO_BSPLINE(4);
-                               }
-                       }
-                       break;
-                       
-               default:
-                       for(nn=0; (nn<atc->n); nn++) 
-                       {
-                               n = nn;
-                               qn     = atc->q[n];
-                               idxptr = atc->idx[n];
-                               
-                               if (qn != 0) 
-                               {
-                                       norder  = n*order;
-                                       
-                                       /* Pointer arithmetic alert, next six statements */
-                                       i0  = ii0 + idxptr[XX]; 
-                                       j0  = jj0 + idxptr[YY];
-                                       k0  = kk0 + idxptr[ZZ];
-                                       thx = atc->theta[XX] + norder;
-                                       thy = atc->theta[YY] + norder;
-                                       thz = atc->theta[ZZ] + norder;
-                       
-#if ((defined __IBMC__ || defined __IBMCPP__) && defined _IBMSMP)
-                                       /* Magic optimization pragma proposed by Mathias Puetz */
-#pragma ibm independent_loop
-#endif
-                                       DO_BSPLINE(order);
-                               }
-                       }
-                       break;
-                       
-    }
-       
+    for(nn=0; (nn<atc->n);nn++) 
+    {
+        n      = nn;
+        qn     = atc->q[n];
+
+        if (qn != 0) 
+        {
+            idxptr = atc->idx[n];
+            norder = n*order;
+            
+            i0   = idxptr[XX]; 
+            j0   = idxptr[YY];
+            k0   = idxptr[ZZ];
+            thx = atc->theta[XX] + norder;
+            thy = atc->theta[YY] + norder;
+            thz = atc->theta[ZZ] + norder;
+            
+            switch (order) {
+            case 4:  DO_BSPLINE(4);     break;
+            case 5:  DO_BSPLINE(5);     break;
+            default: DO_BSPLINE(order); break;
+            }
+        }
+    }  
 }
 
-real solve_pme(gmx_pme_t pme,t_fftgrid *grid,
-               real ewaldcoeff,real vol,matrix vir,t_commrec *cr)
+
+#if ( !defined(GMX_DOUBLE) && ( defined(GMX_IA32_SSE) || defined(GMX_X86_64_SSE) || defined(GMX_X86_64_SSE2) ) )
+    /* Calculate exponentials through SSE in float precision */
+#define CALC_EXPONENTIALS(start,end,r_aligned)      \
+    {                                               \
+        __m128 tmp_sse;                             \
+        for(kx=0; kx<end; kx+=4)                    \
+        {                                           \
+            tmp_sse = _mm_load_ps(r_aligned+kx);    \
+            tmp_sse = gmx_mm_exp_ps_lbc(tmp_sse);   \
+            _mm_store_ps(r_aligned+kx,tmp_sse);     \
+        }                                           \
+    }
+#else
+#define CALC_EXPONENTIALS(start,end,r)          \
+    for(kx=start; kx<end; kx++)                 \
+    {                                           \
+        r[kx] = exp(r[kx]);                     \
+    }
+#endif
+
+
+static int solve_pme_yzx(gmx_pme_t pme,t_complex *grid,
+                         real ewaldcoeff,real vol,
+                         bool bEnerVir,real *mesh_energy,matrix vir)
 {
     /* do recip sum over local cells in grid */
-    t_complex *ptr,*p0;
-    int     nx,ny,nz,nx2,ny2,nz2,la2,la12;
-    int     kx,ky,kz,maxkx,maxky,maxkz,kystart=0,kyend=0,kzstart;
+    /* y major, z middle, x minor or continuous */
+    t_complex *p0;
+    int     kx,ky,kz,maxkx,maxky,maxkz;
+    int     nx,ny,nz,iy,iz,kxstart,kxend;
     real    mx,my,mz;
     real    factor=M_PI*M_PI/(ewaldcoeff*ewaldcoeff);
     real    ets2,struct2,vfactor,ets2vf;
     real    eterm,d1,d2,energy=0;
-    real    bx,by;
-    real    mhx,mhy;
+    real    by,bz;
     real    virxx=0,virxy=0,virxz=0,viryy=0,viryz=0,virzz=0;
     real    rxx,ryx,ryy,rzx,rzy,rzz;
-       real    *mhz,*m2,*denom,*tmp1,*m2inv;
-
-#if ((defined __IBMC__ || defined __IBMCPP__) && defined _IBMSMP)
-       /* xlc optimization proposed by Mathias Puetz */
-#pragma disjoint(*mhz,*m2,*denom,*tmp1,*m2inv,*p0)
-#endif
-       
-    unpack_fftgrid(grid,&nx,&ny,&nz,
-                   &nx2,&ny2,&nz2,&la2,&la12,FALSE,(real **)&ptr);
+       real    *mhx,*mhy,*mhz,*m2,*denom,*tmp1,*m2inv;
+    real    mhxk,mhyk,mhzk,m2k;
+    real    corner_fac;
+    ivec    complex_order;
+    ivec    local_ndata,local_offset,local_size;
+    
+    nx = pme->nkx;
+    ny = pme->nky;
+    nz = pme->nkz;
+    
+    /* Dimensions should be identical for A/B grid, so we just use A here */
+    gmx_parallel_3dfft_complex_limits(pme->pfft_setupA,
+                                      complex_order,
+                                      local_ndata,
+                                      local_offset,
+                                      local_size);
     
     rxx = pme->recipbox[XX][XX];
     ryx = pme->recipbox[YY][XX];
@@ -1024,182 +1206,263 @@ real solve_pme(gmx_pme_t pme,t_fftgrid *grid,
     maxkx = (nx+1)/2;
     maxky = (ny+1)/2;
     maxkz = nz/2+1;
-
-       if(maxkz > pme->maxkz)
-       {
-               /* At the moment the dimensions are actually fixed, but this is for the future... */
-               srenew(pme->work_mhz,maxkz);
-               srenew(pme->work_m2,maxkz);
-               srenew(pme->work_denom,maxkz);
-               srenew(pme->work_tmp1,maxkz);
-               srenew(pme->work_m2inv,maxkz);
-               pme->maxkz=maxkz;
-       }
        
+       mhx   = pme->work_mhx;
+       mhy   = pme->work_mhy;
        mhz   = pme->work_mhz;
        m2    = pme->work_m2;
        denom = pme->work_denom;
        tmp1  = pme->work_tmp1;
        m2inv = pme->work_m2inv;        
-       
-    if (pme->ndecompdim > 0) { 
-        /* transpose X & Y and only sum local cells */
-#ifdef GMX_MPI
-        kystart = grid->pfft.local_y_start_after_transpose;
-        kyend   = kystart+grid->pfft.local_ny_after_transpose;
-        if (debug)
-            fprintf(debug,"solve_pme: kystart = %d, kyend=%d\n",kystart,kyend);
-#else
-        gmx_fatal(FARGS,"Parallel PME attempted without MPI and FFTW");
-#endif /* end of parallel case loop */
-    }
-    else {
-        kystart = 0;
-        kyend   = ny;
-    }
-    
-    for(ky=kystart; (ky<kyend); ky++) {  /* our local cells */
+
+    for(iy=0;iy<local_ndata[YY];iy++)
+    {
+        ky = iy + local_offset[YY];
         
-        if(ky<maxky) {
+        if (ky < maxky) 
+        {
             my = ky;
-        } else {
-            my = (ky-ny);
         }
-        by = M_PI*vol*pme->bsp_mod[YY][ky];
+        else 
+        {
+            my = (ky - ny);
+        }
         
-        for(kx=0; (kx<nx); kx++) {    
-            if(kx < maxkx) {
-                mx = kx;
-            } else {
-                mx = (kx-nx);
-            }
+        by = M_PI*vol*pme->bsp_mod[YY][ky];
 
-            mhx = mx * rxx;
-            mhy = mx * ryx + my * ryy;
+        for(iz=0;iz<local_ndata[ZZ];iz++)
+        {
+            kz = iz + local_offset[ZZ];
             
-            bx = pme->bsp_mod[XX][kx];
+            mz = kz;
+
+            bz = pme->bsp_mod[ZZ][kz];
             
-            if (pme->nnodes > 1) {
-                p0 = ptr + INDEX(ky,kx,0); /* Pointer Arithmetic */
-            } else {
-                p0 = ptr + INDEX(kx,ky,0); /* Pointer Arithmetic */
-            }
+            /* 0.5 correction for corner points */
+                       corner_fac = 1;
+            if (kz == 0)
+                corner_fac = 0.5;
+            if (kz == (nz+1)/2)
+                corner_fac = 0.5;
+                      
+            p0 = grid + iy*local_size[ZZ]*local_size[XX] + iz*local_size[XX];
             
-            if ((kx>0) || (ky>0)) {
-                kzstart = 0;
-            } else {
-                kzstart = 1;
-                p0++;
+            /* We should skip the k-space point (0,0,0) */
+            if (local_offset[XX] > 0 ||
+                local_offset[YY] > 0 || ky > 0 ||
+                kz > 0)
+            {
+                kxstart = local_offset[XX];
             }
-                       
-            for(kz=kzstart,mz=kzstart; (kz<maxkz); kz++,mz+=1.0)  {
-                mhz[kz]   = mx * rzx + my * rzy + mz * rzz;
-                m2[kz]    = mhx*mhx+mhy*mhy+mhz[kz]*mhz[kz];
-                denom[kz] = m2[kz]*bx*by*pme->bsp_mod[ZZ][kz];
-                tmp1[kz]  = -factor*m2[kz];
+            else
+            {
+                kxstart = local_offset[XX] + 1;
+                p0++;
             }
+            kxend = local_offset[XX] + local_ndata[XX];
                        
-            for(kz=kzstart; (kz<maxkz); kz++) m2inv[kz] = 1.0/m2[kz];
-            for(kz=kzstart; (kz<maxkz); kz++) denom[kz] = 1.0/denom[kz];
-            for(kz=kzstart; (kz<maxkz); kz++) tmp1[kz]  = exp(tmp1[kz]);
-                       
-            for(kz=kzstart; (kz<maxkz); kz++,p0++)  {
-                d1      = p0->re;
-                d2      = p0->im;
-                               
-                eterm    = ONE_4PI_EPS0/pme->epsilon_r*tmp1[kz]*denom[kz];
-                               
-                p0->re  = d1*eterm;
-                p0->im  = d2*eterm;
-                               
-                struct2 = 2.0*(d1*d1+d2*d2);
-                               
-                tmp1[kz] = eterm*struct2;
+            if (bEnerVir)
+            {
+                /* More expensive inner loop, especially because of the storage
+                 * of the mh elements in array's.
+                 * Because x is the minor grid index, all mh elements
+                 * depend on kx for triclinic unit cells.
+                 */
+
+                /* Two explicit loops to avoid a conditional inside the loop */
+                for(kx=kxstart; kx<maxkx; kx++)
+                {
+                    mx = kx;
+                    
+                    mhxk      = mx * rxx;
+                    mhyk      = mx * ryx + my * ryy;
+                    mhzk      = mx * rzx + my * rzy + mz * rzz;
+                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+                    mhx[kx]   = mhxk;
+                    mhy[kx]   = mhyk;
+                    mhz[kx]   = mhzk;
+                    m2[kx]    = m2k;
+                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+                    tmp1[kx]  = -factor*m2k;
+                }
+                
+                for(kx=maxkx; kx<kxend; kx++)
+                {
+                    mx = (kx - nx);
+
+                    mhxk      = mx * rxx;
+                    mhyk      = mx * ryx + my * ryy;
+                    mhzk      = mx * rzx + my * rzy + mz * rzz;
+                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+                    mhx[kx]   = mhxk;
+                    mhy[kx]   = mhyk;
+                    mhz[kx]   = mhzk;
+                    m2[kx]    = m2k;
+                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+                    tmp1[kx]  = -factor*m2k;
+                }
+                
+                for(kx=kxstart; kx<kxend; kx++)
+                {
+                    m2inv[kx] = 1.0/m2[kx];
+                }
+                for(kx=kxstart; kx<kxend; kx++)
+                {
+                    denom[kx] = 1.0/denom[kx];
+                }
+
+                CALC_EXPONENTIALS(kxstart,kxend,tmp1);
+
+                for(kx=kxstart; kx<kxend; kx++,p0++)
+                {
+                    d1      = p0->re;
+                    d2      = p0->im;
+                    
+                    eterm    = ONE_4PI_EPS0/pme->epsilon_r*tmp1[kx]*denom[kx];
+                    
+                    p0->re  = d1*eterm;
+                    p0->im  = d2*eterm;
+                    
+                    struct2 = 2.0*(d1*d1+d2*d2);
+                    
+                    tmp1[kx] = eterm*struct2;
+                }
+                
+                for(kx=kxstart; kx<kxend; kx++)
+                {
+                    ets2     = corner_fac*tmp1[kx];
+                    vfactor  = (factor*m2[kx] + 1.0)*2.0*m2inv[kx];
+                    energy  += ets2;
+                    
+                    ets2vf   = ets2*vfactor;
+                    virxx   += ets2vf*mhx[kx]*mhx[kx] - ets2;
+                    virxy   += ets2vf*mhx[kx]*mhy[kx];
+                    virxz   += ets2vf*mhx[kx]*mhz[kx];
+                    viryy   += ets2vf*mhy[kx]*mhy[kx] - ets2;
+                    viryz   += ets2vf*mhy[kx]*mhz[kx];
+                    virzz   += ets2vf*mhz[kx]*mhz[kx] - ets2;
+                }
             }
-                       
-            /* 0.5 correction for corner points */
-                       
-            if (kzstart == 0)
-                tmp1[0] *= 0.5;
-                       
-            if (((nz+1)/2) < maxkz)
-                tmp1[((nz+1)/2)] *= 0.5;
-                       
-            for(kz=kzstart; (kz<maxkz); kz++)  {
-                ets2     = tmp1[kz];
-                vfactor  = (factor*m2[kz]+1.0)*2.0*m2inv[kz];
-                energy  += ets2;
-                               
-                ets2vf   = ets2*vfactor;
-                virxx   += ets2vf*mhx*mhx-ets2;
-                virxy   += ets2vf*mhx*mhy;
-                virxz   += ets2vf*mhx*mhz[kz];
-                viryy   += ets2vf*mhy*mhy-ets2;
-                viryz   += ets2vf*mhy*mhz[kz];
-                virzz   += ets2vf*mhz[kz]*mhz[kz]-ets2;
+            else
+            {
+                /* We don't need to calculate the energy and the virial.
+                 * In this case the triclinic overhead is small.
+                 */
+
+                /* Two explicit loops to avoid a conditional inside the loop */
+
+                for(kx=kxstart; kx<maxkx; kx++)
+                {
+                    mx = kx;
+                    
+                    mhxk      = mx * rxx;
+                    mhyk      = mx * ryx + my * ryy;
+                    mhzk      = mx * rzx + my * rzy + mz * rzz;
+                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+                    tmp1[kx]  = -factor*m2k;
+                }
+                
+                for(kx=maxkx; kx<kxend; kx++)
+                {
+                    mx = (kx - nx);
+                    
+                    mhxk      = mx * rxx;
+                    mhyk      = mx * ryx + my * ryy;
+                    mhzk      = mx * rzx + my * rzy + mz * rzz;
+                    m2k       = mhxk*mhxk + mhyk*mhyk + mhzk*mhzk;
+                    denom[kx] = m2k*bz*by*pme->bsp_mod[XX][kx];
+                    tmp1[kx]  = -factor*m2k;
+                }
+                
+                for(kx=kxstart; kx<kxend; kx++)
+                {
+                    denom[kx] = 1.0/denom[kx];
+                }
+
+                CALC_EXPONENTIALS(kxstart,kxend,tmp1);
+               
+                for(kx=kxstart; kx<kxend; kx++,p0++)
+                {
+                    d1      = p0->re;
+                    d2      = p0->im;
+                    
+                    eterm    = ONE_4PI_EPS0/pme->epsilon_r*tmp1[kx]*denom[kx];
+                    
+                    p0->re  = d1*eterm;
+                    p0->im  = d2*eterm;
+                }
             }
         }
     }
     
-    /* Update virial with local values. The virial is symmetric by definition.
-     * this virial seems ok for isotropic scaling, but I'm
-     * experiencing problems on semiisotropic membranes.
-     * IS THAT COMMENT STILL VALID??? (DvdS, 2001/02/07).
-     */
-    vir[XX][XX] = 0.25*virxx;
-    vir[YY][YY] = 0.25*viryy;
-    vir[ZZ][ZZ] = 0.25*virzz;
-    vir[XX][YY] = vir[YY][XX] = 0.25*virxy;
-    vir[XX][ZZ] = vir[ZZ][XX] = 0.25*virxz;
-    vir[YY][ZZ] = vir[ZZ][YY] = 0.25*viryz;
-       
-    /* This energy should be corrected for a charged system */
-    return(0.5*energy);
+    if (bEnerVir)
+    {
+        /* Update virial with local values.
+         * The virial is symmetric by definition.
+         * this virial seems ok for isotropic scaling, but I'm
+         * experiencing problems on semiisotropic membranes.
+         * IS THAT COMMENT STILL VALID??? (DvdS, 2001/02/07).
+         */
+        vir[XX][XX] = 0.25*virxx;
+        vir[YY][YY] = 0.25*viryy;
+        vir[ZZ][ZZ] = 0.25*virzz;
+        vir[XX][YY] = vir[YY][XX] = 0.25*virxy;
+        vir[XX][ZZ] = vir[ZZ][XX] = 0.25*virxz;
+        vir[YY][ZZ] = vir[ZZ][YY] = 0.25*viryz;
+        
+        /* This energy should be corrected for a charged system */
+        *mesh_energy = 0.5*energy;
+    }
+
+    /* Return the loop count */
+    return local_ndata[YY]*local_ndata[ZZ]*local_ndata[XX];
 }
 
+
 #define DO_FSPLINE(order)                      \
 for(ithx=0; (ithx<order); ithx++)              \
 {                                                                         \
-    index_x = la12*i0[ithx];                   \
+    index_x = (i0+ithx)*pny*pnz;               \
     tx      = thx[ithx];                       \
     dx      = dthx[ithx];                      \
-                                                                                          \
+                                               \
     for(ithy=0; (ithy<order); ithy++)          \
-       {                                                                                  \
-        index_xy = index_x+la2*j0[ithy];       \
+    {                                                                             \
+        index_xy = index_x+(j0+ithy)*pnz;      \
         ty       = thy[ithy];                  \
         dy       = dthy[ithy];                 \
         fxy1     = fz1 = 0;                    \
                                                \
         for(ithz=0; (ithz<order); ithz++)      \
-               {                                                                  \
-               gval  = ptr[index_xy+k0[ithz]];        \
-               fxy1 += thz[ithz]*gval;                \
-               fz1  += dthz[ithz]*gval;               \
-               }                                      \
-               fx += dx*ty*fxy1;                      \
-               fy += tx*dy*fxy1;                      \
-               fz += tx*ty*fz1;                       \
-       }                                          \
+        {                                                                 \
+            gval  = grid[index_xy+(k0+ithz)];  \
+            fxy1 += thz[ithz]*gval;            \
+            fz1  += dthz[ithz]*gval;           \
+        }                                      \
+        fx += dx*ty*fxy1;                      \
+        fy += tx*dy*fxy1;                      \
+        fz += tx*ty*fz1;                       \
+    }                                          \
 }
 
 
-void gather_f_bsplines(gmx_pme_t pme,t_fftgrid *grid,
+void gather_f_bsplines(gmx_pme_t pme,real *grid,
                        bool bClearF,pme_atomcomm_t *atc,real scale)
 {
     /* sum forces for local particles */  
-    int     nn,n,*i0,*j0,*k0,*ii0,*jj0,*kk0,ithx,ithy,ithz;
-    int     nx,ny,nz,nx2,ny2,nz2,la2,la12,index_x,index_xy;
-    real *  ptr;
+    int     nn,n,ithx,ithy,ithz,i0,j0,k0;
+    int     index_x,index_xy;
+    int     nx,ny,nz,pnx,pny,pnz;
+    int *   idxptr;
     real    tx,ty,dx,dy,qn;
     real    fx,fy,fz,gval;
     real    fxy1,fz1;
     real    *thx,*thy,*thz,*dthx,*dthy,*dthz;
-    int     norder,*idxptr;
+    int     norder;
     real    rxx,ryx,ryy,rzx,rzy,rzz;
     int     order;
     
-    unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
     order = pme->pme_order;
     thx   = atc->theta[XX];
     thy   = atc->theta[YY];
@@ -1207,9 +1470,12 @@ void gather_f_bsplines(gmx_pme_t pme,t_fftgrid *grid,
     dthx  = atc->dtheta[XX];
     dthy  = atc->dtheta[YY];
     dthz  = atc->dtheta[ZZ];
-    ii0   = pme->nnx + nx2 + 1 - order/2;
-    jj0   = pme->nny + ny2 + 1 - order/2;
-    kk0   = pme->nnz + nz2 + 1 - order/2;
+    nx    = pme->nkx;
+    ny    = pme->nky;
+    nz    = pme->nkz;
+    pnx   = pme->pmegrid_nx;
+    pny   = pme->pmegrid_ny;
+    pnz   = pme->pmegrid_nz;
     
     rxx   = pme->recipbox[XX][XX];
     ryx   = pme->recipbox[YY][XX];
@@ -1218,26 +1484,30 @@ void gather_f_bsplines(gmx_pme_t pme,t_fftgrid *grid,
     rzy   = pme->recipbox[ZZ][YY];
     rzz   = pme->recipbox[ZZ][ZZ];
 
-    for(nn=0; (nn<atc->n); nn++) {
+    for(nn=0; (nn<atc->n); nn++) 
+    {
         n = nn;
         qn      = scale*atc->q[n];
         
-        if (bClearF) {
+        if (bClearF) 
+        {
             atc->f[n][XX] = 0;
             atc->f[n][YY] = 0;
             atc->f[n][ZZ] = 0;
         }
-        if (qn != 0) {
+        if (qn != 0) 
+        {
             fx     = 0;
             fy     = 0;
             fz     = 0;
             idxptr = atc->idx[n];
             norder = n*order;
             
-            /* Pointer arithmetic alert, next nine statements */
-            i0   = ii0 + idxptr[XX]; 
-            j0   = jj0 + idxptr[YY];
-            k0   = kk0 + idxptr[ZZ];
+            i0   = idxptr[XX]; 
+            j0   = idxptr[YY];
+            k0   = idxptr[ZZ];
+            
+            /* Pointer arithmetic alert, next six statements */
             thx  = atc->theta[XX] + norder;
             thy  = atc->theta[YY] + norder;
             thz  = atc->theta[ZZ] + norder;
@@ -1245,16 +1515,12 @@ void gather_f_bsplines(gmx_pme_t pme,t_fftgrid *grid,
             dthy = atc->dtheta[YY] + norder;
             dthz = atc->dtheta[ZZ] + norder;
             
-            switch(order)
-                       {
-                               case 4 :
-                                       DO_FSPLINE(4);
-                                       break;
-                               default:
-                                       DO_FSPLINE(order);
-                                       break;
+            switch (order) {
+            case 4:  DO_FSPLINE(4);     break;
+            case 5:  DO_FSPLINE(5);     break;
+            default: DO_FSPLINE(order); break;
             }
-                       
+
             atc->f[n][XX] += -qn*( fx*nx*rxx );
             atc->f[n][YY] += -qn*( fx*nx*ryx + fy*ny*ryy );
             atc->f[n][ZZ] += -qn*( fx*nx*rzx + fy*ny*rzy + fz*nz*rzz );
@@ -1271,25 +1537,22 @@ void gather_f_bsplines(gmx_pme_t pme,t_fftgrid *grid,
      */
 }
 
-static real gather_energy_bsplines(gmx_pme_t pme,t_fftgrid *grid,
+static real gather_energy_bsplines(gmx_pme_t pme,real *grid,
                                    pme_atomcomm_t *atc)
 {
-    int     n,*i0,*j0,*k0,*ii0,*jj0,*kk0,ithx,ithy,ithz;
-    int     nx,ny,nz,nx2,ny2,nz2,la2,la12,index_x,index_xy;
-    real *  ptr;
+    int     n,ithx,ithy,ithz,i0,j0,k0;
+    int     index_x,index_xy;
+    int *   idxptr;
     real    energy,pot,tx,ty,qn,gval;
     real    *thx,*thy,*thz;
-    int     norder,*idxptr;
+    int     norder;
     int     order;
     
-    unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
+    
     order = pme->pme_order;
     thx   = atc->theta[XX];
     thy   = atc->theta[YY];
     thz   = atc->theta[ZZ];
-    ii0   = pme->nnx + nx2 + 1 - order/2;
-    jj0   = pme->nny + ny2 + 1 - order/2;
-    kk0   = pme->nnz + nz2 + 1 - order/2;
     
     energy = 0;
     for(n=0; (n<atc->n); n++) {
@@ -1299,10 +1562,11 @@ static real gather_energy_bsplines(gmx_pme_t pme,t_fftgrid *grid,
             idxptr = atc->idx[n];
             norder = n*order;
             
-            /* Pointer arithmetic alert, next nine statements */
-            i0   = ii0 + idxptr[XX]; 
-            j0   = jj0 + idxptr[YY];
-            k0   = kk0 + idxptr[ZZ];
+            i0   = idxptr[XX]; 
+            j0   = idxptr[YY];
+            k0   = idxptr[ZZ];
+            
+            /* Pointer arithmetic alert, next three statements */
             thx  = atc->theta[XX] + norder;
             thy  = atc->theta[YY] + norder;
             thz  = atc->theta[ZZ] + norder;
@@ -1310,17 +1574,17 @@ static real gather_energy_bsplines(gmx_pme_t pme,t_fftgrid *grid,
             pot = 0;
             for(ithx=0; (ithx<order); ithx++)
             {
-                index_x = la12*i0[ithx];
+                index_x = (i0+ithx)*pme->pmegrid_ny*pme->pmegrid_nz;
                 tx      = thx[ithx];
 
                 for(ithy=0; (ithy<order); ithy++)
                 {
-                    index_xy = index_x+la2*j0[ithy];
+                    index_xy = index_x+(j0+ithy)*pme->pmegrid_nz;
                     ty       = thy[ithy];
 
                     for(ithz=0; (ithz<order); ithz++)
                     {
-                        gval  = ptr[index_xy+k0[ithz]];
+                        gval  = grid[index_xy+(k0+ithz)];
                         pot  += tx*ty*thz[ithz]*gval;
                     }
 
@@ -1334,8 +1598,8 @@ static real gather_energy_bsplines(gmx_pme_t pme,t_fftgrid *grid,
     return energy;
 }
 
-void make_bsplines(splinevec theta,splinevec dtheta,int order,int nx,int ny,
-                   int nz,rvec fractx[],int nr,real charge[],
+void make_bsplines(splinevec theta,splinevec dtheta,int order,
+                   rvec fractx[],int nr,real charge[],
                    bool bFreeEnergy)
 {
     /* construct splines for local atoms */
@@ -1490,15 +1754,22 @@ int gmx_pme_destroy(FILE *log,gmx_pme_t *pmedata)
     sfree((*pmedata)->nny);
     sfree((*pmedata)->nnz);
        
-    done_fftgrid((*pmedata)->gridA);
-    if((*pmedata)->gridB)
+    sfree((*pmedata)->pmegridA);
+    sfree((*pmedata)->fftgridA);
+    sfree((*pmedata)->cfftgridA);
+    gmx_parallel_3dfft_destroy((*pmedata)->pfft_setupA);
+    
+    if((*pmedata)->pmegridB)
     {
-        done_fftgrid((*pmedata)->gridB);
+        sfree((*pmedata)->pmegridB);
+        sfree((*pmedata)->fftgridB);
+        sfree((*pmedata)->cfftgridB);
+        gmx_parallel_3dfft_destroy((*pmedata)->pfft_setupB);
     }
     sfree((*pmedata)->work_mhz);
     sfree((*pmedata)->work_m2);
     sfree((*pmedata)->work_denom);
-    sfree((*pmedata)->work_tmp1);
+    sfree((*pmedata)->work_tmp1_alloc);
     sfree((*pmedata)->work_m2inv);
        
     sfree(*pmedata);
@@ -1507,63 +1778,42 @@ int gmx_pme_destroy(FILE *log,gmx_pme_t *pmedata)
   return 0;
 }
 
-int pme_inconvenient_nnodes(int nkx,int nky,int nnodes)
+static int mult_up(int n,int f)
 {
-  int   nnx,nny;
-  float imbal;
-  int   ret;
-
-  ret = 0;
-  if (nnodes > nkx && nnodes > nky) {
-    /* This is probably always bad */
-    ret = 2;
-  } else if (2*nnodes > nkx && nnodes != nkx) {
-    /* This is inconvenient for the grid overlap communication */
-    ret = 1;
-  } 
-
-  /* Determine the maximum number of grid slabs per PME node */
-  nnx = (nkx + nnodes - 1)/nnodes;
-  nny = (nky + nnodes - 1)/nnodes;
-  /* Estimate the FFT + solve_pme load imbalance.
-   * Imbalance in x for 2D FFT.
-   * Imbalance in y for 1D FFT + solve_pme.
-   * x and y imbalance affect the performance roughly equally.
-   */
-  imbal = (nnx*nnodes/(float)nkx + nny*nnodes/(float)nky)*0.5 - 1;
-  if (debug)
-    fprintf(debug,"PME load imbalance estimate for npme=%d: %f\n",
-           nnodes,imbal);
-
-  /* The cost of charge spreading and force gathering (which is always
-   * load balanced) is usually 1-2 times more than FFT+solve_pme.
-   * So we compare the imbalance to (a rough guess of) the performance gain
-   * in spreading and gathering with respect to one node less.
-   */
-  if (imbal > 2.0/nnodes) {
-    ret = max(ret,2);
-  } else if (imbal > 1.0/nnodes) {
-    ret = max(ret,1);
-  }
+    return ((n + f - 1)/f)*f;
+}
+
 
-  return ret;
+static double pme_load_imbalance(gmx_pme_t pme)
+{
+    int    nma,nmi;
+    double n1,n2,n3;
+
+    nma = pme->nnodes_major;
+    nmi = pme->nnodes_minor;
+
+    n1 = mult_up(pme->nkx,nma)*mult_up(pme->nky,nmi)*pme->nkz;
+    n2 = mult_up(pme->nkx,nma)*mult_up(pme->nkz,nmi)*pme->nky;
+    n3 = mult_up(pme->nky,nma)*mult_up(pme->nkz,nmi)*pme->nkx;
+
+    /* pme_solve is roughly double the cost of an fft */
+
+    return (n1 + n2 + 3*n3)/(double)(6*pme->nkx*pme->nky*pme->nkz);
 }
 
 static void init_atomcomm(gmx_pme_t pme,pme_atomcomm_t *atc, t_commrec *cr,
                           int dimind,bool bSpread)
 {
-    int lbnd,rbnd,maxlr,b,i;
-    int nn,nk;
-    pme_grid_comm_t *pgc;
+    int nk,k,s;
 
     atc->dimind = dimind;
     atc->nslab  = 1;
     atc->nodeid = 0;
     atc->pd_nalloc = 0;
 #ifdef GMX_MPI
-    if (PAR(cr))
+    if (pme->nnodes > 1)
     {
-        atc->mpi_comm = pme->mpi_comm_d[atc->dimind];
+        atc->mpi_comm = pme->mpi_comm_d[dimind];
         MPI_Comm_size(atc->mpi_comm,&atc->nslab);
         MPI_Comm_rank(atc->mpi_comm,&atc->nodeid);
     }
@@ -1589,143 +1839,283 @@ static void init_atomcomm(gmx_pme_t pme,pme_atomcomm_t *atc, t_commrec *cr,
     }
 }
 
-static void init_overlap_comm(gmx_pme_t pme,pme_overlap_t *ol, t_commrec *cr)
+static void 
+init_overlap_comm(pme_overlap_t *  ol,
+                  int              norder,
+#ifdef GMX_MPI
+                  MPI_Comm         comm,  
+#endif
+                  int              nnodes, 
+                  int              nodeid,
+                  int              ndata)
 {
     int lbnd,rbnd,maxlr,b,i;
+    int exten;
     int nn,nk;
     pme_grid_comm_t *pgc;
-
+    bool bCont;
+    int fft_start,fft_end,send_index1,recv_index1;
+    
 #ifdef GMX_MPI
-    ol->mpi_comm = pme->mpi_comm;
+    ol->mpi_comm = comm;
 #endif
-
-    ol->nodeid = pme->nodeid;
     
-    nn = pme->nnodes;
-    nk = pme->nkx;
+    ol->nnodes = nnodes;
+    ol->nodeid = nodeid;
+    
+    ol->ndata  = ndata;
 
-    /* Determine the grid boundary communication sizes and nodes */
-    if (nk % nn == 0) {
-        lbnd = pme->pme_order/2 - 1;
-    } else {
-        lbnd = pme->pme_order - (pme->pme_order/2 - 1) - 1;
-    }
-    rbnd     = pme->pme_order - (pme->pme_order/2 - 1) - 1;
-    /* Round up */
-    ol->nleftbnd  = (lbnd*nn + nk - 1)/nk;
-    ol->nrightbnd = (rbnd*nn + nk - 1)/nk;
-    maxlr = max(ol->nleftbnd,ol->nrightbnd);
-    snew(ol->leftid, maxlr);
-    snew(ol->rightid,maxlr);
-    for(b=0; b<maxlr; b++) {
-        ol->leftid[b]  = (ol->nodeid - (b + 1) + nn) % nn;
-        ol->rightid[b] = (ol->nodeid + (b + 1)) % nn;
-    }
-    snew(ol->leftc, ol->nleftbnd);
-    snew(ol->rightc,ol->nrightbnd);
-    snew(ol->s2g,nn+1);
-    for(i=0; i<nn+1; i++) {
-        /* The definition of the grid position requires rounding up here */
-        ol->s2g[i] = (i*nk + nn - 1)/nn;
-    }
-    /* The left boundary */
-    for(b=0; b<ol->nleftbnd; b++) {
-        pgc = &ol->leftc[b];
-        /* Send */
-        i = ol->s2g[ol->nodeid];
-        if (ol->leftid[b] > ol->nodeid) {
-            i += pme->nkx;
+    /* Linear translation of the PME grid wo'nt affect reciprocal space
+     * calculations, so to optimize we only interpolate "upwards",
+     * which also means we only have to consider overlap in one direction.
+     * I.e., particles on this node might also be spread to grid indices
+     * that belong to higher nodes (modulo nnodes)
+     */
+
+    snew(ol->s2g0,ol->nnodes+1);
+    snew(ol->s2g1,ol->nnodes);
+    if (debug) { fprintf(debug,"PME slab boundaries:"); }
+    for(i=0; i<nnodes; i++) 
+    {
+        /* s2g0 the local interpolation grid start.
+         * s2g1 the local interpolation grid end.
+         * Because grid overlap communication only goes forward,
+         * the grid the slabs for fft's should be rounded down.
+         */
+        ol->s2g0[i] = ( i   *ndata + 0       )/nnodes;
+        ol->s2g1[i] = ((i+1)*ndata + nnodes-1)/nnodes + norder - 1;
+
+        if (debug)
+        {
+            fprintf(debug,"  %3d %3d",ol->s2g0[i],ol->s2g1[i]);
         }
-        pgc->snd0 = max(i - lbnd,ol->s2g[ol->leftid[b]]);
-        pgc->snds = min(i       ,ol->s2g[ol->leftid[b]+1]) - pgc->snd0;
-        pgc->snds = max(pgc->snds,0);
-        /* Receive */
-        i = ol->s2g[ol->rightid[b]];
-        if (ol->rightid[b] < ol->nodeid)
-            i += pme->nkx;
-        pgc->rcv0 = max(i - lbnd,ol->s2g[ol->nodeid]);
-        pgc->rcvs = min(i       ,ol->s2g[ol->nodeid+1]) - pgc->rcv0;
-        pgc->rcvs = max(pgc->rcvs,0);
-    }
-    /* The right boundary */
-    for(b=0; b<ol->nrightbnd; b++) {
-        pgc = &ol->rightc[b];
+    }
+    ol->s2g0[nnodes] = ndata;
+    if (debug) { fprintf(debug,"\n"); }
+
+    /* Determine with how many nodes we need to communicate the grid overlap */
+    b = 0;
+    do
+    {
+        b++;
+        bCont = FALSE;
+        for(i=0; i<nnodes; i++)
+        {
+            if ((i+b <  nnodes && ol->s2g1[i] > ol->s2g0[i+b]) ||
+                (i+b >= nnodes && ol->s2g1[i] > ol->s2g0[i+b-nnodes] + ndata))
+            {
+                bCont = TRUE;
+            }
+        }
+    }
+    while (bCont && b < nnodes);
+    ol->noverlap_nodes = b - 1;
+
+    snew(ol->send_id,ol->noverlap_nodes);
+    snew(ol->recv_id,ol->noverlap_nodes);
+    for(b=0; b<ol->noverlap_nodes; b++)
+    {
+        ol->send_id[b] = (ol->nodeid + (b + 1)) % ol->nnodes;
+        ol->recv_id[b] = (ol->nodeid - (b + 1) + ol->nnodes) % ol->nnodes;
+    }
+    snew(ol->comm_data, ol->noverlap_nodes);
+
+    for(b=0; b<ol->noverlap_nodes; b++)
+    {
+        pgc = &ol->comm_data[b];
         /* Send */
-        i = ol->s2g[ol->nodeid+1];
-        if (ol->rightid[b] < ol->nodeid) {
-            i -= nk;
+        fft_start        = ol->s2g0[ol->send_id[b]];
+        fft_end          = ol->s2g0[ol->send_id[b]+1];
+        if (ol->send_id[b] < nodeid)
+        {
+            fft_start += ol->ndata;
+            fft_end  += ol->ndata;
+        }
+        send_index1      = ol->s2g1[nodeid];
+        send_index1      = min(send_index1,fft_end);
+        pgc->send_index0 = fft_start;
+        pgc->send_nindex = max(0,send_index1 - pgc->send_index0);
+
+        /* We always start receiving to the first index of our slab */
+        fft_start        = ol->s2g0[ol->nodeid];
+        fft_end          = ol->s2g0[ol->nodeid+1];
+        recv_index1      = ol->s2g1[ol->recv_id[b]];
+        if (ol->recv_id[b] > nodeid)
+        {
+            recv_index1 -= ol->ndata;
+        }
+        recv_index1      = min(recv_index1,fft_end);
+        pgc->recv_index0 = fft_start;
+        pgc->recv_nindex = max(0,recv_index1 - pgc->recv_index0);
+    }
+}
+
+static void
+make_gridindex5_to_localindex(int n,int local_start,int local_end,
+                              int **global_to_local,
+                              real **fraction_shift)
+{
+    int local_size,i;
+    int * gtl;
+    real * fsh;
+
+    local_size = local_end - local_start;
+
+    snew(gtl,5*n);
+    snew(fsh,5*n);
+    for(i=0; (i<5*n); i++) {
+        /* Determine the global to local grid index */
+        gtl[i] = (i - local_start + n) % n;
+        /* For coordinates that fall within the local grid the fraction
+         * is correct, we don't need to shift it.
+         */
+        fsh[i] = 0;
+        if (local_size < n)
+        {
+            /* Due to rounding issues i could be 1 beyond the lower or
+             * upper boundary of the local grid. Correct the index for this.
+             * If we shift the index, we need to shift the fraction by
+             * the same amount in the other direction to not affect
+             * the weights.
+             * Note that due to this shifting the weights at the end of
+             * the spline might change, but that will only involve values
+             * between zero and values close to the precision of a real,
+             * which is anyhow the accuracy of the whole mesh calculation.
+             */
+            /* With local_size=0 we should not change i=local_start */
+            if (i % n != local_start)
+            {
+                if (gtl[i] == n-1)
+                {
+                    gtl[i] = 0;
+                    fsh[i] = -1; 
+                }
+                else if (gtl[i] == local_size)
+                {
+                    gtl[i] = local_size - 1;
+                    fsh[i] = 1;
+                }
+            }
+        }
+    }
+
+    *global_to_local = gtl;
+    *fraction_shift  = fsh;
+}
+
+static void
+gmx_pme_check_grid_restrictions(FILE *fplog,char dim,int nnodes,int *nk)
+{
+    int nk_new;
+
+    if (*nk % nnodes != 0)
+    {
+        nk_new = nnodes*(*nk/nnodes + 1);
+
+        if (2*nk_new >= 3*(*nk))
+        {
+            gmx_fatal(FARGS,"The PME grid size in dim %c (%d) is not divisble by the number of nodes doing PME in dim %c (%d). The grid size would have to be increased by more than 50%% to make the grid divisible. Change the total number of nodes or the number of domain decomposition cells in x or the PME grid %c dimension (and the cut-off).",
+                      dim,*nk,dim,nnodes,dim);
         }
-        pgc->snd0 = max(i       ,ol->s2g[ol->rightid[b]]);
-        pgc->snds = min(i + rbnd,ol->s2g[ol->rightid[b]+1]) - pgc->snd0;
-        pgc->snds = max(pgc->snds,0);
-        /* Receive */
-        i = ol->s2g[ol->leftid[b]+1];
-        if (ol->leftid[b] > ol->nodeid)
-            i -= pme->nkx;
-        pgc->rcv0 = max(i       ,ol->s2g[ol->nodeid]);
-        pgc->rcvs = min(i + rbnd,ol->s2g[ol->nodeid+1]) - pgc->rcv0;
-        pgc->rcvs = max(pgc->rcvs,0);
+        
+        if (fplog != NULL)
+        {
+            fprintf(fplog,"\nNOTE: The PME grid size in dim %c (%d) is not divisble by the number of nodes doing PME in dim %c (%d). Increasing the PME grid size in dim %c to %d. This will increase the accuracy and will not decrease the performance significantly on this number of nodes. For optimal performance change the total number of nodes or the number of domain decomposition cells in x or the PME grid %c dimension (and the cut-off).\n\n",
+                    dim,*nk,dim,nnodes,dim,nk_new,dim);
+        }
+            
+        *nk = nk_new;
     }
 }
 
-int gmx_pme_init(gmx_pme_t *pmedata,t_commrec *cr,int nnodes_major,
-                 t_inputrec *ir,int homenr,
-                 bool bFreeEnergy,
-                 bool bReproducible)
+int gmx_pme_init(gmx_pme_t *         pmedata,
+                 t_commrec *         cr,
+                 int                 nnodes_major,
+                 int                 nnodes_minor,
+                 t_inputrec *        ir,
+                 int                 homenr,
+                 bool                bFreeEnergy,
+                 bool                bReproducible)
 {
     gmx_pme_t pme=NULL;
     
     pme_atomcomm_t *atc;
-    int nminor,b,d,i,lbnd,rbnd,maxlr;
-
+    int bufsizex,bufsizey,bufsize;
+    ivec ndata;
     
     if (debug)
         fprintf(debug,"Creating PME data structures.\n");
     snew(pme,1);
+        
+    pme->redist_init         = FALSE;
+    pme->sum_qgrid_tmp       = NULL;
+    pme->sum_qgrid_dd_tmp    = NULL;
+    pme->buf_nalloc          = 0;
+    pme->redist_buf_nalloc   = 0;
     
-   
-    pme->redist_init   = FALSE;
-    pme->sum_qgrid_tmp = NULL;
-    pme->sum_qgrid_dd_tmp = NULL;
-    pme->buf_nalloc = 0;
-    pme->redist_buf_nalloc = 0;
+    pme->nnodes              = 1;
+    pme->bPPnode             = TRUE;
     
-    pme->nnodes  = 1;
-    pme->bPPnode = TRUE;
+    pme->nnodes_major        = nnodes_major;
+    pme->nnodes_minor        = nnodes_minor;
+
 #ifdef GMX_MPI
     if (PAR(cr)) 
     {
-        pme->mpi_comm = cr->mpi_comm_mygroup;
+        pme->mpi_comm        = cr->mpi_comm_mygroup;
+        
         MPI_Comm_rank(pme->mpi_comm,&pme->nodeid);
         MPI_Comm_size(pme->mpi_comm,&pme->nnodes);
-
-        pme->mpi_comm_d[0] = pme->mpi_comm;
     }
 #endif
 
     if (pme->nnodes == 1)
     {
         pme->ndecompdim = 0;
+        pme->nodeid_major = 0;
+        pme->nodeid_minor = 0;
     }
     else
     {
-        if (pme->nnodes == nnodes_major)
+        if (nnodes_minor == 1)
         {
+#ifdef GMX_MPI
+            pme->mpi_comm_d[0] = pme->mpi_comm;
+            pme->mpi_comm_d[1] = NULL;
+#endif
             pme->ndecompdim = 1;
+            pme->nodeid_major = pme->nodeid;
+            pme->nodeid_minor = 0;
+            
         }
-        else
+        else if (nnodes_major == 1)
+        {
+#ifdef GMX_MPI
+            pme->mpi_comm_d[0] = NULL;
+            pme->mpi_comm_d[1] = pme->mpi_comm;
+#endif
+            pme->ndecompdim = 1;
+            pme->nodeid_major = 0;
+            pme->nodeid_minor = pme->nodeid;
+        }
+        else 
         {
             if (pme->nnodes % nnodes_major != 0)
             {
-                gmx_incons("nnodes_major incompatible with #PME nodes");
+                gmx_incons("For 2D PME decomposition, #PME nodes must be divisible by the number of nodes in the major dimension");
             }
             pme->ndecompdim = 2;
+            
 #ifdef GMX_MPI
-            nminor = pme->nnodes/nnodes_major;
-            MPI_Comm_split(pme->mpi_comm,pme->nodeid % nminor,
-                           pme->nodeid,&pme->mpi_comm_d[0]);
-            MPI_Comm_split(pme->mpi_comm,pme->nodeid/nminor,
-                           pme->nodeid,&pme->mpi_comm_d[1]);
+            MPI_Comm_split(pme->mpi_comm,pme->nodeid % nnodes_minor,
+                           pme->nodeid,&pme->mpi_comm_d[0]);  /* My communicator along major dimension */
+            MPI_Comm_split(pme->mpi_comm,pme->nodeid/nnodes_minor,
+                           pme->nodeid,&pme->mpi_comm_d[1]);  /* My communicator along minor dimension */
+            
+            MPI_Comm_rank(pme->mpi_comm_d[0],&pme->nodeid_major);
+            MPI_Comm_size(pme->mpi_comm_d[0],&pme->nnodes_major);
+            MPI_Comm_rank(pme->mpi_comm_d[1],&pme->nodeid_minor);
+            MPI_Comm_size(pme->mpi_comm_d[1],&pme->nnodes_minor);
 #endif
         }
         pme->bPPnode = (cr->duty & DUTY_PP);
@@ -1736,26 +2126,42 @@ int gmx_pme_init(gmx_pme_t *pmedata,t_commrec *cr,int nnodes_major,
         gmx_fatal(FARGS,"pme does not (yet) work with pbc = screw");
     }
     
-    pme->bFEP = ((ir->efep != efepNO) && bFreeEnergy);
-    pme->nkx  = ir->nkx;
-    pme->nky  = ir->nky;
-    pme->nkz  = ir->nkz;
+    pme->bFEP        = ((ir->efep != efepNO) && bFreeEnergy);
+    pme->nkx         = ir->nkx;
+    pme->nky         = ir->nky;
+    pme->nkz         = ir->nkz;
     pme->pme_order   = ir->pme_order;
     pme->epsilon_r   = ir->epsilon_r;
     
-    /* Use atc[0] for spreading */
-    init_atomcomm(pme,&pme->atc[0],cr,0,TRUE);
+    /* Currently pme.c supports only the fft5d FFT code.
+     * Therefore the grid always needs to be divisible by nnodes.
+     * When the old 1D code is also supported again, change this check.
+     *
+     * This check should be done before calling gmx_pme_init
+     * and fplog should be passed iso stderr.
+     *
     if (pme->ndecompdim >= 2)
+    */
+    if (pme->ndecompdim >= 1)
     {
-        init_atomcomm(pme,&pme->atc[1],cr,1,FALSE);
+        /*
+        gmx_pme_check_grid_restrictions(pme->nodeid==0 ? stderr : NULL,
+                                        'x',nnodes_major,&pme->nkx);
+        gmx_pme_check_grid_restrictions(pme->nodeid==0 ? stderr : NULL,
+                                        'y',nnodes_minor,&pme->nky);
+        */
     }
-    
-    if (pme->nkx <= pme->pme_order*(pme->nnodes > 1 ? 2 : 1) ||
-        pme->nky <= pme->pme_order ||
+
+    if (pme->nkx <= pme->pme_order*(pme->nnodes_major > 1 ? 2 : 1) ||
+        pme->nky <= pme->pme_order*(pme->nnodes_minor > 1 ? 2 : 1) ||
         pme->nkz <= pme->pme_order)
-        gmx_fatal(FARGS,"The pme grid dimensions need to be larger than pme_order (%d) and in parallel larger than 2*pme_order for x",pme->pme_order);
-    
+    {
+        gmx_fatal(FARGS,"The pme grid dimensions need to be larger than pme_order (%d) and in parallel larger than 2*pme_ordern for x and/or y",pme->pme_order);
+    }
+
     if (pme->nnodes > 1) {
+        double imbal;
+
 #ifdef GMX_MPI
         MPI_Type_contiguous(DIM, mpi_type, &(pme->rvec_mpi));
         MPI_Type_commit(&(pme->rvec_mpi));
@@ -1767,70 +2173,125 @@ int gmx_pme_init(gmx_pme_t *pmedata,t_commrec *cr,int nnodes_major,
          * (unless the charge distribution is inhomogeneous).
          */
         
-        if (pme_inconvenient_nnodes(pme->nkx,pme->nky,pme->nnodes) &&
-            pme->nodeid == 0) {
+        imbal = pme_load_imbalance(pme);
+        if (imbal >= 1.2 && pme->nodeid_major == 0 && pme->nodeid_minor == 0)
+        {
             fprintf(stderr,
                     "\n"
-                    "NOTE: For optimal PME load balancing at high parallelization\n"
-                    "      PME grid_x (%d) and grid_y (%d) should be divisible by #PME_nodes (%d)\n"
+                    "NOTE: The load imbalance in PME FFT and solve is %d%%.\n"
+                    "      For optimal PME load balancing\n"
+                    "      PME grid_x (%d) and grid_y (%d) should be divisible by #PME_nodes_x (%d)\n"
+                    "      and PME grid_y (%d) and grid_z (%d) should be divisible by #PME_nodes_y (%d)\n"
                     "\n",
-                    pme->nkx,pme->nky,pme->nnodes);
-        }
-        
-        if (debug) {
-            fprintf(debug,"Parallelized PME sum used. nkx=%d, npme=%d\n",
-                    ir->nkx,pme->nnodes);
-            if ((ir->nkx % pme->nnodes) != 0)
-                fprintf(debug,"Warning: For load balance, fourier_nx should be divisible by the number of PME nodes\n");
+                    (int)((imbal-1)*100 + 0.5),
+                    pme->nkx,pme->nky,pme->nnodes_major,
+                    pme->nky,pme->nkz,pme->nnodes_minor);
         }
-
-        init_overlap_comm(pme,&pme->overlap[0],cr);
-    } else {
-        pme->overlap[0].s2g = NULL;
     }
+
+    init_overlap_comm(&pme->overlap[0],pme->pme_order,
+#ifdef GMX_MPI
+                      pme->mpi_comm_d[0],
+#endif
+                      pme->nnodes_major,pme->nodeid_major,pme->nkx);
     
-    /* With domain decomposition we need nnx on the PP only nodes */
-    snew(pme->nnx,5*pme->nkx);
-    snew(pme->nny,5*pme->nky);
-    snew(pme->nnz,5*pme->nkz);
-    for(i=0; (i<5*pme->nkx); i++) {
-        pme->nnx[i] = i % pme->nkx;
-    }
-    for(i=0; (i<5*pme->nky); i++) {
-        pme->nny[i] = i % pme->nky;
-    }
-    for(i=0; (i<5*pme->nkz); i++) {
-        pme->nnz[i] = i % pme->nkz;
-    }
+    init_overlap_comm(&pme->overlap[1],pme->pme_order,
+#ifdef GMX_MPI
+                      pme->mpi_comm_d[1],
+#endif
+                      pme->nnodes_minor,pme->nodeid_minor,pme->nky);
     
     snew(pme->bsp_mod[XX],pme->nkx);
     snew(pme->bsp_mod[YY],pme->nky);
     snew(pme->bsp_mod[ZZ],pme->nkz);
     
-    pme->gridA = mk_fftgrid(pme->nkx,pme->nky,pme->nkz,
-                            NULL,pme->overlap[0].s2g,cr,
+    /* Allocate data for the interpolation grid, including overlap */
+    pme->pmegrid_nx = pme->overlap[0].s2g1[pme->nodeid_major] -
+                      pme->overlap[0].s2g0[pme->nodeid_major];
+    pme->pmegrid_ny = pme->overlap[1].s2g1[pme->nodeid_minor] - 
+                      pme->overlap[1].s2g0[pme->nodeid_minor];
+    pme->pmegrid_nz = pme->nkz + pme->pme_order - 1;
+    
+    pme->pmegrid_start_ix = pme->overlap[0].s2g0[pme->nodeid_major];
+    pme->pmegrid_start_iy = pme->overlap[1].s2g0[pme->nodeid_minor];
+    pme->pmegrid_start_iz = 0;
+    
+    make_gridindex5_to_localindex(pme->nkx,
+                                  pme->pmegrid_start_ix,
+                                  pme->overlap[0].s2g0[pme->nodeid_major+1],
+                                  &pme->nnx,&pme->fshx);
+    make_gridindex5_to_localindex(pme->nky,
+                                  pme->pmegrid_start_iy,
+                                  pme->overlap[1].s2g0[pme->nodeid_minor+1],
+                                  &pme->nny,&pme->fshy);
+    make_gridindex5_to_localindex(pme->nkz,
+                                  pme->pmegrid_start_iz,
+                                  pme->nkz,
+                                  &pme->nnz,&pme->fshz);
+    
+    snew(pme->pmegridA,pme->pmegrid_nx*pme->pmegrid_ny*pme->pmegrid_nz);
+    
+    /* For non-divisible grid we need pme_order iso pme_order-1 */
+    bufsizex = pme->pme_order*pme->pmegrid_ny*pme->pmegrid_nz;
+    bufsizey = pme->pmegrid_nx*pme->pme_order*pme->nkz;
+    bufsize  = (bufsizex>bufsizey) ? bufsizex : bufsizey;
+    
+    snew(pme->pmegrid_sendbuf,bufsize);
+    snew(pme->pmegrid_recvbuf,bufsize);
+    
+    ndata[0] = pme->nkx;
+    ndata[1] = pme->nky;
+    ndata[2] = pme->nkz;
+    
+    /* This routine will allocate the grid data to fit the FFTs */
+    gmx_parallel_3dfft_init(&pme->pfft_setupA,ndata,
+                            &pme->fftgridA,&pme->cfftgridA,
+                            pme->mpi_comm_d,
+                            pme->overlap[0].s2g0,pme->overlap[1].s2g0,
                             bReproducible);
-    if (bFreeEnergy) {
-        pme->gridB = mk_fftgrid(pme->nkx,pme->nky,pme->nkz,
-                                NULL,pme->overlap[0].s2g,cr,
+    
+    if (bFreeEnergy)
+    {
+        snew(pme->pmegridB,pme->pmegrid_nx*pme->pmegrid_ny*pme->pmegrid_nz);    
+        gmx_parallel_3dfft_init(&pme->pfft_setupB,ndata,
+                                &pme->fftgridB,&pme->cfftgridB,
+                                pme->mpi_comm_d,
+                                pme->overlap[0].s2g0,pme->overlap[1].s2g0,
                                 bReproducible);
-    } else {
-        pme->gridB = NULL;
+    } else 
+    {
+        pme->pmegridB    = NULL;
+        pme->fftgridB    = NULL;
+        pme->cfftgridB   = NULL;
     }
     
     make_bspline_moduli(pme->bsp_mod,pme->nkx,pme->nky,pme->nkz,pme->pme_order);
     
+    /* Use atc[0] for spreading */
+    init_atomcomm(pme,&pme->atc[0],cr,nnodes_major > 1 ? 0 : 1,TRUE);
+    if (pme->ndecompdim >= 2)
+    {
+        init_atomcomm(pme,&pme->atc[1],cr,1,FALSE);
+    }
+    
     if (pme->nnodes == 1) {
         pme->atc[0].n = homenr;
         pme_realloc_atomcomm_things(&pme->atc[0]);
     }
     
-       pme->maxkz = pme->nkz/2+1;
-       snew(pme->work_mhz,pme->maxkz);
-       snew(pme->work_m2,pme->maxkz);
-       snew(pme->work_denom,pme->maxkz);
-       snew(pme->work_tmp1,pme->maxkz);
-       snew(pme->work_m2inv,pme->maxkz);
+    /* Use fft5d, order after FFT is y major, z, x minor */
+    pme->work_nalloc = pme->nkx;
+    snew(pme->work_mhx,pme->work_nalloc);
+    snew(pme->work_mhy,pme->work_nalloc);
+    snew(pme->work_mhz,pme->work_nalloc);
+    snew(pme->work_m2,pme->work_nalloc);
+    snew(pme->work_denom,pme->work_nalloc);
+    /* Allocate an aligned pointer for SSE operations, including 3 extra
+     * elements at the end since SSE operates on 4 elements at a time.
+     */
+    snew(pme->work_tmp1_alloc,pme->work_nalloc+8);
+    pme->work_tmp1 = (real *) (((size_t) pme->work_tmp1_alloc + 16) & (~((size_t) 15)));
+    snew(pme->work_m2inv,pme->work_nalloc);
 
     *pmedata = pme;
     
@@ -1838,24 +2299,19 @@ int gmx_pme_init(gmx_pme_t *pmedata,t_commrec *cr,int nnodes_major,
 }
 
 static void spread_on_grid(gmx_pme_t pme,
-                           pme_atomcomm_t *atc,t_fftgrid *grid,
+                           pme_atomcomm_t *atc,real *grid,
                            bool bCalcSplines,bool bSpread)
-{ 
-    int nx,ny,nz,nx2,ny2,nz2,la2,la12;
-    real *ptr;
-    
+{    
     if (bCalcSplines)
     {
-        /* Unpack structure */
-        unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
     
         /* Compute fftgrid index for all atoms,
          * with help of some extra variables.
          */
-        calc_idx(pme,atc);
+        calc_interpolation_idx(pme,atc);
         
         /* make local bsplines  */
-        make_bsplines(atc->theta,atc->dtheta,pme->pme_order,nx,ny,nz,
+        make_bsplines(atc->theta,atc->dtheta,pme->pme_order,
                       atc->fractx,atc->n,atc->q,pme->bFEP);
     }    
     
@@ -1863,14 +2319,13 @@ static void spread_on_grid(gmx_pme_t pme,
     {
         /* put local atoms on grid. */
         spread_q_bsplines(pme,atc,grid);
-        /*    pr_grid_dist(logfile,"spread",grid); */
     }
 }
 
 void gmx_pme_calc_energy(gmx_pme_t pme,int n,rvec *x,real *q,real *V)
 {
     pme_atomcomm_t *atc;
-    t_fftgrid *grid;
+    real *grid;
 
     if (pme->nnodes > 1)
     {
@@ -1891,7 +2346,7 @@ void gmx_pme_calc_energy(gmx_pme_t pme,int n,rvec *x,real *q,real *V)
     atc->q         = q;
     
     /* We only use the A-charges grid */
-    grid = pme->gridA;
+    grid = pme->pmegridA;
 
     spread_on_grid(pme,atc,grid,TRUE,FALSE);
 
@@ -1929,6 +2384,7 @@ int gmx_pmeonly(gmx_pme_t pme,
     matrix vir;
     float cycles;
     int  count;
+    bool bEnerVir;
     gmx_large_int_t step,step_rel;
     
     
@@ -1943,7 +2399,9 @@ int gmx_pmeonly(gmx_pme_t pme,
         natoms = gmx_pme_recv_q_x(pme_pp,
                                   &chargeA,&chargeB,box,&x_pp,&f_pp,
                                   &maxshift0,&maxshift1,
-                                  &pme->bFEP,&lambda,&step);
+                                  &pme->bFEP,&lambda,
+                                  &bEnerVir,
+                                  &step);
         
         if (natoms == -1) {
             /* We should stop: break out of the loop */
@@ -1962,15 +2420,13 @@ int gmx_pmeonly(gmx_pme_t pme,
         gmx_pme_do(pme,0,natoms,x_pp,f_pp,chargeA,chargeB,box,
                    cr,maxshift0,maxshift1,nrnb,wcycle,vir,ewaldcoeff,
                    &energy,lambda,&dvdlambda,
-                   GMX_PME_DO_ALL);
+                   GMX_PME_DO_ALL_F | (bEnerVir ? GMX_PME_CALC_ENER_VIR : 0));
         
         cycles = wallcycle_stop(wcycle,ewcPMEMESH);
         
         gmx_pme_send_force_vir_ener(pme_pp,
                                     f_pp,vir,energy,dvdlambda,
-                                    cycles,
-                                    bGotStopNextStepSignal,
-                                    bGotStopNextNSStepSignal);
+                                    cycles);
         
         count++;
 
@@ -1999,17 +2455,20 @@ int gmx_pme_do(gmx_pme_t pme,
                real *dvdlambda, int flags)
 {
     int     q,d,i,j,ntot,npme;
-    int     nx,ny,nz,nx2,ny2,nz2,la12,la2;
+    int     nx,ny,nz;
     int     n_d,local_ny;
+    int     loop_count;
     pme_atomcomm_t *atc=NULL;
-    t_fftgrid *grid=NULL;
+    real *  grid=NULL;
     real    *ptr;
     rvec    *x_d,*f_d;
     real    *charge=NULL,*q_d,vol;
     real    energy_AB[2];
     matrix  vir_AB[2];
     bool    bClearF;
-
+    gmx_parallel_3dfft_t pfft_setup;
+    real *  fftgrid;
+    t_complex * cfftgrid;
 
     if (pme->nnodes > 1) {
         atc = &pme->atc[0];
@@ -2018,15 +2477,21 @@ int gmx_pme_do(gmx_pme_t pme,
             atc->pd_nalloc = over_alloc_dd(atc->npd);
             srenew(atc->pd,atc->pd_nalloc);
         }
-        atc->maxshift = maxshift0;
+        atc->maxshift = (atc->dimind==0 ? maxshift0 : maxshift1);
     }
     
     for(q=0; q<(pme->bFEP ? 2 : 1); q++) {
         if (q == 0) {
-            grid = pme->gridA;
+            grid = pme->pmegridA;
+            fftgrid = pme->fftgridA;
+            cfftgrid = pme->cfftgridA;
+            pfft_setup = pme->pfft_setupA;
             charge = chargeA+start;
         } else {
-            grid = pme->gridB;
+            grid = pme->pmegridB;
+            fftgrid = pme->fftgridB;
+            cfftgrid = pme->cfftgridB;
+            pfft_setup = pme->pfft_setupB;
             charge = chargeB+start;
         }
         /* Unpack structure */
@@ -2038,18 +2503,9 @@ int gmx_pme_do(gmx_pme_t pme,
                 gmx_fatal(FARGS,"No grid!");
         }
         where();
-        unpack_fftgrid(grid,&nx,&ny,&nz,&nx2,&ny2,&nz2,&la2,&la12,TRUE,&ptr);
-#ifdef GMX_MPI
-        if (pme->nnodes > 1) {
-            local_ny = grid->pfft.local_ny_after_transpose;
-        } else {
-            local_ny = ny;
-        }
-#else
-        local_ny = ny;
-#endif
-        where();
         
+        m_inv_ur0(box,pme->recipbox); 
+
         if (pme->nnodes == 1) {
             atc = &pme->atc[0];
             if (DOMAINDECOMP(cr)) {
@@ -2081,8 +2537,8 @@ int gmx_pme_do(gmx_pme_t pme,
                     atc->pd_nalloc = over_alloc_dd(atc->npd);
                     srenew(atc->pd,atc->pd_nalloc);
                 }
-                atc->maxshift = (d==0 ? maxshift0 : maxshift1);
-                pme_calc_pidx(n_d,box,x_d,atc);
+                atc->maxshift = (atc->dimind==0 ? maxshift0 : maxshift1);
+                pme_calc_pidx(n_d,pme->recipbox,x_d,atc);
                 where();
                 
                 GMX_BARRIER(cr->mpi_comm_mygroup);
@@ -2090,10 +2546,11 @@ int gmx_pme_do(gmx_pme_t pme,
                 if (DOMAINDECOMP(cr)) {
                     dd_pmeredist_x_q(pme, n_d, q==0, x_d, q_d, atc);
                 } else {
-                    pmeredist(pme, TRUE, n_d, q==0, x_d, q_d, atc);
+                    pmeredist_pd(pme, TRUE, n_d, q==0, x_d, q_d, atc);
                 }
             }
             where();
+
             wallcycle_stop(wcycle,ewcPME_REDISTXF);
         }
         
@@ -2101,8 +2558,6 @@ int gmx_pme_do(gmx_pme_t pme,
             fprintf(debug,"Node= %6d, pme local particles=%6d\n",
                     cr->nodeid,atc->n);
 
-        calc_recipbox(box,pme->recipbox); 
-
         if (flags & GMX_PME_SPREAD_Q)
         {
             wallcycle_start(wcycle,ewcPME_SPREADGATHER);
@@ -2121,22 +2576,20 @@ int gmx_pme_do(gmx_pme_t pme,
             inc_nrnb(nrnb,eNR_SPREADQBSP,
                      pme->pme_order*pme->pme_order*pme->pme_order*atc->n);
 
+            wrap_periodic_pmegrid(pme,grid);
+
             /* sum contributions to local grid from other nodes */
+#ifdef GMX_MPI
             if (pme->nnodes > 1) {
-#ifdef DEBUG
-                if (debug)
-                    pr_fftgrid(debug,"qgrid before dd sum",grid);
-#endif
                 GMX_BARRIER(cr->mpi_comm_mygroup);
-                gmx_sum_qgrid_dd(pme,&pme->overlap[0],grid,
-                                 GMX_SUM_QGRID_FORWARD);
+                gmx_sum_qgrid_dd(pme,grid,GMX_SUM_QGRID_FORWARD);
                 where();
             }
-#ifdef DEBUG
-            if (debug)
-                pr_fftgrid(debug,"qgrid",grid);
 #endif
             where();
+
+            copy_pmegrid_to_fftgrid(pme,grid,fftgrid);
+
             wallcycle_stop(wcycle,ewcPME_SPREADGATHER);
         }
          
@@ -2146,7 +2599,7 @@ int gmx_pme_do(gmx_pme_t pme,
             GMX_BARRIER(cr->mpi_comm_mygroup);
             GMX_MPE_LOG(ev_gmxfft3d_start);
             wallcycle_start(wcycle,ewcPME_FFT);
-            gmxfft3D(grid,GMX_FFT_REAL_TO_COMPLEX,cr);
+            gmx_parallel_3dfft_execute(pfft_setup,GMX_FFT_REAL_TO_COMPLEX,fftgrid,cfftgrid);
             wallcycle_stop(wcycle,ewcPME_FFT);
             GMX_MPE_LOG(ev_gmxfft3d_finish);
             where();
@@ -2156,46 +2609,51 @@ int gmx_pme_do(gmx_pme_t pme,
             GMX_BARRIER(cr->mpi_comm_mygroup);
             GMX_MPE_LOG(ev_solve_pme_start);
             wallcycle_start(wcycle,ewcPME_SOLVE);
-            energy_AB[q]=solve_pme(pme,grid,ewaldcoeff,vol,vir_AB[q],cr);
+            loop_count =
+                solve_pme_yzx(pme,cfftgrid,ewaldcoeff,vol,
+                              flags & GMX_PME_CALC_ENER_VIR,
+                              &energy_AB[q],vir_AB[q]);
             wallcycle_stop(wcycle,ewcPME_SOLVE);
             where();
             GMX_MPE_LOG(ev_solve_pme_finish);
-            inc_nrnb(nrnb,eNR_SOLVEPME,nx*local_ny*(nz/2+1));
+            inc_nrnb(nrnb,eNR_SOLVEPME,loop_count);
+        }
+
+        if (flags & GMX_PME_CALC_F)
+        {
             
             /* do 3d-invfft */
             GMX_BARRIER(cr->mpi_comm_mygroup);
             GMX_MPE_LOG(ev_gmxfft3d_start);
             where();
             wallcycle_start(wcycle,ewcPME_FFT);
-            gmxfft3D(grid,GMX_FFT_COMPLEX_TO_REAL,cr);
+            gmx_parallel_3dfft_execute(pfft_setup,GMX_FFT_COMPLEX_TO_REAL,cfftgrid,fftgrid);
             wallcycle_stop(wcycle,ewcPME_FFT);
+
             where();
             GMX_MPE_LOG(ev_gmxfft3d_finish);
-            
-            ntot  = grid->nxyz;  
-            npme  = ntot*log((real)ntot)/log(2.0);
-            if (pme->nnodes > 1) {
-                npme /= (cr->nnodes - cr->npmenodes);
+
+            if (pme->nodeid == 0)
+            {
+                ntot = pme->nkx*pme->nky*pme->nkz;
+                npme  = ntot*log((real)ntot)/log(2.0);
+                inc_nrnb(nrnb,eNR_FFT,2*npme);
             }
-            inc_nrnb(nrnb,eNR_FFT,2*npme);
-            where();
-        }
 
-        if (flags & GMX_PME_CALC_F)
-        {
             wallcycle_start(wcycle,ewcPME_SPREADGATHER);
 
+            copy_fftgrid_to_pmegrid(pme,fftgrid,grid);
+
             /* distribute local grid to all nodes */
+#ifdef GMX_MPI
             if (pme->nnodes > 1) {
                 GMX_BARRIER(cr->mpi_comm_mygroup);
-                gmx_sum_qgrid_dd(pme, &pme->overlap[0],grid,
-                                 GMX_SUM_QGRID_BACKWARD);
+                gmx_sum_qgrid_dd(pme,grid,GMX_SUM_QGRID_BACKWARD);
             }
-            where();
-#ifdef DEBUG
-            if (debug)
-                pr_fftgrid(debug,"potential",grid);
 #endif
+            where();
+
+            unwrap_periodic_pmegrid(pme,grid);
             
             /* interpolate forces for our local atoms */
             GMX_BARRIER(cr->mpi_comm_mygroup);
@@ -2240,9 +2698,10 @@ int gmx_pme_do(gmx_pme_t pme,
                 dd_pmeredist_f(pme,atc,n_d,f_d,
                                d==pme->ndecompdim-1 && pme->bPPnode);
             } else {
-                pmeredist(pme, FALSE, n_d, TRUE, f_d, NULL, atc);
+                pmeredist_pd(pme, FALSE, n_d, TRUE, f_d, NULL, atc);
             }
         }
+
         wallcycle_stop(wcycle,ewcPME_REDISTXF);
     }
     where();
@@ -2257,6 +2716,7 @@ int gmx_pme_do(gmx_pme_t pme,
             for(j=0; j<DIM; j++)
                 vir[i][j] += (1.0-lambda)*vir_AB[0][i][j] + lambda*vir_AB[1][i][j];
     }
+
     if (debug)
         fprintf(debug,"PME mesh energy: %g\n",*energy);
     
index 2608ff2623d4bce572f45a0f05795b45812477b1..87e19d231b72bd82d917da87d6619d68ee8bfaef 100644 (file)
@@ -63,7 +63,8 @@
 #define PP_PME_CHARGEB  (1<<1)
 #define PP_PME_COORD    (1<<2)
 #define PP_PME_FEP      (1<<3)
-#define PP_PME_FINISH   (1<<4)
+#define PP_PME_ENER_VIR (1<<4)
+#define PP_PME_FINISH   (1<<5)
 
 #define PME_PP_SIGSTOP     (1<<0)
 #define PME_PP_SIGSTOPNSS     (1<<1)
@@ -103,7 +104,7 @@ typedef struct {
   real   energy;
   real   dvdlambda;
   float  cycles;
-  int    flags;
+  gmx_stop_cond_t stop_cond;
 } gmx_pme_comm_vir_ene_t;
 
 
@@ -237,13 +238,17 @@ void gmx_pme_send_q(t_commrec *cr,
 }
 
 void gmx_pme_send_x(t_commrec *cr, matrix box, rvec *x,
-                   bool bFreeEnergy, real lambda,gmx_large_int_t step)
+                   bool bFreeEnergy, real lambda,
+                   bool bEnerVir,
+                   gmx_large_int_t step)
 {
   int flags;
-
+  
   flags = PP_PME_COORD;
   if (bFreeEnergy)
     flags |= PP_PME_FEP;
+  if (bEnerVir)
+    flags |= PP_PME_ENER_VIR;
 
   gmx_pme_send_q_x(cr,flags,NULL,NULL,box,x,lambda,0,0,step);
 }
@@ -262,6 +267,7 @@ int gmx_pme_recv_q_x(struct gmx_pme_pp *pme_pp,
                      matrix box, rvec **x,rvec **f,
                      int *maxshift0, int *maxshift1,
                      bool *bFreeEnergy,real *lambda,
+                    bool *bEnerVir,
                      gmx_large_int_t *step)
 {
     gmx_pme_comm_n_box_t cnb;
@@ -354,6 +360,7 @@ int gmx_pme_recv_q_x(struct gmx_pme_pp *pme_pp,
             copy_mat(cnb.box,box);
             *bFreeEnergy = (cnb.flags & PP_PME_FEP);
             *lambda      = cnb.lambda;
+           *bEnerVir    = (cnb.flags & PP_PME_ENER_VIR);
 
             if (*bFreeEnergy && !(pme_pp->flags_charge & PP_PME_CHARGEB))
                 gmx_incons("PME-only node received free energy request, but "
@@ -416,8 +423,10 @@ static void receive_virial_energy(t_commrec *cr,
     *dvdlambda += cve.dvdlambda;
     *pme_cycles = cve.cycles;
 
-    bGotStopNextStepSignal = (cve.flags & PME_PP_SIGSTOP);
-    bGotStopNextNSStepSignal = (cve.flags & PME_PP_SIGSTOPNSS);
+    if ( cve.stop_cond != gmx_stop_cond_none )
+    {
+        gmx_set_stop_condition(cve.stop_cond);
+    }
   } else {
     *energy = 0;
     *pme_cycles = 0;
@@ -461,9 +470,7 @@ void gmx_pme_receive_f(t_commrec *cr,
 void gmx_pme_send_force_vir_ener(struct gmx_pme_pp *pme_pp,
                                 rvec *f, matrix vir,
                                 real energy, real dvdlambda,
-                                float cycles,
-                                bool bGotStopNextStepSignal,
-                                bool bGotStopNextNSStepSignal)
+                                float cycles)
 {
   gmx_pme_comm_vir_ene_t cve; 
   int messages,ind_start,ind_end,receiver;
@@ -488,12 +495,9 @@ void gmx_pme_send_force_vir_ener(struct gmx_pme_pp *pme_pp,
   copy_mat(vir,cve.vir);
   cve.energy    = energy;
   cve.dvdlambda = dvdlambda;
-  cve.flags     = 0;
-  if (bGotStopNextStepSignal)
-    cve.flags |= PME_PP_SIGSTOP;
-  if (bGotStopNextNSStepSignal)
-    cve.flags |= PME_PP_SIGSTOPNSS;
-  
+  /* check for the signals to send back to a PP node */
+  cve.stop_cond = gmx_get_stop_condition();
   cve.cycles = cycles;
   
   if (debug)
index 3c8b8512e3779162ff2915b5f1ef28549e1db17f..7320895b10f9660011e7cff0f1f283b1db49e83f 100644 (file)
 #define ulim2  (3)
 
 
+
+/* PPPM temporarily disabled while working on 2D PME */
+#define DISABLE_PPPM
+
+
+
+#ifndef DISABLE_PPPM
+
 /* TODO: fix thread-safety */
 
 static void calc_invh(rvec box,int nx,int ny,int nz,rvec invh)
@@ -444,6 +452,7 @@ static void convolution(FILE *fp,bool bVerbose,t_fftgrid *grid,real ***ghat,
   sfree(nTest);
 }
 
+
 void solve_pppm(FILE *fp,t_commrec *cr,
                t_fftgrid *grid,real ***ghat,rvec box,
                bool bVerbose,t_nrnb *nrnb)
@@ -483,6 +492,9 @@ static rvec      beta;
 static real      ***ghat=NULL;
 static t_fftgrid *grid=NULL;
 
+#endif
+
+
 int gmx_pppm_init(FILE *log,      t_commrec *cr,
                   const output_env_t oenv, bool bVerbose,
                   bool bOld,      matrix box,
@@ -495,6 +507,11 @@ int gmx_pppm_init(FILE *log,      t_commrec *cr,
   const real tol = 1e-5;
   rvec  box_diag,spacing;
 
+#ifdef DISABLE_PPPM
+    gmx_fatal(FARGS,"PPPM is not functional in the current version, we plan to implement PPPM through a small modification of the PME code.");
+    return -1;
+#else
+    
 #ifdef GMX_WITHOUT_FFTW
   gmx_fatal(FARGS,"PPPM used, but GROMACS was compiled without FFTW support!\n");
 #endif
@@ -578,6 +595,7 @@ int gmx_pppm_init(FILE *log,      t_commrec *cr,
   grid = mk_fftgrid(nx,ny,nz,NULL,NULL,cr,bReproducible);
   
   return 0;
+#endif
 }
 
 int gmx_pppm_do(FILE *log,       gmx_pme_t pme,
@@ -589,7 +607,12 @@ int gmx_pppm_do(FILE *log,       gmx_pme_t pme,
                t_nrnb *nrnb,
                int pme_order,   real *energy)
 {
-  /* Make the grid empty */
+#ifdef DISABLE_PPPM
+    gmx_fatal(FARGS,"PPPM temporarily disabled while working on 2DPME\n");
+    return -1;
+#else
+
+    /* Make the grid empty */
   clear_fftgrid(grid);
   
   /* First step: spreading the charges over the grid. */
@@ -613,8 +636,10 @@ int gmx_pppm_do(FILE *log,       gmx_pme_t pme,
                     phi,grid,beta,nrnb);
   
   return 0;
+#endif
 }
 
+#ifndef DISABLE_PPPM
 static int gmx_pppm_opt_do(FILE *log,       gmx_pme_t pme,
                           t_inputrec *ir,  bool bVerbose,
                           int natoms,
@@ -659,3 +684,4 @@ static int gmx_pppm_opt_do(FILE *log,       gmx_pme_t pme,
   return 0;
 }
 
+#endif
index 488df5cddd8ebaeb1e2202e14c8185077f1a20f2..ccb1f1eb6c4e7debce873305a478fce13eeeb59d 100644 (file)
@@ -59,6 +59,7 @@
 #include "mtop_util.h"
 #include "mdrun.h"
 #include "gmx_ga2la.h"
+#include "copyrite.h"
 
 static void pull_print_x_grp(FILE *out,bool bRef,ivec dim,t_pullgrp *pgrp) 
 {
@@ -1194,6 +1195,7 @@ void init_pull(FILE *fplog,t_inputrec *ir,int nfile,const t_filenm fnm[],
     t_pull    *pull;
     t_pullgrp *pgrp;
     int       g,start=0,end=0,m;
+    bool      bCite;
     
     pull = ir->pull;
     
@@ -1219,6 +1221,21 @@ void init_pull(FILE *fplog,t_inputrec *ir,int nfile,const t_filenm fnm[],
             fprintf(fplog,"with an absolute reference on %d group%s\n",
                     pull->ngrp,pull->ngrp==1 ? "" : "s");
         }
+        bCite = FALSE;
+        for(g=0; g<pull->ngrp+1; g++)
+        {
+            if (pull->grp[g].nat > 0 &&
+                pull->grp[g].pbcatom < 0)
+            {
+                /* We are using cosine weighting */
+                fprintf(fplog,"Cosine weighting is used for groupd %d\n",g);
+                bCite = TRUE;
+            }
+        }
+        if (bCite)
+        {
+            please_cite(fplog,"Engin2010");
+        }
     }
     
     /* We always add the virial contribution,
diff --git a/src/mdlib/qm_orca.c b/src/mdlib/qm_orca.c
new file mode 100644 (file)
index 0000000..c692104
--- /dev/null
@@ -0,0 +1,395 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <math.h>
+#include "sysstuff.h"
+#include "typedefs.h"
+#include "macros.h"
+#include "smalloc.h"
+#include "assert.h"
+#include "physics.h"
+#include "macros.h"
+#include "vec.h"
+#include "force.h"
+#include "invblock.h"
+#include "confio.h"
+#include "names.h"
+#include "network.h"
+#include "pbc.h"
+#include "ns.h"
+#include "nrnb.h"
+#include "bondf.h"
+#include "mshift.h"
+#include "txtdump.h"
+#include "copyrite.h"
+#include "qmmm.h"
+#include <stdio.h>
+#include <string.h>
+#include "gmx_fatal.h"
+#include "typedefs.h"
+#include <stdlib.h>
+
+/* ORCA interface routines */
+
+void init_orca(t_commrec *cr, t_QMrec *qm, t_MMrec *mm)
+{
+ char
+   *buf;
+ snew(buf,200);    
+ buf = getenv("BASENAME");
+ if (buf){
+     snew(qm->orca_basename,200);
+     sscanf(buf,"%s",qm->orca_basename);
+ }
+ else
+     gmx_fatal(FARGS,"no $BASENAME\n");
+ fprintf(stderr,"orca initialised...\n");
+ /* since we append the output to the BASENAME.out file,
+ we should delete an existent old out-file here. */
+ sprintf(buf,"%s.out",qm->orca_basename);
+ remove(buf);
+}  
+
+
+void write_orca_input(int step ,t_forcerec *fr, t_QMrec *qm, t_MMrec *mm)
+{
+ int
+   i;
+ t_QMMMrec
+   *QMMMrec;
+ FILE
+   *out, *pcFile, *addInputFile, *LJCoeff;
+ char
+   *buf,*orcaInput,*addInputFilename,*LJCoeffFilename,
+   *pcFilename,*exclInName,*exclOutName;
+ QMMMrec = fr->qr;
+ /* write the first part of the input-file */
+ snew(orcaInput,200);
+ sprintf(orcaInput,"%s.inp",qm->orca_basename);
+ out = fopen(orcaInput,"w");
+ snew(addInputFilename,200);
+ sprintf(addInputFilename,"%s.ORCAINFO",qm->orca_basename);
+ addInputFile = fopen(addInputFilename,"r");
+ fprintf(out, "#input-file generated by gromacs\n");
+ if(qm->bTS){
+     fprintf(out,"!QMMMOpt TightSCF\n");
+     fprintf(out,"%s\n","%geom TS_Search EF end");
+ }
+ else if (qm->bOPT){
+     fprintf(out,"!QMMMOpt TightSCF\n");
+ }
+ else{
+     fprintf(out,"!EnGrad TightSCF\n");
+ }
+ /* here we include the insertion of the additional orca-input */
+ snew(buf,200);
+ if (addInputFile!=NULL) {
+     while (!feof(addInputFile)) {
+         if (fgets(buf , 200 , addInputFile) != '\0' ) 
+             fputs(buf, out);
+     }
+ }
+ else {
+     fprintf(stderr,"No information on the calculation given in <%s>\n",addInputFilename);
+     gmx_call("qm_orca.c");
+ }
+ fclose(addInputFile);
+ if(qm->bTS||qm->bOPT){
+     /* freeze the frontier QM atoms and Link atoms. This is
+      * important only if a full QM subsystem optimization is done
+      * with a frozen MM environmeent. For dynamics, or gromacs's own
+      * optimization routines this is not important.
+      */
+     /* ORCA reads the exclusions from LJCoeffFilename.Excl, 
+      *so we have to rename the file
+      */
+     int didStart = 0;
+     for(i=0;i<qm->nrQMatoms;i++){
+          if(qm->frontatoms[i]){
+             if (!didStart){
+                 fprintf(out,"%s\n","%geom");
+                 fprintf(out,"   Constraints \n");
+                 didStart = 1;
+             }
+              fprintf(out,"        {C %d C}\n",i); /* counting from 0 */
+          }
+     }
+     if (didStart) fprintf(out,"     end\n   end\n");
+     // make a file with information on the C6 and C12 coefficients
+     if(QMMMrec->QMMMscheme!=eQMMMschemeoniom && mm->nrMMatoms){
+         snew(exclInName,200);
+         snew(exclOutName,200);
+         sprintf(exclInName,"QMMMexcl.dat");
+         sprintf(exclOutName,"%s.LJ.Excl",qm->orca_basename);
+         rename(exclInName,exclOutName);
+         snew(LJCoeffFilename,200);
+         sprintf(LJCoeffFilename,"%s.LJ",qm->orca_basename);
+         fprintf(out,"%s%s%s\n","%LJCOEFFICIENTS \"",LJCoeffFilename,"\"");
+         // make a file with information on the C6 and C12 coefficients
+         LJCoeff = fopen(LJCoeffFilename,"w");
+         fprintf(LJCoeff,"%d\n",qm->nrQMatoms);
+         for (i=0;i<qm->nrQMatoms;i++){
+#ifdef GMX_DOUBLE
+             fprintf(LJCoeff,"%10.7lf  %10.7lf\n",qm->c6[i],qm->c12[i]);
+#else
+             fprintf(LJCoeff,"%10.7f  %10.7f\n",qm->c6[i],qm->c12[i]);
+#endif
+         }
+         fprintf(LJCoeff,"%d\n",mm->nrMMatoms);
+         for (i=0;i<mm->nrMMatoms;i++){
+#ifdef GMX_DOUBLE
+             fprintf(LJCoeff,"%10.7lf  %10.7lf\n",mm->c6[i],mm->c12[i]);
+#else
+             fprintf(LJCoeff,"%10.7f  %10.7f\n",mm->c6[i],mm->c12[i]);
+#endif
+         }
+         fclose(LJCoeff);
+     }
+ }
+ /* write charge and multiplicity
+  */
+ fprintf(out,"*xyz %2d%2d\n",qm->QMcharge,qm->multiplicity);
+ /* write the QM coordinates
+  */
+ for (i=0;i<qm->nrQMatoms;i++){
+     int atomNr;
+     if (qm->atomicnumberQM[i]==0) 
+         atomNr = 1;
+     else 
+         atomNr = qm->atomicnumberQM[i];
+#ifdef GMX_DOUBLE
+     fprintf(out,"%3d %10.7lf  %10.7lf  %10.7lf\n",
+     atomNr,
+     qm->xQM[i][XX]/0.1,
+     qm->xQM[i][YY]/0.1,
+     qm->xQM[i][ZZ]/0.1);
+#else
+     fprintf(out,"%3d %10.7f  %10.7f  %10.7f\n",
+     atomNr,
+     qm->xQM[i][XX]/0.1,
+     qm->xQM[i][YY]/0.1,
+     qm->xQM[i][ZZ]/0.1);
+#endif
+ }
+ fprintf(out,"*\n");
+ /* write the MM point charge data 
+  */
+ if(QMMMrec->QMMMscheme!=eQMMMschemeoniom && mm->nrMMatoms){
+     /* name of the point charge file */
+     snew(pcFilename,200);
+     sprintf(pcFilename,"%s.pc",qm->orca_basename);
+     fprintf(out,"%s%s%s\n","%pointcharges \"",pcFilename,"\"");
+     pcFile = fopen(pcFilename,"w");
+     fprintf(pcFile,"%d\n",mm->nrMMatoms);
+     for(i=0;i<mm->nrMMatoms;i++){
+#ifdef GMX_DOUBLE
+         fprintf(pcFile,"%8.4lf %10.7lf  %10.7lf  %10.7lf\n",
+                        mm->MMcharges[i],
+                        mm->xMM[i][XX]/0.1,
+                        mm->xMM[i][YY]/0.1,
+                        mm->xMM[i][ZZ]/0.1);
+#else
+         fprintf(pcFile,"%8.4f %10.7f  %10.7f  %10.7f\n",
+                        mm->MMcharges[i],
+                        mm->xMM[i][XX]/0.1,
+                        mm->xMM[i][YY]/0.1,
+                        mm->xMM[i][ZZ]/0.1);
+#endif
+     }
+     fprintf(pcFile,"\n");
+     fclose(pcFile);
+ }
+ fprintf(out,"\n");
+
+ fclose(out);
+}  /* write_orca_input */
+
+real read_orca_output(rvec QMgrad[],rvec MMgrad[],int step,t_forcerec *fr,
+                         t_QMrec *qm, t_MMrec *mm)
+{
+ int
+   i,j,atnum;
+ char
+   buf[300], tmp[300], orca_xyzFilename[300], orca_pcgradFilename[300], orca_engradFilename[300];
+ real
+   QMener;
+ FILE
+   *xyz, *pcgrad, *engrad;
+ int k;
+ t_QMMMrec
+   *QMMMrec;
+ QMMMrec = fr->qr;
+ sprintf(orca_xyzFilename,"%s.xyz",qm->orca_basename);
+ xyz=fopen(orca_xyzFilename,"r");
+ /* in case of an optimization, the coordinates are printed in the
+  * xyz file, the energy and gradients for the QM part are stored in the engrad file
+  * and the gradients for the point charges are stored in the pc file.
+  */
+
+ /* we need the new xyz coordinates of the QM atoms only for separate QM-optimization
+  */
+
+ if(qm->bTS||qm->bOPT){
+     fgets(buf,300,xyz);
+     fgets(buf,300,xyz);
+     for(i=0;i<qm->nrQMatoms;i++){
+         fgets(buf,300,xyz);
+#ifdef GMX_DOUBLE
+         sscanf(buf,"%s%lf%lf%lf\n",
+                    tmp,
+                    &qm->xQM[i][XX],
+                    &qm->xQM[i][YY],
+                    &qm->xQM[i][ZZ]);
+#else
+         sscanf(buf,"%d%f%f%f\n",
+                    &atnum,
+                    &qm->xQM[i][XX],
+                    &qm->xQM[i][YY],
+                    &qm->xQM[i][ZZ]);
+#endif
+         for(j=0;j<DIM;j++){
+             qm->xQM[i][j]*=0.1;
+         }
+     }
+ fclose(xyz);
+ }
+ sprintf(orca_engradFilename,"%s.engrad",qm->orca_basename);
+ engrad=fopen(orca_engradFilename,"r");
+ /* we read the energy and the gradient for the qm-atoms from the engrad file
+  */
+ /* we can skip the first seven lines
+  */
+ for (j=0;j<7;j++){
+     fgets(buf,300,engrad);
+ }
+ /* now comes the energy
+  */
+ fgets(buf,300,engrad);
+#ifdef GMX_DOUBLE
+ sscanf(buf,"%lf\n",&QMener);
+#else
+ sscanf(buf,"%f\n", &QMener);
+#endif
+ /* we can skip the next three lines
+  */
+ for (j=0;j<3;j++){
+     fgets(buf,300,engrad);
+ }
+ /* next lines contain the gradients of the QM atoms
+  * now comes the gradient, one value per line:
+  * (atom1 x \n atom1 y \n atom1 z \n atom2 x ...
+  */
+ for(i=0;i<3*qm->nrQMatoms;i++){
+     k = i/3;
+     fgets(buf,300,engrad);
+#ifdef GMX_DOUBLE
+     if (i%3==0) 
+         sscanf(buf,"%lf\n", &QMgrad[k][XX]);
+     else if (i%3==1) 
+         sscanf(buf,"%lf\n", &QMgrad[k][YY]);
+     else if (i%3==2)
+         sscanf(buf,"%lf\n", &QMgrad[k][ZZ]);
+#else
+     if (i%3==0) 
+         sscanf(buf,"%f\n", &QMgrad[k][XX]);
+     else if (i%3==1) 
+         sscanf(buf,"%f\n", &QMgrad[k][YY]);
+     else if (i%3==2) 
+         sscanf(buf,"%f\n", &QMgrad[k][ZZ]);
+#endif
+ }
+ fclose(engrad);
+ /* write the MM point charge data 
+  */
+ if(QMMMrec->QMMMscheme!=eQMMMschemeoniom && mm->nrMMatoms){
+     sprintf(orca_pcgradFilename,"%s.pcgrad",qm->orca_basename);
+     pcgrad=fopen(orca_pcgradFilename,"r");
+    
+     /* we read the gradient for the mm-atoms from the pcgrad file
+      */
+     /* we can skip the first line
+      */
+     fgets(buf,300,pcgrad);
+     for(i=0;i<mm->nrMMatoms;i++){
+         fgets(buf,300,pcgrad);
+    #ifdef GMX_DOUBLE
+         sscanf(buf,"%lf%lf%lf\n",
+                    &MMgrad[i][XX],
+                    &MMgrad[i][YY],
+                    &MMgrad[i][ZZ]);
+    #else
+         sscanf(buf,"%f%f%f\n",
+                    &MMgrad[i][XX],
+                    &MMgrad[i][YY],
+                    &MMgrad[i][ZZ]);
+    #endif     
+     }
+     fclose(pcgrad);
+ }
+ return(QMener);  
+}
+
+void do_orca(int step,char *exe, char *basename)
+{
+
+ /* make the call to the orca binary through system()
+  * The location of the binary is set through the
+  * environment.
+  */
+ char
+   buf[100];
+ sprintf(buf,"%s %s.inp >> %s.out",
+             "orca",
+             basename,
+             basename);
+ fprintf(stderr,"Calling '%s'\n",buf);
+ if ( system(buf) != 0 )
+     gmx_fatal(FARGS,"Call to '%s' failed\n",buf);
+}
+
+real call_orca(t_commrec *cr,  t_forcerec *fr, 
+                  t_QMrec *qm, t_MMrec *mm, rvec f[], rvec fshift[])
+{
+ /* normal orca jobs */
+ static int
+   step=0;
+ int
+   i,j;
+ real
+   QMener=0.0;
+ rvec
+   *QMgrad,*MMgrad;
+ char
+   *exe;
+
+ snew(exe,30);
+ sprintf(exe,"%s","orca");
+ snew(QMgrad,qm->nrQMatoms);
+ snew(MMgrad,mm->nrMMatoms);
+
+ write_orca_input(step,fr,qm,mm);
+ do_orca(step,exe,qm->orca_basename);
+ QMener = read_orca_output(QMgrad,MMgrad,step,fr,qm,mm);
+ /* put the QMMM forces in the force array and to the fshift
+  */
+ for(i=0;i<qm->nrQMatoms;i++){
+     for(j=0;j<DIM;j++){
+         f[i][j]      = HARTREE_BOHR2MD*QMgrad[i][j];
+         fshift[i][j] = HARTREE_BOHR2MD*QMgrad[i][j];
+     }
+ }
+ for(i=0;i<mm->nrMMatoms;i++){
+     for(j=0;j<DIM;j++){
+         f[i+qm->nrQMatoms][j]      = HARTREE_BOHR2MD*MMgrad[i][j];      
+         fshift[i+qm->nrQMatoms][j] = HARTREE_BOHR2MD*MMgrad[i][j];
+     }
+ }
+ QMener = QMener*HARTREE2KJ*AVOGADRO;
+ step++;
+ free(exe);
+ return(QMener);
+} /* call_orca */
+
+/* end of orca sub routines */
index 109b3e61775cd4e381d0696d28d517061aa3244f..a7a085bc1b9bd696120292916751c40d1d2408e7 100644 (file)
@@ -107,6 +107,16 @@ real
 call_gaussian(t_commrec *cr,t_forcerec *fr, t_QMrec *qm,
               t_MMrec *mm,rvec f[], rvec fshift[]);
 
+#elif defined GMX_QMMM_ORCA
+/* ORCA interface */
+
+void 
+init_orca(t_commrec *cr ,t_QMrec *qm, t_MMrec *mm);
+
+real 
+call_orca(t_commrec *cr,t_forcerec *fr, t_QMrec *qm,
+              t_MMrec *mm,rvec f[], rvec fshift[]);
+
 #endif
 
 
@@ -186,8 +196,10 @@ real call_QMroutine(t_commrec *cr, t_forcerec *fr, t_QMrec *qm,
             QMener = call_gamess(cr,fr,qm,mm,f,fshift);
 #elif defined GMX_QMMM_GAUSSIAN
             QMener = call_gaussian(cr,fr,qm,mm,f,fshift);
+#elif defined GMX_QMMM_ORCA
+            QMener = call_orca(cr,fr,qm,mm,f,fshift);
 #else
-            gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess or Gaussian.");
+            gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess, Gaussian or ORCA.");
 #endif
         }
     }
@@ -213,8 +225,10 @@ void init_QMroutine(t_commrec *cr, t_QMrec *qm, t_MMrec *mm)
         init_gamess(cr,qm,mm);
 #elif defined GMX_QMMM_GAUSSIAN
         init_gaussian(cr,qm,mm);
+#elif defined GMX_QMMM_ORCA
+        init_orca(cr,qm,mm);
 #else
-        gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess or Gaussian.");   
+        gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess, Gaussian or ORCA.");   
 #endif
     }
 } /* init_QMroutine */
@@ -351,7 +365,7 @@ static void init_QMrec(int grpnr, t_QMrec *qm,int nr, int *atomarray,
   /* Lennard-Jones coefficients */ 
   snew(qm->c6,nr);
   snew(qm->c12,nr);
-  /* do we optimize the QM seperately using the algorithms of the QM program??
+  /* do we optimize the QM separately using the algorithms of the QM program??
    */
   qm->bTS      = ir->opts.bTS[grpnr];
   qm->bOPT     = ir->opts.bOPT[grpnr];
@@ -685,13 +699,15 @@ void init_QMMMrec(t_commrec *cr,
     }
     else 
     { 
-        /* ab initio calculation requested (gamess/gaussian) */
+        /* ab initio calculation requested (gamess/gaussian/ORCA) */
 #ifdef GMX_QMMM_GAMESS
         init_gamess(cr,qr->qm[0],qr->mm);
 #elif defined GMX_QMMM_GAUSSIAN
         init_gaussian(cr,qr->qm[0],qr->mm);
+#elif defined GMX_QMMM_ORCA
+        init_orca(cr,qr->qm[0],qr->mm);
 #else
-        gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess or Gaussian.");
+        gmx_fatal(FARGS,"Ab-initio calculation only supported with Gamess, Gaussian or ORCA.");
 #endif
     }
   }
@@ -979,7 +995,7 @@ real calculate_QMMM(t_commrec *cr,
   real
     QMener=0.0;
   /* a selection for the QM package depending on which is requested
-   * (Gaussian, GAMESS-UK or MOPAC) needs to be implemented here. Now
+   * (Gaussian, GAMESS-UK, MOPAC or ORCA) needs to be implemented here. Now
    * it works through defines.... Not so nice yet 
    */
   t_QMMMrec
index cd2168dee666f7f29822600f1e840909ec27f0b8..2be305ffeaac63bd529cab69f3ec442845075b05 100644 (file)
@@ -92,7 +92,7 @@ static void pv(FILE *log,char *s,rvec x)
 }
 
 void cshake(atom_id iatom[],int ncon,int *nnit,int maxnit,
-           real dist2[],real xp[],real rij[],real m2[],real omega,
+            real dist2[],real xp[],real rij[],real m2[],real omega,
             real invmass[],real tt[],real lagr[],int *nerror)
 {
   /*
@@ -110,7 +110,8 @@ void cshake(atom_id iatom[],int ncon,int *nnit,int maxnit,
   real    xh,yh,zh,rijx,rijy,rijz;
   real    tix,tiy,tiz;
   real    tjx,tjy,tjz;
-  int     nit,error,iconv,nconv;
+  int     nit,error,nconv;
+  real    iconvf;
 
   error=0;
   nconv=1;
@@ -139,11 +140,13 @@ void cshake(atom_id iatom[],int ncon,int *nnit,int maxnit,
       toler   = dist2[ll];
       diff    = toler-rpij2;
       
-      /* iconv is zero when the error is smaller than a bound */
-      iconv   = fabs(diff)*tt[ll];
+      /* iconvf is less than 1 when the error is smaller than a bound */
+      /* But if tt is too big, then it will result in looping in iconv */
+
+      iconvf = fabs(diff)*tt[ll];
       
-      if (iconv != 0) {
-          nconv   = nconv + iconv;
+      if (iconvf > 1) {
+          nconv   = iconvf;
           rrpr    = rijx*tx+rijy*ty+rijz*tz;
        
           if (rrpr < toler*mytol) 
@@ -182,11 +185,11 @@ int vec_shakef(FILE *fplog,gmx_shakedata_t shaked,
     rvec *rij;
     real *M2,*tt,*dist2;
     int     maxnit=1000;
-    int     nit,ll,i,j,type;
+    int     nit=0,ll,i,j,type;
     t_iatom *ia;
     real    L1,tol2,toler;
     real    mm=0.,tmp;
-    int     error;
+    int     error=0;
     real    g,vscale,rscale,rvscale;
 
     if (ncon > shaked->nalloc)
@@ -456,8 +459,8 @@ void crattle(atom_id iatom[],int ncon,int *nnit,int maxnit,
     real    xh,yh,zh,rijx,rijy,rijz;
     real    tix,tiy,tiz;
     real    tjx,tjy,tjz;
-    int     nit,error,iconv,nconv;
-    real    veta,vscale_nhc;
+    int     nit,error,nconv;
+    real    veta,vscale_nhc,iconvf;
 
     veta = vetavar->veta;
     vscale_nhc = vetavar->vscale_nhc[0];  /* for now, just use the first state */
@@ -491,10 +494,10 @@ void crattle(atom_id iatom[],int ncon,int *nnit,int maxnit,
             xdotd   = vpijd*vscale_nhc + veta*toler;
             
             /* iconv is zero when the error is smaller than a bound */
-            iconv   = fabs(xdotd)*(tt[ll]/invdt);
+            iconvf   = fabs(xdotd)*(tt[ll]/invdt);
             
-            if (iconv != 0) {
-                nconv     = nconv + iconv;
+            if (iconvf > 1) {
+                nconv     = iconvf;
                 fac       = omega*2.0*m2[ll]/toler;
                 acor      = -fac*xdotd;
                 lagr[ll] += acor;                
index 07916ba3d355eb2bc3dae178a365d3a8068bea7a..a8792b6b5a2ec6c31b58be41792487247c3e1235 100644 (file)
@@ -131,40 +131,55 @@ gmx_gettime()
 void print_time(FILE *out,gmx_runtime_t *runtime,gmx_large_int_t step,   
                 t_inputrec *ir, t_commrec *cr)
 {
-  time_t finish;
-
-  double dt;
-  char buf[48];
-
+    time_t finish;
+    
+    double dt;
+    char buf[48];
+    
 #ifndef GMX_THREADS
-  if (!PAR(cr))
+    if (!PAR(cr))
 #endif
-    fprintf(out,"\r");
-  fprintf(out,"step %s",gmx_step_str(step,buf));
-  if ((step >= ir->nstlist)) {
-    if ((ir->nstlist == 0) || ((step % ir->nstlist) == 0)) {
-      /* We have done a full cycle let's update time_per_step */
-      runtime->last = gmx_gettime();
-      dt = difftime(runtime->last,runtime->real);
-      runtime->time_per_step = dt/(step - ir->init_step + 1);
+    {
+        fprintf(out,"\r");
     }
-    dt = (ir->nsteps + ir->init_step - step)*runtime->time_per_step;
-
-    if (dt >= 300) {    
-      finish = (time_t) (runtime->last + dt);
-      sprintf(buf,"%s",ctime(&finish));
-      buf[strlen(buf)-1]='\0';
-      fprintf(out,", will finish %s",buf);
+    fprintf(out,"step %s",gmx_step_str(step,buf));
+    if ((step >= ir->nstlist))
+    {
+        if ((ir->nstlist == 0) || ((step % ir->nstlist) == 0))
+        {
+            /* We have done a full cycle let's update time_per_step */
+            runtime->last = gmx_gettime();
+            dt = difftime(runtime->last,runtime->real);
+            runtime->time_per_step = dt/(step - ir->init_step + 1);
+        }
+        dt = (ir->nsteps + ir->init_step - step)*runtime->time_per_step;
+        
+        if (ir->nsteps >= 0)
+        {
+            if (dt >= 300)
+            {    
+                finish = (time_t) (runtime->last + dt);
+                sprintf(buf,"%s",ctime(&finish));
+                buf[strlen(buf)-1]='\0';
+                fprintf(out,", will finish %s",buf);
+            }
+            else
+                fprintf(out,", remaining runtime: %5d s          ",(int)dt);
+        }
+        else
+        {
+            fprintf(out," performance: %.1f ns/day    ",
+                    ir->delta_t/1000*24*60*60/runtime->time_per_step);
+        }
     }
-    else
-      fprintf(out,", remaining runtime: %5d s          ",(int)dt);
-  }
 #ifndef GMX_THREADS
-  if (PAR(cr))
-    fprintf(out,"\n");
+    if (PAR(cr))
+    {
+        fprintf(out,"\n");
+    }
 #endif
 
-  fflush(out);
+    fflush(out);
 }
 
 #ifdef NO_CLOCK 
@@ -506,7 +521,9 @@ void do_force(FILE *fplog,t_commrec *cr,
       svmul(inputrec->wall_ewald_zfac,boxs[ZZ],boxs[ZZ]);
     }
 
-    gmx_pme_send_x(cr,bBS ? boxs : box,x,mdatoms->nChargePerturbed,lambda,step);
+    gmx_pme_send_x(cr,bBS ? boxs : box,x,
+                   mdatoms->nChargePerturbed,lambda,
+                   ( flags & GMX_FORCE_VIRIAL),step);
 
     GMX_MPE_LOG(ev_send_coordinates_finish);
     wallcycle_stop(wcycle,ewcPP_PMESENDX);
@@ -1377,11 +1394,34 @@ void finish_run(FILE *fplog,t_commrec *cr,const char *confout,
     print_dd_statistics(cr,inputrec,fplog);
   }
 
-  if (SIMMASTER(cr)) {
-    if (PARTDECOMP(cr)) {
-      pr_load(fplog,cr,nrnb_tot);
+#ifdef GMX_MPI
+    if (PARTDECOMP(cr))
+    {
+        if (MASTER(cr))
+        {
+            t_nrnb     *nrnb_all;
+            int        s;
+            MPI_Status stat;
+
+            snew(nrnb_all,cr->nnodes);
+            nrnb_all[0] = *nrnb;
+            for(s=1; s<cr->nnodes; s++)
+            {
+                MPI_Recv(nrnb_all[s].n,eNRNB,MPI_DOUBLE,s,0,
+                         cr->mpi_comm_mysim,&stat);
+            }
+            pr_load(fplog,cr,nrnb_all);
+            sfree(nrnb_all);
+        }
+        else
+        {
+            MPI_Send(nrnb->n,eNRNB,MPI_DOUBLE,MASTERRANK(cr),0,
+                     cr->mpi_comm_mysim);
+        }
     }
+#endif  
 
+  if (SIMMASTER(cr)) {
     wallcycle_print(fplog,cr->nnodes,cr->npmenodes,runtime->realtime,
                     wcycle,cycles);
 
@@ -1489,7 +1529,7 @@ void init_md(FILE *fplog,
     
     if (nfile != -1)
     {
-        *outf = init_mdoutf(nfile,fnm,(Flags & MD_APPENDFILES),cr,ir,oenv);
+        *outf = init_mdoutf(nfile,fnm,Flags,cr,ir,oenv);
 
         *mdebin = init_mdebin((Flags & MD_APPENDFILES) ? NULL : (*outf)->fp_ene,
                               mtop,ir);
index cadd840a83c0018faf97a52170d3e7f4d18b6e73..0d3d8bc37946482ecac503b0b34f2cb6afc587cb 100644 (file)
@@ -171,7 +171,8 @@ void global_stat(FILE *fplog,gmx_global_stat_t gs,
   bPres         = flags & CGLO_PRESSURE; 
   bConstrVir    = flags & CGLO_CONSTRAINT;
   bFirstIterate = flags & CGLO_FIRSTITERATE;
-  bEkinAveVel   = (inputrec->eI==eiVV || (inputrec->eI==eiVVAK && IR_NPT_TROTTER(inputrec) && bPres));
+  //bEkinAveVel   = (inputrec->eI==eiVV || (inputrec->eI==eiVVAK && IR_NPT_TROTTER(inputrec) && bPres));
+  bEkinAveVel   = (inputrec->eI==eiVV || (inputrec->eI==eiVVAK && bPres));
   bReadEkin     = flags & CGLO_READEKIN;
 
   rb   = gs->rb;
@@ -431,18 +432,19 @@ static void moveit(t_commrec *cr,
             xx,NULL,(cr->nnodes-cr->npmenodes)-1,NULL);
 }
 
-gmx_mdoutf_t *init_mdoutf(int nfile,const t_filenm fnm[],bool bAppendFiles,
+gmx_mdoutf_t *init_mdoutf(int nfile,const t_filenm fnm[],int mdrun_flags,
                           const t_commrec *cr,const t_inputrec *ir,
                           const output_env_t oenv)
 {
     gmx_mdoutf_t *of;
     char filemode[3];
+    bool bAppendFiles;
 
     snew(of,1);
 
-    of->fp_trn   = -1;
+    of->fp_trn   = NULL;
     of->fp_ene   = NULL;
-    of->fp_xtc   = -1;
+    of->fp_xtc   = NULL;
     of->fp_dhdl  = NULL;
     of->fp_field = NULL;
     
@@ -451,13 +453,26 @@ gmx_mdoutf_t *init_mdoutf(int nfile,const t_filenm fnm[],bool bAppendFiles,
 
     if (MASTER(cr))
     {
+        bAppendFiles = (mdrun_flags & MD_APPENDFILES);
+
+        of->bKeepAndNumCPT = (mdrun_flags & MD_KEEPANDNUMCPT);
+
         sprintf(filemode, bAppendFiles ? "a+" : "w+");  
         
-        if (ir->eI != eiNM)
+        if (ir->eI != eiNM 
+#ifndef GMX_FAHCORE
+            &&
+            !(EI_DYNAMICS(ir->eI) &&
+              ir->nstxout == 0 &&
+              ir->nstvout == 0 &&
+              ir->nstfout == 0)
+#endif
+           )
         {
             of->fp_trn = open_trn(ftp2fn(efTRN,nfile,fnm), filemode);
         }
-        if (ir->nstxtcout > 0 && !EI_ENERGY_MINIMIZATION(ir->eI))
+        if (!EI_ENERGY_MINIMIZATION(ir->eI) &&
+            ir->nstxtcout > 0)
         {
             of->fp_xtc = open_xtc(ftp2fn(efXTC,nfile,fnm), filemode);
             of->xtc_prec = ir->xtcprec;
@@ -504,11 +519,11 @@ void done_mdoutf(gmx_mdoutf_t *of)
     {
         close_enx(of->fp_ene);
     }
-    if (of->fp_xtc >= 0)
+    if (of->fp_xtc)
     {
         close_xtc(of->fp_xtc);
     }
-    if (of->fp_trn >= 0)
+    if (of->fp_trn)
     {
         close_trn(of->fp_trn);
     }
@@ -630,7 +645,8 @@ void write_traj(FILE *fplog,t_commrec *cr,
      {
          if (mdof_flags & MDOF_CPT)
          {
-             write_checkpoint(of->fn_cpt,fplog,cr,of->eIntegrator,
+             write_checkpoint(of->fn_cpt,of->bKeepAndNumCPT,
+                              fplog,cr,of->eIntegrator,
                               of->simulation_part,step,t,state_global);
          }
 
index 2f32c1a57dc429c3fa1aa739e1f57c67b99ab02a..bd3e5d4698a61eecb5e1855c69869542c1e2d46f 100644 (file)
@@ -846,7 +846,6 @@ t_forcetable make_tables(FILE *out,const output_env_t oenv,
   bool        b14only,bReadTab,bGenTab;
   real        x0,y0,yp;
   int         i,j,k,nx,nx0,tabsel[etiNR];
-  void *      p_tmp;
   
   t_forcetable table;
 
@@ -909,21 +908,11 @@ t_forcetable make_tables(FILE *out,const output_env_t oenv,
   }
 
   /* Each table type (e.g. coul,lj6,lj12) requires four 
-   * numbers per datapoint. For performance reasons we want
-   * the table data to be aligned to 16-byte. This is accomplished
-   * by allocating 16 bytes extra to a temporary pointer, and then
-   * calculating an aligned pointer. This new pointer must not be
-   * used in a free() call, but thankfully we're sloppy enough not
-   * to do this :-)
+   * numbers per nx+1 data points. For performance reasons we want
+   * the table data to be aligned to 16-byte.
    */
+  snew_aligned(table.tab, 12*(nx+1)*sizeof(real),16);
 
-  /* 12 fp entries per table point, nx+1 points, and 16 bytes extra to align it. */
-  p_tmp = malloc(12*(nx+1)*sizeof(real)+16);
-  
-  /* align it - size_t has the same same as a pointer */
-  table.tab = (real *) (((size_t) p_tmp + 16) & (~((size_t) 15)));  
-  
-  
   for(k=0; (k<etiNR); k++) {
     if (tabsel[k] != etabUSER) {
       init_table(out,nx,nx0,
index 78bb75043a04e4521bcbb0291759c9f479373836..25d33099a485ccc563b6618105d3eeff89b9115e 100644 (file)
@@ -131,7 +131,7 @@ double do_tpi(FILE *fplog,t_commrec *cr,
   rvec   *f;
   real   lambda,t,temp,beta,drmax,epot;
   double embU,sum_embU,*sum_UgembU,V,V_all,VembU_all;
-  int    status;
+  t_trxstatus   *status;
   t_trxframe rerun_fr;
   bool   bDispCorr,bCharge,bRFExcl,bNotLastFrame,bStateChanged,bNS,bOurStep;
   tensor force_vir,shake_vir,vir,pres;
index f0e9c02348f798134b616b453ab18e1301a49f70..e2973613fa9a9e2c5d16eb612910372c3fb7e7ba 100644 (file)
@@ -16,11 +16,12 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR})
 # used to create build rules automatically.
 #
 set(NGMX_PROGRAMS 
-    ngmx xrama highway gmxlogo dlg scrollw showcol)
+    ngmx g_xrama g_highway g_logo)
 
 foreach(PROG ${NGMX_PROGRAMS})
         add_executable(${PROG} ${PROG}.c ${NGMX_COMMON_SOURCE})
-        target_link_libraries(${PROG} gmx ${GMX_EXTRA_LIBRARIES} ${X11_LIBRARIES})
+        target_link_libraries(${PROG} gmx ${GMX_EXTRA_LIBRARIES} ${X11_LIBRARIES})        
+        set_target_properties(${PROG} PROPERTIES OUTPUT_NAME "${PROG}${GMX_BINARY_SUFFIX}")
 endforeach(PROG) 
 
 
index e166a2085737f409f65e7ba0491bd2b496966428..1acc2da6796011074b1ecb12d537b6aa3cd4772c 100644 (file)
@@ -10,8 +10,8 @@ LDADD = ../mdlib/libmd@LIBSUFFIX@.la ../gmxlib/libgmx@LIBSUFFIX@.la
 
 if USE_X11
 
-bin_PROGRAMS     = ngmx xrama highway
-EXTRA_PROGRAMS   = gmxlogo dlg scrollw showcol
+bin_PROGRAMS     = ngmx g_xrama g_highway g_logo 
+EXTRA_PROGRAMS   = test_ngmx_dialog  g_showcol
 
 endif
 
@@ -34,12 +34,10 @@ EXTRA_DIST =        alert.bm        gromacs.bm      play.bm         \
 
 
 ngmx_SOURCES    = ngmx.c $(XSRC)
-xrama_SOURCES   = xrama.c $(XSRC)
-highway_SOURCES = highway.c $(XSRC) 
-gmxlogo_SOURCES = gmxlogo.c logo.c $(XSRC)
-dlg_SOURCES     = dlg.c $(XSRC)
-scrollw_SOURCES = scrollw.c $(XSRC)
-showcol_SOURCES = showcol.c $(XSRC)
-
+g_xrama_SOURCES   = g_xrama.c $(XSRC)
+g_highway_SOURCES = g_highway.c $(XSRC) 
+g_logo_SOURCES = g_logo.c $(XSRC)
+g_showcol_SOURCES = g_showcol.c $(XSRC)
+test_ngmx_dialog_SOURCES     = test_ngmx_dialog.c $(XSRC)
 
 CLEANFILES   =         *~ \\\#*
similarity index 100%
rename from src/ngmx/highway.c
rename to src/ngmx/g_highway.c
similarity index 97%
rename from src/ngmx/gmxlogo.c
rename to src/ngmx/g_logo.c
index 754ca6d55f48d9e7976c6c2600c6fd73280ddf14..016170609fbc2ccf62b2fa85a49a4165fcf0e000 100644 (file)
@@ -48,9 +48,10 @@ main(int argc, char *argv[])
     fprintf(stderr,"No X!\n");
     exit(1);
   }
-  logo=init_logo(x11,x11->root);
+  logo=init_logo(x11,x11->root,TRUE);
   show_logo(x11,logo);
   x11->MainLoop(x11);
 
   x11->CleanUp(x11);
+  return 0;
 }
similarity index 97%
rename from src/ngmx/showcol.c
rename to src/ngmx/g_showcol.c
index 8272c3c82113436cb69b55685c6ab90754087109..a1a4270fd3c76791f6c6622dc82b147d8a387e08 100644 (file)
@@ -42,6 +42,7 @@
 #include <string2.h>
 #include <Xstuff.h>
 #include "xutil.h"
+#include "futil.h"
 
 typedef struct {
   XColor    xc;
@@ -265,9 +266,16 @@ main(int argc, char *argv[])
     fn=argv[1];
   else
     fn="/usr/lib/X11/rgb.txt";
+  if (!gmx_fexist(fn)) {
+    fprintf(stderr,"Usage: %s rgb.txt\n",argv[0]);
+    fprintf(stderr,"rgb.txt is usually somewhere in your X windows directories.\n");
+    exit(1);
+  }
   sc=init_sc(x11,x11->root,fn);
   XMapWindow(x11->disp,sc->wd.self);
   XMapSubwindows(x11->disp,sc->wd.self);
   x11->MainLoop(x11);
   x11->CleanUp(x11);
+
+  return 0;
 }
similarity index 100%
rename from src/ngmx/xrama.c
rename to src/ngmx/g_xrama.c
index e93ed7ab882a488a1743087092dc969c1b9a565d..2f56c72512aa0e7e27486268ccaadcad76c06c9e 100644 (file)
@@ -102,7 +102,7 @@ static bool LogoCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
   static t_mess Mess[] = {
     { "GROMACS",                         0,       20, NULL },
     { NULL,                             16,        9, NULL },
-    { "Copyright (c) 1991-2004",        COFFS+ 2,  9, NULL },
+    { "Copyright (c) 1991-2010",        COFFS+ 2,  9, NULL },
     { "D.v.d.Spoel, E.Lindahl, B.Hess", COFFS+11,  9, NULL },
     { "& Groningen University ",        COFFS+20,  9, NULL },
     { "click to dismiss",               COFFS+31,  8, NULL }
@@ -154,6 +154,7 @@ static bool LogoCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
     break;
   case ButtonPress:
     hide_logo(x11,logo);
+    return logo->bQuitOnClick;
     break;
   default:
     break;
@@ -162,7 +163,7 @@ static bool LogoCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
   return FALSE;
 }
 
-t_logo *init_logo(t_x11 *x11,Window parent)
+t_logo *init_logo(t_x11 *x11,Window parent,bool bQuitOnClick)
 {
   static const char *bfname[]= {
     "-b&h-lucida-bold-i-normal-sans-34-240-100-100-p-215-iso8859-1",
@@ -185,6 +186,7 @@ t_logo *init_logo(t_x11 *x11,Window parent)
   t_logo *logo;
 
   snew(logo,1);
+  logo->bQuitOnClick = bQuitOnClick;
   InitWin(&logo->wd,0,0,360,270,1,"GROMACS");
   bg=LIGHTGREY;
   if ((newcol=getenv("LOGO"))!=NULL)
index 64a0abe640b10b53ab7100c7c230482581b96286..3fe7f429bff2ae2ba2fdd7e35fe2957c717c74de 100644 (file)
@@ -43,13 +43,14 @@ typedef struct {
   XFontStruct *bigfont;
   XFontStruct *smallfont;
   t_windata   wd;
+  bool bQuitOnClick;
 } t_logo;
 
 extern void show_logo(t_x11 *x11,t_logo *logo);
 
 extern void hide_logo(t_x11 *x11,t_logo *logo);
 
-extern t_logo *init_logo(t_x11 *x11,Window parent);
+extern t_logo *init_logo(t_x11 *x11,Window parent,bool bQuitOnClick);
 
 extern void done_logo(t_x11 *x11,t_logo *logo);
 
index ae648b868ca5f11197fbf99b77f874edbb7fc73d..29fd19f07a780b4c25e49b7418d465179e87f0b3 100644 (file)
@@ -198,6 +198,7 @@ void set_file(t_x11 *x11,t_manager *man,const char *trajectory,
   snew(man->bHydro,sh.natoms);
   snew(bB,sh.natoms);
   read_tpx_top(status,NULL,man->box,&man->natom,NULL,NULL,NULL,&man->top);
+  man->gpbc = gmx_rmpbc_init(&man->top.idef,-1,man->natom,man->box);
   
   man->natom=
     read_first_x(man->oenv,&man->status,trajectory,&(man->time),&(man->x),
@@ -337,8 +338,7 @@ static bool step_man(t_manager *man,int *nat)
       break;
     }
     if (man->bPbc) {
-      rm_pbc(&(man->top.idef),man->molw->ePBC,
-            man->natom,man->box,man->x,man->x);
+      gmx_rmpbc(man->gpbc,man->box,man->x,man->x);
       reset_mols(&(man->top.mols),man->box,man->x);
     }
     ncount=0;
@@ -391,7 +391,7 @@ static void HandleClient(t_x11 *x11,t_manager *man,long data[])
     draw_mol(x11,man);
     break;
   case IDREWIND:
-    if (man->status != -1) {
+    if (man->status) {
       rewind_trj(man->status);
       read_next_x(man->oenv,man->status,&(man->time),man->natom,man->x,
                   man->box);
@@ -547,7 +547,7 @@ void map_man(t_x11 *x11,t_manager *man)
 
 bool toggle_animate (t_x11 *x11,t_manager *man)
 { 
-  if (man->status != -1) {
+  if (man->status) {
     man->bAnimate=!man->bAnimate;
     man->bStop=TRUE;
     man->bEof=FALSE;
@@ -576,7 +576,7 @@ t_manager *init_man(t_x11 *x11,Window Parent,
   t_manager *man;
 
   snew(man,1);
-  man->status=-1;
+  man->status=NULL;
   man->bPlus=TRUE;
   man->bSort=TRUE;
   man->oenv=oenv;
index 0c13baa3da2f30a0412f860aed93d98220414105..0fc964c4b1c4210845830730d80c76e6c2386ec2 100644 (file)
@@ -43,6 +43,8 @@
 #include "3dview.h"
 #include "nleg.h"
 #include "buttons.h"
+#include "statutil.h"
+#include "rmpbc.h"
 
 /* Some window sizes */
 #define EWIDTH         200
@@ -91,7 +93,7 @@ typedef struct {
  *
  */
 typedef struct {
-  int       status;
+  t_trxstatus *status;
   const char  *trajfile;
   int       natom;             /* The number of atoms                  */
   t_topology top;               /* topology                             */
@@ -118,7 +120,8 @@ typedef struct {
   bool      bPlus;             /* Draw plus for single atom            */
   int       nSkip;             /* Skip n steps after each frame        */
   int       nWait;             /* Wait n ms after each frame           */
-
+  gmx_rmpbc_t gpbc;             /* For removing peridiocity             */
+  
   t_windata   wd;               /* The manager subwindow                */
   t_windata   title;           /* Title window                         */
   t_3dview    *view;            /* The 3d struct                        */
index 870f5b5e5cd06f040a201783b992b6e93d7cb9fe..afcf0ee0cf1ad9792a88bac61ac14c92953fe776 100644 (file)
@@ -209,7 +209,7 @@ void ps_draw_mol(t_psdata ps,t_manager *man)
   real      sx,sy;
   vec4      x4;
 
-  if (man->status == -1)
+  if (!man->status)
     return;
 
   view=man->view;
index 46bcf269450788c4e3834832777b1eec3957a04b..a2234f82d31753715f91a9cbc39fcaef07c11eaa 100644 (file)
@@ -358,7 +358,7 @@ void init_gmx(t_x11 *x11,char *program,int nfile,t_filenm fnm[],
   int                  ePBC;
   matrix               box;
   t_trxframe           fr;
-  int                  status;
+  t_trxstatus          *status;
   char                 quote[256];
   
   snew(gmx,1);
@@ -399,7 +399,7 @@ void init_gmx(t_x11 *x11,char *program,int nfile,t_filenm fnm[],
   /* The order of creating windows is important here! */
   /* Manager */
   gmx->man  = init_man(x11,gmx->wd->self,0,0,1,1,WHITE,BLACK,ePBC,box,oenv);
-  gmx->logo = init_logo(x11,gmx->wd->self);
+  gmx->logo = init_logo(x11,gmx->wd->self,FALSE);
 
   /* Now put all windows in the proper place */
   move_gmx(x11,gmx,w0,h0,FALSE);
index a4399a9d4592a0c241ddb3a3a37ec9f094940816..d13d20fb26c60e4e49eab5cfd84ef5dd669df50e 100644 (file)
@@ -495,7 +495,7 @@ void draw_mol(t_x11 *x11,t_manager *man)
   real      sx,sy;
   vec4      x4;
 
-  if (man->status == -1)
+  if (!man->status)
     return;
 
   view=man->view;
diff --git a/src/ngmx/scrollw.c b/src/ngmx/scrollw.c
deleted file mode 100644 (file)
index 20bd01c..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Gyas ROwers Mature At Cryogenic Speed
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <sysstuff.h>
-#include <Xstuff.h>
-#include <xutil.h>
-#include <smalloc.h>
-#include <macros.h>
-#include <futil.h>
-#include <string2.h>
-
-#define YSPACE 2
-
-typedef struct {
-  t_windata   wd;              /* Window structure                     */
-  int         nlines,top;      /* Number of lines, current top line    */
-  char        **lines;         /* The strings                          */
-  int         wheight,wwidth;  /* The size of the window in chars      */
-  XFontStruct *font;           /* Font                                 */
-  unsigned long       fg,bg;           /* Colours                              */
-} t_scrollw;
-
-static void calc_scrollw(t_scrollw *sw,int w,int h)
-{
-  sw->wd.width=w;
-  sw->wd.height=h;
-  sw->wheight=h/(YSPACE+XTextHeight(sw->font));
-  sw->wwidth=w/XTextWidth(sw->font,"W",1);
-}
-
-static bool SWCallback(t_x11 *x11,XEvent *event,Window w,void *data)
-{
-  t_scrollw *sw;
-  int       i,y,nl,barw,btop,bheight;
-  real      h,frac;
-
-  sw=(t_scrollw *)data;
-
-  /* Calc some bar data */
-  barw=20;
-  h=XTextHeight(sw->font)+YSPACE;
-  frac=min(1.0,((real)sw->wheight)/((real)sw->nlines));
-  btop=((((real)sw->top)/((real)sw->nlines)))*(sw->wd.height);
-  bheight=frac*sw->wd.height;
-  bheight-=bheight/h;
-
-  switch(event->type) {
-  case Expose:
-    nl=min(sw->nlines,sw->top+sw->wheight);
-    y=0;
-
-    XClearWindow(x11->disp,w);
-#ifdef DEBUG
-    printf("btop: %d, bheight: %d, frac: %e, h: %e\n",btop,bheight,frac,h);
-#endif
-    /* Draw the bar */
-    XSetForeground(x11->disp,x11->gc,LIGHTGREY);
-    XFillRectangle(x11->disp,w,x11->gc,2,btop+2,barw-4,bheight-4);
-    XDrawLine(x11->disp,w,x11->gc,barw,0,barw,sw->wd.height);
-
-    /* Draw the text */
-    XSetForeground(x11->disp,x11->gc,sw->fg);
-    for(i=sw->top; (i<nl); i++) {
-      SpecialTextInRect(x11,sw->font,w,
-                       sw->lines[i],barw+2,y,sw->wd.width-barw-4,(int)h,
-                       eXLeft,eYCenter);
-      y+=h;
-    }
-    XSetForeground(x11->disp,x11->gc,x11->fg);
-    break;
-  case ConfigureNotify:
-    calc_scrollw(sw,event->xconfigure.width,event->xconfigure.height);
-    break;
-  case ButtonPress:
-    if (event->xbutton.x < barw) {
-      int y=event->xbutton.y;
-
-      if (sw->nlines > sw->wheight) {
-       if (y<btop) 
-         sw->top=max(0,sw->top-1);
-       else if (y>btop+bheight) 
-         sw->top=min(sw->nlines-sw->wheight,sw->top+1);
-       else
-         break;
-       ExposeWin(x11->disp,sw->wd.self);
-      }
-    }
-    break;
-  default:
-    break;
-  }
-
-  return FALSE;
-}
-
-t_scrollw *init_scrollw(t_x11 *x11,Window parent,int x,int y,int w,int h,
-                       unsigned long fg,unsigned long bg)
-{
-  t_scrollw *sw;
-
-  snew(sw,1);
-
-  InitWin(&sw->wd,x,y,w,h,1,"Scroll Window");
-  sw->fg=fg;
-  sw->bg=bg;
-  sw->font=x11->font;
-  sw->wd.self=XCreateSimpleWindow(x11->disp,parent,x,y,w,h,
-                                 sw->wd.bwidth,fg,bg);
-  x11->RegisterCallback(x11,sw->wd.self,parent,SWCallback,sw);
-  x11->SetInputMask(x11,sw->wd.self,ExposureMask | ButtonPressMask |
-                   StructureNotifyMask);
-  calc_scrollw(sw,w,h);
-
-  return sw;
-}
-
-void show_scrollw(t_x11 *x11,t_scrollw *sw)
-{
-  XMapWindow(x11->disp,sw->wd.self);
-}
-
-char *tab2spc(char *buf)
-{
-  char *buf2;
-  char *new;
-  int  i,j;
-
-  snew(buf2,8*strlen(buf)+1);
-  for(i=j=0; (buf[i]!='\0'); i++)
-    if (buf[i]=='\t') 
-      do {
-       buf2[j++]=' ';
-      } while ((j % 8)!=0);
-    else
-      buf2[j++]=buf[i];
-  buf2[j]='\0';
-  new=strdup(buf2);
-  sfree(buf2);
-  return new;
-}
-
-void read_lines(FILE *in,t_scrollw *sw)
-{
-  char buf[1024];
-
-  while (fgets2(buf,1023,in)) {
-    sw->nlines++;
-    srenew(sw->lines,sw->nlines);
-    sw->lines[sw->nlines-1]=tab2spc(buf);
-  }
-}
-
-int
-main(int argc, char *argv[])
-{
-  t_x11     *x11;
-  t_scrollw *sw;
-
-  if ((x11=GetX11(&argc,argv))==NULL) {
-    fprintf(stderr,"No X!\n");
-    exit(1);
-  }
-  sw=init_scrollw(x11,x11->root,0,0,600,200,WHITE,BLACK);
-  read_lines(stdin,sw);
-  show_scrollw(x11,sw);
-  x11->MainLoop(x11);
-
-  x11->CleanUp(x11);
-}
similarity index 100%
rename from src/ngmx/dlg.c
rename to src/ngmx/test_ngmx_dialog.c
index 6bf3d37fc9aad09ced833828194b0e985c901911..998997b8d0b08eba2f65ead924f0c81265c2727f 100644 (file)
@@ -5,6 +5,7 @@ add_library(gmxana
             eigio.c         cmat.c          
             eigensolver.c   nsc.c           
             hxprops.c       fitahx.c        
+            geminate.c
             gmx_analyze.c   gmx_anaeig.c    gmx_angle.c     gmx_bond.c      
             gmx_bundle.c    gmx_chi.c       gmx_cluster.c   gmx_confrms.c   
             gmx_covar.c     gmx_current.c   
@@ -27,18 +28,19 @@ add_library(gmxana
             gmx_trjconv.c   gmx_trjcat.c    gmx_trjorder.c  gmx_xpm2ps.c    
             gmx_editconf.c  gmx_genbox.c    gmx_genion.c    gmx_genconf.c   
             gmx_genpr.c     gmx_eneconv.c   gmx_vanhove.c   gmx_wheel.c     
-            addconf.c       calcpot.c       edittop.c       gmx_bar.c)
+            addconf.c       calcpot.c       edittop.c       gmx_bar.c
+            gmx_membed.c    )
 
 target_link_libraries(gmxana md ${GMX_EXTRA_LIBRARIES})
-
+set_target_properties(gmxana PROPERTIES OUTPUT_NAME "gmxana${GMX_BINARY_SUFFIX}")
 
 # List of programs with single corresponding .c source file,
 # used to create build rules automatically.
 #
 set(GMX_TOOLS_PROGRAMS
     do_dssp editconf eneconv genbox genconf genrestr g_nmtraj 
-    make_ndx mk_angndx trjcat trjconv trjorder wheel 
-    xpm2ps genion anadock make_edi g_analyze g_anaeig
+    make_ndx mk_angndx trjcat trjconv trjorder g_wheel 
+    xpm2ps genion g_anadock make_edi g_analyze g_anaeig
     g_angle g_bond g_bundle g_chi g_cluster g_confrms g_covar
     g_current g_density g_densmap g_dih g_dielectric
     g_helixorient g_principal g_dipoles g_disre g_dist
@@ -47,7 +49,8 @@ set(GMX_TOOLS_PROGRAMS
     g_nmens g_order g_polystat g_potential g_rama g_rdf g_rms
     g_rmsf g_rotacf g_saltbr g_sas g_select g_sgangle g_sham g_sorient
     g_spol g_sdf g_spatial g_tcaf g_traj g_tune_pme g_vanhove
-    g_velacc g_clustsize g_mdmat g_wham g_kinetics sigeps g_bar
+    g_velacc g_clustsize g_mdmat g_wham g_kinetics g_sigeps g_bar
+    g_membed
     )
 
 
@@ -55,6 +58,7 @@ set(GMX_TOOLS_PROGRAMS
 foreach(TOOL ${GMX_TOOLS_PROGRAMS})
     add_executable(${TOOL} ${TOOL}.c)
     target_link_libraries(${TOOL} gmxana)
+    set_target_properties(${TOOL} PROPERTIES OUTPUT_NAME "${TOOL}${GMX_BINARY_SUFFIX}")
 endforeach(TOOL ${GMX_TOOLS_PROGRAMS}) 
 
 
index fb1a49ac5c5dd064862fe05361585a27015a4a74..baf5421568be1377c69fedbd5c16c46a1a7681f3 100644 (file)
@@ -15,6 +15,7 @@ libgmxana@LIBSUFFIX@_la_LDFLAGS        = -version-info @SHARED_VERSION_INFO@
 
 
 libgmxana@LIBSUFFIX@_la_SOURCES = \
+       geminate.c      geminate.h                                      \
        autocorr.c      expfit.c        polynomials.c   levenmar.c      \
        anadih.c        pp2shift.c      pp2shift.h      dlist.c         \
        eigio.c         cmat.c          cmat.h          \
@@ -42,15 +43,15 @@ libgmxana@LIBSUFFIX@_la_SOURCES = \
        gmx_trjconv.c   gmx_trjcat.c    gmx_trjorder.c  gmx_xpm2ps.c    \
        gmx_editconf.c  gmx_genbox.c    gmx_genion.c    gmx_genconf.c   \
        gmx_genpr.c     gmx_eneconv.c   gmx_vanhove.c   gmx_wheel.c     \
-       addconf.c       addconf.h       gmx_tune_pme.c    \
+       addconf.c       addconf.h       gmx_tune_pme.c  gmx_membed.c    \
        calcpot.c       calcpot.h       edittop.c
 
 bin_PROGRAMS = \
        do_dssp         editconf        eneconv         \
        genbox          genconf         genrestr        g_nmtraj        \
        make_ndx        mk_angndx       trjcat          trjconv         \
-       trjorder        wheel           xpm2ps          genion          \
-       anadock         make_edi        \
+       trjorder        g_wheel         xpm2ps          genion          \
+       g_anadock       make_edi        \
        g_analyze       g_anaeig        g_bar           \
        g_angle         g_bond          \
        g_bundle        g_chi           g_cluster       g_confrms       \
@@ -69,9 +70,9 @@ bin_PROGRAMS = \
        g_sham          g_sorient       g_spol          \
        g_sdf           g_spatial       \
        g_tcaf          g_traj          g_tune_pme   \
-       g_vanhove       g_velacc        \
+       g_vanhove       g_velacc        g_membed      \
        g_clustsize     g_mdmat         g_wham          g_kinetics      \
-       sigeps
+       g_sigeps
 
 
 LDADD = $(lib_LTLIBRARIES) ../mdlib/libmd@LIBSUFFIX@.la \
index 6380cacc59799ae598334274beb50fe0f241c57b..7688e90e1d74d5fbed601a86756f534e4e69b7d0 100644 (file)
@@ -307,7 +307,7 @@ void do_nsgrid(FILE *fp,bool bVerbose,
     dump_nblist(debug,cr,fr,0);
 
   if (bVerbose)    
-    fprintf(stderr,"Succesfully made neighbourlist\n");
+    fprintf(stderr,"Successfully made neighbourlist\n");
 }
 
 bool bXor(bool b1,bool b2)
index 9ac6f174377b77ee6af54a2c284954c57926dcd7..069673b5a6d7e9f7bc1b9fac3a453e7cbe4fa7d2 100644 (file)
@@ -662,7 +662,8 @@ void read_ang_dih(const char *trj_fn,
                   const output_env_t oenv)
 {
   t_pbc      *pbc;
-  int        i,angind,status,natoms,total,teller;
+  t_trxstatus *status;
+  int        i,angind,natoms,total,teller;
   int        nangles,n_alloc;
   real       t,fraction,pifac,aa,angle;
   real       *angles[2];
index bb72d984b54ec945bd84a175e5088636899ddb6f..7305d5419bbc48388d2955cb8fab0ae200a244fc 100644 (file)
@@ -600,7 +600,7 @@ void low_do_autocorr(const char *fn,const output_env_t oenv,const char *title,
   bool    bFour = acf.bFour;
  
   /* Check flags and parameters */ 
-  /*  nout = get_acfnout();*/
+  nout = get_acfnout();
   if (nout == -1)
     nout = acf.nout = (nframes+1)/2;
   else if (nout > nframes)
@@ -745,7 +745,7 @@ t_pargs *add_acf_pargs(int *npargs,t_pargs *pa)
     { "-beginfit", FALSE, etREAL, {&acf.tbeginfit},
       "Time where to begin the exponential fit of the correlation function" },
     { "-endfit",   FALSE, etREAL, {&acf.tendfit},
-      "Time where to end the exponential fit of the correlation function, -1 is till the end" },
+      "Time where to end the exponential fit of the correlation function, -1 is until the end" },
    };
 #define NPA asize(acfpa)
   t_pargs *ppa;
diff --git a/src/tools/average.c b/src/tools/average.c
deleted file mode 100644 (file)
index ab39d1b..0000000
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * 
- *                This source code is part of
- * 
- *                 G   R   O   M   A   C   S
- * 
- *          GROningen MAchine for Chemical Simulations
- * 
- *                        VERSION 3.2.0
- * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
- * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
- * Copyright (c) 2001-2004, The GROMACS development team,
- * check out http://www.gromacs.org for more information.
-
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- * 
- * If you want to redistribute modifications, please consider that
- * scientific software is very special. Version control is crucial -
- * bugs must be traceable. We will be happy to consider code for
- * inclusion in the official distribution, but derived work must not
- * be called official GROMACS. Details are found in the README & COPYING
- * files - if they are missing, get the official version at www.gromacs.org.
- * 
- * To help us fund GROMACS development, we humbly ask that you cite
- * the papers on the package - you can find them in the top README file.
- * 
- * For more info, check our website at http://www.gromacs.org
- * 
- * And Hey:
- * Green Red Orange Magenta Azure Cyan Skyblue
- */
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <stdio.h>
-#include <math.h>
-#include "string2.h"
-#include "smalloc.h"
-#include "statutil.h"
-#include "vec.h"
-
-static void my_usage(char *prog,char *arg)
-{
-  fprintf(stderr," Usage: %s [-p] [-s] [-c #columns]"
-         " naver < infile > outfile\n",prog);
-  fprintf(stderr,"-p means picoseconds rather than nanoseconds\n");
-  fprintf(stderr,"-s means silent rather than verbose\n");
-  fprintf(stderr,"Don't ever use argument %s again!\n",arg);
-  exit(1);
-}
-
-void lsq_y_ax_b_double(int n, double x[], double y[], double *a, double *b)
-{
-  int    i;
-  double yx,xx,sx,sy;
-
-  yx=xx=sx=sy=0.0;
-  for (i=0; (i < n); i++) {
-    yx+=y[i]*x[i];
-    xx+=x[i]*x[i];
-    sx+=x[i];
-    sy+=y[i];
-  }
-  *a=(n*yx-sy*sx)/(n*xx-sx*sx);
-  *b=(sy-(*a)*sx)/n;
-}
-
-int main(int argc, char *argv[]) 
-{
-  double *x,**y,value=0.001;
-  double *yav,yyy,yyy2,ymin,ymax,aver,var,sd;
-  int    i,j,k,nav=100,ncol=1,MAX=50000;
-  char   buf[STRLEN];
-  bool   bSilent=FALSE,bVerySilent=FALSE;
-  double   lsq_a,lsq_b,rms_res;
-  
-  for(i=1; (i<argc); i++) {
-    if (argv[i][0] == '-')
-      switch (argv[i][1]) {
-      case 'p':
-       value=1.0;
-       break;
-      case 'm':
-       MAX=iscan(argc,argv,&i);
-       break;
-      case 'c':
-       ncol=iscan(argc,argv,&i);
-       break;
-      case 's':
-       bSilent=TRUE;
-       break;
-      case 'S':
-       bVerySilent=bSilent=TRUE;
-       break;
-      default:
-       my_usage(argv[0],argv[i]);
-      }
-    else
-      nav=strtol(argv[i],NULL,10);
-  }
-  if (!bSilent)
-    fprintf(stderr,"Will average stdin with %d columns, over %d points\n",
-           ncol,nav);
-  
-  
-  snew(x,MAX);
-  snew(y,ncol);
-  for(i=0; (i<ncol); i++) {
-    snew(y[i],MAX);
-  }
-  snew(yav,MAX);
-  i=0;
-  do {
-    if (scanf("%s",buf) == 1) {
-      if ((buf[0] != '@') && (buf[0] != '#')) {
-       sscanf(buf,"%lf",&x[i]);
-       for(k=0; (k<ncol); k++)
-         scanf("%lf",&(y[k][i]));
-       if (i >= nav) {
-         if (!bVerySilent) 
-           printf("%10e",x[i-nav/2]*value);
-         for(k=0; (k<ncol); k++) {
-           yav[k]=0;
-           for(j=i-nav+1; (j<=i); j++)
-             yav[k]+=y[k][j];
-           yav[k]/=nav;
-           if (!bVerySilent) 
-             printf("  %10e",yav[k]);
-         }
-         if (!bVerySilent) 
-           printf("\n");
-       }
-       i++;
-      }
-      else {
-       while (getc(stdin) != '\n')
-         ;
-      }
-    }
-    else
-      break;
-  } while (((int)strlen(buf) > 0) && (i<MAX));
-
-
-  if (!bSilent)
-    fprintf(stderr,"%3s  %12s  %12s  %12s  %12s  %12s  %12s  %12s\n",
-           "i","min","aver","max","var","sd","drift","fluc");
-  for(k=0; (k<ncol); k++) {
-    aver=y[k][0];
-    ymin=aver;
-    ymax=aver;
-    yyy2=aver*aver;
-    for(j=1; (j<i); j++) {
-      yyy=y[k][j];
-      aver+=yyy;
-      yyy2+=(yyy*yyy);
-      if (yyy < ymin)
-       ymin=yyy;
-      else if (yyy > ymax)
-       ymax=yyy;
-    }
-    aver/=i;
-    var=yyy2/i-aver*aver;
-    sd=sqrt(var);
-
-    lsq_y_ax_b_double(i,x,y[k],&lsq_a,&lsq_b);
-    rms_res=0;
-    for(j=0; (j<i);j++)
-      rms_res+=sqr(y[k][j]-(lsq_a*x[j]+lsq_b));
-    rms_res=sqrt(rms_res/i);
-
-    fprintf(stderr,"%3d  %12g  %12g  %12g  %12g  %12g  %12g  %12g\n",
-           k,ymin,aver,ymax,var,sd,lsq_a,rms_res);
-  }
-  return 0;
-}
-
-
index 6587ea299af96c9fdd273ccf43a4d30cdcad0262..e17843773e45bede99476fc9c14afcb58927ac80 100644 (file)
@@ -234,7 +234,12 @@ FILE *init_calcpot(const char *log,const char *tpx,const char *table,
 
   init_nrnb(&nrnb);
   snew(state,1);
-  init_single(fplog,inputrec,tpx,mtop,state);
+  read_tpx_state(tpx,inputrec,state, NULL, mtop);
+  set_state_entries(state,inputrec,1);
+  if (fplog)
+      pr_inputrec(fplog,0,"Input Parameters",inputrec,FALSE);
+
+
 
   if (inputrec->efep) {
     fprintf(stderr,"WARNING: turning of free energy, will use lambda=0\n");
index f3ad63326a359abebb670d98616d4df32e7e47d4..77c3d4802cfeea7572de135d5fb0503757f180a4 100644 (file)
@@ -196,6 +196,8 @@ static void check_oo(t_atoms *atoms)
        *atoms->atomname[i]=OOO;
     else if (strcmp(*(atoms->atomname[i]),"O1")==0)
       *atoms->atomname[i]=OOO;
+    else if (strcmp(*(atoms->atomname[i]),"OC1")==0)
+      *atoms->atomname[i]=OOO;
   }
 }
 
@@ -373,7 +375,7 @@ int main(int argc,char *argv[])
       "Secondary structures for structure count"}
   };
   
-  int        status;
+  t_trxstatus *status;
   FILE       *tapein;
   FILE       *ss,*acc,*fTArea,*tmpf;
   const char *fnSCount,*fnArea,*fnTArea,*fnAArea;
@@ -397,7 +399,7 @@ int main(int argc,char *argv[])
   char       dssp[256];
   const char *dptr;
   output_env_t oenv;
-  
+  gmx_rmpbc_t  gpbc=NULL;
   
   t_filenm   fnm[] = {
     { efTRX, "-f",   NULL,      ffREAD },
@@ -493,6 +495,8 @@ int main(int argc,char *argv[])
   snew(norm_av_area, atoms->nres);
   accr=NULL;
   naccr=0;
+  
+  gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
   do {
     t = output_env_conv_time(oenv,t);
     if (bDoAccSurf && nframe>=naccr) {
@@ -501,7 +505,7 @@ int main(int argc,char *argv[])
       for(i=naccr-10; i<naccr; i++)
         snew(accr[i],2*atoms->nres-1);
     }
-    rm_pbc(&(top.idef),ePBC,natoms,box,x,x);
+    gmx_rmpbc(gpbc,box,x,x);
     tapein=ffopen(pdbfile,"w");
     write_pdbfile_indexed(tapein,NULL,atoms,x,ePBC,box,0,-1,gnx,index,NULL);
     ffclose(tapein);
@@ -533,7 +537,8 @@ int main(int argc,char *argv[])
   close_trj(status);
   if (fTArea)
     ffclose(fTArea);
-  
+  gmx_rmpbc_done(gpbc);
+
   prune_ss_legend(&mat);
   
   ss=opt2FILE("-o",NFILE,fnm,"w");
index 74753ad59f80326708d9a6ef41bf3267e0cae461..3faba70c9fb49145e204fd3df356d126265f54af 100644 (file)
@@ -41,6 +41,7 @@
 #include "eigio.h"
 #include "trnio.h"
 #include "tpxio.h"
+#include "statutil.h"
 #include "futil.h"
 
 void read_eigenvectors(const char *file,int *natoms,bool *bFit,
@@ -50,7 +51,8 @@ void read_eigenvectors(const char *file,int *natoms,bool *bFit,
                        rvec ***eigvec,real **eigval)
 {
   t_trnheader head;
-  int    status,i,snew_size;
+  int    i,snew_size;
+  t_fileio *status;
   rvec   *x;
   matrix box;
   bool   bOK;
@@ -141,7 +143,7 @@ void write_eigenvectors(const char *trnname,int natoms,real mat[],
                         int WriteXref,rvec *xref,bool bDMR,
                         rvec xav[], bool bDMA,real eigval[])
 {
-    int    trnout;
+    t_fileio *trnout;
     int    ndim,i,j,d,vec;
     matrix zerobox;
     rvec   *x;
index b6de7fececd008d5cec89ad143fbb8935d28d5ab..a511241b3600ee346bccede50e2e529f45ef7ddf 100644 (file)
@@ -412,7 +412,7 @@ real do_lmfit(int ndata,real c1[],real sig[],real dt,real x0[],
   nparm = nfp_ffn[eFitFn];
   if (debug) {
     fprintf(debug,"There are %d points to fit %d vars!\n",ndata,nparm);
-    fprintf(debug,"Fit to function %d from %g thru %g, dt=%g\n",
+    fprintf(debug,"Fit to function %d from %g through %g, dt=%g\n",
            eFitFn,begintimefit,endtimefit,dt);
   }
 
similarity index 100%
rename from src/tools/anadock.c
rename to src/tools/g_anadock.c
diff --git a/src/tools/g_membed.c b/src/tools/g_membed.c
new file mode 100644 (file)
index 0000000..ad85387
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * $Id: g_prot2mem.c 2009/04/02 M.G. Wolf $
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ *                        VERSION 4.0.3
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Green Red Orange Magenta Azure Cyan Skyblue
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <gmx_ana.h>
+
+
+/* This is just a wrapper binary.
+* The code that used to be in g_anaeig.c is now in gmx_anaeig.c,
+* where the old main function is called gmx_anaeig().
+*/
+int
+main(int argc, char *argv[])
+{
+  gmx_membed(argc,argv);
+  return 0;
+}
+
+
+
similarity index 100%
rename from src/tools/sigeps.c
rename to src/tools/g_sigeps.c
similarity index 100%
rename from src/tools/wheel.c
rename to src/tools/g_wheel.c
diff --git a/src/tools/geminate.c b/src/tools/geminate.c
new file mode 100644 (file)
index 0000000..2ec855c
--- /dev/null
@@ -0,0 +1,1181 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_LIBGSL
+#include <gsl/gsl_rng.h>
+#include <gsl/gsl_randist.h>
+#include <gsl/gsl_vector.h>
+#include <gsl/gsl_blas.h>
+#include <gsl/gsl_multimin.h>
+#include <gsl/gsl_multifit_nlin.h>
+#include <gsl/gsl_sf.h>
+#include <gsl/gsl_version.h>
+#endif
+
+#include "typedefs.h"
+#include "smalloc.h"
+#include "vec.h"
+#include "geminate.h"
+
+#ifdef DOUSEOPENMP
+#define HAVE_OPENMP
+#endif
+#ifdef HAVE_OPENMP
+#include <omp.h>
+#endif
+
+/* The first few sections of this file contain functions that were adopted,
+ * and to some extent modified, by Erik Marklund (erikm[aT]xray.bmc.uu.se,
+ * http://folding.bmc.uu.se) from code written by Omer Markovitch (email, url).
+ * This is also the case with the function eq10v2().
+ * 
+ * The parts menetioned in the previous paragraph were contributed under a BSD license.
+ */
+
+
+/* This first part is from complex.c which I recieved from Omer Markowitch.
+ * - Erik Marklund
+ *
+ * ------------- from complex.c ------------- */
+
+/* Complexation of a paired number (r,i)                                     */
+static gem_complex gem_cmplx(double r, double i)
+{
+  gem_complex value;
+  value.r = r;
+  value.i=i;
+  return value;
+}
+
+/* Complexation of a real number, x */
+static gem_complex gem_c(double x)
+{
+  gem_complex value;
+  value.r=x;
+  value.i=0;
+  return value;
+}
+
+/* Real and Imaginary part of a complex number z -- Re (z) and Im (z)        */
+static double gem_Re(gem_complex z) {return z.r;}
+static double gem_Im(gem_complex z) {return z.i;}
+
+/* Magnitude of a complex number z                                           */
+static double gem_cx_abs(gem_complex z) { return (sqrt(z.r*z.r+z.i*z.i)); }
+
+/* Addition of two complex numbers z1 and z2                                 */
+static gem_complex gem_cxadd(gem_complex z1, gem_complex z2)
+{
+  gem_complex value;
+  value.r=z1.r+z2.r;
+  value.i=z1.i+z2.i;
+  return value;
+}
+
+/* Addition of a complex number z1 and a real number r */
+static gem_complex gem_cxradd(gem_complex z, double r)
+{
+  gem_complex value;
+  value.r = z.r + r;
+  value.i = z.i;
+  return value;
+}
+
+/* Subtraction of two complex numbers z1 and z2                              */
+static gem_complex gem_cxsub(gem_complex z1, gem_complex z2)
+{
+  gem_complex value;
+  value.r=z1.r-z2.r;
+  value.i=z1.i-z2.i;
+  return value;
+}
+
+/* Multiplication of two complex numbers z1 and z2                           */
+static gem_complex gem_cxmul(gem_complex z1, gem_complex z2)
+{
+  gem_complex value;
+  value.r = z1.r*z2.r-z1.i*z2.i;
+  value.i = z1.r*z2.i+z1.i*z2.r;
+  return value;
+}
+
+/* Square of a complex number z                                              */
+static gem_complex gem_cxsq(gem_complex z)
+{
+  gem_complex value;
+  value.r = z.r*z.r-z.i*z.i;
+  value.i = z.r*z.i*2.;
+  return value;
+}
+
+/* multiplication of a complex number z and a real number r */
+static gem_complex gem_cxrmul(gem_complex z, double r)
+{
+  gem_complex value;
+  value.r = z.r*r;
+  value.i= z.i*r;
+  return value;
+}
+
+/* Division of two complex numbers z1 and z2                                 */
+static gem_complex gem_cxdiv(gem_complex z1, gem_complex z2)
+{
+  gem_complex value;
+  double num;
+  num = z2.r*z2.r+z2.i*z2.i;
+  if(num == 0.)
+    {
+      fprintf(stderr, "ERROR in gem_cxdiv function\n");
+    }
+  value.r = (z1.r*z2.r+z1.i*z2.i)/num; value.i = (z1.i*z2.r-z1.r*z2.i)/num;
+  return value;
+}
+
+/* division of a complex z number by a real number x */
+static gem_complex gem_cxrdiv(gem_complex z, double r)
+{
+  gem_complex value;
+  value.r = z.r/r;
+  value.i = z.i/r;
+  return value;
+}
+
+/* division of a real number r by a complex number x */
+static gem_complex gem_rxcdiv(double r, gem_complex z)
+{
+  gem_complex value;
+  double f;
+  f = r/(z.r*z.r+z.i*z.i);
+  value.r = f*z.r;
+  value.i = -f*z.i;
+  return value;
+}
+
+/* Integer power of a complex number z -- z^x                                */
+static gem_complex gem_cxintpow(gem_complex z, int x)
+{
+  int i;
+  gem_complex value;
+
+  value.r = 1.;
+  value.i = 0.;
+
+  if(x>0)
+    {
+      for(i=0; i < x; i++)
+       value = gem_cxmul(value, z);
+      return value;
+    }
+  else
+    { 
+      if(x<0) {
+       for(i=0; i > x; i--)
+         value = gem_cxdiv(value, z);
+       return value;
+      }
+      else {
+       return value;
+      }
+    }
+}
+
+/* Exponential of a complex number-- exp (z)=|exp(z.r)|*{cos(z.i)+I*sin(z.i)}*/
+static gem_complex gem_cxdexp(gem_complex z)
+{
+  gem_complex value;
+  double exp_z_r;
+  exp_z_r = exp(z.r);
+  value.r = exp_z_r*cos(z.i);
+  value.i = exp_z_r*sin(z.i);
+  return value;
+}
+
+/* Logarithm of a complex number -- log(z)=log|z|+I*Arg(z),                  */
+/*                                  where -PI < Arg(z) < PI                  */ 
+static gem_complex gem_cxlog(gem_complex z)
+{
+  gem_complex value;
+  double mag2;
+  mag2 = z.r*z.r+z.i*z.i;
+  if(mag2 < 0.) {
+    fprintf(stderr, "ERROR in gem_cxlog func\n");
+  }
+  value.r = log(sqrt(mag2));
+  if(z.r == 0.) {
+    value.i = PI/2.;
+    if(z.i <0.) {
+      value.i = -value.i;
+    }
+  } else {
+    value.i = atan2(z.i, z.r);
+  }
+  return value;
+}
+
+/* Square root of a complex number z = |z| exp(I*the) -- z^(1/2)             */
+/*                               z^(1/2)=|z|^(1/2)*[cos(the/2)+I*sin(the/2)] */
+/*                               where 0 < the < 2*PI                        */
+static gem_complex gem_cxdsqrt(gem_complex z)
+{
+  gem_complex value;
+  double sq;
+  sq = gem_cx_abs(z);
+  value.r = sqrt(fabs((sq+z.r)*0.5)); /* z'.r={|z|*[1+cos(the)]/2}^(1/2) */
+  value.i = sqrt(fabs((sq-z.r)*0.5)); /* z'.i={|z|*[1-cos(the)]/2}^(1/2) */
+  if(z.i < 0.) {
+    value.r = -value.r;
+  }
+  return value;
+}
+
+/* square root of a real number r  */
+static gem_complex gem_cxrsqrt(double r) {
+  if (r < 0)
+    {
+      return(gem_cmplx(0, sqrt(-r)));
+    }
+  else
+    {
+      return(gem_c(sqrt(r)));
+    }
+}
+
+/* Complex power of a complex number z1^z2                                   */
+static gem_complex gem_cxdpow(gem_complex z1, gem_complex z2)
+{
+  gem_complex value;
+  value=gem_cxdexp(gem_cxmul(gem_cxlog(z1),z2));
+  return value;
+}
+
+/* Print out a complex number z as z: z.r, z.i                               */
+static void gem_cxprintf(gem_complex z) { fprintf(stdout, "z: %lg + %lg_i\n", z.r, z.i); }
+/* ------------ end of complex.c ------------ */
+
+/* This next part was derived from cubic.c, also received from Omer Markovitch.
+ * ------------- from cubic.c ------------- */
+
+/* Solver for a cubic equation: x^3-a*x^2+b*x-c=0                            */
+static void gem_solve(gem_complex *al, gem_complex *be, gem_complex *gam,
+                 double a, double b, double c)
+{
+  double t1, t2, two_3, temp;
+  gem_complex ctemp, ct3;
+  
+  two_3=pow(2., 1./3.); t1 = -a*a+3.*b; t2 = 2.*a*a*a-9.*a*b+27.*c;
+  temp = 4.*t1*t1*t1+t2*t2;
+  
+  ctemp = gem_cmplx(temp,0.);  ctemp = gem_cxadd(gem_cmplx(t2,0.),gem_cxdsqrt(ctemp));
+  ct3 = gem_cxdpow(ctemp, gem_cmplx(1./3.,0.));
+  
+  ctemp = gem_rxcdiv(-two_3*t1/3., ct3);
+  ctemp = gem_cxadd(ctemp, gem_cxrdiv(ct3, 3.*two_3));
+       
+  *gam = gem_cxadd(gem_cmplx(a/3.,0.), ctemp);
+  
+  ctemp=gem_cxmul(gem_cxsq(*gam), gem_cxsq(gem_cxsub(*gam, gem_cmplx(a,0.))));
+  ctemp=gem_cxadd(ctemp, gem_cxmul(gem_cmplx(-4.*c,0.), *gam));
+  ctemp = gem_cxdiv(gem_cxdsqrt(ctemp), *gam);
+  *al = gem_cxrmul(gem_cxsub(gem_cxsub(gem_cmplx(a,0.), *gam),ctemp),0.5);
+  *be = gem_cxrmul(gem_cxadd(gem_cxsub(gem_cmplx(a,0.), *gam),ctemp),0.5);
+}
+
+/* ------------ end of cubic.c ------------ */
+
+/* This next part was derived from cerror.c and rerror.c, also received from Omer Markovitch.
+ * ------------- from [cr]error.c ------------- */
+
+/************************************************************/
+/* Real valued error function and related functions         */
+/* x, y     : real variables                                */
+/* erf(x)   : error function                                */
+/* erfc(x)  : complementary error function                  */
+/* omega(x) : exp(x*x)*erfc(x)                              */
+/* W(x,y)   : exp(-x*x)*omega(x+y)=exp(2*x*y+y^2)*erfc(x+y) */
+/************************************************************/
+
+/*---------------------------------------------------------------------------*/
+/* Utilzed the series approximation of erf(x)                                */
+/* Relative error=|err(x)|/erf(x)<EPS                                        */
+/* Handbook of Mathematical functions, Abramowitz, p 297                     */
+/* Note: When x>=6 series sum deteriorates -> Asymptotic series used instead */
+/*---------------------------------------------------------------------------*/
+/*  This gives erfc(z) correctly only upto >10-15 */
+
+static double gem_erf(double x)
+{
+  double n,sum,temp,exp2,xm,x2,x4,x6,x8,x10,x12;
+  temp = x;
+  sum  = temp;
+  xm   = 26.;
+  x2   = x*x;
+  x4   = x2*x2;
+  x6   = x4*x2;
+  x8   = x6*x2;
+  x10  = x8*x2;
+  x12 = x10*x2;
+  exp2 = exp(-x2);
+  if(x <= xm)
+    {
+      for(n=1.; n<=2000.; n+=1.){
+       temp *= 2.*x2/(2.*n+1.);
+       sum  += temp;
+       if(fabs(temp/sum)<1.E-16)
+         break;
+      }
+      
+      if(n >= 2000.)
+       fprintf(stderr, "In Erf calc - iteration exceeds %lg\n",n);
+      sum *= 2./sPI*exp2;
+    }
+  else
+    {
+      /* from the asymptotic expansion of experfc(x) */
+      sum = (1. - 0.5/x2 + 0.75/x4
+            - 1.875/x6 + 6.5625/x8
+            - 29.53125/x10 + 162.421875/x12)
+       / sPI/x;
+      sum*=exp2; /* now sum is erfc(x) */
+      sum=-sum+1.;
+    }
+  return x>=0.0 ? sum : -sum;
+}
+
+/* Result --> Alex's code for erfc and experfc behaves better than this      */
+/* complementray error function.                Returns 1.-erf(x)            */
+static double gem_erfc(double x)
+{
+  double t,z,ans;
+  z = fabs(x);
+  t = 1.0/(1.0+0.5*z);
+  
+  ans = t * exp(-z*z - 1.26551223 +
+               t*(1.00002368 +
+                  t*(0.37409196 +
+                     t*(0.09678418 +
+                        t*(-0.18628806 +
+                           t*(0.27886807 +
+                              t*(-1.13520398 +
+                                 t*(1.48851587 +
+                                    t*(-0.82215223 +
+                                       t*0.17087277)))))))));
+       
+  return  x>=0.0 ? ans : 2.0-ans;
+}
+
+/* omega(x)=exp(x^2)erfc(x)                                                  */
+static double gem_omega(double x)
+{
+  double xm, ans, xx, x4, x6, x8, x10, x12;
+  xm = 26;
+  xx=x*x;
+  x4=xx*xx;
+  x6=x4*xx;
+  x8=x6*xx;
+  x10=x8*xx;
+  x12=x10*xx;
+
+  if(x <= xm) {
+    ans = exp(xx)*gem_erfc(x);
+  } else {
+    /* Asymptotic expansion */
+    ans = (1. - 0.5/xx + 0.75/x4 - 1.875/x6 + 6.5625/x8 - 29.53125/x10 + 162.421875/x12) / sPI/x;
+  }
+  return ans;
+}
+
+/* W(x,y)=exp(-x^2)*omega(x+y)=exp(2xy+y^2)*erfc(x+y)                        */
+static double gem_W(double x, double y){ return(exp(-x*x)*gem_omega(x+y)); }
+
+/**************************************************************/
+/* Complex error function and related functions               */
+/* x, y     : real variables                                  */
+/* z        : complex variable                                */
+/* cerf(z)  : error function                                  */
+/* comega(z): exp(z*z)*cerfc(z)                               */
+/* W(x,z)   : exp(-x*x)*comega(x+z)=exp(2*x*z+z^2)*cerfc(x+z) */
+/**************************************************************/
+static gem_complex gem_cerf(gem_complex z)
+{
+  gem_complex value;
+  double x,y;
+  double sumr,sumi,n,n2,f,temp,temp1;
+  double x2,cos_2xy,sin_2xy,cosh_2xy,sinh_2xy,cosh_ny,sinh_ny;
+
+  x    = z.r;
+  y    = z.i;
+  x2   = x*x;
+  sumr = 0.;
+  sumi = 0.;
+  cos_2xy  = cos(2.*x*y);
+  sin_2xy  = sin(2.*x*y);
+  cosh_2xy = cosh(2.*x*y);
+  sinh_2xy = sinh(2.*x*y);
+
+  for(n=1.0,temp=0.; n<=2000.; n+=1.0)
+    {
+      n2      = n*n;
+      cosh_ny = cosh(n*y);
+      sinh_ny = sinh(n*y);
+      f       = exp(-n2/4.)/(n2+4.*x2);
+      sumr    += (2.*x - 2.*x*cosh_ny*cos_2xy+n*sinh_ny*sin_2xy)*f;
+      sumi    += (2.*x*cosh_ny*sin_2xy + n*sinh_ny*cos_2xy)*f;
+      temp1    = sqrt(sumr*sumr+sumi*sumi);
+      if(fabs((temp1-temp)/temp1)<1.E-16) {
+       break;
+      }
+      temp = temp1;
+    }
+
+  if(n==2000.) {
+    fprintf(stderr, "iteration exceeds %lg\n",n);
+  }
+  
+  sumr*=2./PI;
+  sumi*=2./PI;
+
+  if(x!=0.) {
+    f = 1./2./PI/x;
+  } else {
+    f = 0.;
+  }
+  value.r = gem_erf(x) + (f*(1.-cos_2xy) + sumr)*exp(-x2);
+  value.i = (f*sin_2xy+sumi)*exp(-x2);
+  return value;
+}
+
+/*---------------------------------------------------------------------------*/
+/* Utilzed the series approximation of erf(z=x+iy)                           */
+/* Relative error=|err(z)|/|erf(z)|<EPS                                      */
+/* Handbook of Mathematical functions, Abramowitz, p 299                     */
+/* comega(z=x+iy)=cexp(z^2)*cerfc(z)                                         */
+/*---------------------------------------------------------------------------*/
+static gem_complex gem_comega(gem_complex z)
+{
+  gem_complex value;
+  double x,y;
+  double sumr,sumi,n,n2,f,temp,temp1;
+  double x2, y2,cos_2xy,sin_2xy,cosh_2xy,sinh_2xy,cosh_ny,sinh_ny,exp_y2;
+
+  x        = z.r;
+  y        = z.i;
+  x2       = x*x;
+  y2       = y*y;
+  sumr     = 0.;
+  sumi     = 0.;
+  cos_2xy  = cos(2.*x*y);
+  sin_2xy  = sin(2.*x*y);
+  cosh_2xy = cosh(2.*x*y);
+  sinh_2xy = sinh(2.*x*y);
+  exp_y2   = exp(-y2);
+
+  for(n=1.0, temp=0.; n<=2000.; n+=1.0){
+    n2      = n*n;
+    cosh_ny = cosh(n*y);
+    sinh_ny = sinh(n*y);
+    f       = exp(-n2/4.)/(n2+4.*x2);
+    /* if(f<1.E-200) break; */
+    sumr += (2.*x - 2.*x*cosh_ny*cos_2xy + n*sinh_ny*sin_2xy)*f;
+    sumi += (2.*x*cosh_ny*sin_2xy + n*sinh_ny*cos_2xy)*f;
+    temp1 = sqrt(sumr*sumr+sumi*sumi);
+    if(fabs((temp1-temp)/temp1)<1.E-16) {
+      break;
+    }
+    temp=temp1;
+  }
+  if(n==2000.) {
+    fprintf(stderr, "iteration exceeds %lg\n",n);
+  }
+  sumr *= 2./PI;
+  sumi *= 2./PI;
+
+  if(x!=0.) {
+    f = 1./2./PI/x;
+  } else {
+    f = 0.;
+  }
+  value.r = gem_omega(x)-(f*(1.-cos_2xy)+sumr);
+  value.i = -(f*sin_2xy+sumi);
+  value   = gem_cxmul(value,gem_cmplx(exp_y2*cos_2xy,exp_y2*sin_2xy));
+  return (value);
+}
+
+/* W(x,z) exp(-x^2)*omega(x+z)                                               */
+static gem_complex gem_cW(double x, gem_complex z){ return(gem_cxrmul(gem_comega(gem_cxradd(z,x)),exp(-x*x))); }
+
+/* ------------ end of [cr]error.c ------------ */
+
+/*_ REVERSIBLE GEMINATE RECOMBINATION
+ *
+ * Here are the functions for reversible geminate recombination. */
+
+/* Changes the unit from square cm per s to square Ångström per ps,
+ * since Omers code uses the latter units while g_mds outputs the former.
+ * g_hbond expects a diffusion coefficent given in square cm per s. */
+static double sqcm_per_s_to_sqA_per_ps (real D) {
+  fprintf(stdout, "Diffusion coefficient is %f A^2/ps\n", D*1e4);
+  return (double)(D*1e4);
+}
+
+
+static double eq10v2(double theoryCt[], double time[], int manytimes,
+                    double ka, double kd, t_gemParams *params)
+{
+  /* Finding the 3 roots */
+  int i;
+  double kD, D, r, a, b, c, tsqrt, sumimaginary;
+  gem_complex
+    alpha, beta, gamma,
+    c1, c2, c3, c4,
+    oma, omb, omc,
+    part1, part2, part3, part4;
+
+  kD = params->kD;
+  D  = params->D;
+  r  = params->sigma;
+  a = (1.0 + ka/kD) * sqrt(D)/r;
+  b = kd;
+  c = kd * sqrt(D)/r;
+
+  gem_solve(&alpha, &beta, &gamma, a, b, c);
+  /* Finding the 3 roots */
+
+  sumimaginary = 0;
+  part1 = gem_cxmul(alpha, gem_cxmul(gem_cxadd(beta,  gamma), gem_cxsub(beta,  gamma))); /* 1(2+3)(2-3) */
+  part2 = gem_cxmul(beta,  gem_cxmul(gem_cxadd(gamma, alpha), gem_cxsub(gamma, alpha))); /* 2(3+1)(3-1) */
+  part3 = gem_cxmul(gamma, gem_cxmul(gem_cxadd(alpha, beta) , gem_cxsub(alpha, beta)));  /* 3(1+2)(1-2) */
+  part4 = gem_cxmul(gem_cxsub(gamma, alpha), gem_cxmul(gem_cxsub(alpha, beta), gem_cxsub(beta, gamma))); /* (3-1)(1-2)(2-3) */
+
+#ifdef HAVE_OPENMP
+#pragma omp parallel for                               \
+  private(i, tsqrt, oma, omb, omc, c1, c2, c3, c4),    \
+  reduction(+:sumimaginary),                           \
+  default(shared),                                     \
+  schedule(guided)
+#endif
+  for (i=0; i<manytimes; i++){
+    tsqrt = sqrt(time[i]);
+    oma   = gem_comega(gem_cxrmul(alpha, tsqrt));
+    c1    = gem_cxmul(oma, gem_cxdiv(part1, part4));
+    omb   = gem_comega(gem_cxrmul(beta, tsqrt));
+    c2    = gem_cxmul(omb, gem_cxdiv(part2, part4));
+    omc   = gem_comega(gem_cxrmul(gamma, tsqrt));
+    c3    = gem_cxmul(omc, gem_cxdiv(part3, part4));
+    c4.r  = c1.r+c2.r+c3.r;
+    c4.i  = c1.i+c2.i+c3.i;
+    theoryCt[i]  = c4.r;
+    sumimaginary += c4.i * c4.i;
+  }
+
+  return sumimaginary;
+
+} /* eq10v2 */
+
+/* This returns the real-valued index(!) to an ACF, equidistant on a log scale. */
+static double getLogIndex(const int i, const t_gemParams *params)
+{
+  return (exp(((double)(i)) * params->logQuota) -1);
+}
+
+extern t_gemParams *init_gemParams(const double sigma, const double D,
+                                  const real *t, const int len, const int nFitPoints,
+                                  const real begFit, const real endFit,
+                                  const real ballistic, const int nBalExp, const bool bDt)
+{
+  double tDelta;
+  t_gemParams *p;
+
+  snew(p,1);
+
+  /* A few hardcoded things here. For now anyway. */
+/*   p->ka_min   = 0; */
+/*   p->ka_max   = 100; */
+/*   p->dka      = 10; */
+/*   p->kd_min   = 0; */
+/*   p->kd_max   = 2; */
+/*   p->dkd      = 0.2; */
+  p->ka       = 0;
+  p->kd       = 0;
+/*   p->lsq      = -1; */
+/*   p->lifetime = 0; */
+  p->sigma    = sigma*10; /* Omer uses Å, not nm */
+/*   p->lsq_old  = 99999; */
+  p->D        = sqcm_per_s_to_sqA_per_ps(D);
+  p->kD       = 4*acos(-1.0)*sigma*p->D;
+
+
+  /* Parameters used by calcsquare(). Better to calculate them
+   * here than in calcsquare every time it's called. */
+  p->len = len;
+/*   p->logAfterTime = logAfterTime; */
+  tDelta       = (t[len-1]-t[0]) / len;
+  if (tDelta <= 0) {
+    gmx_fatal(FARGS, "Time between frames is non-positive!");
+  } else {
+    p->tDelta = tDelta;
+  }
+
+  p->nExpFit      = nBalExp;
+/*   p->nLin         = logAfterTime / tDelta; */
+  p->nFitPoints   = nFitPoints;
+  p->begFit       = begFit;
+  p->endFit       = endFit;
+  p->logQuota     = (double)(log(p->len))/(p->nFitPoints-1);
+/*   if (p->nLin <= 0) { */
+/*     fprintf(stderr, "Number of data points in the linear regime is non-positive!\n"); */
+/*     sfree(p); */
+/*     return NULL; */
+/*   } */
+  /* We want the same number of data points in the log regime. Not crucial, but seems like a good idea. */
+  /* p->logDelta = log(((float)len)/p->nFitPoints) / p->nFitPoints;/\* log(((float)len)/p->nLin) / p->nLin; *\/ */
+/*   p->logPF    = p->nFitPoints*p->nFitPoints/(float)len; /\* p->nLin*p->nLin/(float)len; *\/ */
+  /* logPF and logDelta are stitched together with the macro GETLOGINDEX defined in geminate.h */
+  
+/*   p->logMult      = pow((float)len, 1.0/nLin);/\* pow(t[len-1]-t[0], 1.0/p->nLin); *\/ */
+  p->ballistic    =  ballistic;
+  p->bDt;
+  return p;
+}
+
+/* There was a misunderstanding regarding the fitting. From our
+ * recent correspondence it appears that Omer's code require
+ * the ACF data on a log-scale and does not operate on the raw data.
+ * This needs to be redone in gemFunc_residual() as well as in the
+ * t_gemParams structure. */
+#ifdef HAVE_LIBGSL
+static double gemFunc_residual2(const gsl_vector *p, void *data)
+{
+  gemFitData *GD;
+  int i, iLog, nLin, nFitPoints, nData;
+  double r, residual2, *ctTheory, *y;
+
+  GD         = (gemFitData *)data;
+  nLin       = GD->params->nLin;
+  nFitPoints = GD->params->nFitPoints;
+  nData      = GD->nData;
+  residual2  = 0;
+  ctTheory  = GD->ctTheory;
+  y         = GD->y;
+
+  /* Now, we'd save a lot of time by not calculating eq10v2 for all
+   * time points, but only those that we sample to calculate the mse.
+   */
+
+  eq10v2(GD->ctTheory, GD->doubleLogTime/* GD->time */, nFitPoints/* GD->nData */,
+        gsl_vector_get(p, 0), gsl_vector_get(p, 1),
+        GD->params);
+  
+  /* Removing a bunch of points from the log-part. */
+#ifdef HAVE_OPENMP
+#pragma omp parallel for schedule(dynamic)     \
+  firstprivate(nData, ctTheory, y, nFitPoints) \
+  private (i, iLog, r)                 \
+  reduction(+:residual2)                       \
+  default(shared)
+#endif
+  for(i=0; i<nFitPoints; i++)
+    {
+      iLog = GD->logtime[i];
+      r = log(ctTheory[i /* iLog */]);
+      residual2 += sqr(r-log(y[iLog]));
+    }
+  residual2 /= nFitPoints; /* Not really necessary for the fitting, but gives more meaning to the returned data. */
+  /* printf("ka=%3.5f\tkd=%3.5f\trmse=%3.5f\n", gsl_vector_get(p,0), gsl_vector_get(p,1), residual2); */
+  return residual2;
+
+/*   for (i=0; i<nLin; i++) { */
+/*     /\* Linear part ----------*\/ */
+/*     r = ctTheory[i]; */
+/*     residual2 += sqr(r-y[i]); */
+/*     /\* Log part -------------*\/ */
+/*     iLog = GETLOGINDEX(i, GD->params); */
+/*     if (iLog >= nData) */
+/*       gmx_fatal(FARGS, "log index out of bounds: %i", iLog); */
+/*     r = ctTheory[iLog]; */
+/*     residual2 += sqr(r-y[iLog]); */
+
+/*   } */
+/*   residual2 /= GD->n; */
+/*   return residual2; */
+}
+#endif
+
+static real* d2r(const double *d, const int nn);
+
+extern real fitGemRecomb(double *ct, double *time, double **ctFit,
+                       const int nData, t_gemParams *params)
+{
+
+  int    nThreads, i, iter, status, maxiter;
+  real   size, d2, tol, *dumpdata;
+  size_t p, n;
+  gemFitData *GD;
+  char *dumpstr, dumpname[128];
+
+  /* nmsimplex2 had convergence problems prior to gsl v1.14,
+   * but it's O(N) instead of O(N) operations, so let's use it if v >= 1.14 */
+#ifdef HAVE_LIBGSL
+  gsl_multimin_fminimizer *s;
+  gsl_vector *x,*dx;             /* parameters and initial step size */
+  gsl_multimin_function fitFunc;
+#ifdef GSL_MAJOR_VERSION
+#ifdef GSL_MINOR_VERSION
+#if ((GSL_MAJOR_VERSION == 1 && GSL_MINOR_VERSION >= 14) || \
+  (GSL_MAJOR_VERSION > 1))
+    const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex2;
+#else
+  const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
+#endif /* #if ... */
+#endif /* GSL_MINOR_VERSION */
+#else
+  const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex;
+#endif /* GSL_MAJOR_VERSION */
+  fprintf(stdout, "Will fit ka and kd to the ACF according to the reversible geminate recombination model.\n");
+#else  /* HAVE_LIBGSL */
+  fprintf(stderr, "Sorry, can't do reversible geminate recombination without gsl. "
+        "Recompile using --with-gsl.\n");
+  return -1;
+#endif /* HAVE_LIBGSL */
+
+#ifdef HAVE_LIBGSL
+#ifdef HAVE_OPENMP
+  nThreads = omp_get_num_procs();
+  omp_set_num_threads(nThreads);
+  fprintf(stdout, "We will be using %i threads.\n", nThreads);
+#endif
+
+  iter    = 0;
+  status  = 0;
+  maxiter = 100;
+  tol     = 1e-10;
+
+  p = 2;                  /* Number of parameters to fit. ka and kd.  */
+  n = params->nFitPoints; /* params->nLin*2 */;       /* Number of points in the reduced dataset  */
+
+  if (params->D <= 0)
+    {
+      fprintf(stderr, "Fitting of D is not implemented yet. It must be provided on the command line.\n");
+      return -1;
+    }
+  
+/*   if (nData<n) { */
+/*     fprintf(stderr, "Reduced data set larger than the complete data set!\n"); */
+/*     n=nData; */
+/*   } */
+  snew(dumpdata, nData);
+  snew(GD,1);
+
+  GD->n = n;
+  GD->y = ct;
+  GD->ctTheory=NULL;
+  snew(GD->ctTheory, nData);
+  GD->LinLog=NULL;
+  snew(GD->LinLog, n);
+  GD->time = time;
+  GD->ka = 0;
+  GD->kd = 0;
+  GD->tDelta = time[1]-time[0];
+  GD->nData = nData;
+  GD->params = params;
+  snew(GD->logtime,params->nFitPoints);
+  snew(GD->doubleLogTime,params->nFitPoints);
+
+  for (i=0; i<params->nFitPoints; i++)
+    {
+      GD->doubleLogTime[i] = (double)(getLogIndex(i, params));
+      GD->logtime[i] = (int)(GD->doubleLogTime[i]);
+      GD->doubleLogTime[i]*=GD->tDelta;
+
+      if (GD->logtime[i] >= nData)
+       {
+         fprintf(stderr, "Ayay. It seems we're indexing out of bounds.\n");
+         params->nFitPoints = i;
+       }      
+    }
+
+  fitFunc.f = &gemFunc_residual2;
+  fitFunc.n = 2;
+  fitFunc.params = (void*)GD;
+
+  x  = gsl_vector_alloc (fitFunc.n);
+  dx = gsl_vector_alloc (fitFunc.n);
+  gsl_vector_set (x,  0, 25);
+  gsl_vector_set (x,  1, 0.5);
+  gsl_vector_set (dx, 0, 0.1);
+  gsl_vector_set (dx, 1, 0.01);
+  
+  
+  s = gsl_multimin_fminimizer_alloc (T, fitFunc.n);
+  gsl_multimin_fminimizer_set (s, &fitFunc, x, dx);
+  gsl_vector_free (x);
+  gsl_vector_free (dx);
+
+  do  {
+    iter++;
+    status = gsl_multimin_fminimizer_iterate (s);
+    
+    if (status != 0)
+      gmx_fatal(FARGS,"Something went wrong in the iteration in minimizer %s:\n \"%s\"\n",
+               gsl_multimin_fminimizer_name(s), gsl_strerror(status));
+    
+    d2     = gsl_multimin_fminimizer_minimum(s);
+    size   = gsl_multimin_fminimizer_size(s);
+    params->ka = gsl_vector_get (s->x, 0);
+    params->kd = gsl_vector_get (s->x, 1);
+    
+    if (status)
+      {
+       fprintf(stderr, "%s\n", gsl_strerror(status));
+       break;
+      }
+
+    status = gsl_multimin_test_size(size,tol);
+
+    if (status == GSL_SUCCESS) {
+      fprintf(stdout, "Converged to minimum at\n");
+    }
+
+    printf ("iter %5d: ka = %2.5f  kd = %2.5f  f() = %7.3f  size = %.3f  chi2 = %2.5f\n",
+           iter,
+           params->ka,
+           params->kd,
+           s->fval, size, d2);
+
+    if (iter%10 == 1)
+      {
+       eq10v2(GD->ctTheory, time, nData, params->ka, params->kd, params);
+       sprintf(dumpname, "Iter_%i.xvg", iter);
+       for(i=0; i<GD->nData; i++)
+         dumpdata[i] = (real)(GD->ctTheory[i]);
+       dumpN(dumpdata, GD->nData, dumpname);
+      }
+  }
+  while ((status == GSL_CONTINUE) && (iter < maxiter));
+
+  /*   /\* Calculate the theoretical ACF from the parameters one last time. *\/ */
+  eq10v2(GD->ctTheory, time, nData, params->ka, params->kd, params);
+  *ctFit = GD->ctTheory;
+
+  sfree(GD);
+  gsl_multimin_fminimizer_free (s);
+
+
+  return d2;
+
+#endif /* HAVE_LIBGSL */
+}
+
+#ifdef HAVE_LIBGSL
+static int balFunc_f(const gsl_vector *x, void *data, gsl_vector *f)
+{
+  /* C + sum{ A_i * exp(-B_i * t) }*/
+
+  balData *BD;
+  int n, i,j, nexp;
+  double *y, *A, *B, C,        /* There are the parameters to be optimized. */
+    t, ct;
+
+  BD   = (balData *)data;
+  n    = BD->n;
+  nexp = BD->nexp;
+  y    = BD->y,
+  snew(A, nexp);
+  snew(B, nexp);
+  
+  for (i = 0; i<nexp; i++)
+    {
+      A[i] = gsl_vector_get(x, i*2);
+      B[i] = gsl_vector_get(x, i*2+1);
+    }
+  C = gsl_vector_get(x, nexp*2);
+
+  for (i=0; i<n; i++)
+    {
+      t = i*BD->tDelta;
+      ct = 0;
+      for (j=0; j<nexp; j++) {
+       ct += A[j] * exp(B[j] * t);
+      }
+      ct += C;
+      gsl_vector_set (f, i, ct - y[i]);
+    }
+  return GSL_SUCCESS;
+}
+
+/* The derivative stored in jacobian form (J)*/
+static int balFunc_df(const gsl_vector *params, void *data, gsl_matrix *J)
+{
+  balData *BD;
+  size_t n,i,j;
+  double *y, *A, *B, C, /* There are the parameters. */
+    t;
+  int nexp;
+
+  BD   = (balData*)data;
+  n    = BD->n;
+  y    = BD->y;
+  nexp = BD->nexp;
+
+  snew(A, nexp);
+  snew(B, nexp);
+
+  for (i=0; i<nexp; i++)
+    {
+      A[i] = gsl_vector_get(params, i*2);
+      B[i] = gsl_vector_get(params, i*2+1);
+    }
+  C = gsl_vector_get(params, nexp*2);
+  for (i=0; i<n; i++)
+    {
+      t = i*BD->tDelta;
+      for (j=0; j<nexp; j++)
+       {
+         gsl_matrix_set (J, i, j*2,   exp(B[j]*t));        /* df(t)/dA_j */
+         gsl_matrix_set (J, i, j*2+1, A[j]*t*exp(B[j]*t)); /* df(t)/dB_j */
+       }
+      gsl_matrix_set (J, i, nexp*2, 1); /* df(t)/dC */
+    }
+  return GSL_SUCCESS;
+}
+
+/* Calculation of the function and its derivative */
+static int balFunc_fdf(const gsl_vector *params, void *data,
+                      gsl_vector *f, gsl_matrix *J)
+{
+  balFunc_f(params, data, f);
+  balFunc_df(params, data, J);
+  return GSL_SUCCESS;
+}
+#endif /* HAVE_LIBGSL */
+
+/* Removes the ballistic term from the beginning of the ACF,
+ * just like in Omer's paper.
+ */
+extern void takeAwayBallistic(double *ct, double *t, int len, real tMax, int nexp, bool bDerivative)
+{
+
+  /* Use nonlinear regression with GSL instead.
+   * Fit with 4 exponentials and one constant term,
+   * subtract the fatest exponential. */
+
+  int nData,i,status, iter;
+  balData *BD;
+  double *guess,              /* Initial guess. */
+    *A,                       /* The fitted parameters. (A1, B1, A2, B2,... C) */
+    a[2],
+    ddt[2];
+  bool sorted;
+  size_t n;
+  size_t p;
+
+  nData = 0;
+  do {
+    nData++;
+  } while (t[nData]<tMax+t[0] && nData<len);
+
+  p = nexp*2+1;              /* Number of parameters. */
+
+#ifdef HAVE_LIBGSL
+  const gsl_multifit_fdfsolver_type *T
+    = gsl_multifit_fdfsolver_lmsder;
+
+  gsl_multifit_fdfsolver *s;              /* The solver itself. */
+  gsl_multifit_function_fdf fitFunction;  /* The function to be fitted. */
+  gsl_matrix *covar;  /* Covariance matrix for the parameters.
+                      * We'll not use the result, though. */
+  gsl_vector_view theParams;
+
+  nData = 0;
+  do {
+    nData++;
+  } while (t[nData]<tMax+t[0] && nData<len);
+
+  guess = NULL;
+  n = nData;
+
+  snew(guess, p);
+  snew(A, p);
+  covar = gsl_matrix_alloc (p, p);
+
+  /* Set up an initial gess for the parameters.
+   * The solver is somewhat sensitive to the initial guess,
+   * but this worked fine for a TIP3P box with -geminate dd
+   * EDIT: In fact, this seems like a good starting pont for other watermodels too. */
+  for (i=0; i<nexp; i++)
+    {
+      guess[i*2] = 0.1;
+      guess[i*2+1] = -0.5 + (((double)i)/nexp - 0.5)*0.3;
+    }
+  guess[nexp * 2] = 0.01;
+
+  theParams = gsl_vector_view_array(guess, p);
+
+  snew(BD,1);
+  BD->n     = n;
+  BD->y     = ct;
+  BD->tDelta = t[1]-t[0];
+  BD->nexp = nexp;
+
+  fitFunction.f      =  &balFunc_f;
+  fitFunction.df     =  &balFunc_df;
+  fitFunction.fdf    =  &balFunc_fdf;
+  fitFunction.n      =  nData;
+  fitFunction.p      =  p;
+  fitFunction.params =  BD;
+
+  s = gsl_multifit_fdfsolver_alloc (T, nData, p);
+  if (s==NULL)
+    gmx_fatal(FARGS, "Could not set up the nonlinear solver.");
+
+  gsl_multifit_fdfsolver_set(s, &fitFunction, &theParams.vector);
+
+  /* \=============================================/ */
+
+  iter = 0;
+  do
+    {
+      iter++;
+      status = gsl_multifit_fdfsolver_iterate (s);
+      
+      if (status)
+       break;
+      status = gsl_multifit_test_delta (s->dx, s->x, 1e-4, 1e-4);
+    }
+  while (iter < 5000 && status == GSL_CONTINUE);
+
+  if (iter == 5000)
+    {
+      fprintf(stderr, "The non-linear fitting did not converge in 5000 steps.\n"
+            "Check the quality of the fit!\n");
+    }
+  else
+    {
+      fprintf(stderr, "Non-linear fitting of ballistic term converged in %d steps.\n\n", (int)iter);
+    }
+  for (i=0; i<nexp; i++) {
+    fprintf(stdout, "%c * exp(%c * t) + ", 'A'+(char)i*2, 'B'+(char)i*2);
+  }
+
+  fprintf(stdout, "%c\n", 'A'+(char)nexp*2);
+  fprintf(stdout, "Here are the actual numbers for A-%c:\n", 'A'+nexp*2);
+
+  for (i=0; i<nexp; i++)
+    {
+      A[i*2]  = gsl_vector_get(s->x, i*2);
+      A[i*2+1] = gsl_vector_get(s->x, i*2+1);
+      fprintf(stdout, " %g*exp(%g * x) +", A[i*2], A[i*2+1]);
+    }
+  A[i*2] = gsl_vector_get(s->x, i*2);          /* The last and constant term */
+  fprintf(stdout, " %g\n", A[i*2]);
+
+  fflush(stdout);
+
+  /* Implement some check for parameter quality */
+  for (i=0; i<nexp; i++)
+    {
+      if (A[i*2]<0 || A[i*2]>1) {
+       fprintf(stderr, "WARNING: ----------------------------------\n"
+              " | A coefficient does not lie within [0,1].\n"
+              " | This may or may not be a problem.\n"
+              " | Double check the quality of the fit!\n");
+      }
+      if (A[i*2+1]>0) {
+       fprintf(stderr, "WARNING: ----------------------------------\n"
+              " | One factor in the exponent is positive.\n"
+              " | This could be a problem if the coefficient\n"
+              " | is large. Double check the quality of the fit!\n");
+      }
+    }
+  if (A[i*2]<0 || A[i*2]>1) {
+    fprintf(stderr, "WARNING: ----------------------------------\n"
+          " | The constant term does not lie within [0,1].\n"
+          " | This may or may not be a problem.\n"
+          " | Double check the quality of the fit!\n");
+  }
+
+  /* Sort the terms */
+  sorted = (nexp > 1) ?  FALSE : TRUE;
+  while (!sorted)
+    {
+      sorted = TRUE;
+      for (i=0;i<nexp-1;i++)
+       {
+         ddt[0] = A[i*2] * A[i*2+1];
+         ddt[1] =A[i*2+2] * A[i*2+3];
+         
+         if ((bDerivative && (ddt[0]<0 && ddt[1]<0 && ddt[0]>ddt[1])) || /* Compare derivative at t=0... */
+             (!bDerivative && (A[i*2+1] > A[i*2+3])))                    /* Or just the coefficient in the exponent */
+           {
+             sorted = FALSE;
+             a[0] = A[i*2];  /* coefficient */
+             a[1] = A[i*2+1]; /* parameter in the exponent */
+             
+             A[i*2] = A[i*2+2];
+             A[i*2+1] = A[i*2+3];
+             
+             A[i*2+2] = a[0];
+             A[i*2+3] = a[1];
+           }
+       }
+    }
+
+  /* Subtract the fastest component */
+  fprintf(stdout, "Fastest component is %g * exp(%g * t)\n"
+        "Subtracting fastest component from ACF.\n", A[0], A[1]);
+
+  for (i=0; i<len; i++) {
+    ct[i] = (ct[i] - A[0] * exp(A[1] * i*BD->tDelta)) / (1-A[0]);
+  }
+
+  sfree(guess);
+  sfree(A);
+
+  gsl_multifit_fdfsolver_free(s);
+  gsl_matrix_free(covar);
+  fflush(stdout);
+
+#else
+  /* We have no gsl. */
+  fprintf(stderr, "Sorry, can't take away ballistic component without gsl. "
+        "Recompile using --with-gsl.\n");
+  return;
+#endif /* HAVE_LIBGSL */
+
+}
+
+extern void dumpN(const real *e, const int nn, char *fn)
+{
+  /* For debugging only */
+  int i;
+  FILE *f;
+  char standardName[] = "Nt.xvg";
+  if (fn == NULL) {
+    fn = standardName;
+  }
+
+  f = fopen(fn, "w");
+  fprintf(f,
+         "@ type XY\n"
+         "@ xaxis label \"Frame\"\n"
+         "@ yaxis label \"N\"\n"
+         "@ s0 line type 3\n");
+
+  for (i=0; i<nn; i++) {
+    fprintf(f, "%-10i %-g\n", i, e[i]);
+  }
+
+  fclose(f);
+}
+
+static real* d2r(const double *d, const int nn)
+{
+  real *r;
+  int i;
+  
+  snew(r, nn);
+  for (i=0; i<nn; i++)
+    r[i] = (real)d[i];
+
+  return r;
+}
diff --git a/src/tools/geminate.h b/src/tools/geminate.h
new file mode 100644 (file)
index 0000000..3b33cee
--- /dev/null
@@ -0,0 +1,140 @@
+#ifndef _GEMINATE_H
+#define _GEMINATE_H
+
+enum { gemNULL, gemNONE, gemDD, gemAD, gemAA, gemA4, gemNR};
+static const char *gemType[] = {NULL, "none", "dd", "ad", "aa", "a4", NULL};
+
+/* The first few sections of this file contain functions that were adopted,
+ * and to some extent modified, by Erik Marklund (erikm[aT]xray.bmc.uu.se,
+ * http://folding.bmc.uu.se) from code written by Omer Markovitch (email, url).
+ * This is also the case with the function eq10v2() in geminate.c.
+ * 
+ * The parts menetioned in the previous paragraph were contributed under a BSD license.
+ */
+
+/* This first part is derived from complex.c which I recieved from Omer Markowitch.
+ * - Erik Marklund
+ *
+ * ------------- from complex.c ------------- */
+
+#include <math.h>
+/* definition of PI */
+#ifndef PI
+#define PI (acos(-1.0))
+#endif
+
+/* definition of the type complex */
+typedef struct
+{
+  double r,i;
+} gem_complex;
+
+
+/* ------------ end of complex.c ------------ */
+
+/* This next part was derived from cerror.c and rerror.c,
+ * also received from Omer Markovitch.
+ * ------------- from [cr]error.c ------------- */
+
+#ifndef sPI
+#define sPI (sqrt(PI))
+#endif
+
+/* ------------ end of [cr]error.c ------------ */
+
+/* ///////////////// REVERSIBLE GEMINATE RECOMBINATION ///////////////////
+ * Here follow routines and structs for reversible geminate recombination.
+ */
+
+typedef struct{
+  size_t n;
+  double *y;
+  double tDelta;
+  int nexp;
+} balData;
+
+
+typedef struct {
+  /* Used in the rewritten version of Omer's gem. recomb. analysis */
+  double ka, kd;                 /* -- || -- results[]  */
+  double sigma;                  /* -- || -- sigma      */
+  double D;                      /* The diffusion coefficient */
+  double kD;                     /* Replaces kD in analyse_corr_gem3d() */
+
+  /* The following members are for calcsquare() and takeAwayBallistic() */
+  double tDelta;              /* Time between frames */
+  /* double logAfterTime;        /\* Time after which we do the lsq calculations on a logarithmic timescale. *\/ */
+  int nFitPoints;             /* Number of points to take from the ACF for fitting */
+  double begFit;              /* Fit from this time (ps) */
+  double endFit;              /* Fit up to this time (ps) */
+/*   double logDelta; */
+/*   double logPF; */
+  /* To get an equal number of points in the lin and log regime,
+   * we'll use logDelta to calculate where to sample the ACF.
+   * if i and j are indices in the linear and log regime, then:
+   *   j = Cexp(A(i+nLin)),
+   * where C = (nLin**2 / len) and A = log(len/nLin) / nLin.
+   * This expands to j = (nLin**2 / len) * exp((i+nLin) * log(len/nLin) / nLin).
+   * We'll save part of our brains and some computing time if we pre-calculate
+   *  1) logDelta = log(len/nLin) / nLin
+   *  2) logPF    = nLin**2 / len
+   * and get j = logPF * exp((i+nLin) * logDelta). */
+
+  /* I will redo this for a fit done entirely in log-log.
+   *  j' = j+1
+   *  nFitPoints' = nFitPoints-1
+   *  
+   *  j' = Cexp(Ai)
+   *  (j'= 1 <=> i=0)
+   *     => C=1
+   *  (j'=len <=> i=nFitPoints')
+   *     => A=log(len)/nFitPoints'
+   *     => j = exp(i*log(len)/(nFitPoints-1)) -1
+   **/
+/* #define GETLOGINDEX(i,params) (params)->logPF * exp(((i)+(params)->nLin) * (params)->logDelta)
+ */
+  double logQuota;
+  int nLin;                 /* Number of timepoints in the linear regime */
+  int len;                  /* Length of time and ct arrays */
+  int nExpFit;              /* Number of exponentials to fit */       
+  real ballistic;           /* Time before which the ballistic term should be fitted */
+  bool bDt;                 /* TRUE =>  use time derivative at time 0
+                            *          to find fastest component.
+                            * FALSE => use coefficient in exponenetial
+                            *          to find fastest component. */
+} t_gemParams;
+
+
+typedef struct{
+  size_t n;         /* Number of data points (lin-log) */
+  double *y;        /* The datapoints */
+  double *ctTheory; /* The theoretical ct which will be built by gemFunc_f. */
+  double *LinLog;
+  double *time;
+  double ka;
+  double kd;
+  double tDelta;    /* time difference between subsequent datapoints */
+  size_t nData;     /* real size of the data */
+  int    *logtime;
+  double *doubleLogTime;
+  t_gemParams *params;
+} gemFitData;
+
+extern void takeAwayBallistic(double *ct, double *t,
+                             int len, real tMax,
+                             int nexp, bool bDerivative);
+
+
+extern t_gemParams *init_gemParams(const double sigma, const double D,
+                                  const real *t, const int len, const int nFitPoints,
+                                  const real begFit, const real endFit,
+                                  const real ballistic, const int nBalExp, const bool bDt);
+
+/* Fit to geminate recombination model.
+   Returns root mean square error of fit. */
+extern real fitGemRecomb(double *ct, double *time, double **ctFit,
+                        const int nData, t_gemParams *params);
+
+extern void dumpN(const real *e, const int nn, char *fn);
+
+#endif
index f007d26864ae46936f7dc8fc88ed7e5a572920bf..f506b1bba1f6c798c22da6e089c84f496386728a 100644 (file)
@@ -100,7 +100,7 @@ static void calc_entropy_schlitter(FILE *fp,int n,int nskip,
 
   hbar = PLANCK1/(2*M_PI);
   kt   = BOLTZMANN*temp;
-  kteh = kt*exp(2.0)/(hbar*hbar)*AMU*sqr(NANO);
+  kteh = kt*exp(2.0)/(hbar*hbar)*AMU*(NANO*NANO);
   if (debug)
     fprintf(debug,"n = %d, nskip = %d kteh = %g\n",n,nskip,kteh);
   
@@ -405,7 +405,9 @@ static void project(const char *trajfile,t_topology *top,int ePBC,matrix topbox,
                     const output_env_t oenv)
 {
   FILE    *xvgrout=NULL;
-  int     status,out=0,nat,i,j,d,v,vec,nfr,nframes=0,snew_size,frame;
+  int     nat,i,j,d,v,vec,nfr,nframes=0,snew_size,frame;
+  t_trxstatus *out=NULL;
+  t_trxstatus *status;
   int     noutvec_extr,*imin,*imax;
   atom_id *all_at;
   matrix  box;
@@ -413,6 +415,7 @@ static void project(const char *trajfile,t_topology *top,int ePBC,matrix topbox,
   real    t,inp,**inprod=NULL,min=0,max=0;
   char    str[STRLEN],str2[STRLEN],**ylabel,*c;
   real    fact;
+  gmx_rmpbc_t  gpbc=NULL;
 
   snew(x,natoms);
   
@@ -440,12 +443,18 @@ static void project(const char *trajfile,t_topology *top,int ePBC,matrix topbox,
     if (nat>atoms->nr)
       gmx_fatal(FARGS,"the number of atoms in your trajectory (%d) is larger than the number of atoms in your structure file (%d)",nat,atoms->nr); 
     snew(all_at,nat);
+    
+    if (top)
+      gpbc = gmx_rmpbc_init(&top->idef,ePBC,nat,box);
+    if (top)
+    gmx_rmpbc_done(gpbc);
+
     for(i=0; i<nat; i++)
       all_at[i]=i;
     do {
       if (nfr % skip == 0) {
        if (top)
-         rm_pbc(&(top->idef),ePBC,nat,box,xread,xread);
+         gmx_rmpbc(gpbc,box,xread,xread);
        if (nframes>=snew_size) {
          snew_size+=100;
          for(i=0; i<noutvec+1; i++)
@@ -486,7 +495,7 @@ static void project(const char *trajfile,t_topology *top,int ePBC,matrix topbox,
       }
       nfr++;
     } while (read_next_x(oenv,status,&t,nat,xread,box));
-    close_trj(status);
+    close_trj(out);
      sfree(x);
      if (filterfile)
        close_trx(out);
@@ -494,6 +503,9 @@ static void project(const char *trajfile,t_topology *top,int ePBC,matrix topbox,
   else
     snew(xread,atoms->nr);
   
+  if (top)
+    gmx_rmpbc_done(gpbc);
+
 
   if (projfile) {
     snew(ylabel,noutvec);
@@ -737,7 +749,7 @@ int gmx_anaeig(int argc,char *argv[])
 {
   static const char *desc[] = {
     "[TT]g_anaeig[tt] analyzes eigenvectors. The eigenvectors can be of a",
-    "covariance matrix ([TT]g_covar[tt]) or of a Normal Modes anaysis",
+    "covariance matrix ([TT]g_covar[tt]) or of a Normal Modes analysis",
     "([TT]g_nmeig[tt]).[PAR]",
     
     "When a trajectory is projected on eigenvectors, all structures are",
@@ -757,7 +769,7 @@ int gmx_anaeig(int argc,char *argv[])
     "[TT]-first[tt] to [TT]-last[tt].",
     "The projections of a trajectory on the eigenvectors of its",
     "covariance matrix are called principal components (pc's).",
-    "It is often useful to check the cosine content the pc's,",
+    "It is often useful to check the cosine content of the pc's,",
     "since the pc's of random diffusion are cosines with the number",
     "of periods equal to half the pc index.",
     "The cosine content of the pc's can be calculated with the program",
@@ -864,7 +876,8 @@ int gmx_anaeig(int argc,char *argv[])
   int        neig1,neig2;
   double     **xvgdata;
   output_env_t oenv;
-  
+  gmx_rmpbc_t  gpbc=NULL;
+
   t_filenm fnm[] = { 
     { efTRN, "-v",    "eigenvec",    ffREAD  },
     { efTRN, "-v2",   "eigenvec2",   ffOPTRD },
@@ -986,13 +999,15 @@ int gmx_anaeig(int argc,char *argv[])
   nfit=0;
   ifit=NULL;
   w_rls=NULL;
+  gpbc = gmx_rmpbc_init(&top.idef,ePBC,atoms->nr,topbox);
+
   if (!bTPS)
     bTop=FALSE;
   else {
     bTop=read_tps_conf(ftp2fn(efTPS,NFILE,fnm),
                       title,&top,&ePBC,&xtop,NULL,topbox,bM);
     atoms=&top.atoms;
-    rm_pbc(&(top.idef),ePBC,atoms->nr,topbox,xtop,xtop);
+    gmx_rmpbc(gpbc,topbox,xtop,xtop);
     /* Fitting is only required for the projection */ 
     if (bProj && bFit1) {
       if (xref1 == NULL) {
@@ -1025,7 +1040,8 @@ int gmx_anaeig(int argc,char *argv[])
       }
     }
   }
-  
+  gmx_rmpbc_done(gpbc);
+
   if (bIndex) {
     printf("\nSelect an index group of %d elements that corresponds to the eigenvectors\n",natoms);
     get_index(atoms,indexfile,1,&i,&index,&grpname);
index 833f5239fd82a5d94c5269e3cdf94a9777cfe679..3084e7e31c08e261f2afa4536a71aab49d205884 100644 (file)
 #include "statutil.h"
 #include "txtdump.h"
 #include "gstat.h"
+#include "gmx_matrix.h"
 #include "gmx_statistics.h"
 #include "xvgr.h"
 #include "gmx_ana.h"
+#include "geminate.h"
 
 /* must correspond to char *avbar_opt[] declared in main() */
 enum { avbarSEL, avbarNONE, avbarSTDDEV, avbarERROR, avbar90, avbarNR };
@@ -133,30 +135,64 @@ static void plot_coscont(const char *ccfile,int n,int nset,real **val,
   ffclose(fp);
 }
 
-static void regression_analysis(int n,bool bXYdy,real *x,real **val)
+static void regression_analysis(int n,bool bXYdy,
+                                real *x,int nset,real **val)
 {
   real S,chi2,a,b,da,db,r=0;
 
-  printf("Fitting data to a function f(x) = ax + b\n");
-  printf("Minimizing residual chi2 = Sum_i w_i [f(x_i) - y_i]2\n");
-  printf("Error estimates will be given if w_i (sigma) values are given\n");
-  printf("(use option -xydy).\n\n");
-  if (bXYdy) 
-    lsq_y_ax_b_error(n,x,val[0],val[1],&a,&b,&da,&db,&r,&S);
-  else
-    lsq_y_ax_b(n,x,val[0],&a,&b,&r,&S);
-  chi2 = sqr((n-2)*S);
-  printf("Chi2                    = %g\n",chi2);
-  printf("S (Sqrt(Chi2/(n-2))     = %g\n",S);
-  printf("Correlation coefficient = %.1f%%\n",100*r);
-  printf("\n");
-  if (bXYdy) {
-    printf("a    = %g +/- %g\n",a,da);
-    printf("b    = %g +/- %g\n",b,db);
+  if (bXYdy || (nset == 1)) 
+  {
+      printf("Fitting data to a function f(x) = ax + b\n");
+      printf("Minimizing residual chi2 = Sum_i w_i [f(x_i) - y_i]2\n");
+      printf("Error estimates will be given if w_i (sigma) values are given\n");
+      printf("(use option -xydy).\n\n");
+      if (bXYdy) 
+          lsq_y_ax_b_error(n,x,val[0],val[1],&a,&b,&da,&db,&r,&S);
+      else
+          lsq_y_ax_b(n,x,val[0],&a,&b,&r,&S);
+      chi2 = sqr((n-2)*S);
+      printf("Chi2                    = %g\n",chi2);
+      printf("S (Sqrt(Chi2/(n-2))     = %g\n",S);
+      printf("Correlation coefficient = %.1f%%\n",100*r);
+      printf("\n");
+      if (bXYdy) {
+          printf("a    = %g +/- %g\n",a,da);
+          printf("b    = %g +/- %g\n",b,db);
+      }
+      else {
+          printf("a    = %g\n",a);
+          printf("b    = %g\n",b);
+      }
   }
-  else {
-    printf("a    = %g\n",a);
-    printf("b    = %g\n",b);
+  else 
+  {
+      double chi2,*a,**xx,*y;
+      int i,j;
+      
+      snew(y,n);
+      snew(xx,nset-1);
+      for(j=0; (j<nset-1); j++)
+          snew(xx[j],n);
+      for(i=0; (i<n); i++)
+      {
+          y[i] = val[0][i];
+          for(j=1; (j<nset); j++)
+              xx[j-1][i] = val[j][i];
+      }
+      snew(a,nset-1);
+      chi2 = multi_regression(NULL,n,y,nset-1,xx,a);
+      printf("Fitting %d data points in %d sets\n",n,nset-1);
+      printf("chi2 = %g\n",chi2);
+      printf("A =");
+      for(i=0; (i<nset-1); i++)
+      {
+          printf("  %g",a[i]);
+          sfree(xx[i]);
+      }
+      printf("\n");
+      sfree(xx);
+      sfree(y);
+      sfree(a);
   }
 }
 
@@ -734,6 +770,111 @@ static void do_fit(FILE *out,int n,bool bYdy,int ny,real *x0,real **val,
   }
 }
 
+static void do_ballistic(const char *balFile, int nData,
+                         real *t, real **val, int nSet,
+                         real balTime, int nBalExp,
+                         bool bDerivative,
+                         const output_env_t oenv)
+{
+  double **ctd=NULL, *td=NULL;
+  t_gemParams *GP = init_gemParams(0, 0, t, nData, 0, 0, 0, balTime, nBalExp, bDerivative);
+  static char *leg[] = {"Ac'(t)"};
+  FILE *fp;
+  int i, set;
+  
+  if (GP->ballistic/GP->tDelta >= GP->nExpFit*2+1)
+  {
+      snew(ctd, nSet);
+      snew(td,  nData);
+
+      fp = xvgropen(balFile, "Hydrogen Bond Autocorrelation","Time (ps)","C'(t)", oenv);
+      xvgr_legend(fp,asize(leg),leg,oenv);
+      
+      for (set=0; set<nSet; set++)
+      {
+          snew(ctd[set], nData);
+          for (i=0; i<nData; i++) {
+              ctd[set][i] = (double)val[set][i];
+              if (set==0)
+                  td[i] = (double)t[i];
+          }
+          
+          takeAwayBallistic(ctd[set], td, nData, GP->ballistic, GP->nExpFit, GP->bDt);
+      }
+      
+      for (i=0; i<nData; i++)
+      {
+          fprintf(fp, "  %g",t[i]);
+          for (set=0; set<nSet; set++)
+          {
+              fprintf(fp, "  %g", ctd[set][i]);
+          }
+          fprintf(fp, "\n");
+      }
+
+
+      for (set=0; set<nSet; set++)
+          sfree(ctd[set]);
+      sfree(ctd);
+      sfree(td);
+  }
+  else
+      printf("Number of data points is less than the number of parameters to fit\n."
+             "The system is underdetermined, hence no ballistic term can be found.\n\n");
+}
+
+static void do_geminate(const char *gemFile, int nData,
+                        real *t, real **val, int nSet,
+                        const real D, const real rcut, const real balTime,
+                        const int nFitPoints, const real begFit, const real endFit,
+                        const output_env_t oenv)
+{
+    double **ctd=NULL, **ctdGem=NULL, *td=NULL;
+    t_gemParams *GP = init_gemParams(rcut, D, t, nData, nFitPoints,
+                                     begFit, endFit, balTime, 1, FALSE);
+    static char *leg[] = {"Ac\\sgem\\N(t)"};
+    FILE *fp;
+    int i, set;
+    
+    snew(ctd,    nSet);
+    snew(ctdGem, nSet);
+    snew(td,  nData);
+    
+    fp = xvgropen(gemFile, "Hydrogen Bond Autocorrelation","Time (ps)","C'(t)", oenv);
+    xvgr_legend(fp,asize(leg),leg,oenv);
+    
+    for (set=0; set<nSet; set++)
+    {
+        snew(ctd[set],    nData);
+        snew(ctdGem[set], nData);
+        for (i=0; i<nData; i++) {
+            ctd[set][i] = (double)val[set][i];
+            if (set==0)
+                td[i] = (double)t[i];
+        }
+        fitGemRecomb(ctd[set], td, &(ctd[set]), nData, GP);
+    }
+
+    for (i=0; i<nData; i++)
+       {
+        fprintf(fp, "  %g",t[i]);
+        for (set=0; set<nSet; set++)
+           {
+            fprintf(fp, "  %g", ctdGem[set][i]);
+           }
+        fprintf(fp, "\n");
+       }
+
+    for (set=0; set<nSet; set++)
+    {
+        sfree(ctd[set]);
+        sfree(ctdGem[set]);
+    }
+    sfree(ctd);
+    sfree(ctdGem);
+    sfree(td);
+}
+
 int gmx_analyze(int argc,char *argv[])
 {
   static const char *desc[] = {
@@ -741,7 +882,7 @@ int gmx_analyze(int argc,char *argv[])
     "A line in the input file may start with a time",
     "(see option [TT]-time[tt]) and any number of y values may follow.",
     "Multiple sets can also be",
-    "read when they are seperated by & (option [TT]-n[tt]),",
+    "read when they are separated by & (option [TT]-n[tt]),",
     "in this case only one y value is read from each line.",
     "All lines starting with # and @ are skipped.",
     "All analyses can also be done for the derivative of a set",
@@ -752,7 +893,7 @@ int gmx_analyze(int argc,char *argv[])
 
     "g_analyze always shows the average and standard deviation of each",
     "set. For each set it also shows the relative deviation of the third",
-    "and forth cumulant from those of a Gaussian distribution with the same",
+    "and fourth cumulant from those of a Gaussian distribution with the same",
     "standard deviation.[PAR]",
 
     "Option [TT]-ac[tt] produces the autocorrelation function(s).[PAR]",
@@ -793,6 +934,20 @@ int gmx_analyze(int argc,char *argv[])
     "The complete derivation is given in",
     "B. Hess, J. Chem. Phys. 116:209-217, 2002.[PAR]",
 
+    "Option [TT]-bal[TT] finds and subtracts the ultrafast \"ballistic\"",
+    "component from a hydrogen bond autocorrelation function by the fitting",
+    "of a sum of exponentials, as described in e.g.",
+    "O. Markovitch, J. Chem. Phys. 129:084505, 2008. The fastest term",
+    "is the one with the most negative coefficient in the exponential,",
+    "or with [TT]-d[TT], the one with most negative time derivative at time 0.",
+    "[]TT-nbalexp[TT] sets the number of exponentials to fit.[PAR]",
+
+    "Option [TT]-gem[TT] fits bimolecular rate constants ka and kb",
+    "(and optionally kD) to the hydrogen bond autocorrelation function",
+    "according to the reversible geminate recombination model. Removal of",
+    "the ballistic component first is strongly adviced. The model is presented in",
+    "O. Markovitch, J. Chem. Phys. 129:084505, 2008.[PAR]",
+
     "Option [TT]-filter[tt] prints the RMS high-frequency fluctuation",
     "of each set and over all sets with respect to a filtered average.",
     "The filter is proportional to cos(pi t/len) where t goes from -len/2",
@@ -815,8 +970,8 @@ int gmx_analyze(int argc,char *argv[])
   static bool bHaveT=TRUE,bDer=FALSE,bSubAv=TRUE,bAverCorr=FALSE,bXYdy=FALSE;
   static bool bEESEF=FALSE,bEENLC=FALSE,bEeFitAc=FALSE,bPower=FALSE;
   static bool bIntegrate=FALSE,bRegression=FALSE,bLuzar=FALSE,bLuzarError=FALSE; 
-  static int  nsets_in=1,d=1,nb_min=4,resol=10;
-  static real temp=298.15,fit_start=1,smooth_tail_start=-1;
+  static int  nsets_in=1,d=1,nb_min=4,resol=10, nBalExp=4, nFitPoints=100;
+  static real temp=298.15,fit_start=1, fit_end=60, smooth_tail_start=-1, balTime=0.2, diffusion=5e-5,rcut=0.35;
   
   /* must correspond to enum avbar* declared at beginning of file */
   static const char *avbar_opt[avbarNR+1] = { 
@@ -831,7 +986,7 @@ int gmx_analyze(int argc,char *argv[])
     { "-e",       FALSE, etREAL, {&te},
       "Last time to read from set" },
     { "-n",       FALSE, etINT, {&nsets_in},
-      "Read # sets seperated by &" },
+      "Read # sets separated by &" },
     { "-d",       FALSE, etBOOL, {&bDer},
        "Use the derivative" },
     { "-dp",      FALSE, etINT, {&d}, 
@@ -847,13 +1002,15 @@ int gmx_analyze(int argc,char *argv[])
     { "-xydy",    FALSE, etBOOL, {&bXYdy},
       "Interpret second data set as error in the y values for integrating" },
     { "-regression",FALSE,etBOOL,{&bRegression},
-      "Perform a linear regression analysis on the data" },
+      "Perform a linear regression analysis on the data. If -xydy is set a second set will be interpreted as the error bar in the Y value. Otherwise, if multiple data sets are present a multilinear regression will be performed yielding the constant A that minimize chi^2 = (y - A0 x0 - A1 x1 - ... - AN xN)^2 where now Y is the first data set in the input file and xi the others. Do read the information at the option [TT]-time[tt]." },
     { "-luzar",   FALSE, etBOOL, {&bLuzar},
       "Do a Luzar and Chandler analysis on a correlation function and related as produced by g_hbond. When in addition the -xydy flag is given the second and fourth column will be interpreted as errors in c(t) and n(t)." },
     { "-temp",    FALSE, etREAL, {&temp},
       "Temperature for the Luzar hydrogen bonding kinetics analysis" },
     { "-fitstart", FALSE, etREAL, {&fit_start},
       "Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation" }, 
+    { "-fitend", FALSE, etREAL, {&fit_end},
+      "Time (ps) where to stop fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation. Only with -gem" }, 
     { "-smooth",FALSE, etREAL, {&smooth_tail_start},
       "If >= 0, the tail of the ACF will be smoothed by fitting it to an exponential function: y = A exp(-x/tau)" },
     { "-nbmin",   FALSE, etINT, {&nb_min},
@@ -874,7 +1031,19 @@ int gmx_analyze(int argc,char *argv[])
     { "-subav", FALSE, etBOOL, {&bSubAv},
       "Subtract the average before autocorrelating" },
     { "-oneacf", FALSE, etBOOL, {&bAverCorr},
-      "Calculate one ACF over all sets" }
+      "Calculate one ACF over all sets" },
+    { "-nbalexp", FALSE, etINT, {&nBalExp},
+      "HIDDENNumber of exponentials to fit to the ultrafast component" },
+    { "-baltime", FALSE, etREAL, {&balTime},
+      "HIDDENTime up to which the ballistic component will be fitted" },
+/*     { "-gemnp", FALSE, etINT, {&nFitPoints}, */
+/*       "HIDDENNumber of data points taken from the ACF to use for fitting to rev. gem. recomb. model."}, */
+/*     { "-rcut", FALSE, etREAL, {&rcut}, */
+/*       "Cut-off for hydrogen bonds in geminate algorithms" }, */
+/*     { "-gemtype", FALSE, etENUM, {gemType}, */
+/*       "What type of gminate recombination to use"}, */
+/*     { "-D", FALSE, etREAL, {&diffusion}, */
+/*       "The self diffusion coefficient which is used for the reversible geminate recombination model."} */
   };
 #define NPA asize(pa)
 
@@ -882,7 +1051,7 @@ int gmx_analyze(int argc,char *argv[])
   int      n,nlast,s,nset,i,j=0;
   real     **val,*t,dt,tot,error;
   double   *av,*sig,cum1,cum2,cum3,cum4,db;
-  const char     *acfile,*msdfile,*ccfile,*distfile,*avfile,*eefile,*fitfile;
+  const char     *acfile,*msdfile,*ccfile,*distfile,*avfile,*eefile,*balfile,*gemfile,*fitfile;
   output_env_t oenv;
   
   t_filenm fnm[] = { 
@@ -893,6 +1062,8 @@ int gmx_analyze(int argc,char *argv[])
     { efXVG, "-dist", "distr",    ffOPTWR  },
     { efXVG, "-av",   "average",  ffOPTWR  },
     { efXVG, "-ee",   "errest",   ffOPTWR  },
+    { efXVG, "-bal",  "ballisitc",ffOPTWR  },
+/*     { efXVG, "-gem",  "geminate", ffOPTWR  }, */
     { efLOG, "-g",    "fitlog",   ffOPTWR  }
   }; 
 #define NFILE asize(fnm) 
@@ -913,6 +1084,8 @@ int gmx_analyze(int argc,char *argv[])
   distfile = opt2fn_null("-dist",NFILE,fnm);
   avfile   = opt2fn_null("-av",NFILE,fnm);
   eefile   = opt2fn_null("-ee",NFILE,fnm);
+  balfile  = opt2fn_null("-bal",NFILE,fnm);
+/*   gemfile  = opt2fn_null("-gem",NFILE,fnm); */
   if (opt2parg_bSet("-fitfn",npargs,ppa)) 
     fitfile  = opt2fn("-g",NFILE,fnm);
   else
@@ -1027,6 +1200,11 @@ int gmx_analyze(int argc,char *argv[])
   if (eefile)
     estimate_error(eefile,nb_min,resol,n,nset,av,sig,val,dt,
                   bEeFitAc,bEESEF,bEENLC,oenv);
+  if (balfile)
+      do_ballistic(balfile,n,t,val,nset,balTime,nBalExp,bDer,oenv);
+/*   if (gemfile) */
+/*       do_geminate(gemfile,n,t,val,nset,diffusion,rcut,balTime, */
+/*                   nFitPoints, fit_start, fit_end, oenv); */
   if (bPower)
     power_fit(n,nset,val,t);
   if (acfile) {
@@ -1038,7 +1216,7 @@ int gmx_analyze(int argc,char *argv[])
                eacNormal,bAverCorr);
   }
   if (bRegression)
-    regression_analysis(n,bXYdy,t,val);
+      regression_analysis(n,bXYdy,t,nset,val);
 
   if (bLuzar) 
     luzar_correl(n,t,nset,val,temp,bXYdy,fit_start,smooth_tail_start,oenv);
index 0c2d69ed9162699ad00818b88b1a9f764f4b9686..c44cff85441c4a6e5d38f08892660ac33741dc34 100644 (file)
@@ -58,7 +58,8 @@
 static void dump_dih_trn(int nframes,int nangles,real **dih,const char *fn,
                          real dt)
 {
-  int    i,j,k,l,m,na,trn;
+  int    i,j,k,l,m,na;
+  t_fileio *trn;
   rvec   *x;
   matrix box = {{2,0,0},{0,2,0},{0,0,2}};  
   
@@ -104,7 +105,7 @@ int gmx_g_angle(int argc,char *argv[])
     "It should be noted that the indexfile should contain",
     "atom-triples for angles or atom-quadruplets for dihedrals.",
     "If this is not the case, the program will crash.[PAR]",
-    "With option [TT]-or[tt] a trajectory file is dumped containing cos and"
+    "With option [TT]-or[tt] a trajectory file is dumped containing cos and",
     "sin of selected dihedral angles which subsequently can be used as",
     "input for a PCA analysis using [TT]g_covar[tt]."
   };
index 12a005d8cbf321014d5bc8714cfc6d92275b8c5e..501c717b8c0f49dfa4349ef54fe156e4e2fbc4a8 100644 (file)
@@ -493,29 +493,81 @@ static double legend2lambda(char *fn,const char *legend,bool bdhdl)
     return lambda;
 }
 
+static bool subtitle2lambda(const char *subtitle,double *lambda)
+{
+    bool bFound;
+    char *ptr;
+
+    bFound = FALSE;
+
+    /* plain text lambda string */
+    ptr = strstr(subtitle,"lambda");
+    if (ptr == NULL)
+    {
+        /* xmgrace formatted lambda string */
+        ptr = strstr(subtitle,"\\xl\\f{}");
+    }
+    if (ptr == NULL)
+    {
+        /* xmgr formatted lambda string */
+        ptr = strstr(subtitle,"\\8l\\4");
+    }
+    if (ptr != NULL)
+    {
+        ptr = strstr(ptr,"=");
+    }
+    if (ptr != NULL)
+    {
+        bFound = (sscanf(ptr+1,"%lf",lambda) == 1);
+    }
+
+    return bFound;
+}
+
 static double filename2lambda(char *fn)
 {
     double lambda;
-    char   *ptr,*endptr;
-    
+    char   *ptr,*endptr,*digitptr;
+    int     dirsep;
     ptr = fn;
-    while (ptr[0] != '\0' && !isdigit(ptr[0]))
+    /* go to the end of the path string and search backward to find the last 
+       directory in the path which has to contain the value of lambda 
+     */
+    while (ptr[1] != '\0')
     {
         ptr++;
     }
-    if (!isdigit(ptr[0]))
+    /* searching backward to find the second directory separator */
+    dirsep = 0;
+    digitptr = NULL;
+    while (ptr >= fn)
     {
-        gmx_fatal(FARGS,"While trying to read the lambda value from the filename: filename '%s' does not contain a number",fn);
+        if (ptr[0] != DIR_SEPARATOR && ptr[1] == DIR_SEPARATOR)
+        {            
+            if (dirsep == 1) break;
+            dirsep++;
+        }
+        /* save the last position of a digit between the last two 
+           separators = in the last dirname */
+        if (dirsep > 0 && isdigit(*ptr))
+        {
+            digitptr = ptr;
+        }
+        ptr--;
     }
-    if (ptr > fn && fn[ptr-fn-1] == '-')
+    if (!digitptr)
     {
-        ptr--;
+        gmx_fatal(FARGS,"While trying to read the lambda value from the file path:"
+                    " last directory in the path '%s' does not contain a number",fn);
     }
-
-    lambda = strtod(ptr,&endptr);
-    if (endptr == ptr)
+    if (digitptr[-1] == '-')
+    {
+        digitptr--;
+    }
+    lambda = strtod(digitptr,&endptr);
+    if (endptr == digitptr)
     {
-        gmx_fatal(FARGS,"Malformed number in filename '%s'",fn);
+        gmx_fatal(FARGS,"Malformed number in file path '%s'",fn);
     }
 
     return lambda;
@@ -574,8 +626,13 @@ static void read_barsim(char *fn,double begin,double end,real temp,
         /* Check if we have a single set, nset=2 means t and dH/dl */
         if (ba->nset == 2)
         {
-            /* Deduce lambda from the file name */
-            ba->lambda[0] = filename2lambda(fn);
+            /* Try to deduce lambda from the subtitle */
+            if (subtitle != NULL &&
+                !subtitle2lambda(subtitle,&ba->lambda[0]))
+            {
+                /* Deduce lambda from the file name */
+                ba->lambda[0] = filename2lambda(fn);
+            }
             printf(" %g",ba->lambda[0]);
         }
         else
@@ -620,8 +677,8 @@ int gmx_bar(int argc,char *argv[])
         "* Files with only one y-value, for such files it is assumed ",
         "that the y-value is dH/dlambda and that the Hamiltonian depends ",
         "linearly on lambda. The lambda value of the simulation is inferred ",
-        "from the legend if present, otherwise from a number in the file ",
-        "name.",
+        "from the subtitle if present, otherwise from a number in the",
+        "subdirectory in the file name.",
         "[BR]",
         "* Files with more than one y-value. The files should have columns ",
         "with dH/dlambda and Delta lambda. The lambda values are inferred ",
@@ -698,6 +755,7 @@ int gmx_bar(int argc,char *argv[])
     double   *partsum;
     double   prec,dg_tot,dg,sig;
     FILE     *fpb,*fpi;
+    char     lamformat[20];
     char     dgformat[20],xvg2format[STRLEN],xvg3format[STRLEN],buf[STRLEN];
     char     ktformat[STRLEN], sktformat[STRLEN];
     char     kteformat[STRLEN], skteformat[STRLEN];
@@ -721,6 +779,7 @@ int gmx_bar(int argc,char *argv[])
         gmx_fatal(FARGS,"Can not have negative number of digits");
     }
     prec = pow(10,-nd);
+    sprintf(lamformat,"%%6.3f");
     sprintf( dgformat,"%%%d.%df",3+nd,nd);
     /* the format strings of the results in kT */
     sprintf( ktformat,"%%%d.%df",5+nd,nd);
@@ -826,8 +885,8 @@ int gmx_bar(int argc,char *argv[])
     printf("\nTemperature: %g K\n", ba[0].temp);
 
     printf("\nDetailed results in kT (see help for explanation):\n\n");
-    printf(skteformat, "lam_A ");
-    printf(skteformat, "lam_B ");
+    printf("%6s ", " lam_A");
+    printf("%6s ", " lam_B");
     printf(sktformat,  "DG ");
     printf(skteformat, "+/- ");
     printf(sktformat,  "s_A ");
@@ -839,9 +898,9 @@ int gmx_bar(int argc,char *argv[])
     printf("\n");
     for(f=0; f<nfile-1; f++)
     {
-        printf(kteformat, results[f].lambda_a);
+        printf(lamformat, results[f].lambda_a);
         printf(" ");
-        printf(kteformat, results[f].lambda_b);
+        printf(lamformat, results[f].lambda_b);
         printf(" ");
         printf(ktformat,  results[f].dg);
         printf(" ");
@@ -900,9 +959,9 @@ int gmx_bar(int argc,char *argv[])
         /*printf("lambda %4.2f - %4.2f, DG ", results[f].lambda_a,
                                               results[f].lambda_b);*/
         printf("lambda ");
-        printf(dgformat, results[f].lambda_a);
+        printf(lamformat, results[f].lambda_a);
         printf(" - ");
-        printf(dgformat, results[f].lambda_b);
+        printf(lamformat, results[f].lambda_b);
         printf(",   DG ");
 
         printf(dgformat,results[f].dg*kT);
@@ -914,9 +973,9 @@ int gmx_bar(int argc,char *argv[])
     }
     printf("\n");
     printf("total  ");
-    printf(dgformat, ba[0].lambda[0]);
+    printf(lamformat, ba[0].lambda[0]);
     printf(" - ");
-    printf(dgformat, ba[nfile-1].lambda[0]);
+    printf(lamformat, ba[nfile-1].lambda[0]);
     printf(",   DG ");
 
     printf(dgformat,dg_tot*kT);
index 0b0ec2eb1b0b74dd326ba7c44ab7328a1e677ca9..6d067518acbfe52f335fc4394daa6bad956f6b7e 100644 (file)
@@ -93,7 +93,8 @@ static void do_bonds(FILE *log,const char *fn,const char *fbond,
     int    counter;*/
   rvec   *x;
   rvec   dx;
-  int    status,natoms;
+  t_trxstatus *status;
+  int    natoms;
   matrix box;
   real   t,fac;
   int    bind,i,nframes,i0,i1;
@@ -228,8 +229,8 @@ int gmx_bond(int argc,char *argv[])
   const char *desc[] = {
     "g_bond makes a distribution of bond lengths. If all is well a",
     "gaussian distribution should be made when using a harmonic potential.",
-    "bonds are read from a single group in the index file in order i1-j1",
-    "i2-j2 thru in-jn.[PAR]",
+    "Bonds are read from a single group in the index file in order i1-j1",
+    "i2-j2 through in-jn.[PAR]",
     "[TT]-tol[tt] gives the half-width of the distribution as a fraction",
     "of the bondlength ([TT]-blen[tt]). That means, for a bond of 0.2",
     "a tol of 0.1 gives a distribution from 0.18 to 0.22.[PAR]",
index e7a47aec181511be5bb23c9616db5c8b24223096..0772cec7bd67985f078765862dc8563fc4de44ec 100644 (file)
@@ -135,7 +135,8 @@ static void calc_axes(rvec x[],t_atom atom[],int gnx[],atom_id *index[],
   }
 }
 
-static void dump_axes(int fp,t_trxframe *fr,t_atoms *outat,t_bundle *bun)
+static void dump_axes(t_trxstatus *status,t_trxframe *fr,t_atoms *outat,
+                      t_bundle *bun)
 {
   t_trxframe  frout;
   static rvec *xout=NULL;
@@ -160,7 +161,7 @@ static void dump_axes(int fp,t_trxframe *fr,t_atoms *outat,t_bundle *bun)
   frout.natoms = outat->nr;
   frout.atoms  = outat;
   frout.x      = xout;
-  write_trxframe(fp,&frout,NULL);
+  write_trxframe(status,&frout,NULL);
 }
 
 int gmx_bundle(int argc,char *argv[])
@@ -198,7 +199,8 @@ int gmx_bundle(int argc,char *argv[])
   };
   FILE       *out,*flen,*fdist,*fz,*ftilt,*ftiltr,*ftiltl;
   FILE       *fkink=NULL,*fkinkr=NULL,*fkinkl=NULL;
-  int        status,fpdb;
+  t_trxstatus *status;
+  t_trxstatus *fpdb;
   t_topology top;
   int        ePBC;
   rvec       *xtop;
@@ -216,6 +218,8 @@ int gmx_bundle(int argc,char *argv[])
   bool       bKink;
   rvec       va,vb,vc,vr,vl;
   output_env_t oenv;
+  gmx_rmpbc_t  gpbc=NULL;
+  
 #define NLEG asize(leg) 
   t_filenm fnm[] = { 
     { efTRX, "-f", NULL, ffREAD }, 
@@ -302,12 +306,13 @@ int gmx_bundle(int argc,char *argv[])
     }
     fpdb = open_trx(opt2fn("-oa",NFILE,fnm),"w");
   } else
-    fpdb = -1;
+    fpdb = NULL;
   
   read_first_frame(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&fr,TRX_NEED_X); 
-  
+  gpbc = gmx_rmpbc_init(&top.idef,ePBC,fr.natoms,fr.box);
+
   do {
-    rm_pbc(&top.idef,ePBC,fr.natoms,fr.box,fr.x,fr.x);
+    gmx_rmpbc(gpbc,fr.box,fr.x,fr.x);
     calc_axes(fr.x,top.atoms.atom,gnx,index,!bZ,&bun);
     t = output_env_conv_time(oenv,fr.time);
     fprintf(flen," %10g",t);
@@ -361,13 +366,14 @@ int gmx_bundle(int argc,char *argv[])
       fprintf(fkinkr,"\n");
       fprintf(fkinkl,"\n");
     }
-    if (fpdb >= 0)
+    if (fpdb )
       dump_axes(fpdb,&fr,&outatoms,&bun);
   } while(read_next_frame(oenv,status,&fr));
+  gmx_rmpbc_done(gpbc);
 
   close_trx(status);
   
-  if (fpdb >= 0)
+  if (fpdb )
     close_trx(fpdb);
   ffclose(flen);
   ffclose(fdist);
index 35c40a253ebd187f9c9d4e617886b2e83c53b8c2..472735256757d9a166176e9ccd4a669a81f0ad9a 100644 (file)
@@ -886,6 +886,7 @@ static void order_params(FILE *log,
 {
   FILE *fp;
   int  nh[edMax];
+  char buf[STRLEN];
   int  i,Dih,Xi;
   real S2Max, S2Min;
 
@@ -897,8 +898,8 @@ static void order_params(FILE *log,
   
   char *leg[2+edMax];  
        
-       for(i=0;i<NLEG;i++)
-               leg[i]=strdup(const_leg[i]);
+  for(i=0;i<NLEG;i++)
+    leg[i]=strdup(const_leg[i]);
        
   /* Print order parameters */
   fp=xvgropen(fn,"Dihedral Order Parameters","Residue","S2",oenv);
@@ -936,9 +937,11 @@ static void order_params(FILE *log,
   }
   ffclose(fp);
   
-  if (pdbfn) {
+  if (NULL != pdbfn) {
     real x0,y0,z0;
-    
+
+    if (NULL == atoms->pdbinfo)
+      snew(atoms->pdbinfo,atoms->nr);
     for(i=0; (i<atoms->nr); i++)
       atoms->pdbinfo[i].bfac=bfac_init;
     
@@ -968,9 +971,11 @@ static void order_params(FILE *log,
     x0*=10.0;/* nm -> angstrom */
     y0*=10.0;/* nm -> angstrom */
     z0*=10.0;/* nm -> angstrom */
-    for (i=0; (i<10); i++)
-      fprintf(fp,pdbformat,"ATOM  ", atoms->nr+1+i, "CA", "LEG",' ', 
-             atoms->nres+1, x0, y0, z0+(1.2*i), 0.0, -0.1*i);
+    sprintf(buf,"%s%%6.f%%6.2f\n",pdbformat);
+    for (i=0; (i<10); i++) {
+      fprintf(fp,buf,"ATOM  ", atoms->nr+1+i, "CA", "LEG",' ', 
+             atoms->nres+1, ' ',x0, y0, z0+(1.2*i), 0.0, -0.1*i);
+    }
     ffclose(fp);
   }
   
@@ -989,8 +994,8 @@ static void order_params(FILE *log,
       fprintf(log,"%4d  ",nh[NONCHI+Xi]);
   fprintf(log,"\n");
        
-       for(i=0;i<NLEG;i++)
-               sfree(leg[i]);
+  for(i=0;i<NLEG;i++)
+    sfree(leg[i]);
 
 }
 
index b73c6f9cddbf62e5ffa6770eb3bed59874667c82..8a62ce7d87f0e1820441437d9cb8a1d6ce14c0f0 100644 (file)
@@ -555,7 +555,9 @@ rvec **read_whole_trj(const char *fn,int isize,atom_id index[],int skip,
   matrix box;
   real   t;
   int    i,i0,j,max_nf;
-  int    status,natom;
+  int    natom;
+  t_trxstatus *status;
+
   
   max_nf = 0;
   xx     = NULL;
@@ -735,7 +737,8 @@ static void analyze_clusters(int nf, t_clusters *clust, real **rmsd,
 {
   FILE *fp=NULL;
   char buf[STRLEN],buf1[40],buf2[40],buf3[40],*trxsfn;
-  int  trxout=0,trxsout=0;
+  t_trxstatus *trxout=NULL;
+  t_trxstatus *trxsout=NULL;
   int  i,i1,cl,nstr,*structure,first=0,midstr;
   bool *bWrite=NULL;
   real r,clrmsd,midrmsd;
@@ -776,7 +779,7 @@ static void analyze_clusters(int nf, t_clusters *clust, real **rmsd,
   
     /* Prepare a reference structure for the orientation of the clusters  */
     if (bFit)
-    reset_x(ifsize,fitidx,natom,NULL,xtps,mass);
+        reset_x(ifsize,fitidx,natom,NULL,xtps,mass);
     trxout = open_trx(trxfn,"w");
     /* Calculate the average structure in each cluster,               *
      * all structures are fitted to the first struture of the cluster */
@@ -961,7 +964,7 @@ int gmx_cluster(int argc,char *argv[])
     
     "Monte Carlo: reorder the RMSD matrix using Monte Carlo.[PAR]",
     
-    "diagonalization: diagonalize the RMSD matrix.[PAR]"
+    "diagonalization: diagonalize the RMSD matrix.[PAR]",
     
     "gromos: use algorithm as described in Daura [IT]et al.[it]",
     "([IT]Angew. Chem. Int. Ed.[it] [BB]1999[bb], [IT]38[it], pp 236-240).",
@@ -976,7 +979,7 @@ int gmx_cluster(int argc,char *argv[])
     "the smallest average distance to the others or the average structure",
     "or all structures for each cluster will be written to a trajectory",
     "file. When writing all structures, separate numbered files are made",
-    "for each cluster.[PAR]"
+    "for each cluster.[PAR]",
     
     "Two output files are always written:[BR]",
     "[TT]-o[tt] writes the RMSD values in the upper left half of the matrix",
@@ -1016,13 +1019,13 @@ int gmx_cluster(int argc,char *argv[])
   t_topology   top;
   int          ePBC;
   t_atoms      useatoms;
-  t_matrix     *readmat;
+  t_matrix     *readmat=NULL;
   real         *tmp;
   
   int      isize=0,ifsize=0,iosize=0;
   atom_id  *index=NULL, *fitidx, *outidx;
   char     *grpname;
-  real     rmsd,**d1,**d2,*time,time_invfac,*mass=NULL;
+  real     rmsd,**d1,**d2,*time=NULL,time_invfac,*mass=NULL;
   char     buf[STRLEN],buf1[80],title[STRLEN];
   bool     bAnalyze,bUseRmsdCut,bJP_RMSD=FALSE,bReadMat,bReadTraj;
 
index 18f45f36cc3781ef8e351abbdae880c922da4a89..df41652dfd978d6f1e11abd0bda9df7320488c99 100644 (file)
@@ -75,7 +75,8 @@ static void clust_size(const char *ndx,const char *trx,const char *xpm,
 {
   FILE    *fp,*gp,*hp,*tp;
   atom_id *index=NULL;
-  int     nindex,natoms,status;
+  int     nindex,natoms;
+  t_trxstatus *status;
   rvec    *x=NULL,*v=NULL,dx;
   t_pbc   pbc;
   char    *gname;
@@ -360,7 +361,7 @@ int gmx_clustsize(int argc,char *argv[])
     "When the [TT]-mol[tt] option is given clusters will be made out of",
     "molecules rather than atoms, which allows clustering of large molecules.",
     "In this case an index file would still contain atom numbers",
-    "or your calculcation will die with a SEGV.[PAR]",
+    "or your calculation will die with a SEGV.[PAR]",
     "When velocities are present in your trajectory, the temperature of",
     "the largest cluster will be printed in a separate xvg file assuming",
     "that the particles are free to move. If you are using constraints,",
@@ -395,7 +396,7 @@ int gmx_clustsize(int argc,char *argv[])
     { "-nlevels",  FALSE, etINT,  {&nlevels},
       "Number of levels of grey in xpm output" },
     { "-ndf",      FALSE, etINT,  {&ndf},
-      "Number of degrees of freedom of the entire system for temperature calculation. If not set the number of atoms times three is used." },
+      "Number of degrees of freedom of the entire system for temperature calculation. If not set, the number of atoms times three is used." },
     { "-rgblo",    FALSE, etRVEC, {rlo},
       "RGB values for the color of the lowest occupied cluster size" },
     { "-rgbhi",    FALSE, etRVEC, {rhi},
index 3a9ba1b3cf611455f8480a0a16c470790f14ce75..8d95b55f63c17087ab43c011a5c144890f4854e3 100644 (file)
@@ -364,7 +364,7 @@ int gmx_confrms(int argc,char *argv[])
     "only the two index groups used for the fit need to be identical.",
     "With [TT]-name[tt] only matching atom names from the selected groups",
     "will be used for the fit and RMSD calculation. This can be useful ",
-    "when comparing mutants of a protein."
+    "when comparing mutants of a protein.",
     "[PAR]",
     "The superimposed structures are written to file. In a [TT].pdb[tt] file",
     "the two structures will be written as separate models",
@@ -549,9 +549,9 @@ int gmx_confrms(int argc,char *argv[])
   }
   rms = sqrt(rms/totmass);
   
-  printf("Root mean square deviation after lsq fit = %g\n",rms);
+  printf("Root mean square deviation after lsq fit = %g nm\n",rms);
   if (bBfac)
-    printf("Atomic MSD's range from %g to %g\n",minmsd, maxmsd);
+    printf("Atomic MSD's range from %g to %g nm^2\n",minmsd, maxmsd);
   
   if (bFit) {
     /* reset coordinates of reference and fitted structure */
@@ -569,25 +569,46 @@ int gmx_confrms(int argc,char *argv[])
   case efBRK:
   case efENT:
     if (bBfac || bLabel) {
-      snew(atoms1->pdbinfo, atoms1->nr);
-      snew(atoms1->atom, atoms1->nr);
+      srenew(atoms1->pdbinfo, atoms1->nr);
+      srenew(atoms1->atom, atoms1->nr);      /* Why renew atom? */
+
+      /* Avoid segfaults when writing the pdb-file */
+      for (i=0; i<atoms1->nr; i++) {
+       atoms1->pdbinfo[i].type = eptAtom;
+       atoms1->pdbinfo[i].bAnisotropic = FALSE;
+       if (bBfac)
+         atoms1->pdbinfo[i].bfac = 0;
+       if (bLabel)
+         atoms1->resinfo[atoms1->atom[i].resind].chain = 'A';
+      }
+
       for(i=0; i<isize1; i++) {
-       atoms1->pdbinfo[index1[i]].type = eptAtom;
-       atoms1->pdbinfo[index1[i]].bAnisotropic = FALSE;
+       /* atoms1->pdbinfo[index1[i]].type = eptAtom; */
+/*     atoms1->pdbinfo[index1[i]].bAnisotropic = FALSE; */
        if (bBfac)
-         atoms1->pdbinfo[index1[i]].bfac = 800*M_PI*M_PI/3.0*msds[i]/100;
+         atoms1->pdbinfo[index1[i]].bfac = (800*M_PI*M_PI/3.0)*msds[i];
+/*     if (bLabel) */
+/*       atoms1->resinfo[atoms1->atom[index1[i]].resind].chain = 'A'; */
+      }
+      srenew(atoms2->pdbinfo, atoms2->nr);
+      srenew(atoms2->atom, atoms2->nr);      /* Why renew atom? */
+
+      for (i=0; i<atoms2->nr; i++) {
+       atoms2->pdbinfo[i].type = eptAtom;
+       atoms2->pdbinfo[i].bAnisotropic = FALSE;
+       if (bBfac)
+         atoms2->pdbinfo[i].bfac = 0;
        if (bLabel)
-         atoms1->resinfo[atoms1->atom[index1[i]].resind].chain = 'A';
+         atoms2->resinfo[atoms1->atom[i].resind].chain = 'B';
       }
-      snew(atoms2->pdbinfo, atoms2->nr);
-      snew(atoms2->atom, atoms2->nr);
+
       for(i=0; i<isize2; i++) {
-       atoms2->pdbinfo[index2[i]].type = eptAtom;
-       atoms2->pdbinfo[index2[i]].bAnisotropic = FALSE;
+       /* atoms2->pdbinfo[index2[i]].type = eptAtom; */
+/*     atoms2->pdbinfo[index2[i]].bAnisotropic = FALSE; */
        if (bBfac)
-         atoms2->pdbinfo[index2[i]].bfac = 800*M_PI*M_PI/3.0*msds[i]/100;
-       if (bLabel)
-         atoms2->resinfo[atoms2->atom[index2[i]].resind].chain = 'B';
+         atoms2->pdbinfo[index2[i]].bfac = (800*M_PI*M_PI/3.0)*msds[i];
+/*     if (bLabel) */
+/*       atoms2->resinfo[atoms2->atom[index2[i]].resind].chain = 'B'; */
       }
     }
     fp=ffopen(outfile,"w");
index 57ee9ca47132522b6b19ed185f1c9dfb2ff7f835..78da9e032b66c6cd1e975355499c1a4bdfb9faa7 100644 (file)
@@ -112,7 +112,8 @@ int gmx_covar(int argc,char *argv[])
       "Apply corrections for periodic boundary conditions" }
   };
   FILE       *out;
-  int        status,trjout;
+  t_trxstatus *status;
+  t_trxstatus *trjout;
   t_topology top;
   int        ePBC;
   t_atoms    *atoms;  
@@ -137,6 +138,7 @@ int gmx_covar(int argc,char *argv[])
   t_rgb      rlo,rmi,rhi;
   real       *tmp;
   output_env_t oenv;
+  gmx_rmpbc_t  gpbc=NULL;
 
   t_filenm fnm[] = { 
     { efTRX, "-f",  NULL, ffREAD }, 
@@ -216,10 +218,12 @@ int gmx_covar(int argc,char *argv[])
        w_rls[ifit[i]]=1.0;
     }
   }
-
+  
   /* Prepare reference frame */
-  if (bPBC)
-    rm_pbc(&(top.idef),ePBC,atoms->nr,box,xref,xref);
+  if (bPBC) {
+    gpbc = gmx_rmpbc_init(&top.idef,ePBC,atoms->nr,box);
+    gmx_rmpbc(gpbc,box,xref,xref);
+  }
   if (bFit)
     reset_x(nfit,ifit,atoms->nr,NULL,xref,w_rls);
 
@@ -240,7 +244,7 @@ int gmx_covar(int argc,char *argv[])
     nframes0++;
     /* calculate x: a fitted struture of the selected atoms */
     if (bPBC)
-      rm_pbc(&(top.idef),ePBC,nat,box,xread,xread);
+      gmx_rmpbc(gpbc,box,xread,xread);
     if (bFit) {
       reset_x(nfit,ifit,nat,NULL,xread,w_rls);
       do_fit(nat,w_rls,xref,xread);
@@ -269,7 +273,7 @@ int gmx_covar(int argc,char *argv[])
     tend = t;
     /* calculate x: a (fitted) structure of the selected atoms */
     if (bPBC)
-      rm_pbc(&(top.idef),ePBC,nat,box,xread,xread);
+      gmx_rmpbc(gpbc,box,xread,xread);
     if (bFit) {
       reset_x(nfit,ifit,nat,NULL,xread,w_rls);
       do_fit(nat,w_rls,xref,xread);
@@ -295,6 +299,7 @@ int gmx_covar(int argc,char *argv[])
   } while (read_next_x(oenv,status,&t,nat,xread,box) && 
           (bRef || nframes < nframes0));
   close_trj(status);
+  gmx_rmpbc_done(gpbc);
 
   fprintf(stderr,"Read %d frames\n",nframes);
   
index b0044c6df39cd21502af6717f32a74929aea5fa4..8f67f7f550e7ac7b4953e4d9c4432ee2dc59e2d1 100644 (file)
@@ -288,7 +288,7 @@ static void dielectric(FILE *fmj,FILE *fmd,FILE *outf,FILE *fcur,FILE *mcor,
                        FILE *fmjdsp, bool bNoJump,bool bACF,bool bINT,
                        int ePBC,t_topology top, t_trxframe fr,real temp,
                        real trust,real bfit,real efit,real bvit,real evit,
-                      int status,int isize,int nmols, int nshift,
+                      t_trxstatus *status,int isize,int nmols, int nshift,
                        atom_id *index0,int indexm[],real mass2[],
                        real qmol[], real eps_rf, const output_env_t oenv)
 {
@@ -344,7 +344,8 @@ static void dielectric(FILE *fmj,FILE *fmd,FILE *outf,FILE *fcur,FILE *mcor,
   real err=0.0;
   real *xfit;
   real *yfit;
-
+  gmx_rmpbc_t  gpbc=NULL;
   /*
    * indices for EH
    */
@@ -377,7 +378,8 @@ static void dielectric(FILE *fmj,FILE *fmd,FILE *outf,FILE *fcur,FILE *mcor,
   clear_rvec(mjd_tmp);
   clear_rvec(mdvec);
   clear_rvec(tmp);
-  
+  gpbc = gmx_rmpbc_init(&top.idef,ePBC,fr.natoms,fr.box);
+
   do{
     
     refr=(real)(nfr+1);
@@ -426,8 +428,8 @@ static void dielectric(FILE *fmj,FILE *fmd,FILE *outf,FILE *fcur,FILE *mcor,
 
     }
     
-               rm_pbc(&top.idef,ePBC,fr.natoms,fr.box,fr.x,fr.x);
-
+               gmx_rmpbc(gpbc,fr.box,fr.x,fr.x);
+               
                calc_mj(top,ePBC,fr.box,bNoJump,nmols,indexm,fr.x,mtrans[nfr],mass2,qmol);
 
     for(i=0;i<isize;i++){
@@ -505,6 +507,8 @@ static void dielectric(FILE *fmj,FILE *fmd,FILE *outf,FILE *fcur,FILE *mcor,
     
   }while(read_next_frame(oenv,status,&fr));
   
+  gmx_rmpbc_done(gpbc);
   volume_av/=refr;
   
        prefactor=1.0;
@@ -705,7 +709,7 @@ int gmx_current(int argc,char *argv[])
   atom_id    *index0=NULL;
   int                                  *indexm=NULL;
   int        isize;
-  int        status;
+  t_trxstatus *status;
   int        flags = 0;
   bool      bTop;
   bool          bNEU;
@@ -752,7 +756,7 @@ int gmx_current(int argc,char *argv[])
     "[PAR]",
     "The flag [TT]-caf[tt] is for the output of the current autocorrelation function and [TT]-mc[tt] writes the",
     "correlation of the rotational and translational part of the dipole moment in the corresponding",
-    "file. However this option is only available for trajectories containing velocities."
+    "file. However this option is only available for trajectories containing velocities.",
     "Options [TT]-sh[tt] and [TT]-tr[tt] are responsible for the averaging and integration of the",
     "autocorrelation functions. Since averaging proceeds by shifting the starting point",
     "through the trajectory, the shift can be modified with [TT]-sh[tt] to enable the choice of uncorrelated",
@@ -761,7 +765,7 @@ int gmx_current(int argc,char *argv[])
     "the number of frames. The option [TT]-tr[tt] controls the region of the integral taken into account",
     "for calculating the static dielectric constant.",
     "[PAR]",
-    "Option [TT]-temp[tt] sets the temperature required for the computation of the static dielectric constant."
+    "Option [TT]-temp[tt] sets the temperature required for the computation of the static dielectric constant.",
     "[PAR]",
     "Option [TT]-eps[tt] controls the dielectric constant of the surrounding medium for simulations using",
     "a Reaction Field or dipole corrections of the Ewald summation (eps=0 corresponds to",
index 2b2662831aef407e77dfa3a4d6081e78d89b60e2..b1b39e3dc8ac49740c7d68ade016a675ea024d10 100644 (file)
@@ -149,14 +149,15 @@ void calc_electron_density(const char *fn, atom_id **index, int gnx[],
 {
   rvec *x0;              /* coordinates without pbc */
   matrix box;            /* box (3x3) */
-  int natoms,            /* nr. atoms in trj */
-      status,  
-      i,n,               /* loop indices */
+  int natoms;            /* nr. atoms in trj */
+  t_trxstatus *status;  
+  int i,n,               /* loop indices */
       ax1=0, ax2=0,
       nr_frames = 0,     /* number of frames */
       slice;             /* current slice */
   t_electron *found;     /* found by bsearch */
   t_electron sought;     /* thingie thought by bsearch */
+  gmx_rmpbc_t  gpbc=NULL;
  
   real t, 
         z;
@@ -186,9 +187,10 @@ void calc_electron_density(const char *fn, atom_id **index, int gnx[],
   for (i = 0; i < nr_grps; i++)
     snew((*slDensity)[i], *nslices);
   
+  gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
   /*********** Start processing trajectory ***********/
   do {
-    rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x0,x0);
+    gmx_rmpbc(gpbc,box,x0,x0);
 
     if (bCenter)
       center_coords(&top->atoms,box,x0,axis);
@@ -224,7 +226,8 @@ void calc_electron_density(const char *fn, atom_id **index, int gnx[],
     }
       nr_frames++;
   } while (read_next_x(oenv,status,&t,natoms,x0,box));
-  
+  gmx_rmpbc_done(gpbc);
+
   /*********** done with status file **********/
   close_trj(status);
   
@@ -251,9 +254,9 @@ void calc_density(const char *fn, atom_id **index, int gnx[],
 {
   rvec *x0;              /* coordinates without pbc */
   matrix box;            /* box (3x3) */
-  int natoms,            /* nr. atoms in trj */
-      status,  
-      **slCount,         /* nr. of atoms in one slice for a group */
+  int natoms;            /* nr. atoms in trj */
+  t_trxstatus *status;  
+  int  **slCount,         /* nr. of atoms in one slice for a group */
       i,j,n,               /* loop indices */
       teller = 0,      
       ax1=0, ax2=0,
@@ -262,6 +265,7 @@ void calc_density(const char *fn, atom_id **index, int gnx[],
   real t, 
         z;
   char *buf;             /* for tmp. keeping atomname */
+  gmx_rmpbc_t  gpbc=NULL;
 
   switch(axis) {
   case 0:
@@ -289,9 +293,10 @@ void calc_density(const char *fn, atom_id **index, int gnx[],
   for (i = 0; i < nr_grps; i++)
     snew((*slDensity)[i], *nslices);
   
+  gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
   /*********** Start processing trajectory ***********/
   do {
-    rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x0,x0);
+    gmx_rmpbc(gpbc,box,x0,x0);
 
     if (bCenter)
       center_coords(&top->atoms,box,x0,axis);
@@ -315,7 +320,8 @@ void calc_density(const char *fn, atom_id **index, int gnx[],
 
     nr_frames++;
   } while (read_next_x(oenv,status,&t,natoms,x0,box));
-  
+  gmx_rmpbc_done(gpbc);
+
   /*********** done with status file **********/
   close_trj(status);
   
index 4394116bf835022f0117d3e070a61d931fde6d4d..1a4c5406433ace25ca83bd1e2d9083e35ccb17c3 100644 (file)
@@ -134,7 +134,7 @@ int gmx_densmap(int argc,char *argv[])
   };
   bool       bXmin,bXmax,bRadial;
   FILE       *fp;
-  int        status;
+  t_trxstatus *status;
   t_topology top;
   int        ePBC=-1;
   rvec       *x,xcom[2],direction,center,dx;
index 7db575e7021e43e3a1a7b58f5ead31a72345d2f5..fb13f5a85cdedaa3ee92ce1d55552e3df5aa64ec 100644 (file)
@@ -97,7 +97,7 @@ real numerical_deriv(int nx,real x[],real y[],real fity[],real combined[],real d
   else {
     i0 = max(0,nbegin);
     i1 = min(nx-1,nbegin+nsmooth);
-    printf("Making smooth transition from %d thru %d\n",i0,i1);
+    printf("Making smooth transition from %d through %d\n",i0,i1);
     for(i=0; (i<i0); i++)
       combined[i]=y[i];
     for(i=i0; (i<=i1); i++) {
@@ -201,10 +201,10 @@ int gmx_dielectric(int argc,char *argv[])
     "For an estimate of the error you can run g_statistics on the",
     "ACF, and use the output thus generated for this program.",
     "The functional forms of the available functions are:[PAR]",
-    "One parmeter  : y = Exp[-a1 x]",
-    "Two parmeters : y = a2 Exp[-a1 x]",
-    "Three parmeter: y = a2 Exp[-a1 x] + (1 - a2) Exp[-a3 x]",
-    "Startvalues for the fit procedure can be given on the commandline.",
+    "One parameter  : y = Exp[-a1 x],",
+    "Two parameters : y = a2 Exp[-a1 x],",
+    "Three parameters: y = a2 Exp[-a1 x] + (1 - a2) Exp[-a3 x].",
+    "Start values for the fit procedure can be given on the command line.",
     "It is also possible to fix parameters at their start value, use -fix",
     "with the number of the parameter you want to fix.",
     "[PAR]",
@@ -213,10 +213,10 @@ int gmx_dielectric(int argc,char *argv[])
     "numerical derivative of the combination data/fit.",
     "The second file contains the real and imaginary parts of the",
     "frequency-dependent dielectric constant, the last gives a plot",
-    "known as the Cole-Cole plot, in which the  imaginary",
+    "known as the Cole-Cole plot, in which the imaginary",
     "component is plotted as a function of the real component.",
     "For a pure exponential relaxation (Debye relaxation) the latter",
-    "plot should be one half of a circle"
+    "plot should be one half of a circle."
   };
   t_filenm fnm[] = {
     { efXVG, "-f", "dipcorr",ffREAD  },
index f0d9838acb9734fd3274772e4ae6226a7b725f0f..7b8be92b49ebf3fd5b2cb6209d98e2e20bc36026 100644 (file)
@@ -262,7 +262,7 @@ static void ana_trans(FILE *out, t_xrama *xr,real **dih,real time[],
   fprintf(out,"%-10s %10s %10s %10s %10s %10s %10s\n",
          "index","minimum","average","maximum","variance","std.dev",
          "transition");
-  for(i=0; (i>xr->ndih); i++) {
+  for(i=0; (i<xr->ndih); i++) {
     sprintf(buf,"dih-%d",i);
     ana_dih(out,buf,nframes,dih[i],&(xr->dih[i]));
   }
index f94c92336316d0bd24056eee82eacebdee4e0a80..2224c00c7fb1e88b2debf14ee559fe685ba7707d 100644 (file)
@@ -673,7 +673,8 @@ static void do_dip(t_topology *top,int ePBC,real volume,
   t_enxframe *fr;
   int        nframes=1000,nre,timecheck=0,ncolour=0;
   ener_file_t fmu=NULL;
-  int        i,j,k,n,m,natom=0,nmol,status,gnx_tot,teller,tel3;
+  int        i,j,k,n,m,natom=0,nmol,gnx_tot,teller,tel3;
+  t_trxstatus *status;
   int        *dipole_bin,ndipbin,ibin,iVol,step,idim=-1;
   unsigned long mode;
   char       buf[STRLEN];
@@ -690,6 +691,7 @@ static void do_dip(t_topology *top,int ePBC,real volume,
   rvec       *slab_dipoles=NULL;
   t_atom     *atom=NULL;
   t_block    *mols=NULL;
+  gmx_rmpbc_t gpbc=NULL;
 
   gnx_tot = gnx[0];
   if (ncos > 1) {
@@ -847,6 +849,7 @@ static void do_dip(t_topology *top,int ePBC,real volume,
 
     gkrbin = mk_gkrbin(rcut,rcmax,bPhi,ndegrees); 
   }
+  gpbc = gmx_rmpbc_init(&top->idef,ePBC,natom,box);
 
   /* Start while loop over frames */
   t1 = t0 = t;
@@ -875,7 +878,7 @@ static void do_dip(t_topology *top,int ePBC,real volume,
        M_av[m] = 0;
        M_av2[m] = 0;
       }
-      rm_pbc(&(top->idef),ePBC,natom,box,x,x);
+      gmx_rmpbc(gpbc,box,x,x);
       
       muframelsq = gmx_stats_init();
       /* Begin loop of all molecules in frame */
@@ -1069,6 +1072,8 @@ static void do_dip(t_topology *top,int ePBC,real volume,
       bCont = read_next_x(oenv,status,&t,natom,x,box);
   } while (bCont);
   
+  gmx_rmpbc_done(gpbc);
+
   if (!bMU)
     close_trj(status);
     
@@ -1221,7 +1226,7 @@ int gmx_dipoles(int argc,char *argv[])
     "option -corr is used. The output file name is given with the [TT]-c[tt]",
     "option.",
     "The correlation functions can be averaged over all molecules",
-    "([TT]mol[tt]), plotted per molecule seperately ([TT]molsep[tt])",
+    "([TT]mol[tt]), plotted per molecule separately ([TT]molsep[tt])",
     "or it can be computed over the total dipole moment of the simulation box",
     "([TT]total[tt]).[PAR]",
     "Option [TT]-g[tt] produces a plot of the distance dependent Kirkwood",
@@ -1256,7 +1261,7 @@ int gmx_dipoles(int argc,char *argv[])
     { "-mumax",    FALSE, etREAL, {&mu_max},
       "max dipole in Debye (for histrogram)" },
     { "-epsilonRF",FALSE, etREAL, {&epsilonRF},
-      "epsilon of the reaction field used during the simulation, needed for dieclectric constant calculation. WARNING: 0.0 means infinity (default)" },
+      "epsilon of the reaction field used during the simulation, needed for dielectric constant calculation. WARNING: 0.0 means infinity (default)" },
     { "-skip",     FALSE, etINT, {&skip},
       "Skip steps in the output (but not in the computations)" },
     { "-temp",     FALSE, etREAL, {&temp},
index 47d9335cf69fa4eb79d4bf928739621cd20d0655..e67d3c145034a6f320f1a1dd5db8e81bb8b086e5 100644 (file)
@@ -588,7 +588,8 @@ int gmx_disre(int argc,char *argv[])
   t_nrnb      nrnb;
   t_commrec   *cr;
   t_graph     *g;
-  int         status,ntopatoms,natoms,i,j,kkk;
+  int         ntopatoms,natoms,i,j,kkk;
+  t_trxstatus *status;
   real        t;
   rvec        *x,*f,*xav=NULL;
   matrix      box;
@@ -605,7 +606,8 @@ int gmx_disre(int argc,char *argv[])
   int         my_clust;
   FILE        *fplog;
   output_env_t oenv;
-
+  gmx_rmpbc_t  gpbc=NULL;
+  
   t_filenm fnm[] = {
     { efTPX, NULL, NULL, ffREAD },
     { efTRX, "-f", NULL, ffREAD },
@@ -712,13 +714,16 @@ int gmx_disre(int argc,char *argv[])
   init_forcerec(fplog,oenv,fr,NULL,&ir,&mtop,cr,box,FALSE,NULL,NULL,NULL,
                 FALSE,-1);
   init_nrnb(&nrnb);
+  if (ir.ePBC != epbcNONE)
+    gpbc = gmx_rmpbc_init(&top->idef,ir.ePBC,natoms,box);
+  
   j=0;
   do {
     if (ir.ePBC != epbcNONE) {
       if (ir.bPeriodicMols)
        set_pbc(&pbc,ir.ePBC,box);
       else
-       rm_pbc(&top->idef,ir.ePBC,natoms,box,x,x);
+       gmx_rmpbc(gpbc,box,x,x);
     }
     
     if (clust) {
@@ -760,6 +765,8 @@ int gmx_disre(int argc,char *argv[])
     j++;
   } while (read_next_x(oenv,status,&t,natoms,x,box));
   close_trj(status);
+  if (ir.ePBC != epbcNONE)
+    gmx_rmpbc_done(gpbc);
 
   if (clust) {
     dump_clust_stats(fplog,fcd.disres.nres,&(top->idef.il[F_DISRES]),
index 744c7bcffb43b54a91341914cb6ee76c437e4629..ca23546dbc3e50c60436cffc05b939d165ef25f0 100644 (file)
@@ -87,7 +87,7 @@ int gmx_dist(int argc,char *argv[])
   real t,t0,cut2,dist2;
   rvec *x=NULL,*v=NULL,dx;
   matrix box;
-  int status;
+  t_trxstatus *status;
   int natoms;
 
   int g,d,i,j,res,teller=0;
@@ -105,6 +105,7 @@ int gmx_dist(int argc,char *argv[])
   int     *contact_time=NULL,*ccount=NULL,ccount_nalloc=0,sum;
   char    buf[STRLEN];
   output_env_t oenv;
+  gmx_rmpbc_t  gpbc=NULL;
   
   char *leg[4] = { "|d|","d\\sx\\N","d\\sy\\N","d\\sz\\N" };
 
@@ -181,12 +182,13 @@ int gmx_dist(int argc,char *argv[])
   else
     pbc = NULL;
     
+  gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
   do {
     /* initialisation for correct distance calculations */
     if (pbc) {
       set_pbc(pbc,ePBC,box);
       /* make molecules whole again */
-      rm_pbc(&top->idef,ePBC,natoms,box,x,x);
+      gmx_rmpbc(gpbc,box,x,x);
     }
     /* calculate center of masses */
     for(g=0;(g<ngrps);g++) {
@@ -247,6 +249,7 @@ int gmx_dist(int argc,char *argv[])
     
     teller++;
   } while (read_next_x(oenv,status,&t,natoms,x,box));
+  gmx_rmpbc_done(gpbc);
 
   if (!bCutoff)
     ffclose(fp);
index 0390c5c0177cfd4e11028439d150b47d71941950..356776c29d090945caa74e36c614291fefcac3fd 100644 (file)
@@ -167,7 +167,8 @@ int gmx_dyndom(int argc,char *argv[])
     { "-tail",     FALSE, etRVEC, {tail},
       "Last atom of the arrow vector" }
   };
-  int     i,j,natoms,isize,status;
+  int     i,j,natoms,isize;
+  t_trxstatus *status;
   atom_id *index=NULL,*index_all;
   char    title[256],*grpname;
   t_atoms atoms;
index 3445dae339efd5c772c4df0fa836470b912562d0..9f6d0f7c3b5c14445b0c766e28fe7dc152e727a1 100644 (file)
@@ -462,8 +462,8 @@ int gmx_editconf(int argc, char *argv[])
                 "[PAR]",
                 "Option [TT]-bt[tt] determines the box type: [TT]triclinic[tt] is a",
                 "triclinic box, [TT]cubic[tt] is a rectangular box with all sides equal",
-                "[TT]dodecahedron[tt] represents a rhombic dodecahedron and "
-                    "[TT]octahedron[tt] is a truncated octahedron.",
+                "[TT]dodecahedron[tt] represents a rhombic dodecahedron and",
+                "[TT]octahedron[tt] is a truncated octahedron.",
                 "The last two are special cases of a triclinic box.",
                 "The length of the three box vectors of the truncated octahedron is the",
                 "shortest distance between two opposite hexagons.",
@@ -529,7 +529,7 @@ int gmx_editconf(int argc, char *argv[])
                                "with an optional center of rotation specified by [TT]-aligncenter[tt].",
                 "[PAR]",
                 "Finally with option [TT]-label[tt] editconf can add a chain identifier",
-                "to a pdb file, which can be useful for analysis with e.g. rasmol."
+                "to a pdb file, which can be useful for analysis with e.g. rasmol.",
                     "[PAR]",
                 "To convert a truncated octrahedron file produced by a package which uses",
                 "a cubic box with the corners cut off (such as Gromos) use:[BR]",
@@ -537,8 +537,8 @@ int gmx_editconf(int argc, char *argv[])
                 "where [TT]veclen[tt] is the size of the cubic box times sqrt(3)/2." };
     const char *bugs[] =
         {
-            "For complex molecules, the periodicity removal routine may break down, "
-                "in that case you can use trjconv" };
+            "For complex molecules, the periodicity removal routine may break down, ",
+                "in that case you can use trjconv." };
     static real dist = 0.0, rbox = 0.0, to_diam = 0.0;
     static bool bNDEF = FALSE, bRMPBC = FALSE, bCenter = FALSE, bReadVDW =
         FALSE, bCONECT = FALSE;
index 769bcef984c6de9561674322463f2937988f4d1e..f94a3dbf1c75a7d8c713436d63571a0b5081a1ed 100644 (file)
@@ -425,7 +425,7 @@ static void update_ee_sum(int nre,
     }
     nsteps = fr->nsteps;
     nsum   = fr_nsum;
-  } else if (out_step - *ee_sum_step == nsteps + fr->nsteps) {
+  } else if (out_step + *ee_sum_nsum - *ee_sum_step == nsteps + fr->nsteps) {
     if (fr_nsum == 1) {
       for(i=0;i<nre;i++) {
        ee_sum[i].eav  +=
@@ -661,7 +661,8 @@ int gmx_eneconv(int argc,char *argv[])
        if (ee_sum_nsum <= 1) {
          fro->nsum = 0;
        } else {
-         fro->nsum = ee_sum_nsum;
+         fro->nsum = gmx_large_int_to_int(ee_sum_nsum,
+                                          "energy average summation");
          /* Copy the energy sums */
          for(i=0; i<nre; i++) {
            fro->ener[i].esum = ee_sum[i].esum;
index 786a90997197fd1f2b01cb499b3ed1b44e2b7ac1..89fbdf40c71ce522b2d63b86ad0e5ac0453dd1be 100644 (file)
@@ -117,7 +117,7 @@ int gmx_enemat(int argc,char *argv[])
     { "-skip", FALSE, etINT,  {&skip},
       "Skip number of frames between data points" },
     { "-mean", FALSE, etBOOL, {&bMeanEmtx},
-      "with -groups extracts matrix of mean energies in stead of "
+      "with -groups extracts matrix of mean energies instead of "
       "matrix for each timestep" },
     { "-nlevels", FALSE, etINT, {&nlevels},"number of levels for matrix colors"},
     { "-max",FALSE, etREAL, {&cutmax},"max value for energies"},
index 552090887c6817a261f7f3933b5c2292cf921d35..967ef43a6bb1bf1c5254283bb5301b4dc5870135 100644 (file)
@@ -865,7 +865,7 @@ static void analyse_ener(bool bCorr,const char *corrfn,
   int  nexact,nnotexact;
   double x1m,x1mk;
   real Temp=-1,Pres=-1,VarV=-1,VarT=-1,VarEtot=-1,AvEtot=0,VarEnthalpy=-1;
-  int  i,j;
+  int  i,j,nout;
   real chi2;
   char buf[256],eebuf[100];
 
@@ -878,7 +878,7 @@ static void analyse_ener(bool bCorr,const char *corrfn,
     /* Calculate the time difference */
     delta_t = t - start_t;
     
-    fprintf(stdout,"\nStatistics over %s steps [ %.4f thru %.4f ps ], %d data sets\n",
+    fprintf(stdout,"\nStatistics over %s steps [ %.4f through %.4f ps ], %d data sets\n",
            gmx_step_str(nsteps,buf),start_t,t,nset);
 
     calc_averages(nset,edat,nbmin,nbmax);
@@ -1100,23 +1100,27 @@ static void analyse_ener(bool bCorr,const char *corrfn,
       /* Use trapezium rule for integration */
       integral = 0;
       intBulk  = 0;
-      for(i=1; (i<edat->nframes/2); i++) {
-       integral += 0.5*(eneset[0][i-1]  + eneset[0][i])*factor;
-       intBulk  += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
-       fprintf(fp,"%10g  %10g  %10g\n",(i*Dt),integral,intBulk);
+      nout = get_acfnout();
+      if ((nout < 2) || (nout >= edat->nframes/2))
+          nout = edat->nframes/2;
+      for(i=1; (i<nout); i++) 
+      {
+          integral += 0.5*(eneset[0][i-1]  + eneset[0][i])*factor;
+          intBulk  += 0.5*(eneset[11][i-1] + eneset[11][i])*factor;
+          fprintf(fp,"%10g  %10g  %10g\n",(i*Dt),integral,intBulk);
       }
       ffclose(fp);
     }
     else if (bCorr) {
       if (bFluct)
-       strcpy(buf,"Autocorrelation of Energy Fluctuations");
+          strcpy(buf,"Autocorrelation of Energy Fluctuations");
       else
-       strcpy(buf,"Energy Autocorrelation");
+          strcpy(buf,"Energy Autocorrelation");
 #if 0
       do_autocorr(corrfn,oenv,buf,edat->nframes,
-                 bSum ? 1                 : nset,
-                 bSum ? &edat->s[nset-1].ener : eneset,
-                 (delta_t/edat->nframes),eacNormal,FALSE);
+                  bSum ? 1                 : nset,
+                  bSum ? &edat->s[nset-1].ener : eneset,
+                  (delta_t/edat->nframes),eacNormal,FALSE);
 #endif
     }
   }
@@ -1301,7 +1305,7 @@ int gmx_energy(int argc,char *argv[])
     "difference with an ideal gas state: [BR]",
     "  Delta A = A(N,V,T) - A_idgas(N,V,T) = kT ln < e^(Upot/kT) >[BR]",
     "  Delta G = G(N,p,T) - G_idgas(N,p,T) = kT ln < e^(Upot/kT) >[BR]",
-    "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and"
+    "where k is Boltzmann's constant, T is set by [TT]-fetemp[tt] and",
     "the average is over the ensemble (or time in a trajectory).",
     "Note that this is in principle",
     "only correct when averaging over the whole (Boltzmann) ensemble",
index c07deeed82fc93c556dde985c942379c34fe5b74..5c7c67218a32c193d136154a0317672502227985 100644 (file)
@@ -102,12 +102,14 @@ int gmx_filter(int argc,char *argv[])
   int        isize;
   atom_id    *index;
   real       *w_rls=NULL;
-  int        in,outl,outh;
+  t_trxstatus *in;
+  t_trxstatus *outl,*outh;
   int        nffr,i,fr,nat,j,d,m;
   atom_id    *ind;
   real       flen,*filt,sum,*t;
   rvec       xcmtop,xcm,**x,*ptr,*xf,*xn,*xp,hbox;
   output_env_t oenv;
+  gmx_rmpbc_t  gpbc=NULL;
 
 #define NLEG asize(leg)
   t_filenm fnm[] = { 
@@ -131,12 +133,12 @@ int gmx_filter(int argc,char *argv[])
     topfile = ftp2fn_null(efTPS,NFILE,fnm);
     lowfile = opt2fn("-ol",NFILE,fnm);
   }
-
   if (topfile) {
     bTop = read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,
                         &xtop,NULL,topbox,TRUE);
     if (bTop) {
-      rm_pbc(&(top.idef),ePBC,top.atoms.nr,topbox,xtop,xtop);
+      gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,topbox);
+      gmx_rmpbc(gpbc,topbox,xtop,xtop);
     }
   }
 
@@ -212,7 +214,7 @@ int gmx_filter(int argc,char *argv[])
          }
     }
     if (bTop) {
-      rm_pbc(&(top.idef),ePBC,nat,box[nffr - 1],xn,xn);
+      gmx_rmpbc(gpbc,box[nffr - 1],xn,xn);
     }
     if (bFit) {
       calc_xcm(xn,isize,index,top.atoms.atom,xcm,FALSE);
@@ -264,6 +266,9 @@ int gmx_filter(int argc,char *argv[])
     fr++;
   } while (read_next_x(oenv,in,&(t[nffr - 1]),nat,x[nffr - 1],box[nffr - 1]));
   
+  if (bTop)
+    gmx_rmpbc_done(gpbc);
+
   if (outh)
     close_trx(outh);
   if (outl)
index beb071407c2f9b95e025ec513156f70f5db98555..08932cc60761af5652708f53ad694dea4c83e6dd 100644 (file)
@@ -124,7 +124,7 @@ int gmx_genconf(int argc, char *argv[])
     
   };
   const char *bugs[] = {
-    "The program should allow for random displacement off lattice points." };
+    "The program should allow for random displacement of lattice points." };
 
   int     vol;          
   t_atoms *atoms;       /* list with all atoms */
@@ -137,7 +137,8 @@ int gmx_genconf(int argc, char *argv[])
   rvec    shift;         
   int     natoms;       /* number of atoms in one molecule  */
   int     nres;         /* number of molecules? */
-  int     i,j,k,l,m,ndx,nrdx,nx,ny,nz,status=-1;
+  int     i,j,k,l,m,ndx,nrdx,nx,ny,nz;
+  t_trxstatus *status;
   bool    bTRX;
   output_env_t oenv;
   
index 7798c63f64683a8e14aa6e9c2b32d089a90b9e44..c6a7f97ad474c4604368ec3bf5d6c6fdd108c44b 100644 (file)
@@ -175,7 +175,7 @@ int gmx_gyrate(int argc,char *argv[])
       "Calculate the 2D radii of gyration of # slices along the z-axis" },
   };
   FILE       *out;
-  int        status;
+  t_trxstatus *status;
   t_topology top;
   int        ePBC;
   rvec       *x,*x_s;
@@ -191,6 +191,7 @@ int gmx_gyrate(int argc,char *argv[])
   int        i,j,m,gnx,nam,mol;
   atom_id    *index;
   output_env_t oenv;
+  gmx_rmpbc_t  gpbc=NULL;
   char *leg[]  = { "Rg", "RgX", "RgY", "RgZ" }; 
   char *legI[] = { "Itot", "I1", "I2", "I3" }; 
 #define NLEG asize(leg) 
@@ -260,9 +261,11 @@ int gmx_gyrate(int argc,char *argv[])
        fprintf(out,"@ subtitle \"Axes are principal component axes\"\n");
     xvgr_legend(out,NLEG,leg,oenv);
   }
+  if (nz == 0)
+    gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
   do {
     if (nz == 0)
-      rm_pbc(&top.idef,ePBC,natoms,box,x,x_s);
+      gmx_rmpbc(gpbc,box,x,x_s);
     gyro = 0;
     clear_rvec(gvec);
     clear_rvec(d);
@@ -300,6 +303,8 @@ int gmx_gyrate(int argc,char *argv[])
     j++;
   } while(read_next_x(oenv,status,&t,natoms,x,box));
   close_trj(status);
+  if (nz == 0)
+    gmx_rmpbc_done(gpbc);
   
   ffclose(out);
 
index 1244baea2ef4b86ae2996c271671a0d02a84fb6c..2ee87b786fc357874c99ee3f53491ff56539103d 100644 (file)
@@ -76,7 +76,7 @@ void calc_h2order(const char *fn, atom_id index[], int ngx, rvec **slDipole,
        com;              /* center of mass of micel, with bMicel */
   rvec *dip;             /* sum of dipoles, unnormalized */
   matrix box;            /* box (3x3) */
-  int   status;
+  t_trxstatus *status;
   real  t,               /* time from trajectory */
        *sum,             /* sum of all cosines of dipoles, per slice */
        *frame;           /* order over one frame */
@@ -84,7 +84,8 @@ void calc_h2order(const char *fn, atom_id index[], int ngx, rvec **slDipole,
       i,j,teller = 0,
       slice=0,           /* current slice number */
       *count;            /* nr. of atoms in one slice */
-
+  gmx_rmpbc_t  gpbc=NULL;
+  
   if ((natoms = read_first_x(oenv,&status,fn,&t,&x0,box)) == 0)
     gmx_fatal(FARGS,"Could not read coordinates from statusfile\n");
 
@@ -121,13 +122,14 @@ void calc_h2order(const char *fn, atom_id index[], int ngx, rvec **slDipole,
 
   teller = 0; 
 
+  gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
   /*********** Start processing trajectory ***********/
   do 
   {
     *slWidth = box[axis][axis]/(*nslices);
     teller++;
     
-    rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x0,x0);
+    gmx_rmpbc(gpbc,box,x0,x0);
 
     if (bMicel)
       calc_xcm(x0, nmic, micel, top->atoms.atom, com, FALSE);
@@ -197,6 +199,7 @@ void calc_h2order(const char *fn, atom_id index[], int ngx, rvec **slDipole,
   /*********** done with status file **********/
  
   fprintf(stderr,"\nRead trajectory. Printing parameters to file\n");
+  gmx_rmpbc_done(gpbc);
 
   for (i = 0; i < *nslices; i++)  /* average over frames */
   {
index 867b76d64bafb79644935601cd577ac9bb7a8770..78889448ff63980deb26392b2c9ba065f096b41c 100644 (file)
@@ -1,4 +1,4 @@
-/*
+/* -*- mode: c; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4; c-file-style: "stroustrup"; -*-
  * 
  * 
  *                This source code is part of
 #endif
 #include <math.h>
 
+/*#define HAVE_NN_LOOPS*/
+/* Set environment variable CFLAGS = "-fopenmp" when running
+ * configure and define DOUSEOPENMP to make use of parallelized
+ * calculation of autocorrelation function.
+ * It also adds a new option -nthreads which sets the number of threads.
+ * */
+/*#define DOUSEOPENMP*/
+
+#ifdef DOUSEOPENMP
+#define HAVE_OPENMP
+#include "omp.h"
+#endif
+
 #include "statutil.h"
 #include "copyrite.h"
 #include "sysstuff.h"
 #include "pbc.h"
 #include "correl.h"
 #include "gmx_ana.h"
+#include "geminate.h"
 
-
+typedef short int t_E;
+typedef int t_EEst;
 #define max_hx 7
 typedef int t_hx[max_hx];
 #define NRHXTYPES max_hx
@@ -66,9 +81,18 @@ char *hxtypenames[NRHXTYPES]=
 {"n-n","n-n+1","n-n+2","n-n+3","n-n+4","n-n+5","n-n>6"};
 #define MAXHH 4
 
+#ifdef HAVE_OPENMP
+#define MASTER_THREAD_ONLY(threadNr) ((threadNr)==0)
+#else
+#define MASTER_THREAD_ONLY(threadNr) ((threadNr)==(threadNr))
+#endif
+
+/* -----------------------------------------*/
+
 enum { gr0,  gr1,    grI,  grNR };
 enum { hbNo, hbDist, hbHB, hbNR, hbR2}; 
 enum { noDA, ACC, DON, DA, INGROUP};
+enum {NN_NULL, NN_NONE, NN_BINARY, NN_1_over_r3, NN_dipole, NN_NR};
   
 static const char *grpnames[grNR] = {"0","1","I" };
 
@@ -89,122 +113,504 @@ static bool bDebug = FALSE;
 #define ISINGRP(h) (((h) & 4) == 4)
 
 typedef struct {
-  int nr;
-  int maxnr;
-  atom_id *atoms;
+    int nr;
+    int maxnr;
+    atom_id *atoms;
 } t_ncell;
 
 typedef struct {
-  t_ncell d[grNR];
-  t_ncell a[grNR];
+    t_ncell d[grNR];
+    t_ncell a[grNR];
 } t_gridcell;
 
 typedef int     t_icell[grNR];
 typedef atom_id h_id[MAXHYDRO];
  
 typedef struct {
-  int      history[MAXHYDRO]; 
-  /* Has this hbond existed ever? If so as hbDist or hbHB or both.
-   * Result is stored as a bitmap (1 = hbDist) || (2 = hbHB)
-   */
-  /* Bitmask array which tells whether a hbond is present
-   * at a given time. Either of these may be NULL 
-   */
-  int      n0;       /* First frame a HB was found     */ 
-  int      nframes,maxframes;  /* Amount of frames in this hbond */
-  unsigned int **h; 
-  unsigned int **g; 
-  /* See Xu and Berne, JPCB 105 (2001), p. 11929. We define the
-   * function g(t) = [1-h(t)] H(t) where H(t) is one when the donor-
-   * acceptor distance is less than the user-specified distance (typically
-   * 0.35 nm).
-   */
+    int      history[MAXHYDRO]; 
+    /* Has this hbond existed ever? If so as hbDist or hbHB or both.
+     * Result is stored as a bitmap (1 = hbDist) || (2 = hbHB)
+     */
+    /* Bitmask array which tells whether a hbond is present
+     * at a given time. Either of these may be NULL 
+     */
+    int      n0;       /* First frame a HB was found     */ 
+    int      nframes,maxframes;  /* Amount of frames in this hbond */
+    unsigned int **h; 
+    unsigned int **g; 
+    /* See Xu and Berne, JPCB 105 (2001), p. 11929. We define the
+     * function g(t) = [1-h(t)] H(t) where H(t) is one when the donor-
+     * acceptor distance is less than the user-specified distance (typically
+     * 0.35 nm).
+     */
 } t_hbond;
 
 typedef struct {
-  int     nra,max_nra;
-  atom_id *acc;             /* Atom numbers of the acceptors     */
-  int     *grp;             /* Group index                       */
-  int     *aptr;            /* Map atom number to acceptor index */
+    int     nra,max_nra;
+    atom_id *acc;             /* Atom numbers of the acceptors     */
+    int     *grp;             /* Group index                       */
+    int     *aptr;            /* Map atom number to acceptor index */
 } t_acceptors;
 
 typedef struct {
-  int      nrd,max_nrd;
-  int      *don;               /* Atom numbers of the donors         */
-  int      *grp;               /* Group index                        */
-  int      *dptr;              /* Map atom number to donor index     */
-  int      *nhydro;            /* Number of hydrogens for each donor */
-  h_id     *hydro;             /* The atom numbers of the hydrogens  */
-  h_id     *nhbonds;           /* The number of HBs per H at current */
+    int      nrd,max_nrd;
+    int      *don;               /* Atom numbers of the donors         */
+    int      *grp;               /* Group index                        */
+    int      *dptr;              /* Map atom number to donor index     */
+    int      *nhydro;            /* Number of hydrogens for each donor */
+    h_id     *hydro;             /* The atom numbers of the hydrogens  */
+    h_id     *nhbonds;           /* The number of HBs per H at current */
 } t_donors;
 
+/* Tune this to match memory requirements. It should be a signed integer type, e.g. signed char.*/
+#define PSTYPE int
+
+typedef struct {
+    int len;     /* The length of frame and p. */
+    int *frame;  /* The frames at which transitio*/
+    PSTYPE *p;
+} t_pShift;
+
+typedef struct {
+    /* Periodicity history. Used for the reversible geminate recombination. */
+    t_pShift **pHist;            /* The periodicity of every hbond in t_hbdata->hbmap:
+                                  *   pHist[d][a]. We can safely assume that the same
+                                  *   periodic shift holds for all hydrogens of a da-pair.
+                                  *
+                                  * Nowadays it only stores TRANSITIONS, and not the shift at every frame.
+                                  *   That saves a LOT of memory, an hopefully kills a mysterious bug where
+                                  *   pHist gets contaminated. */
+  
+    PSTYPE nper;    /* The length of p2i */
+    ivec *p2i;       /* Maps integer to periodic shift for a pair.*/
+    matrix P;        /* Projection matrix to find the box shifts. */
+    int gemtype;     /* enumerated type */
+} t_gemPeriod;
+
+typedef struct {
+    int nframes;
+    int *Etot;  /* Total energy for each frame */
+    t_E ****E;  /* Energy estimate for [d][a][h][frame-n0] */
+} t_hbEmap;
+
 typedef struct {
-  bool        bHBmap,bDAnr;
-  int         wordlen;
-  /* The following arrays are nframes long */
-  int         nframes,max_frames,maxhydro;
-  int         *nhb,*ndist;
-  h_id        *n_bound;
-  real        *time;
-  t_icell     *danr;
-  t_hx        *nhx;
-  /* These structures are initialized from the topology at start up */
-  t_donors    d;
-  t_acceptors a;
-  /* This holds a matrix with all possible hydrogen bonds */
-  int         nrhb,nrdist;
-  t_hbond     ***hbmap;
+    bool        bHBmap,bDAnr,bGem;
+    int         wordlen;
+    /* The following arrays are nframes long */
+    int         nframes,max_frames,maxhydro;
+    int         *nhb,*ndist;
+    h_id        *n_bound;
+    real        *time;
+    t_icell     *danr;
+    t_hx        *nhx;
+    /* These structures are initialized from the topology at start up */
+    t_donors    d;
+    t_acceptors a;
+    /* This holds a matrix with all possible hydrogen bonds */
+    int         nrhb,nrdist;
+    t_hbond     ***hbmap;
+#ifdef HAVE_NN_LOOPS
+    t_hbEmap    hbE;
+#endif
+    /* For parallelization reasons this will have to be a pointer.
+     * Otherwise discrepancies may arise between the periodicity data
+     * seen by different threads. */
+    t_gemPeriod *per;
 } t_hbdata;
 
+static void clearPshift(t_pShift *pShift)
+{
+    if (pShift->len > 0) {
+        sfree(pShift->p);
+        sfree(pShift->frame);
+        pShift->len = 0;
+    }
+}
+
+static void calcBoxProjection(matrix B, matrix P)
+{
+    const int vp[] = {XX,YY,ZZ};
+    int i,j;
+    int m,n;
+    matrix M, N, U;
+
+    for (i=0; i<3; i++){ m = vp[i];
+        for (j=0; j<3; j++){ n = vp[j];
+            U[m][n] = i==j ? 1:0;
+        }
+    }
+    m_inv(B,M);
+    for (i=0; i<3; i++){ m = vp[i];
+        mvmul(M, U[m], P[m]);
+    }
+    transpose(P,N);
+}
+
+static void calcBoxDistance(matrix P, rvec d, ivec ibd){
+    /* returns integer distance in box coordinates.
+     * P is the projection matrix from cartesian coordinates
+     * obtained with calcBoxProjection(). */
+    int i;
+    rvec bd;
+    mvmul(P, d, bd);
+    /* extend it by 0.5 in all directions since (int) rounds toward 0.*/
+    for (i=0;i<3;i++)
+        bd[i]=bd[i] + (bd[i]<0 ? -0.5 : 0.5);
+    ibd[XX] = (int)bd[XX];
+    ibd[YY] = (int)bd[YY];
+    ibd[ZZ] = (int)bd[ZZ];
+}
 
 /* Changed argument 'bMerge' into 'oneHB' below,
  * since -contact should cause maxhydro to be 1,
  * not just -merge.
  * - Erik Marklund May 29, 2006
  */
-static t_hbdata *mk_hbdata(bool bHBmap,bool bDAnr,bool oneHB)
+
+static PSTYPE periodicIndex(ivec r, t_gemPeriod *per, bool daSwap) {
+    /* Try to merge hbonds on the fly. That means that if the
+     * acceptor and donor are mergable, then:
+     * 1) store the hb-info so that acceptor id > donor id,
+     * 2) add the periodic shift in pairs, so that [-x,-y,-z] is
+     *    stored in per.p2i[] whenever acceptor id < donor id.
+     * Note that [0,0,0] should already be the first element of per.p2i
+     * by the time this function is called. */
+
+    /* daSwap is TRUE if the donor and acceptor were swapped.
+     * If so, then the negative vector should be used. */
+    PSTYPE i;
+
+    if (per->p2i == NULL || per->nper == 0)
+        gmx_fatal(FARGS, "'per' not initialized properly.");
+    for (i=0; i<per->nper; i++) {
+        if (r[XX] == per->p2i[i][XX] &&
+            r[YY] == per->p2i[i][YY] &&
+            r[ZZ] == per->p2i[i][ZZ])
+            return i;
+    }
+    /* Not found apparently. Add it to the list! */
+    /* printf("New shift found: %i,%i,%i\n",r[XX],r[YY],r[ZZ]); */
+
+/* Unfortunately this needs to be critical it seems. */
+#ifdef HAVE_OPENMP
+#pragma omp critical
+#endif
+    {
+        if (!per->p2i) {
+            fprintf(stderr, "p2i not initialized. This shouldn't happen!\n");
+            snew(per->p2i, 1);
+        }
+        else
+            srenew(per->p2i, per->nper+2);
+        copy_ivec(r, per->p2i[per->nper]);
+        (per->nper)++;
+
+        /* Add the mirror too. It's rather likely that it'll be needed. */
+        per->p2i[per->nper][XX] = -r[XX];
+        per->p2i[per->nper][YY] = -r[YY];
+        per->p2i[per->nper][ZZ] = -r[ZZ];
+        (per->nper)++;
+    } /* omp critical */
+    return per->nper - 1 - (daSwap ? 0:1);
+}
+
+static t_hbdata *mk_hbdata(bool bHBmap,bool bDAnr,bool oneHB, bool bGem, int gemmode)
 {
-  t_hbdata *hb;
+    t_hbdata *hb;
   
-  snew(hb,1);
-  hb->wordlen = 8*sizeof(unsigned int);
-  hb->bHBmap  = bHBmap;
-  hb->bDAnr   = bDAnr;
-  if (oneHB)
-    hb->maxhydro = 1;
-  else
-    hb->maxhydro = MAXHYDRO;
+    snew(hb,1);
+    hb->wordlen = 8*sizeof(unsigned int);
+    hb->bHBmap  = bHBmap;
+    hb->bDAnr   = bDAnr;
+    hb->bGem    = bGem;
+    if (oneHB)
+        hb->maxhydro = 1;
+    else
+        hb->maxhydro = MAXHYDRO;
+    snew(hb->per, 1);
+    hb->per->gemtype = bGem ? gemmode : 0;
   
-  return hb;
+    return hb;
 }
 
 static void mk_hbmap(t_hbdata *hb,bool bTwo,bool bInsert)
 {
-  int  i,j;
+    int  i,j;
+
+    snew(hb->hbmap,hb->d.nrd);
+    for(i=0; (i<hb->d.nrd); i++) {
+        snew(hb->hbmap[i],hb->a.nra);
+        if (hb->hbmap[i] == NULL)
+            gmx_fatal(FARGS,"Could not allocate enough memory for hbmap");
+        for (j=0; (j>hb->a.nra); j++)
+            hb->hbmap[i][j] = NULL;
+    }
+}
+
+/* Consider redoing pHist so that is only stores transitions between
+ * periodicities and not the periodicity for all frames. This eats heaps of memory. */
+static void mk_per(t_hbdata *hb)
+{
+    int i,j;
+    if (hb->bGem) {
+        snew(hb->per->pHist, hb->d.nrd);
+        for (i=0; i<hb->d.nrd; i++) {
+            snew(hb->per->pHist[i], hb->a.nra);
+            if (hb->per->pHist[i]==NULL)
+                gmx_fatal(FARGS,"Could not allocate enough memory for per->pHist");
+            for (j=0; j<hb->a.nra; j++) {
+                clearPshift(&(hb->per->pHist[i][j]));
+            }
+        }
+        /* add the [0,0,0] shift to element 0 of p2i. */
+        snew(hb->per->p2i, 1);
+        clear_ivec(hb->per->p2i[0]);
+        hb->per->nper = 1;
+    }
+}
+
+#ifdef HAVE_NN_LOOPS
+static void mk_hbEmap (t_hbdata *hb, int n0)
+{
+    int i, j, k;
+    hb->hbE.E = NULL;
+    hb->hbE.nframes = 0;
+    snew(hb->hbE.E, hb->d.nrd);
+    for (i=0; i<hb->d.nrd; i++)
+    {
+        snew(hb->hbE.E[i], hb->a.nra);
+        for (j=0; j<hb->a.nra; j++)
+        {
+            snew(hb->hbE.E[i][j], MAXHYDRO);
+            for (k=0; k<MAXHYDRO; k++)
+                hb->hbE.E[i][j][k] = NULL;
+        }
+    }
+    hb->hbE.Etot = NULL;
+}
+
+static void free_hbEmap (t_hbdata *hb)
+{
+    int i, j, k;
+    for (i=0; i<hb->d.nrd; i++)
+    {
+        for (j=0; j<hb->a.nra; j++)
+        {
+            for (k=0; k<MAXHYDRO; k++)
+                sfree(hb->hbE.E[i][j][k]);
+            sfree(hb->hbE.E[i][j]);
+        }
+        sfree(hb->hbE.E[i]);
+    }
+    sfree(hb->hbE.E);
+    sfree(hb->hbE.Etot);
+}
+
+static void addFramesNN(t_hbdata *hb, int frame)
+{
+
+#define DELTAFRAMES_HBE 10
+
+    int d,a,h,nframes;
+
+    if (frame >= hb->hbE.nframes) {
+        nframes =  hb->hbE.nframes + DELTAFRAMES_HBE;
+        srenew(hb->hbE.Etot, nframes);
+
+        for (d=0; d<hb->d.nrd; d++)
+            for (a=0; a<hb->a.nra; a++)
+                for (h=0; h<hb->d.nhydro[d]; h++)
+                    srenew(hb->hbE.E[d][a][h], nframes);
+       
+        hb->hbE.nframes += DELTAFRAMES_HBE;
+    }
+}
+
+static t_E calcHbEnergy(int d, int a, int h, rvec x[], t_EEst EEst,
+                        matrix box, rvec hbox, t_donors *donors){
+    /* d     - donor atom
+     * a     - acceptor atom
+     * h     - hydrogen
+     * alpha - angle between dipoles
+     * x[]   - atomic positions
+     * EEst  - the type of energy estimate (see enum in hbplugin.h)
+     * box   - the box vectors   \
+     * hbox  - half box lengths  _These two are only needed for the pbc correction
+     */
+
+    t_E E;
+    rvec dist;
+    rvec dipole[2], xmol[3], xmean[2]; 
+    int i;
+    real r, realE;
+
+    if (d == a)
+        /* Self-interaction */
+        return NONSENSE_E;
+
+    switch (EEst)
+    {
+    case NN_BINARY:
+        /* This is a simple binary existence function that sets E=1 whenever
+         * the distance between the oxygens is equal too or less than 0.35 nm.
+         */
+        rvec_sub(x[d], x[a], dist);
+        pbc_correct_gem(dist, box, hbox);
+        if (norm(dist) <= 0.35)
+            E = 1;
+        else
+            E = 0;
+        break;
+
+    case NN_1_over_r3:
+        /* Negative potential energy of a dipole.
+         * E = -cos(alpha) * 1/r^3 */     
+     
+        copy_rvec(x[d], xmol[0]); /* donor */
+        copy_rvec(x[donors->hydro[donors->dptr[d]][0]], xmol[1]); /* hydrogen */
+        copy_rvec(x[donors->hydro[donors->dptr[d]][1]], xmol[2]); /* hydrogen */
+
+        svmul(15.9994*(1/1.008), xmol[0], xmean[0]);
+        rvec_inc(xmean[0], xmol[1]);
+        rvec_inc(xmean[0], xmol[2]);
+        for(i=0; i<3; i++)
+            xmean[0][i] /= (15.9994 + 1.008 + 1.008)/1.008;
+
+        /* Assumes that all acceptors are also donors. */
+        copy_rvec(x[a], xmol[0]); /* acceptor */
+        copy_rvec(x[donors->hydro[donors->dptr[a]][0]], xmol[1]); /* hydrogen */
+        copy_rvec(x[donors->hydro[donors->dptr[a]][1]], xmol[2]); /* hydrogen */
+
+
+        svmul(15.9994*(1/1.008), xmol[0], xmean[1]);
+        rvec_inc(xmean[1], xmol[1]);
+        rvec_inc(xmean[1], xmol[2]);
+        for(i=0; i<3; i++)
+            xmean[1][i] /= (15.9994 + 1.008 + 1.008)/1.008;
+
+        rvec_sub(xmean[0], xmean[1], dist);
+        pbc_correct_gem(dist, box, hbox);
+        r = norm(dist);
+
+        realE = pow(r, -3.0);
+        E = (t_E)(SCALEFACTOR_E * realE);
+        break;
+
+    case NN_dipole:
+        /* Negative potential energy of a (unpolarizable) dipole.
+         * E = -cos(alpha) * 1/r^3 */
+        clear_rvec(dipole[1]);
+        clear_rvec(dipole[0]);
+     
+        copy_rvec(x[d], xmol[0]); /* donor */
+        copy_rvec(x[donors->hydro[donors->dptr[d]][0]], xmol[1]); /* hydrogen */
+        copy_rvec(x[donors->hydro[donors->dptr[d]][1]], xmol[2]); /* hydrogen */
+
+        rvec_inc(dipole[0], xmol[1]);
+        rvec_inc(dipole[0], xmol[2]);
+        for (i=0; i<3; i++)
+            dipole[0][i] *= 0.5;
+        rvec_dec(dipole[0], xmol[0]);
+
+        svmul(15.9994*(1/1.008), xmol[0], xmean[0]);
+        rvec_inc(xmean[0], xmol[1]);
+        rvec_inc(xmean[0], xmol[2]);
+        for(i=0; i<3; i++)
+            xmean[0][i] /= (15.9994 + 1.008 + 1.008)/1.008;
+
+        /* Assumes that all acceptors are also donors. */
+        copy_rvec(x[a], xmol[0]); /* acceptor */
+        copy_rvec(x[donors->hydro[donors->dptr[a]][0]], xmol[1]); /* hydrogen */
+        copy_rvec(x[donors->hydro[donors->dptr[a]][2]], xmol[2]); /* hydrogen */
+
+
+        rvec_inc(dipole[1], xmol[1]);
+        rvec_inc(dipole[1], xmol[2]);
+        for (i=0; i<3; i++)
+            dipole[1][i] *= 0.5;
+        rvec_dec(dipole[1], xmol[0]);
+
+        svmul(15.9994*(1/1.008), xmol[0], xmean[1]);
+        rvec_inc(xmean[1], xmol[1]);
+        rvec_inc(xmean[1], xmol[2]);
+        for(i=0; i<3; i++)
+            xmean[1][i] /= (15.9994 + 1.008 + 1.008)/1.008;
+
+        rvec_sub(xmean[0], xmean[1], dist);
+        pbc_correct_gem(dist, box, hbox);
+        r = norm(dist);
+
+        double cosalpha = cos_angle(dipole[0],dipole[1]);
+        realE = cosalpha * pow(r, -3.0);
+        E = (t_E)(SCALEFACTOR_E * realE);
+        break;
+      
+    default:
+        printf("Can't do that type of energy estimate: %i\n.", EEst);
+        E = NONSENSE_E;
+    }
+
+    return E;
+}
+
+static void storeHbEnergy(t_hbdata *hb, int d, int a, int h, t_E E, int frame){
+    /* hb - hbond data structure
+       d  - donor
+       a  - acceptor
+       h  - hydrogen
+       E  - estimate of the energy
+       frame - the current frame.
+    */
+
+    /* Store the estimated energy */
+    if (E == NONSENSE_E)
+        E = 0;
+
+    hb->hbE.E[d][a][h][frame] = E;
+#ifdef HAVE_OPENMP
+#pragma omp critical
+#endif
+    {
+        hb->hbE.Etot[frame] += E;
+    }
+}
+#endif /* HAVE_NN_LOOPS */
+
 
-  snew(hb->hbmap,hb->d.nrd);
-  for(i=0; (i<hb->d.nrd); i++) {
-    snew(hb->hbmap[i],hb->a.nra);
-    if (hb->hbmap[i] == NULL)
-      gmx_fatal(FARGS,"Could not allocate enough memory for hbmap");
-  }
+/* Finds -v[] in the periodicity index */
+static int findMirror(PSTYPE p, ivec v[], PSTYPE nper)
+{
+    PSTYPE i;
+    ivec u;
+    for (i=0; i<nper; i++){
+        if (v[i][XX] == -(v[p][XX]) &&
+            v[i][YY] == -(v[p][YY]) &&
+            v[i][ZZ] == -(v[p][ZZ]))
+            return (int)i;
+    }
+    printf("Couldn't find mirror of [%i, %i, %i], index \n",
+           v[p][XX],
+           v[p][YY],
+           v[p][ZZ]);
+    return -1;
 }
+  
 
 static void add_frames(t_hbdata *hb,int nframes)
 {
-  int  i,j,k,l;
+    int  i,j,k,l;
   
-  if (nframes >= hb->max_frames) {
-    hb->max_frames += 4096;
-    srenew(hb->time,hb->max_frames);
-    srenew(hb->nhb,hb->max_frames);
-    srenew(hb->ndist,hb->max_frames);
-    srenew(hb->n_bound,hb->max_frames);
-    srenew(hb->nhx,hb->max_frames);
-    if (hb->bDAnr)
-      srenew(hb->danr,hb->max_frames);
-  }
-  hb->nframes=nframes;
+    if (nframes >= hb->max_frames) {
+        hb->max_frames += 4096;
+        srenew(hb->time,hb->max_frames);
+        srenew(hb->nhb,hb->max_frames);
+        srenew(hb->ndist,hb->max_frames);
+        srenew(hb->n_bound,hb->max_frames);
+        srenew(hb->nhx,hb->max_frames);
+        if (hb->bDAnr)
+            srenew(hb->danr,hb->max_frames);
+    }
+    hb->nframes=nframes;
 }
 
 #define OFFSET(frame) (frame / 32)
@@ -212,590 +618,733 @@ static void add_frames(t_hbdata *hb,int nframes)
 
 static void _set_hb(unsigned int hbexist[],unsigned int frame,bool bValue)
 {
-  if (bValue)
-    hbexist[OFFSET(frame)] |= MASK(frame);
-  else
-    hbexist[OFFSET(frame)] &= ~MASK(frame);
+    if (bValue)
+        hbexist[OFFSET(frame)] |= MASK(frame);
+    else
+        hbexist[OFFSET(frame)] &= ~MASK(frame);
 }
 
 static bool is_hb(unsigned int hbexist[],int frame)
 {
-  return ((hbexist[OFFSET(frame)] & MASK(frame)) != 0) ? 1 : 0;
+    return ((hbexist[OFFSET(frame)] & MASK(frame)) != 0) ? 1 : 0;
 }
 
 static void set_hb(t_hbdata *hb,int id,int ih, int ia,int frame,int ihb)
 {
-  unsigned int *ghptr=NULL;
+    unsigned int *ghptr=NULL;
   
-  if (ihb == hbHB)
-    ghptr = hb->hbmap[id][ia]->h[ih];
-  else if (ihb == hbDist)
-    ghptr = hb->hbmap[id][ia]->g[ih];
-  else
-    gmx_fatal(FARGS,"Incomprehensible iValue %d in set_hb",ihb);
+    if (ihb == hbHB)
+        ghptr = hb->hbmap[id][ia]->h[ih];
+    else if (ihb == hbDist)
+        ghptr = hb->hbmap[id][ia]->g[ih];
+    else
+        gmx_fatal(FARGS,"Incomprehensible iValue %d in set_hb",ihb);
 
-  _set_hb(ghptr,frame-hb->hbmap[id][ia]->n0,TRUE);
+    _set_hb(ghptr,frame-hb->hbmap[id][ia]->n0,TRUE);
 }
 
-static void add_ff(t_hbdata *hbd,int id,int h,int ia,int frame,int ihb)
+static void addPshift(t_pShift *pHist, PSTYPE p, int frame)
 {
-  int     i,j,n;
-  t_hbond *hb      = hbd->hbmap[id][ia];
-  int     maxhydro = hbd->d.nhydro[id];
-  int     wlen     = hbd->wordlen;
-  int     delta    = 32*wlen;
-  
-  if (!hb->h[0]) {
-    hb->n0        = frame;
-    hb->maxframes = delta;
-    for(i=0; (i<maxhydro); i++) {
-      snew(hb->h[i],hb->maxframes/wlen);
-      snew(hb->g[i],hb->maxframes/wlen);
-    }
-  }
-  else {
-    hb->nframes = frame-hb->n0;
-    /* We need a while loop here because hbonds may be returning
-     * after a long time.
-     */
-    while (hb->nframes >= hb->maxframes) {
-      n = hb->maxframes + delta;
-      for(i=0; (i<maxhydro); i++) {
-       srenew(hb->h[i],n/wlen);
-       srenew(hb->g[i],n/wlen);
-       for(j=hb->maxframes/wlen; (j<n/wlen); j++) {
-         hb->h[i][j] = 0;
-         hb->g[i][j] = 0;
-       }
-      }
-      hb->maxframes = n;
-    }
-  }
-  if (frame >= 0)
-    set_hb(hbd,id,h,ia,frame,ihb);
-  /*hb->nframes++;*/
+    if (pHist->len == 0) {
+        snew(pHist->frame, 1);
+        snew(pHist->p, 1);
+        pHist->len      = 1;
+        pHist->frame[0] = frame;
+        pHist->p[0]     = p;
+        return;
+    } else
+        if (pHist->p[pHist->len-1] != p) {
+            pHist->len++;
+            srenew(pHist->frame, pHist->len);
+            srenew(pHist->p, pHist->len);
+            pHist->frame[pHist->len-1] = frame;
+            pHist->p[pHist->len-1]     = p;
+        } /* Otherwise, there is no transition. */
+    return;
+}
+
+static PSTYPE getPshift(t_pShift pHist, int frame)
+{
+    int f, i;
+
+    if (pHist.len == 0
+        || (pHist.len > 0 && pHist.frame[0]>frame))
+        return -1;
+  
+    for (i=0; i<pHist.len; i++)
+    {
+        f = pHist.frame[i];
+        if (f==frame)
+            return pHist.p[i];
+        if (f>frame)
+            return pHist.p[i-1];
+    }
+  
+    /* It seems that frame is after the last periodic transition. Return the last periodicity. */
+    return pHist.p[pHist.len-1];
+}
+
+static void add_ff(t_hbdata *hbd,int id,int h,int ia,int frame,int ihb, PSTYPE p)
+{
+    int     i,j,n;
+    t_hbond *hb      = hbd->hbmap[id][ia];
+    int     maxhydro = min(hbd->maxhydro,hbd->d.nhydro[id]);
+    int     wlen     = hbd->wordlen;
+    int     delta    = 32*wlen;
+    bool    bGem     = hbd->bGem;
+
+    if (!hb->h[0]) {
+        hb->n0        = frame;
+        hb->maxframes = delta;
+        for(i=0; (i<maxhydro); i++) {
+            snew(hb->h[i],hb->maxframes/wlen);
+            snew(hb->g[i],hb->maxframes/wlen);
+        }
+    } else {
+        hb->nframes = frame-hb->n0;
+        /* We need a while loop here because hbonds may be returning
+         * after a long time.
+         */
+        while (hb->nframes >= hb->maxframes) {
+            n = hb->maxframes + delta;
+            for(i=0; (i<maxhydro); i++) {
+                srenew(hb->h[i],n/wlen);
+                srenew(hb->g[i],n/wlen);
+                for(j=hb->maxframes/wlen; (j<n/wlen); j++) {
+                    hb->h[i][j] = 0;
+                    hb->g[i][j] = 0;
+                }
+            }
+
+            hb->maxframes = n;
+        }
+    }
+    if (frame >= 0) {
+        set_hb(hbd,id,h,ia,frame,ihb);
+        if (bGem) {
+            if (p>=hbd->per->nper)
+                gmx_fatal(FARGS, "invalid shift: p=%u, nper=%u", p, hbd->per->nper);
+            else
+                addPshift(&(hbd->per->pHist[id][ia]), p, frame);
+      
+        }
+    }
 }
 
 static void inc_nhbonds(t_donors *ddd,int d, int h)
 {
-  int j;
-  int dptr = ddd->dptr[d];
-  
-  for(j=0; (j<ddd->nhydro[dptr]); j++)
-    if (ddd->hydro[dptr][j] == h) {
-      ddd->nhbonds[dptr][j]++;
-      break;
-    }
-  if (j == ddd->nhydro[dptr])
-    gmx_fatal(FARGS,"No such hydrogen %d on donor %d\n",h+1,d+1);
-}
-/* Added argument bContact. The reason may not be obvious,
-   but when using -contacts all contacts are stored in h[],
-   while contacts within -r2 (when provided) are stored in g[].
-   Therefore bContact needs to be passed in order to prevent
-   add_hbond from trying to deal with hydrogens.
- * - Erik Marklund, June 29, 2006 
- */
-static void add_hbond(t_hbdata *hb,int d,int a,int h,int grpd,int grpa,
-                     int frame,bool bInsert,bool bMerge,int ihb,bool bContact)
-{ 
-  int k,id,ia,hh;
-  
-  if ((id = hb->d.dptr[d]) == NOTSET)
-    gmx_fatal(FARGS,"No donor atom %d",d+1);
-  else if (grpd != hb->d.grp[id])
-    gmx_fatal(FARGS,"Inconsistent donor groups, %d iso %d, atom %d",
-             grpd,hb->d.grp[id],d+1);
-  if ((ia = hb->a.aptr[a]) == NOTSET)
-    gmx_fatal(FARGS,"No acceptor atom %d",a+1);
-  else if (grpa != hb->a.grp[ia])
-    gmx_fatal(FARGS,"Inconsistent acceptor groups, %d iso %d, atom %d",
-             grpa,hb->a.grp[ia],a+1);
-
-  if (hb->hbmap) {
-    /* Loop over hydrogens to find which hydrogen is in this particular HB */
-    if ((ihb == hbHB) && !bMerge && !bContact) {
-      for(k=0; (k<hb->d.nhydro[id]); k++) 
-       if (hb->d.hydro[id][k] == h)
-         break;
-      if (k == hb->d.nhydro[id])
-       gmx_fatal(FARGS,"Donor %d does not have hydrogen %d (a = %d)",
-                 d+1,h+1,a+1);
+    int j;
+    int dptr = ddd->dptr[d];
+  
+    for(j=0; (j<ddd->nhydro[dptr]); j++)
+        if (ddd->hydro[dptr][j] == h) {
+            ddd->nhbonds[dptr][j]++;
+            break;
+        }
+    if (j == ddd->nhydro[dptr])
+        gmx_fatal(FARGS,"No such hydrogen %d on donor %d\n",h+1,d+1);
+}
+
+static int _acceptor_index(t_acceptors *a,int grp,atom_id i,
+                           const char *file,int line)
+{
+    int ai = a->aptr[i];
+
+    if (a->grp[ai] != grp) {
+        if (debug && bDebug) 
+            fprintf(debug,"Acc. group inconsist.. grp[%d] = %d, grp = %d (%s, %d)\n",
+                    ai,a->grp[ai],grp,file,line);
+        return NOTSET;
     }
     else
-      k = 0;
-    
-    if (hb->bHBmap) {
-      if (hb->hbmap[id][ia] == NULL) {
-       snew(hb->hbmap[id][ia],1);
-       snew(hb->hbmap[id][ia]->h,hb->maxhydro);
-       snew(hb->hbmap[id][ia]->g,hb->maxhydro);
-      }
-      add_ff(hb,id,k,ia,frame,ihb);
+        return ai;
+}
+#define acceptor_index(a,grp,i) _acceptor_index(a,grp,i,__FILE__,__LINE__)
+
+static int _donor_index(t_donors *d,int grp,atom_id i,const char *file,int line)
+{
+    int di = d->dptr[i];
+  
+    if (di == NOTSET)
+        return NOTSET;
+
+    if (d->grp[di] != grp) {
+        if (debug && bDebug)
+            fprintf(debug,"Don. group inconsist.. grp[%d] = %d, grp = %d (%s, %d)\n",
+                    di,d->grp[di],grp,file,line);
+        return NOTSET;
     }
+    else
+        return di;
+}
+#define donor_index(d,grp,i) _donor_index(d,grp,i,__FILE__,__LINE__)
+
+static bool isInterchangable(t_hbdata *hb, int d, int a, int grpa, int grpd)
+{
+    /* g_hbond doesn't allow overlapping groups */
+    if (grpa!=grpd)
+        return FALSE;
+    return
+        donor_index(&hb->d,grpd,a) != NOTSET
+        && acceptor_index(&hb->a,grpa,d) != NOTSET;
+}
+
+
+static void add_hbond(t_hbdata *hb,int d,int a,int h,int grpd,int grpa,
+                      int frame,bool bInsert,bool bMerge,int ihb,bool bContact, PSTYPE p)
+{ 
+    int k,id,ia,hh;
+    bool daSwap = FALSE;
+
+    if ((id = hb->d.dptr[d]) == NOTSET)
+        gmx_fatal(FARGS,"No donor atom %d",d+1);
+    else if (grpd != hb->d.grp[id])
+        gmx_fatal(FARGS,"Inconsistent donor groups, %d iso %d, atom %d",
+                  grpd,hb->d.grp[id],d+1);
+    if ((ia = hb->a.aptr[a]) == NOTSET)
+        gmx_fatal(FARGS,"No acceptor atom %d",a+1);
+    else if (grpa != hb->a.grp[ia])
+        gmx_fatal(FARGS,"Inconsistent acceptor groups, %d iso %d, atom %d",
+                  grpa,hb->a.grp[ia],a+1);
+
+    if (bMerge)
+        if ((daSwap = isInterchangable(hb, d, a, grpd, grpa) || bContact) && d>a)
+            /* Then swap identity so that the id of d is lower then that of a.
+             *
+             * This should really be redundant by now, as is_hbond() now ought to return
+             * hbNo in the cases where this conditional is TRUE. */
+        {
+            k = d;
+            d = a;
+            a = k;
+       
+            /* Now repeat donor/acc check. */
+            if ((id = hb->d.dptr[d]) == NOTSET)
+                gmx_fatal(FARGS,"No donor atom %d",d+1);
+            else if (grpd != hb->d.grp[id])
+                gmx_fatal(FARGS,"Inconsistent donor groups, %d iso %d, atom %d",
+                          grpd,hb->d.grp[id],d+1);
+            if ((ia = hb->a.aptr[a]) == NOTSET)
+                gmx_fatal(FARGS,"No acceptor atom %d",a+1);
+            else if (grpa != hb->a.grp[ia])
+                gmx_fatal(FARGS,"Inconsistent acceptor groups, %d iso %d, atom %d",
+                          grpa,hb->a.grp[ia],a+1);
+        }
+
+    if (hb->hbmap) {
+        /* Loop over hydrogens to find which hydrogen is in this particular HB */
+        if ((ihb == hbHB) && !bMerge && !bContact) {
+            for(k=0; (k<hb->d.nhydro[id]); k++) 
+                if (hb->d.hydro[id][k] == h)
+                    break;
+            if (k == hb->d.nhydro[id])
+                gmx_fatal(FARGS,"Donor %d does not have hydrogen %d (a = %d)",
+                          d+1,h+1,a+1);
+        }
+        else
+            k = 0;
     
-    /* Strange construction with frame >=0 is a relic from old code
-     * for selected hbond analysis. It may be necessary again if that
-     * is made to work again.
-     */
-    if (frame >= 0) {
-      hh = hb->hbmap[id][ia]->history[k];
-      if (ihb == hbHB) {
-       hb->nhb[frame]++;
-       if (!(ISHB(hh))) {
-         hb->hbmap[id][ia]->history[k] = hh | 2;
-         hb->nrhb++;
-       }
-      }
-      else if (ihb == hbDist) {
-       hb->ndist[frame]++;
-       if (!(ISDIST(hh))) {
-         hb->hbmap[id][ia]->history[k] = hh | 1;
-         hb->nrdist++;
-       }
-      }
-    }
-  } else {
-    if (frame >= 0) {
-      if (ihb == hbHB) {
-       hb->nhb[frame]++;
-      } else if (ihb == hbDist) {
-       hb->ndist[frame]++;
-      }
+        if (hb->bHBmap) {
+            if (hb->hbmap[id][ia] == NULL) {
+                snew(hb->hbmap[id][ia],1);
+                snew(hb->hbmap[id][ia]->h,hb->maxhydro);
+                snew(hb->hbmap[id][ia]->g,hb->maxhydro);
+            }
+            add_ff(hb,id,k,ia,frame,ihb,p);
+        }
+    
+        /* Strange construction with frame >=0 is a relic from old code
+         * for selected hbond analysis. It may be necessary again if that
+         * is made to work again.
+         */
+        if (frame >= 0) {
+            hh = hb->hbmap[id][ia]->history[k];
+            if (ihb == hbHB) {
+                hb->nhb[frame]++;
+                if (!(ISHB(hh))) {
+                    hb->hbmap[id][ia]->history[k] = hh | 2;
+                    hb->nrhb++;
+                }
+            }
+            else
+            {
+                if (ihb == hbDist) {
+                    hb->ndist[frame]++;
+                    if (!(ISDIST(hh))) {
+                        hb->hbmap[id][ia]->history[k] = hh | 1;
+                        hb->nrdist++;
+                    }
+                }
+            }
+        }
+    } else {
+        if (frame >= 0) {
+            if (ihb == hbHB) {
+                hb->nhb[frame]++;
+            } else {
+                if (ihb == hbDist) {
+                    hb->ndist[frame]++;
+                }
+            }
+        }
     }
-  }
-  /* Increment number if HBonds per H */
-  if (ihb == hbHB && !bContact)
-    inc_nhbonds(&(hb->d),d,h);
+    if (bMerge && daSwap)
+        h = hb->d.hydro[id][0];
+    /* Increment number if HBonds per H */
+    if (ihb == hbHB && !bContact)
+        inc_nhbonds(&(hb->d),d,h);
 }
 
 /* Now a redundant function. It might find use at some point though. */
 static bool in_list(atom_id selection,int isize,atom_id *index)
 {
-  int i;
-  bool bFound;
+    int i;
+    bool bFound;
   
-  bFound=FALSE;
-  for(i=0; (i<isize) && !bFound; i++)
-    if(selection == index[i])
-      bFound=TRUE;
+    bFound=FALSE;
+    for(i=0; (i<isize) && !bFound; i++)
+        if(selection == index[i])
+            bFound=TRUE;
   
-  return bFound;
+    return bFound;
 }
 
 static char *mkatomname(t_atoms *atoms,int i)
 {
-  static char buf[32];
-  int rnr;
+    static char buf[32];
+    int rnr;
   
-  rnr = atoms->atom[i].resind;
-  sprintf(buf,"%4s%d%-4s",
-         *atoms->resinfo[rnr].name,atoms->resinfo[rnr].nr,*atoms->atomname[i]);
+    rnr = atoms->atom[i].resind;
+    sprintf(buf,"%4s%d%-4s",
+            *atoms->resinfo[rnr].name,atoms->resinfo[rnr].nr,*atoms->atomname[i]);
   
-  return buf;
+    return buf;
 }
 
 static void gen_datable(atom_id *index, int isize, unsigned char *datable, int natoms){
-  /* Generates table of all atoms and sets the ingroup bit for atoms in index[] */
-  int i;
+    /* Generates table of all atoms and sets the ingroup bit for atoms in index[] */
+    int i;
 
-  for (i=0; i<isize; i++){
-    if (index[i] >= natoms)
-      gmx_fatal(FARGS,"Atom has index %d larger than number of atoms %d.",index[i],natoms);
-    datable[index[i]] |= INGROUP;
-  }
+    for (i=0; i<isize; i++){
+        if (index[i] >= natoms)
+            gmx_fatal(FARGS,"Atom has index %d larger than number of atoms %d.",index[i],natoms);
+        datable[index[i]] |= INGROUP;
+    }
 }
 
 static void clear_datable_grp(unsigned char *datable, int size){
-  /* Clears group information from the table */
-  int i;
-  const char mask = !(char)INGROUP;
-  if (size > 0)
-    for (i=0;i<size;i++)
-      datable[i] &= mask;
+    /* Clears group information from the table */
+    int i;
+    const char mask = !(char)INGROUP;
+    if (size > 0)
+        for (i=0;i<size;i++)
+            datable[i] &= mask;
 }
 
 static void add_acc(t_acceptors *a,int ia,int grp)
 {
-  if (a->nra >= a->max_nra) {
-    a->max_nra += 16;
-    srenew(a->acc,a->max_nra);
-    srenew(a->grp,a->max_nra);
-  }
-  a->grp[a->nra]   = grp;
-  a->acc[a->nra++] = ia;
+    if (a->nra >= a->max_nra) {
+        a->max_nra += 16;
+        srenew(a->acc,a->max_nra);
+        srenew(a->grp,a->max_nra);
+    }
+    a->grp[a->nra]   = grp;
+    a->acc[a->nra++] = ia;
 }
 
 static void search_acceptors(t_topology *top,int isize, 
-                            atom_id *index,t_acceptors *a,int grp,
-                            bool bNitAcc,
-                            bool bContact,bool bDoIt, unsigned char *datable)
-{
-  int i,n;
-  
-  if (bDoIt) {
-    for (i=0; (i<isize); i++) {
-      n = index[i];
-      if ((bContact ||
-          (((*top->atoms.atomname[n])[0] == 'O') || 
-           (bNitAcc && ((*top->atoms.atomname[n])[0] == 'N')))) &&
-         ISINGRP(datable[n])) {
-       datable[n] |= ACC; /* set the atom's acceptor flag in datable. */
-       add_acc(a,n,grp);
-      }
-    }
-  }
-  snew(a->aptr,top->atoms.nr);
-  for(i=0; (i<top->atoms.nr); i++)
-    a->aptr[i] = NOTSET;
-  for(i=0; (i<a->nra); i++)
-    a->aptr[a->acc[i]] = i;
-}
-
-static int _acceptor_index(t_acceptors *a,int grp,atom_id i,
-                          const char *file,int line)
-{
-  int ai = a->aptr[i];
-
-  if (a->grp[ai] != grp) {
-    if (debug && bDebug) 
-      fprintf(debug,"Acc. group inconsist.. grp[%d] = %d, grp = %d (%s, %d)\n",
-             ai,a->grp[ai],grp,file,line);
-    return NOTSET;
-  }
-  else
-    return ai;
-}
-#define acceptor_index(a,grp,i) _acceptor_index(a,grp,i,__FILE__,__LINE__)
-
-static int _donor_index(t_donors *d,int grp,atom_id i,const char *file,int line)
+                             atom_id *index,t_acceptors *a,int grp,
+                             bool bNitAcc,
+                             bool bContact,bool bDoIt, unsigned char *datable)
 {
-  int di = d->dptr[i];
+    int i,n;
   
-  if (d->grp[di] != grp) {
-    if (debug && bDebug)
-      fprintf(debug,"Don. group inconsist.. grp[%d] = %d, grp = %d (%s, %d)\n",
-             di,d->grp[di],grp,file,line);
-    return NOTSET;
-  }
-  else
-    return di;
+    if (bDoIt) {
+        for (i=0; (i<isize); i++) {
+            n = index[i];
+            if ((bContact ||
+                 (((*top->atoms.atomname[n])[0] == 'O') || 
+                  (bNitAcc && ((*top->atoms.atomname[n])[0] == 'N')))) &&
+                ISINGRP(datable[n])) {
+                datable[n] |= ACC; /* set the atom's acceptor flag in datable. */
+                add_acc(a,n,grp);
+            }
+        }
+    }
+    snew(a->aptr,top->atoms.nr);
+    for(i=0; (i<top->atoms.nr); i++)
+        a->aptr[i] = NOTSET;
+    for(i=0; (i<a->nra); i++)
+        a->aptr[a->acc[i]] = i;
 }
-#define donor_index(d,grp,i) _donor_index(d,grp,i,__FILE__,__LINE__)
 
 static void add_h2d(int id,int ih,t_donors *ddd)
 {
-  int i;
+    int i;
   
-  for(i=0; (i<ddd->nhydro[id]); i++) 
-    if (ddd->hydro[id][i] == ih) {
-      printf("Hm. This isn't first time I find this donor (%d,%d)\n",
-            ddd->don[id],ih);
-      break;
+    for(i=0; (i<ddd->nhydro[id]); i++) 
+        if (ddd->hydro[id][i] == ih) {
+            printf("Hm. This isn't the first time I found this donor (%d,%d)\n",
+                   ddd->don[id],ih);
+            break;
+        }
+    if (i == ddd->nhydro[id]) {
+        if (ddd->nhydro[id] >= MAXHYDRO)
+            gmx_fatal(FARGS,"Donor %d has more than %d hydrogens!",
+                      ddd->don[id],MAXHYDRO);
+        ddd->hydro[id][i] = ih;
+        ddd->nhydro[id]++;
     }
-  if (i == ddd->nhydro[id]) {
-    if (ddd->nhydro[id] >= MAXHYDRO)
-      gmx_fatal(FARGS,"Donor %d has more than %d hydrogens!",
-                 ddd->don[id],MAXHYDRO);
-    ddd->hydro[id][i] = ih;
-    ddd->nhydro[id]++;
-  }
 }
   
 static void add_dh(t_donors *ddd,int id,int ih,int grp, unsigned char *datable)
 {
-  int i;
-
-  if (ISDON(datable[id]) || !datable) {
-    if (ddd->dptr[id] == NOTSET) { /* New donor */
-      i = ddd->nrd;
-      ddd->dptr[id] = i;
-    } else 
-      i = ddd->dptr[id];
-  
-    if (i == ddd->nrd) {
-      if (ddd->nrd >= ddd->max_nrd) {
-       ddd->max_nrd += 128;
-       srenew(ddd->don,ddd->max_nrd);
-       srenew(ddd->nhydro,ddd->max_nrd);
-       srenew(ddd->hydro,ddd->max_nrd);
-       srenew(ddd->nhbonds,ddd->max_nrd);
-       srenew(ddd->grp,ddd->max_nrd);
-      }
-      ddd->don[ddd->nrd] = id;
-      ddd->nhydro[ddd->nrd] = 0;
-      ddd->grp[ddd->nrd] = grp;
-      ddd->nrd++;
+    int i;
+
+    if (ISDON(datable[id]) || !datable) {
+        if (ddd->dptr[id] == NOTSET) { /* New donor */
+            i = ddd->nrd;
+            ddd->dptr[id] = i;
+        } else 
+            i = ddd->dptr[id];
+  
+        if (i == ddd->nrd) {
+            if (ddd->nrd >= ddd->max_nrd) {
+                ddd->max_nrd += 128;
+                srenew(ddd->don,ddd->max_nrd);
+                srenew(ddd->nhydro,ddd->max_nrd);
+                srenew(ddd->hydro,ddd->max_nrd);
+                srenew(ddd->nhbonds,ddd->max_nrd);
+                srenew(ddd->grp,ddd->max_nrd);
+            }
+            ddd->don[ddd->nrd] = id;
+            ddd->nhydro[ddd->nrd] = 0;
+            ddd->grp[ddd->nrd] = grp;
+            ddd->nrd++;
+        } else
+            ddd->don[i] = id;
+        add_h2d(i,ih,ddd);
     } else
-      ddd->don[i] = id;
-    add_h2d(i,ih,ddd);
-  } else
-    if (datable)
-      printf("Warning: Atom %d is not in the d/a-table!\n", id);
+        if (datable)
+            printf("Warning: Atom %d is not in the d/a-table!\n", id);
 }
 
 static void search_donors(t_topology *top, int isize, atom_id *index,
-                         t_donors *ddd,int grp,bool bContact,bool bDoIt,
-                         unsigned char *datable)
+                          t_donors *ddd,int grp,bool bContact,bool bDoIt,
+                          unsigned char *datable)
 {
-  int        i,j,nra,n;
-  t_functype func_type;
-  t_ilist    *interaction;
-  atom_id    nr1,nr2;
-  bool       stop;
-
-  if (!ddd->dptr) {
-    snew(ddd->dptr,top->atoms.nr);
-    for(i=0; (i<top->atoms.nr); i++)
-      ddd->dptr[i] = NOTSET;
-  }
-
-  if (bContact) {
-    if (bDoIt)
-      for(i=0; (i<isize); i++) {
-       datable[index[i]] |= DON;
-       add_dh(ddd,index[i],-1,grp,datable);
-      }
-  }
-  else {
-    for(func_type=0; (func_type < F_NRE); func_type++) {
-      interaction=&(top->idef.il[func_type]);
-      for(i=0; i < interaction->nr; 
-         i+=interaction_function[top->idef.functype[interaction->iatoms[i]]].nratoms+1) {
-       /* next function */
-       if (func_type != top->idef.functype[interaction->iatoms[i]]) {
-         fprintf(stderr,"Error in func_type %s",
-                 interaction_function[func_type].longname);
-         continue;
-       }
+    int        i,j,nra,n;
+    t_functype func_type;
+    t_ilist    *interaction;
+    atom_id    nr1,nr2;
+    bool       stop;
+
+    if (!ddd->dptr) {
+        snew(ddd->dptr,top->atoms.nr);
+        for(i=0; (i<top->atoms.nr); i++)
+            ddd->dptr[i] = NOTSET;
+    }
+
+    if (bContact) {
+        if (bDoIt)
+            for(i=0; (i<isize); i++) {
+                datable[index[i]] |= DON;
+                add_dh(ddd,index[i],-1,grp,datable);
+            }
+    }
+    else {
+        for(func_type=0; (func_type < F_NRE); func_type++) {
+            interaction=&(top->idef.il[func_type]);
+            if (func_type == F_POSRES)
+            { /* The ilist looks strange for posre. Bug in grompp?
+               * We don't need posre interactions for hbonds anyway.*/
+                continue;
+            }
+            for(i=0; i < interaction->nr; 
+                i+=interaction_function[top->idef.functype[interaction->iatoms[i]]].nratoms+1) {
+                /* next function */
+                if (func_type != top->idef.functype[interaction->iatoms[i]]) {
+                    fprintf(stderr,"Error in func_type %s",
+                            interaction_function[func_type].longname);
+                    continue;
+                }
        
-       /* check out this functype */
-       if (func_type == F_SETTLE) {
-         nr1=interaction->iatoms[i+1];
+                /* check out this functype */
+                if (func_type == F_SETTLE) {
+                    nr1=interaction->iatoms[i+1];
          
-         if (ISINGRP(datable[nr1])) {
-           if (ISINGRP(datable[nr1+1])) {
-             datable[nr1] |= DON;
-             add_dh(ddd,nr1,nr1+1,grp,datable);
-           }
-           if (ISINGRP(datable[nr1+2])) {
-             datable[nr1] |= DON;
-             add_dh(ddd,nr1,nr1+2,grp,datable);
-           }
-         }
-       } 
-       else if (IS_CHEMBOND(func_type)) {
-         for (j=0; j<2; j++) {
-           nr1=interaction->iatoms[i+1+j];
-           nr2=interaction->iatoms[i+2-j];
-           if ((*top->atoms.atomname[nr1][0] == 'H') && 
-               ((*top->atoms.atomname[nr2][0] == 'O') ||
-                (*top->atoms.atomname[nr2][0] == 'N')) &&
-               ISINGRP(datable[nr1]) && ISINGRP(datable[nr2])) {
-             datable[nr2] |= DON;
-             add_dh(ddd,nr2,nr1,grp,datable);
-           }
-         }
-       }
-      }
-    }
+                    if (ISINGRP(datable[nr1])) {
+                        if (ISINGRP(datable[nr1+1])) {
+                            datable[nr1] |= DON;
+                            add_dh(ddd,nr1,nr1+1,grp,datable);
+                        }
+                        if (ISINGRP(datable[nr1+2])) {
+                            datable[nr1] |= DON;
+                            add_dh(ddd,nr1,nr1+2,grp,datable);
+                        }
+                    }
+                
+                else if (IS_CHEMBOND(func_type)) {
+                    for (j=0; j<2; j++) {
+                        nr1=interaction->iatoms[i+1+j];
+                        nr2=interaction->iatoms[i+2-j];
+                        if ((*top->atoms.atomname[nr1][0] == 'H') && 
+                            ((*top->atoms.atomname[nr2][0] == 'O') ||
+                             (*top->atoms.atomname[nr2][0] == 'N')) &&
+                            ISINGRP(datable[nr1]) && ISINGRP(datable[nr2])) {
+                            datable[nr2] |= DON;
+                            add_dh(ddd,nr2,nr1,grp,datable);
+                        }
+                    }
+                }
+            }
+        }
 #ifdef SAFEVSITES
-    for(func_type=0; func_type < F_NRE; func_type++) {
-      interaction=&top->idef.il[func_type];
-      for(i=0; i < interaction->nr; 
-         i+=interaction_function[top->idef.functype[interaction->iatoms[i]]].nratoms+1) {
-       /* next function */
-       if (func_type != top->idef.functype[interaction->iatoms[i]])
-         gmx_incons("function type in search_donors");
+        for(func_type=0; func_type < F_NRE; func_type++) {
+            interaction=&top->idef.il[func_type];
+            for(i=0; i < interaction->nr; 
+                i+=interaction_function[top->idef.functype[interaction->iatoms[i]]].nratoms+1) {
+                /* next function */
+                if (func_type != top->idef.functype[interaction->iatoms[i]])
+                    gmx_incons("function type in search_donors");
        
-       if ( interaction_function[func_type].flags & IF_VSITE ) {
-         nr1=interaction->iatoms[i+1];
-         if ( *top->atoms.atomname[nr1][0]  == 'H') {
-           nr2=nr1-1;
-           stop=FALSE;
-           while (!stop && ( *top->atoms.atomname[nr2][0] == 'H'))
-             if (nr2)
-               nr2--;
-             else
-               stop=TRUE;
-           if ( !stop && ( ( *top->atoms.atomname[nr2][0] == 'O') ||
-                           ( *top->atoms.atomname[nr2][0] == 'N') ) &&
-                ISINGRP(datable[nr1]) && ISINGRP(datable[nr2])) {
-             datable[nr2] |= DON;
-             add_dh(ddd,nr2,nr1,grp,datable);
-           }
-         }
-       }
-      }
-    }
+                if ( interaction_function[func_type].flags & IF_VSITE ) {
+                    nr1=interaction->iatoms[i+1];
+                    if ( *top->atoms.atomname[nr1][0]  == 'H') {
+                        nr2=nr1-1;
+                        stop=FALSE;
+                        while (!stop && ( *top->atoms.atomname[nr2][0] == 'H'))
+                            if (nr2)
+                                nr2--;
+                            else
+                                stop=TRUE;
+                        if ( !stop && ( ( *top->atoms.atomname[nr2][0] == 'O') ||
+                                        ( *top->atoms.atomname[nr2][0] == 'N') ) &&
+                             ISINGRP(datable[nr1]) && ISINGRP(datable[nr2])) {
+                            datable[nr2] |= DON;
+                            add_dh(ddd,nr2,nr1,grp,datable);
+                        }
+                    }
+                }
+            }
+        }
 #endif
-  }
+    }
 }
 
 static t_gridcell ***init_grid(bool bBox,rvec box[],real rcut,ivec ngrid)
 {
-  t_gridcell ***grid;
-  int i,y,z;
-  
-  if (bBox)
-    for(i=0; i<DIM; i++)
-      ngrid[i]=(box[i][i]/(1.2*rcut));
-  
-  if ( !bBox || (ngrid[XX]<3) || (ngrid[YY]<3) || (ngrid[ZZ]<3) )
-    for(i=0; i<DIM; i++)
-      ngrid[i]=1;
-  else 
-    printf("\nWill do grid-seach on %dx%dx%d grid, rcut=%g\n",
-          ngrid[XX],ngrid[YY],ngrid[ZZ],rcut);
-  snew(grid,ngrid[ZZ]);
-  for (z=0; z<ngrid[ZZ]; z++) {
-    snew((grid)[z],ngrid[YY]);
-    for (y=0; y<ngrid[YY]; y++)
-      snew((grid)[z][y],ngrid[XX]);
-  }
-  return grid;
+    t_gridcell ***grid;
+    int i,y,z;
+  
+    if (bBox)
+        for(i=0; i<DIM; i++)
+            ngrid[i]=(box[i][i]/(1.2*rcut));
+  
+    if ( !bBox || (ngrid[XX]<3) || (ngrid[YY]<3) || (ngrid[ZZ]<3) )
+        for(i=0; i<DIM; i++)
+            ngrid[i]=1;
+    else 
+        printf("\nWill do grid-seach on %dx%dx%d grid, rcut=%g\n",
+               ngrid[XX],ngrid[YY],ngrid[ZZ],rcut);
+    snew(grid,ngrid[ZZ]);
+    for (z=0; z<ngrid[ZZ]; z++) {
+        snew((grid)[z],ngrid[YY]);
+        for (y=0; y<ngrid[YY]; y++)
+            snew((grid)[z][y],ngrid[XX]);
+    }
+    return grid;
+}
+
+static void control_pHist(t_hbdata *hb, int nframes)
+{
+    int i,j,k;
+    PSTYPE p;
+    for (i=0;i<hb->d.nrd;i++)
+        for (j=0;j<hb->a.nra;j++)
+            if (hb->per->pHist[i][j].len != 0)
+                for (k=hb->hbmap[i][j][0].n0; k<nframes; k++) {
+                    p = getPshift(hb->per->pHist[i][j], k);
+                    if (p>hb->per->nper)
+                        fprintf(stderr, "Weird stuff in pHist[%i][%i].p at frame %i: p=%i\n",
+                                i,j,k,p);
+                }
 }
 
 static void reset_nhbonds(t_donors *ddd)
 {
-  int i,j;
+    int i,j;
   
-  for(i=0; (i<ddd->nrd); i++) 
-    for(j=0; (j<MAXHH); j++)
-      ddd->nhbonds[i][j] = 0;
+    for(i=0; (i<ddd->nrd); i++) 
+        for(j=0; (j<MAXHH); j++)
+            ddd->nhbonds[i][j] = 0;
 }
 
+void pbc_correct_gem(rvec dx,matrix box,rvec hbox);
+
 static void build_grid(t_hbdata *hb,rvec x[], rvec xshell,
-                      bool bBox, matrix box, rvec hbox,
-                      real rcut, real rshell,
-                      ivec ngrid, t_gridcell ***grid)
+                       bool bBox, matrix box, rvec hbox,
+                       real rcut, real rshell,
+                       ivec ngrid, t_gridcell ***grid)
 {
-  int     i,m,gr,xi,yi,zi,nr;
-  atom_id *ad;
-  ivec    grididx;
-  rvec    invdelta,dshell;
-  t_ncell *newgrid;
-  bool    bDoRshell,bInShell,bAcc;
-  real    rshell2=0;
-  int     gx,gy,gz;
-  int     dum = -1;
-  
-  bDoRshell = (rshell > 0);
-  rshell2   = sqr(rshell);
-  bInShell  = TRUE;
+    int     i,m,gr,xi,yi,zi,nr;
+    atom_id *ad;
+    ivec    grididx;
+    rvec    invdelta,dshell,xtemp={0,0,0};
+    t_ncell *newgrid;
+    bool    bDoRshell,bInShell,bAcc;
+    real    rshell2=0;
+    int     gx,gy,gz;
+    int     dum = -1;
+  
+    bDoRshell = (rshell > 0);
+    rshell2   = sqr(rshell);
+    bInShell  = TRUE;
   
 #define DBB(x) if (debug && bDebug) fprintf(debug,"build_grid, line %d, %s = %d\n",__LINE__,#x,x)
-  DBB(dum);
-  for(m=0; m<DIM; m++) {
-    hbox[m]=box[m][m]*0.5;
-    if (bBox) {
-      invdelta[m]=ngrid[m]/box[m][m];
-      if (1/invdelta[m] < rcut)
-       gmx_fatal(FARGS,"Your computational box has shrunk too much.\n"
-                 "%s can not handle this situation, sorry.\n",
-                 ShortProgram());
-    } else
-      invdelta[m]=0;
-  }
-  grididx[XX]=0;
-  grididx[YY]=0;
-  grididx[ZZ]=0;
-  DBB(dum);
-  /* resetting atom counts */
-  for(gr=0; (gr<grNR); gr++) {
-    for (zi=0; zi<ngrid[ZZ]; zi++)
-      for (yi=0; yi<ngrid[YY]; yi++)
-       for (xi=0; xi<ngrid[XX]; xi++) {
-         grid[zi][yi][xi].d[gr].nr=0;
-         grid[zi][yi][xi].a[gr].nr=0;
-      }
     DBB(dum);
+    for(m=0; m<DIM; m++) {
+        hbox[m]=box[m][m]*0.5;
+        if (bBox) {
+            invdelta[m]=ngrid[m]/box[m][m];
+            if (1/invdelta[m] < rcut)
+                gmx_fatal(FARGS,"Your computational box has shrunk too much.\n"
+                          "%s can not handle this situation, sorry.\n",
+                          ShortProgram());
+        } else
+            invdelta[m]=0;
+    }
+    grididx[XX]=0;
+    grididx[YY]=0;
+    grididx[ZZ]=0;
+    DBB(dum);
+    /* resetting atom counts */
+    for(gr=0; (gr<grNR); gr++) {
+        for (zi=0; zi<ngrid[ZZ]; zi++)
+            for (yi=0; yi<ngrid[YY]; yi++)
+                for (xi=0; xi<ngrid[XX]; xi++) {
+                    grid[zi][yi][xi].d[gr].nr=0;
+                    grid[zi][yi][xi].a[gr].nr=0;
+                }
+        DBB(dum);
     
-    /* put atoms in grid cells */
-    for(bAcc=FALSE; (bAcc<=TRUE); bAcc++) {
-      if (bAcc) {
-       nr = hb->a.nra;
-       ad = hb->a.acc;
-      }
-      else {
-       nr = hb->d.nrd;
-       ad = hb->d.don;
-      }
-      DBB(bAcc);
-      for(i=0; (i<nr); i++) {
-       /* check if we are inside the shell */
-       /* if bDoRshell=FALSE then bInShell=TRUE always */
-       DBB(i);
-       if ( bDoRshell ) {
-         bInShell=TRUE;
-         rvec_sub(x[ad[i]],xshell,dshell);
-         if (bBox) 
-           for(m=DIM-1; m>=0 && bInShell; m--) {
-             if ( dshell[m] < -hbox[m] )
-               rvec_inc(dshell,box[m]);
-             else if ( dshell[m] >= hbox[m] ) 
-               dshell[m] -= 2*hbox[m];
-             /* if we're outside the cube, we're outside the sphere also! */
-             if ( (dshell[m]>rshell) || (-dshell[m]>rshell) )
-               bInShell=FALSE;
-           }
-         /* if we're inside the cube, check if we're inside the sphere */
-         if (bInShell)
-           bInShell = norm2(dshell) < rshell2;
-       }
-       DBB(i);
-       if ( bInShell ) {
-         if (bBox) 
-           for(m=DIM-1; m>=0; m--) {
-             /* put atom in the box */
-             while( x[ad[i]][m] < 0 ) 
-               rvec_inc(x[ad[i]],box[m]);
-             while( x[ad[i]][m] >= box[m][m] ) 
-               rvec_dec(x[ad[i]],box[m]);
-             /* determine grid index of atom */
-             grididx[m]=x[ad[i]][m]*invdelta[m];
-             grididx[m] = (grididx[m]+ngrid[m]) % ngrid[m];
-           }
-         gx = grididx[XX];
-         gy = grididx[YY];
-         gz = grididx[ZZ];
-         range_check(gx,0,ngrid[XX]);
-         range_check(gy,0,ngrid[YY]);
-         range_check(gz,0,ngrid[ZZ]);
-         DBB(gx);
-         DBB(gy);
-         DBB(gz);
-         /* add atom to grid cell */
-         if (bAcc)
-           newgrid=&(grid[gz][gy][gx].a[gr]);
-         else
-           newgrid=&(grid[gz][gy][gx].d[gr]);
-         if (newgrid->nr >= newgrid->maxnr) {
-           newgrid->maxnr+=10;
-           DBB(newgrid->maxnr);
-           srenew(newgrid->atoms, newgrid->maxnr);
-         }
-         DBB(newgrid->nr);
-         newgrid->atoms[newgrid->nr]=ad[i];
-         newgrid->nr++;
-       }
-      }
-    }
-  }
+        /* put atoms in grid cells */
+        for(bAcc=FALSE; (bAcc<=TRUE); bAcc++) {
+            if (bAcc) {
+                nr = hb->a.nra;
+                ad = hb->a.acc;
+            }
+            else {
+                nr = hb->d.nrd;
+                ad = hb->d.don;
+            }
+            DBB(bAcc);
+            for(i=0; (i<nr); i++) {
+                /* check if we are inside the shell */
+                /* if bDoRshell=FALSE then bInShell=TRUE always */
+                DBB(i);
+                if ( bDoRshell ) {
+                    bInShell=TRUE;
+                    rvec_sub(x[ad[i]],xshell,dshell);
+                    if (bBox) {
+                        if (FALSE && !hb->bGem) {
+                            for(m=DIM-1; m>=0 && bInShell; m--) {
+                                if ( dshell[m] < -hbox[m] )
+                                    rvec_inc(dshell,box[m]);
+                                else if ( dshell[m] >= hbox[m] ) 
+                                    dshell[m] -= 2*hbox[m];
+                                /* if we're outside the cube, we're outside the sphere also! */
+                                if ( (dshell[m]>rshell) || (-dshell[m]>rshell) )
+                                    bInShell=FALSE;
+                            }
+                        } else {
+                            bool bDone = FALSE;
+                            while (!bDone)
+                            {
+                                bDone = TRUE;
+                                for(m=DIM-1; m>=0 && bInShell; m--) {
+                                    if ( dshell[m] < -hbox[m] ) {
+                                        bDone = FALSE;
+                                        rvec_inc(dshell,box[m]);
+                                    }
+                                    if ( dshell[m] >= hbox[m] ) {
+                                        bDone = FALSE;
+                                        dshell[m] -= 2*hbox[m];
+                                    }
+                                }
+                            }
+                            for(m=DIM-1; m>=0 && bInShell; m--) {
+                                /* if we're outside the cube, we're outside the sphere also! */
+                                if ( (dshell[m]>rshell) || (-dshell[m]>rshell) )
+                                    bInShell=FALSE;
+                            }
+                        }
+                    }
+                    /* if we're inside the cube, check if we're inside the sphere */
+                    if (bInShell)
+                        bInShell = norm2(dshell) < rshell2;
+                }
+                DBB(i);
+                if ( bInShell ) {
+                    if (bBox) {
+                        if (hb->bGem)
+                            copy_rvec(x[ad[i]], xtemp);
+                        pbc_correct_gem(x[ad[i]], box, hbox);
+                    }
+                    for(m=DIM-1; m>=0; m--) {
+                        if (TRUE || !hb->bGem){
+                            /* put atom in the box */
+                            while( x[ad[i]][m] < 0 )
+                                rvec_inc(x[ad[i]],box[m]);
+                            while( x[ad[i]][m] >= box[m][m] )
+                                rvec_dec(x[ad[i]],box[m]);
+                        }
+                        /* determine grid index of atom */
+                        grididx[m]=x[ad[i]][m]*invdelta[m];
+                        grididx[m] = (grididx[m]+ngrid[m]) % ngrid[m];
+                    }
+                    if (hb->bGem)
+                        copy_rvec(xtemp, x[ad[i]]); /* copy back */
+                    gx = grididx[XX];
+                    gy = grididx[YY];
+                    gz = grididx[ZZ];
+                    range_check(gx,0,ngrid[XX]);
+                    range_check(gy,0,ngrid[YY]);
+                    range_check(gz,0,ngrid[ZZ]);
+                    DBB(gx);
+                    DBB(gy);
+                    DBB(gz);
+                    /* add atom to grid cell */
+                    if (bAcc)
+                        newgrid=&(grid[gz][gy][gx].a[gr]);
+                    else
+                        newgrid=&(grid[gz][gy][gx].d[gr]);
+                    if (newgrid->nr >= newgrid->maxnr) {
+                        newgrid->maxnr+=10;
+                        DBB(newgrid->maxnr);
+                        srenew(newgrid->atoms, newgrid->maxnr);
+                    }
+                    DBB(newgrid->nr);
+                    newgrid->atoms[newgrid->nr]=ad[i];
+                    newgrid->nr++;
+                }
+            }
+        }
+    }
 }
 
 static void count_da_grid(ivec ngrid, t_gridcell ***grid, t_icell danr)
 {
-  int gr,xi,yi,zi;
+    int gr,xi,yi,zi;
   
-  for(gr=0; (gr<grNR); gr++) {
-    danr[gr]=0;
-    for (zi=0; zi<ngrid[ZZ]; zi++)
-      for (yi=0; yi<ngrid[YY]; yi++)
-       for (xi=0; xi<ngrid[XX]; xi++) {
-         danr[gr] += grid[zi][yi][xi].d[gr].nr;
-       }
-  }
+    for(gr=0; (gr<grNR); gr++) {
+        danr[gr]=0;
+        for (zi=0; zi<ngrid[ZZ]; zi++)
+            for (yi=0; yi<ngrid[YY]; yi++)
+                for (xi=0; xi<ngrid[XX]; xi++) {
+                    danr[gr] += grid[zi][yi][xi].d[gr].nr;
+                }
+    }
 }
 
 /* The grid loop.
@@ -810,54 +1359,55 @@ static void count_da_grid(ivec ngrid, t_gridcell ***grid, t_icell danr)
 #define B(n,x,bTric,bEdge) ((n==1) ? x : bTric&&(bEdge) ? 0   : (x-1))
 #define E(n,x,bTric,bEdge) ((n==1) ? x : bTric&&(bEdge) ? n-1 : (x+1))
 #define GRIDMOD(j,n) (j+n)%(n)
-#define LOOPGRIDINNER(x,y,z,xx,yy,zz,xo,yo,zo,n,bTric)\
-     for(zz=B(n[ZZ],zo,bTric,FALSE); zz<=E(n[ZZ],zo,bTric,FALSE); zz++) {\
-       z=GRIDMOD(zz,n[ZZ]);\
-       for(yy=B(n[YY],yo,bTric,z==0||z==n[ZZ]-1); \
-         yy<=E(n[YY],yo,bTric,z==0||z==n[ZZ]-1); yy++) {\
-        y=GRIDMOD(yy,n[YY]);\
-        for(xx=B(n[XX],xo,bTric,y==0||y==n[YY]-1||z==0||z==n[ZZ]-1); \
-            xx<=E(n[XX],xo,bTric,y==0||y==n[YY]-1||z==0||z==n[ZZ]-1); xx++) {\
-          x=GRIDMOD(xx,n[XX]);
-#define ENDLOOPGRIDINNER\
-        }\
-       }\
-     }\
+#define LOOPGRIDINNER(x,y,z,xx,yy,zz,xo,yo,zo,n,bTric)                  \
+    for(zz=B(n[ZZ],zo,bTric,FALSE); zz<=E(n[ZZ],zo,bTric,FALSE); zz++) { \
+    z=GRIDMOD(zz,n[ZZ]);                                                \
+    for(yy=B(n[YY],yo,bTric,z==0||z==n[ZZ]-1);                          \
+        yy<=E(n[YY],yo,bTric,z==0||z==n[ZZ]-1); yy++) {                 \
+    y=GRIDMOD(yy,n[YY]);                                                \
+    for(xx=B(n[XX],xo,bTric,y==0||y==n[YY]-1||z==0||z==n[ZZ]-1);               \
+        xx<=E(n[XX],xo,bTric,y==0||y==n[YY]-1||z==0||z==n[ZZ]-1); xx++) { \
+    x=GRIDMOD(xx,n[XX]);
+#define ENDLOOPGRIDINNER                                                \
+    }                                                                   \
+        }                                                               \
+                                        }                                                              \
+                                                                        \
 
 static void dump_grid(FILE *fp, ivec ngrid, t_gridcell ***grid)
 {
-  int gr,x,y,z,sum[grNR];
-  
-  fprintf(fp,"grid %dx%dx%d\n",ngrid[XX],ngrid[YY],ngrid[ZZ]);
-  for (gr=0; gr<grNR; gr++) {
-    sum[gr]=0;
-    fprintf(fp,"GROUP %d (%s)\n",gr,grpnames[gr]);
-    for (z=0; z<ngrid[ZZ]; z+=2) {
-      fprintf(fp,"Z=%d,%d\n",z,z+1);
-      for (y=0; y<ngrid[YY]; y++) {
-       for (x=0; x<ngrid[XX]; x++) {
-         fprintf(fp,"%3d",grid[x][y][z].d[gr].nr);
-         sum[gr]+=grid[z][y][x].d[gr].nr;
-         fprintf(fp,"%3d",grid[x][y][z].a[gr].nr);
-         sum[gr]+=grid[z][y][x].a[gr].nr;
+    int gr,x,y,z,sum[grNR];
+  
+    fprintf(fp,"grid %dx%dx%d\n",ngrid[XX],ngrid[YY],ngrid[ZZ]);
+    for (gr=0; gr<grNR; gr++) {
+        sum[gr]=0;
+        fprintf(fp,"GROUP %d (%s)\n",gr,grpnames[gr]);
+        for (z=0; z<ngrid[ZZ]; z+=2) {
+            fprintf(fp,"Z=%d,%d\n",z,z+1);
+            for (y=0; y<ngrid[YY]; y++) {
+                for (x=0; x<ngrid[XX]; x++) {
+                    fprintf(fp,"%3d",grid[x][y][z].d[gr].nr);
+                    sum[gr]+=grid[z][y][x].d[gr].nr;
+                    fprintf(fp,"%3d",grid[x][y][z].a[gr].nr);
+                    sum[gr]+=grid[z][y][x].a[gr].nr;
          
-       }
-       fprintf(fp," | ");
-       if ( (z+1) < ngrid[ZZ] )
-         for (x=0; x<ngrid[XX]; x++) {
-           fprintf(fp,"%3d",grid[z+1][y][x].d[gr].nr);
-           sum[gr]+=grid[z+1][y][x].d[gr].nr;
-           fprintf(fp,"%3d",grid[z+1][y][x].a[gr].nr);
-           sum[gr]+=grid[z+1][y][x].a[gr].nr;
-         }
-       fprintf(fp,"\n");
-      }
-    }
-  }
-  fprintf(fp,"TOTALS:");
-  for (gr=0; gr<grNR; gr++)
-    fprintf(fp," %d=%d",gr,sum[gr]);
-  fprintf(fp,"\n");
+                }
+                fprintf(fp," | ");
+                if ( (z+1) < ngrid[ZZ] )
+                    for (x=0; x<ngrid[XX]; x++) {
+                        fprintf(fp,"%3d",grid[z+1][y][x].d[gr].nr);
+                        sum[gr]+=grid[z+1][y][x].d[gr].nr;
+                        fprintf(fp,"%3d",grid[z+1][y][x].a[gr].nr);
+                        sum[gr]+=grid[z+1][y][x].a[gr].nr;
+                    }
+                fprintf(fp,"\n");
+            }
+        }
+    }
+    fprintf(fp,"TOTALS:");
+    for (gr=0; gr<grNR; gr++)
+        fprintf(fp," %d=%d",gr,sum[gr]);
+    fprintf(fp,"\n");
 }
 
 /* New GMX record! 5 * in a row. Congratulations! 
@@ -865,29 +1415,47 @@ static void dump_grid(FILE *fp, ivec ngrid, t_gridcell ***grid)
  */
 static void free_grid(ivec ngrid, t_gridcell ****grid)
 {
-  int y,z;
-  t_gridcell ***g = *grid;
+    int y,z;
+    t_gridcell ***g = *grid;
   
-  for (z=0; z<ngrid[ZZ]; z++) {
-    for (y=0; y<ngrid[YY]; y++) {
-      sfree(g[z][y]);
+    for (z=0; z<ngrid[ZZ]; z++) {
+        for (y=0; y<ngrid[YY]; y++) {
+            sfree(g[z][y]);
+        }
+        sfree(g[z]);
     }
-    sfree(g[z]);
-  }
-  sfree(g);
-  g=NULL;
+    sfree(g);
+    g=NULL;
 }
 
 static void pbc_correct(rvec dx,matrix box,rvec hbox)
 {
-  int m;
-  
-  for(m=DIM-1; m>=0; m--) {
-    if ( dx[m] < -hbox[m] )
-      rvec_inc(dx,box[m]);
-    else if ( dx[m] >= hbox[m] )
-      rvec_dec(dx,box[m]);
-  }
+    int m;
+    for(m=DIM-1; m>=0; m--) {
+        if ( dx[m] < -hbox[m] )
+            rvec_inc(dx,box[m]);
+        else if ( dx[m] >= hbox[m] )
+            rvec_dec(dx,box[m]);
+    }
+}
+
+void pbc_correct_gem(rvec dx,matrix box,rvec hbox)
+{
+    int m;
+    bool bDone = FALSE;
+    while (!bDone) {
+        bDone = TRUE;
+        for(m=DIM-1; m>=0; m--) {
+            if ( dx[m] < -hbox[m] ) {
+                bDone = FALSE;
+                rvec_inc(dx,box[m]);
+            }
+            if ( dx[m] >= hbox[m] ) {
+                bDone = FALSE;
+                rvec_dec(dx,box[m]);
+            }
+        }
+    }
 }
 
 /* Added argument r2cut, changed contact and implemented 
@@ -895,206 +1463,291 @@ static void pbc_correct(rvec dx,matrix box,rvec hbox)
  * - Erik Marklund, June 29, 2006
  */
 static int is_hbond(t_hbdata *hb,int grpd,int grpa,int d,int a,
-                   real rcut, real r2cut, real ccut, 
-                   rvec x[], bool bBox, matrix box,rvec hbox,
-                   real *d_ha, real *ang,bool bDA,int *hhh,
-                   bool bContact)
+                    real rcut, real r2cut, real ccut, 
+                    rvec x[], bool bBox, matrix box,rvec hbox,
+                    real *d_ha, real *ang,bool bDA,int *hhh,
+                    bool bContact, bool bMerge, PSTYPE *p)
 {
-  int  h,hh,id,ja,ihb;
-  rvec r_da,r_ha,r_dh;
-  real rc2,r2c2,rda2,rha2,ca;
-  bool HAinrange = FALSE; /* If !bDA. Needed for returning hbDist in a correct way. */
-
-  if (d == a)
-    return hbNo;
-
-  if (((id = donor_index(&hb->d,grpd,d)) == NOTSET) ||
-      ((ja = acceptor_index(&hb->a,grpa,a)) == NOTSET))
-    return hbNo;
-  
-  rc2  = rcut*rcut;
-  r2c2 = r2cut*r2cut;
-  
-  rvec_sub(x[d],x[a],r_da);
-  if (bBox) 
-    pbc_correct(r_da,box,hbox);    
-  rda2 = iprod(r_da,r_da);
-  
-  if (bContact) {
-    if (rda2 <= rc2)
-      return hbHB;
-    else if (rda2 < r2c2)
-      return hbDist;
-    else
-      return hbNo;
-  }
-  *hhh = NOTSET;
-  
-  if (bDA && (rda2 > rc2))
-    return hbNo;
-  
-  for(h=0; (h < hb->d.nhydro[id]); h++) {
-    hh = hb->d.hydro[id][h];
-    rha2 = rc2+1;
-    if (!bDA) {
-      rvec_sub(x[hh],x[a],r_ha);
-      if (bBox)
-       pbc_correct(r_ha,box,hbox);
-      rha2 = iprod(r_ha,r_ha);
+    int  h,hh,id,ja,ihb;
+    rvec r_da,r_ha,r_dh, r={0, 0, 0};
+    ivec ri;
+    real rc2,r2c2,rda2,rha2,ca;
+    bool HAinrange = FALSE; /* If !bDA. Needed for returning hbDist in a correct way. */
+    bool daSwap = FALSE;
+
+    if (d == a)
+        return hbNo;
+
+    if (((id = donor_index(&hb->d,grpd,d)) == NOTSET) ||
+        ((ja = acceptor_index(&hb->a,grpa,a)) == NOTSET))
+        return hbNo;
+  
+    rc2  = rcut*rcut;
+    r2c2 = r2cut*r2cut;
+  
+    rvec_sub(x[d],x[a],r_da);
+    /* Insert projection code here */
+
+    /* if (d>a && ((isInterchangable(hb, d, a, grpd, grpa) && bMerge) || bContact)) */
+/*         /\* Then this hbond will be found again, or it has already been found. *\/ */
+/*         return hbNo; */
+
+    if (bBox){
+        if (d>a && bMerge && (bContact || isInterchangable(hb, d, a, grpd, grpa))) { /* acceptor is also a donor and vice versa? */
+            return hbNo;
+            daSwap = TRUE; /* If so, then their history should be filed with donor and acceptor swapped. */
+        }
+        if (hb->bGem) {
+            copy_rvec(r_da, r); /* Save this for later */
+            pbc_correct_gem(r_da,box,hbox);
+        } else {
+            pbc_correct_gem(r_da,box,hbox);    
+        }
     }
-    if (bBox)
-      pbc_correct(r_da,box,hbox);
-    
-    if (bDA || (!bDA && (rha2 <= rc2))) {
-      rvec_sub(x[d],x[hh],r_dh);
-      if (bBox)
-       pbc_correct(r_dh,box,hbox);
-      if (!bDA)
-       HAinrange = TRUE;
-      ca = cos_angle(r_dh,r_da);
-      /* if angle is smaller, cos is larger */
-      if (ca >= ccut) {
-       *hhh  = hh;
-       *d_ha = sqrt(bDA?rda2:rha2);
-       *ang  = acos(ca);
-       return hbHB;
-      }
-    }
-  }
-  if (bDA || (!bDA && HAinrange))
-    return hbDist;
-  else
-    return hbNo;
+    rda2 = iprod(r_da,r_da);
+  
+    if (bContact) {
+        if (daSwap)
+            return hbNo;
+        if (rda2 <= rc2){
+            if (hb->bGem){
+                calcBoxDistance(hb->per->P, r, ri);
+                *p = periodicIndex(ri, hb->per, daSwap);       /* find (or add) periodicity index. */
+            }
+            return hbHB;
+        }
+        else if (rda2 < r2c2)
+            return hbDist;
+        else
+            return hbNo;
+    }
+    *hhh = NOTSET;
+  
+    if (bDA && (rda2 > rc2))
+        return hbNo;
+  
+    for(h=0; (h < hb->d.nhydro[id]); h++) {
+        hh = hb->d.hydro[id][h];
+        rha2 = rc2+1;
+        if (!bDA) {
+            rvec_sub(x[hh],x[a],r_ha);
+            if (bBox) {
+                pbc_correct_gem(r_ha,box,hbox);
+            }
+            rha2 = iprod(r_ha,r_ha);
+        }
+
+        if (hb->bGem) {
+            calcBoxDistance(hb->per->P, r, ri);
+            *p = periodicIndex(ri, hb->per, daSwap);   /* find periodicity index. */
+        }
+
+        if (bDA || (!bDA && (rha2 <= rc2))) {
+            rvec_sub(x[d],x[hh],r_dh);
+            if (bBox) {
+                if (hb->bGem)
+                    pbc_correct_gem(r_dh,box,hbox);
+                else
+                    pbc_correct_gem(r_dh,box,hbox);
+            }
+       
+            if (!bDA)
+                HAinrange = TRUE;
+            ca = cos_angle(r_dh,r_da);
+            /* if angle is smaller, cos is larger */
+            if (ca >= ccut) {
+                *hhh  = hh;
+                *d_ha = sqrt(bDA?rda2:rha2);
+                *ang  = acos(ca);
+                return hbHB;
+            }
+        }
+    }
+    if (bDA || (!bDA && HAinrange))
+        return hbDist;
+    else
+        return hbNo;
 }
 
 /* Fixed previously undiscovered bug in the merge
    code, where the last frame of each hbond disappears.
    - Erik Marklund, June 1, 2006 */
+/* Added the following arguments:
+ *   ptmp[] - temporary periodicity hisory
+ *   a1     - identity of first acceptor/donor
+ *   a2     - identity of second acceptor/donor
+ * - Erik Marklund, FEB 20 2010 */
+
+/* Merging is now done on the fly, so do_merge is most likely obsolete now.
+ * Will do some more testing before removing the function entirely.
+ * - Erik Marklund, MAY 10 2010 */
 static void do_merge(t_hbdata *hb,int ntmp,
-                    unsigned int htmp[],unsigned int gtmp[],
-                    t_hbond *hb0,t_hbond *hb1)
+                     unsigned int htmp[],unsigned int gtmp[],PSTYPE ptmp[],
+                     t_hbond *hb0,t_hbond *hb1, int a1, int a2)
 {
-  int m,mm,n00,n01,nn0,nnframes;
-  /* Decide where to start from when merging */
-  n00      = hb0->n0;
-  n01      = hb1->n0;
-  nn0      = min(n00,n01);
-  nnframes = max(n00 + hb0->nframes,n01 + hb1->nframes) - nn0;
-  /* Initiate tmp arrays */
-  for(m=0; (m<ntmp); m++) {
-    htmp[m] = 0;
-    gtmp[m] = 0;
-  }
-  /* Fill tmp arrays with values due to first HB */
-  /* Once again '<' had to be replaced with '<='
-     to catch the last frame in which the hbond
-     appears.
-     - Erik Marklund, June 1, 2006 */  
-  for(m=0; (m<=hb0->nframes); m++) {
-    mm = m+n00-nn0;
-    htmp[mm] = is_hb(hb0->h[0],m);
-    gtmp[mm] = is_hb(hb0->g[0],m);
-  }
-  /* Next HB */
-  for(m=0; (m<=hb1->nframes); m++) {
-    mm = m+n01-nn0;
-    htmp[mm] = htmp[mm] || is_hb(hb1->h[0],m);
-    gtmp[mm] = gtmp[mm] || is_hb(hb1->g[0],m);
-  }
-  /* Reallocate target array */
-  if (nnframes > hb0->maxframes) {
-    srenew(hb0->h[0],4+nnframes/hb->wordlen);
-    srenew(hb0->g[0],4+nnframes/hb->wordlen);
-  }
-  /* Copy temp array to target array */
-  for(m=0; (m<=nnframes); m++) {
-    _set_hb(hb0->h[0],m,htmp[m]);
-    _set_hb(hb0->g[0],m,gtmp[m]);
-  }
-  /* Set scalar variables */
-  hb0->n0        = nn0;
-  hb0->maxframes = nnframes;
+    /* Here we need to make sure we're treating periodicity in
+     * the right way for the geminate recombination kinetics. */
+
+    int m,mm,n00,n01,nn0,nnframes;
+    PSTYPE pm;
+    t_pShift *pShift;
+
+    /* Decide where to start from when merging */
+    n00      = hb0->n0;
+    n01      = hb1->n0;
+    nn0      = min(n00,n01);
+    nnframes = max(n00 + hb0->nframes,n01 + hb1->nframes) - nn0;
+    /* Initiate tmp arrays */
+    for(m=0; (m<ntmp); m++) {
+        htmp[m] = 0;
+        gtmp[m] = 0;
+        ptmp[m] = 0;
+    }
+    /* Fill tmp arrays with values due to first HB */
+    /* Once again '<' had to be replaced with '<='
+       to catch the last frame in which the hbond
+       appears.
+       - Erik Marklund, June 1, 2006 */  
+    for(m=0; (m<=hb0->nframes); m++) {
+        mm = m+n00-nn0;
+        htmp[mm] = is_hb(hb0->h[0],m);
+        if (hb->bGem) {
+            pm = getPshift(hb->per->pHist[a1][a2], m+hb0->n0);
+            if (pm > hb->per->nper)
+                gmx_fatal(FARGS, "Illegal shift!");
+            else
+                ptmp[mm] = pm; /*hb->per->pHist[a1][a2][m];*/
+        }
+    }
+    /* If we're doing geminate recompbination we usually don't need the distances.
+     * Let's save some memory and time. */
+    if (TRUE || !hb->bGem || hb->per->gemtype == gemAD){
+        for(m=0; (m<=hb0->nframes); m++) {
+            mm = m+n00-nn0;
+            gtmp[mm] = is_hb(hb0->g[0],m);
+        }
+    }
+    /* Next HB */
+    for(m=0; (m<=hb1->nframes); m++) {
+        mm = m+n01-nn0;
+        htmp[mm] = htmp[mm] || is_hb(hb1->h[0],m);
+        gtmp[mm] = gtmp[mm] || is_hb(hb1->g[0],m);
+        if (hb->bGem /* && ptmp[mm] != 0 */) {
+
+            /* If this hbond has been seen before with donor and acceptor swapped,
+             * then we need to find the mirrored (*-1) periodicity vector to truely
+             * merge the hbond history. */
+            pm = findMirror(getPshift(hb->per->pHist[a2][a1],m+hb1->n0), hb->per->p2i, hb->per->nper);
+            /* Store index of mirror */
+            if (pm > hb->per->nper)
+                gmx_fatal(FARGS, "Illegal shift!");
+            ptmp[mm] = pm;
+        }
+    }
+    /* Reallocate target array */
+    if (nnframes > hb0->maxframes) {
+        srenew(hb0->h[0],4+nnframes/hb->wordlen);
+        srenew(hb0->g[0],4+nnframes/hb->wordlen);  
+    }
+    clearPshift(&(hb->per->pHist[a1][a2]));
+
+    /* Copy temp array to target array */
+    for(m=0; (m<=nnframes); m++) {
+        _set_hb(hb0->h[0],m,htmp[m]);
+        _set_hb(hb0->g[0],m,gtmp[m]);
+        if (hb->bGem)
+            addPshift(&(hb->per->pHist[a1][a2]), ptmp[m], m+nn0);
+    }
+  
+    /* Set scalar variables */
+    hb0->n0        = nn0;
+    hb0->maxframes = nnframes;
 }
 
 /* Added argument bContact for nicer output.
  * Erik Marklund, June 29, 2006
  */
-static void merge_hb(t_hbdata *hb,bool bTwo, bool bContact)
-{
-  int  i,inrnew,indnew,j,ii,jj,m,id,ia,grp,ogrp,ntmp;
-  unsigned int *htmp,*gtmp;
-  t_hbond *hb0,*hb1;
+static void merge_hb(t_hbdata *hb,bool bTwo, bool bContact){
+    int  i,inrnew,indnew,j,ii,jj,m,id,ia,grp,ogrp,ntmp;
+    unsigned int *htmp,*gtmp;
+    PSTYPE *ptmp;
+    t_hbond *hb0,*hb1;
 
-  inrnew = hb->nrhb;
-  indnew = hb->nrdist;
+    inrnew = hb->nrhb;
+    indnew = hb->nrdist;
     
-  /* Check whether donors are also acceptors */
-  printf("Merging hbonds with Acceptor and Donor swapped\n");
-
-  ntmp = 2*hb->max_frames;
-  snew(gtmp,ntmp);
-  snew(htmp,ntmp);
-  for(i=0; (i<hb->d.nrd); i++) {
-    fprintf(stderr,"\r%d/%d",i+1,hb->d.nrd);
-    id = hb->d.don[i];
-    ii = hb->a.aptr[id];
-    for(j=0; (j<hb->a.nra); j++) {
-      ia = hb->a.acc[j];
-      jj = hb->d.dptr[ia];
-      if ((id != ia) && (ii != NOTSET) && (jj != NOTSET) &&
-         (!bTwo || (bTwo && (hb->d.grp[i] != hb->a.grp[j])))) {
-       hb0 = hb->hbmap[i][j];
-       hb1 = hb->hbmap[jj][ii];
-       if (hb0 && hb1 && ISHB(hb0->history[0]) && ISHB(hb1->history[0])) {
-         do_merge(hb,ntmp,htmp,gtmp,hb0,hb1);
-         if (ISHB(hb1->history[0])) 
-           inrnew--;
-         else if (ISDIST(hb1->history[0])) 
-           indnew--;
-         else
-           if (bContact) 
-             gmx_incons("No contact history");
-           else
-             gmx_incons("Neither hydrogen bond nor distance");
-         sfree(hb1->h[0]);
-         sfree(hb1->g[0]);
-         hb1->h[0] = NULL;
-         hb1->g[0] = NULL;
-         hb1->history[0] = hbNo;
-       }
-      }
-    }
-  }
-  fprintf(stderr,"\n");
-  printf("- Reduced number of hbonds from %d to %d\n",hb->nrhb,inrnew);
-  printf("- Reduced number of distances from %d to %d\n",hb->nrdist,indnew);
-  hb->nrhb   = inrnew;
-  hb->nrdist = indnew;
-  sfree(gtmp);
-  sfree(htmp);
+    /* Check whether donors are also acceptors */
+    printf("Merging hbonds with Acceptor and Donor swapped\n");
+
+    ntmp = 2*hb->max_frames;
+    snew(gtmp,ntmp);
+    snew(htmp,ntmp);
+    snew(ptmp,ntmp);
+    for(i=0; (i<hb->d.nrd); i++) {
+        fprintf(stderr,"\r%d/%d",i+1,hb->d.nrd);
+        id = hb->d.don[i];
+        ii = hb->a.aptr[id];
+        for(j=0; (j<hb->a.nra); j++) {
+            ia = hb->a.acc[j];
+            jj = hb->d.dptr[ia];
+            if ((id != ia) && (ii != NOTSET) && (jj != NOTSET) &&
+                (!bTwo || (bTwo && (hb->d.grp[i] != hb->a.grp[j])))) {
+                hb0 = hb->hbmap[i][j];
+                hb1 = hb->hbmap[jj][ii];
+                if (hb0 && hb1 && ISHB(hb0->history[0]) && ISHB(hb1->history[0])) {
+                    do_merge(hb,ntmp,htmp,gtmp,ptmp,hb0,hb1,i,j);
+                    if (ISHB(hb1->history[0])) 
+                        inrnew--;
+                    else if (ISDIST(hb1->history[0])) 
+                        indnew--;
+                    else
+                        if (bContact) 
+                            gmx_incons("No contact history");
+                        else
+                            gmx_incons("Neither hydrogen bond nor distance");
+                    sfree(hb1->h[0]);
+                    sfree(hb1->g[0]);
+                    if (hb->bGem) {
+                        clearPshift(&(hb->per->pHist[jj][ii]));
+                    }
+                    hb1->h[0] = NULL;
+                    hb1->g[0] = NULL;
+                    hb1->history[0] = hbNo;
+                }
+            }
+        }
+    }
+    fprintf(stderr,"\n");
+    printf("- Reduced number of hbonds from %d to %d\n",hb->nrhb,inrnew);
+    printf("- Reduced number of distances from %d to %d\n",hb->nrdist,indnew);
+    hb->nrhb   = inrnew;
+    hb->nrdist = indnew;
+    sfree(gtmp);
+    sfree(htmp);
+    sfree(ptmp);
 }
 
 static void do_nhb_dist(FILE *fp,t_hbdata *hb,real t) 
 {
-  int  i,j,k,n_bound[MAXHH],nbtot;
-  h_id nhb;
-
-  
-  /* Set array to 0 */
-  for(k=0; (k<MAXHH); k++)
-    n_bound[k] = 0;
-  /* Loop over possible donors */
-  for(i=0; (i<hb->d.nrd); i++) {
-    for(j=0; (j<hb->d.nhydro[i]); j++)
-      n_bound[hb->d.nhbonds[i][j]]++;
-  }      
-  fprintf(fp,"%12.5e",t);
-  nbtot = 0;
-  for(k=0; (k<MAXHH); k++) {
-    fprintf(fp,"  %8d",n_bound[k]);
-    nbtot += n_bound[k]*k;
-  }
-  fprintf(fp,"  %8d\n",nbtot);
+    int  i,j,k,n_bound[MAXHH],nbtot;
+    h_id nhb;
+
+  
+    /* Set array to 0 */
+    for(k=0; (k<MAXHH); k++)
+        n_bound[k] = 0;
+    /* Loop over possible donors */
+    for(i=0; (i<hb->d.nrd); i++) {
+        for(j=0; (j<hb->d.nhydro[i]); j++)
+            n_bound[hb->d.nhbonds[i][j]]++;
+    }      
+    fprintf(fp,"%12.5e",t);
+    nbtot = 0;
+    for(k=0; (k<MAXHH); k++) {
+        fprintf(fp,"  %8d",n_bound[k]);
+        nbtot += n_bound[k]*k;
+    }
+    fprintf(fp,"  %8d\n",nbtot);
 }
 
 /* Added argument bContact in do_hblife(...). Also
@@ -1106,96 +1759,96 @@ static void do_nhb_dist(FILE *fp,t_hbdata *hb,real t)
 static void do_hblife(const char *fn,t_hbdata *hb,bool bMerge,bool bContact,
                       const output_env_t oenv)
 {
-  FILE *fp;
-  char *leg[] = { "p(t)", "t p(t)" };
-  int  *histo;
-  int  i,j,j0,k,m,nh,ihb,ohb,nhydro,ndump=0;
-  int   nframes = hb->nframes;
-  unsigned int **h;
-  real   t,x1,dt;
-  double sum,integral;
-  t_hbond *hbh;
-  
-  snew(h,hb->maxhydro);
-  snew(histo,nframes+1);
-  /* Total number of hbonds analyzed here */
-  for(i=0; (i<hb->d.nrd); i++) {
-    for(k=0; (k<hb->a.nra); k++) {
-      hbh = hb->hbmap[i][k];
-      if (hbh) {
-       if (bMerge) {
-         if (hbh->h[0]) {
-           h[0] = hbh->h[0];
-           nhydro = 1;
-         }
-         else
-           nhydro = 0;
-       }
-       else {
-         nhydro = 0;
-         for(m=0; (m<hb->maxhydro); m++)
-           if (hbh->h[m]) {
-             h[nhydro++] = bContact ? hbh->g[m] : hbh->h[m];
-           }
-       }
-       for(nh=0; (nh<nhydro); nh++) {
-         ohb = 0;
-         j0  = 0;
-
-         /* Changed '<' into '<=' below, just like I
-            did in the hbm-output-loop in the main code.
-            - Erik Marklund, May 31, 2006
-         */
-         for(j=0; (j<=hbh->nframes); j++) {
-           ihb      = is_hb(h[nh],j);
-           if (debug && (ndump < 10))
-             fprintf(debug,"%5d  %5d\n",j,ihb);
-           if (ihb != ohb) {
-             if (ihb) {
-               j0 = j;
-             }
-             else {
-               histo[j-j0]++;
-             }
-             ohb = ihb;
-           }
-         }
-         ndump++;
-       }
-      }
-    }
-  }
-  fprintf(stderr,"\n");
-  if (bContact)
-    fp = xvgropen(fn,"Uninterrupted contact lifetime","Time (ps)","()",oenv);
-  else
-    fp = xvgropen(fn,"Uninterrupted hydrogen bond lifetime","Time (ps)","()",
-                  oenv);
-
-  xvgr_legend(fp,asize(leg),leg,oenv);
-  j0 = nframes-1;
-  while ((j0 > 0) && (histo[j0] == 0))
-    j0--;
-  sum = 0;
-  for(i=0; (i<=j0); i++)
-    sum+=histo[i];
-  dt       = hb->time[1]-hb->time[0];
-  sum      = dt*sum;
-  integral = 0;
-  for(i=1; (i<=j0); i++) {
-    t  = hb->time[i] - hb->time[0] - 0.5*dt;
-    x1 = t*histo[i]/sum;
-    fprintf(fp,"%8.3f  %10.3e  %10.3e\n",t,histo[i]/sum,x1);
-    integral += x1;
-  }
-  integral *= dt;
-  ffclose(fp);
-  printf("%s lifetime = %.2f ps\n", bContact?"Contact":"HB", integral);
-  printf("Note that the lifetime obtained in this manner is close to useless\n");
-  printf("Use the -ac option instead and check the Forward lifetime\n");
-  please_cite(stdout,"Spoel2006b");
-  sfree(h);
-  sfree(histo);
+    FILE *fp;
+    char *leg[] = { "p(t)", "t p(t)" };
+    int  *histo;
+    int  i,j,j0,k,m,nh,ihb,ohb,nhydro,ndump=0;
+    int   nframes = hb->nframes;
+    unsigned int **h;
+    real   t,x1,dt;
+    double sum,integral;
+    t_hbond *hbh;
+  
+    snew(h,hb->maxhydro);
+    snew(histo,nframes+1);
+    /* Total number of hbonds analyzed here */
+    for(i=0; (i<hb->d.nrd); i++) {
+        for(k=0; (k<hb->a.nra); k++) {
+            hbh = hb->hbmap[i][k];
+            if (hbh) {
+                if (bMerge) {
+                    if (hbh->h[0]) {
+                        h[0] = hbh->h[0];
+                        nhydro = 1;
+                    }
+                    else
+                        nhydro = 0;
+                }
+                else {
+                    nhydro = 0;
+                    for(m=0; (m<hb->maxhydro); m++)
+                        if (hbh->h[m]) {
+                            h[nhydro++] = bContact ? hbh->g[m] : hbh->h[m];
+                        }
+                }
+                for(nh=0; (nh<nhydro); nh++) {
+                    ohb = 0;
+                    j0  = 0;
+
+                    /* Changed '<' into '<=' below, just like I
+                       did in the hbm-output-loop in the main code.
+                       - Erik Marklund, May 31, 2006
+                    */
+                    for(j=0; (j<=hbh->nframes); j++) {
+                        ihb      = is_hb(h[nh],j);
+                        if (debug && (ndump < 10))
+                            fprintf(debug,"%5d  %5d\n",j,ihb);
+                        if (ihb != ohb) {
+                            if (ihb) {
+                                j0 = j;
+                            }
+                            else {
+                                histo[j-j0]++;
+                            }
+                            ohb = ihb;
+                        }
+                    }
+                    ndump++;
+                }
+            }
+        }
+    }
+    fprintf(stderr,"\n");
+    if (bContact)
+        fp = xvgropen(fn,"Uninterrupted contact lifetime","Time (ps)","()",oenv);
+    else
+        fp = xvgropen(fn,"Uninterrupted hydrogen bond lifetime","Time (ps)","()",
+                      oenv);
+
+    xvgr_legend(fp,asize(leg),leg,oenv);
+    j0 = nframes-1;
+    while ((j0 > 0) && (histo[j0] == 0))
+        j0--;
+    sum = 0;
+    for(i=0; (i<=j0); i++)
+        sum+=histo[i];
+    dt       = hb->time[1]-hb->time[0];
+    sum      = dt*sum;
+    integral = 0;
+    for(i=1; (i<=j0); i++) {
+        t  = hb->time[i] - hb->time[0] - 0.5*dt;
+        x1 = t*histo[i]/sum;
+        fprintf(fp,"%8.3f  %10.3e  %10.3e\n",t,histo[i]/sum,x1);
+        integral += x1;
+    }
+    integral *= dt;
+    ffclose(fp);
+    printf("%s lifetime = %.2f ps\n", bContact?"Contact":"HB", integral);
+    printf("Note that the lifetime obtained in this manner is close to useless\n");
+    printf("Use the -ac option instead and check the Forward lifetime\n");
+    please_cite(stdout,"Spoel2006b");
+    sfree(h);
+    sfree(histo);
 }
 
 /* Changed argument bMerge into oneHB to handle contacts properly.
@@ -1203,370 +1856,399 @@ static void do_hblife(const char *fn,t_hbdata *hb,bool bMerge,bool bContact,
  */
 static void dump_ac(t_hbdata *hb,bool oneHB,int nDump)
 {
-  FILE  *fp;
-  int   i,j,k,m,nd,ihb,idist;
-  int   nframes = hb->nframes;
-  bool  bPrint;
-  t_hbond *hbh;
+    FILE  *fp;
+    int   i,j,k,m,nd,ihb,idist;
+    int   nframes = hb->nframes;
+    bool  bPrint;
+    t_hbond *hbh;
 
-  if (nDump <= 0)
-    return;
-  fp = ffopen("debug-ac.xvg","w");
-  for(j=0; (j<nframes); j++) {
-    fprintf(fp,"%10.3f",hb->time[j]);
-    for(i=nd=0; (i<hb->d.nrd) && (nd < nDump); i++) {
-      for(k=0; (k<hb->a.nra) && (nd < nDump); k++) {
-       bPrint = FALSE;
-       ihb = idist = 0;
-       hbh = hb->hbmap[i][k];
-       if (oneHB) {
-         if (hbh->h[0]) {
-           ihb   = is_hb(hbh->h[0],j);
-           idist = is_hb(hbh->g[0],j);
-           bPrint = TRUE;
-         }
-       } 
-       else {
-         for(m=0; (m<hb->maxhydro) && !ihb ; m++) {
-           ihb   = ihb   || ((hbh->h[m]) && is_hb(hbh->h[m],j));
-           idist = idist || ((hbh->g[m]) && is_hb(hbh->g[m],j));
-         }
-         /* This is not correct! */
-         /* What isn't correct? -Erik M */
-         bPrint = TRUE;
-       }
-       if (bPrint) {
-         fprintf(fp,"  %1d-%1d",ihb,idist);
-         nd++;
-       }
-      }
+    if (nDump <= 0)
+        return;
+    fp = ffopen("debug-ac.xvg","w");
+    for(j=0; (j<nframes); j++) {
+        fprintf(fp,"%10.3f",hb->time[j]);
+        for(i=nd=0; (i<hb->d.nrd) && (nd < nDump); i++) {
+            for(k=0; (k<hb->a.nra) && (nd < nDump); k++) {
+                bPrint = FALSE;
+                ihb = idist = 0;
+                hbh = hb->hbmap[i][k];
+                if (oneHB) {
+                    if (hbh->h[0]) {
+                        ihb   = is_hb(hbh->h[0],j);
+                        idist = is_hb(hbh->g[0],j);
+                        bPrint = TRUE;
+                    }
+                } 
+                else {
+                    for(m=0; (m<hb->maxhydro) && !ihb ; m++) {
+                        ihb   = ihb   || ((hbh->h[m]) && is_hb(hbh->h[m],j));
+                        idist = idist || ((hbh->g[m]) && is_hb(hbh->g[m],j));
+                    }
+                    /* This is not correct! */
+                    /* What isn't correct? -Erik M */
+                    bPrint = TRUE;
+                }
+                if (bPrint) {
+                    fprintf(fp,"  %1d-%1d",ihb,idist);
+                    nd++;
+                }
+            }
+        }
+        fprintf(fp,"\n");
     }
-    fprintf(fp,"\n");
-  }
-  ffclose(fp);
+    ffclose(fp);
 }
 
 static real calc_dg(real tau,real temp)
 {
-  real kbt;
+    real kbt;
   
-  kbt = BOLTZ*temp;
-  if (tau <= 0)
-    return -666;
-  else
-    return kbt*log(kbt*tau/PLANCK);  
+    kbt = BOLTZ*temp;
+    if (tau <= 0)
+        return -666;
+    else
+        return kbt*log(kbt*tau/PLANCK);  
 }
 
 typedef struct {
-  int  n0,n1,nparams,ndelta;
-  real kkk[2];
-  real *t,*ct,*nt,*kt,*sigma_ct,*sigma_nt,*sigma_kt;
+    int  n0,n1,nparams,ndelta;
+    real kkk[2];
+    real *t,*ct,*nt,*kt,*sigma_ct,*sigma_nt,*sigma_kt;
 } t_luzar;
 
 #ifdef HAVE_LIBGSL
 #include <gsl/gsl_multimin.h>
 #include <gsl/gsl_sf.h>
+#include <gsl/gsl_version.h>
 
 static double my_f(const gsl_vector *v,void *params)
 {
-  t_luzar *tl = (t_luzar *)params;
-  int    i;
-  double tol=1e-16,chi2=0;
-  double di;
-  real   k,kp;
-  
-  for(i=0; (i<tl->nparams); i++) {
-    tl->kkk[i] = gsl_vector_get(v, i);
-  }
-  k  = tl->kkk[0];
-  kp = tl->kkk[1];
-  
-  for(i=tl->n0; (i<tl->n1); i+=tl->ndelta) {
-    di=sqr(k*tl->sigma_ct[i]) + sqr(kp*tl->sigma_nt[i]) + sqr(tl->sigma_kt[i]);
-    /*di = 1;*/
-    if (di > tol)
-      chi2 += sqr(k*tl->ct[i]-kp*tl->nt[i]-tl->kt[i])/di;
+    t_luzar *tl = (t_luzar *)params;
+    int    i;
+    double tol=1e-16,chi2=0;
+    double di;
+    real   k,kp;
+  
+    for(i=0; (i<tl->nparams); i++) {
+        tl->kkk[i] = gsl_vector_get(v, i);
+    }
+    k  = tl->kkk[0];
+    kp = tl->kkk[1];
+  
+    for(i=tl->n0; (i<tl->n1); i+=tl->ndelta) {
+        di=sqr(k*tl->sigma_ct[i]) + sqr(kp*tl->sigma_nt[i]) + sqr(tl->sigma_kt[i]);
+        /*di = 1;*/
+        if (di > tol)
+            chi2 += sqr(k*tl->ct[i]-kp*tl->nt[i]-tl->kt[i])/di;
       
-    else
-      fprintf(stderr,"WARNING: sigma_ct = %g, sigma_nt = %g, sigma_kt = %g\n"
-             "di = %g k = %g kp = %g\n",tl->sigma_ct[i],
-             tl->sigma_nt[i],tl->sigma_kt[i],di,k,kp);
-  }
+        else
+            fprintf(stderr,"WARNING: sigma_ct = %g, sigma_nt = %g, sigma_kt = %g\n"
+                    "di = %g k = %g kp = %g\n",tl->sigma_ct[i],
+                    tl->sigma_nt[i],tl->sigma_kt[i],di,k,kp);
+    }
 #ifdef DEBUG
-  chi2 = 0.3*sqr(k-0.6)+0.7*sqr(kp-1.3);
+    chi2 = 0.3*sqr(k-0.6)+0.7*sqr(kp-1.3);
 #endif
-  return chi2;
+    return chi2;
 }
 
 static real optimize_luzar_parameters(FILE *fp,t_luzar *tl,int maxiter,
-                                     real tol)
+                                      real tol)
 {
-  real   size,d2;
-  int    iter   = 0;
-  int    status = 0;
-  int    i;
+    real   size,d2;
+    int    iter   = 0;
+    int    status = 0;
+    int    i;
 
-  const gsl_multimin_fminimizer_type *T;
-  gsl_multimin_fminimizer *s;
+    const gsl_multimin_fminimizer_type *T;
+    gsl_multimin_fminimizer *s;
 
-  gsl_vector *x,*dx;
-  gsl_multimin_function my_func;
+    gsl_vector *x,*dx;
+    gsl_multimin_function my_func;
 
-  my_func.f      = &my_f;
-  my_func.n      = tl->nparams;
-  my_func.params = (void *) tl;
+    my_func.f      = &my_f;
+    my_func.n      = tl->nparams;
+    my_func.params = (void *) tl;
 
-  /* Starting point */
-  x = gsl_vector_alloc (my_func.n);
-  for(i=0; (i<my_func.n); i++)
-    gsl_vector_set (x, i, tl->kkk[i]);
+    /* Starting point */
+    x = gsl_vector_alloc (my_func.n);
+    for(i=0; (i<my_func.n); i++)
+        gsl_vector_set (x, i, tl->kkk[i]);
   
-  /* Step size, different for each of the parameters */
-  dx = gsl_vector_alloc (my_func.n);
-  for(i=0; (i<my_func.n); i++)
-    gsl_vector_set (dx, i, 0.01*tl->kkk[i]);
+    /* Step size, different for each of the parameters */
+    dx = gsl_vector_alloc (my_func.n);
+    for(i=0; (i<my_func.n); i++)
+        gsl_vector_set (dx, i, 0.01*tl->kkk[i]);
 
-  T = gsl_multimin_fminimizer_nmsimplex;
-  s = gsl_multimin_fminimizer_alloc (T, my_func.n);
+    T = gsl_multimin_fminimizer_nmsimplex;
+    s = gsl_multimin_fminimizer_alloc (T, my_func.n);
 
-  gsl_multimin_fminimizer_set (s, &my_func, x, dx);
-  gsl_vector_free (x);
-  gsl_vector_free (dx);
+    gsl_multimin_fminimizer_set (s, &my_func, x, dx);
+    gsl_vector_free (x);
+    gsl_vector_free (dx);
 
-  if (fp)
-    fprintf(fp,"%5s %12s %12s %12s %12s\n","Iter","k","kp","NM Size","Chi2");
+    if (fp)
+        fprintf(fp,"%5s %12s %12s %12s %12s\n","Iter","k","kp","NM Size","Chi2");
   
-  do  {
-    iter++;
-    status = gsl_multimin_fminimizer_iterate (s);
+    do  {
+        iter++;
+        status = gsl_multimin_fminimizer_iterate (s);
     
-    if (status != 0)
-      gmx_fatal(FARGS,"Something went wrong in the iteration in minimizer %s",
-               gsl_multimin_fminimizer_name(s));
+        if (status != 0)
+            gmx_fatal(FARGS,"Something went wrong in the iteration in minimizer %s",
+                      gsl_multimin_fminimizer_name(s));
     
-    d2     = gsl_multimin_fminimizer_minimum(s);
-    size   = gsl_multimin_fminimizer_size(s);
-    status = gsl_multimin_test_size(size,tol);
+        d2     = gsl_multimin_fminimizer_minimum(s);
+        size   = gsl_multimin_fminimizer_size(s);
+        status = gsl_multimin_test_size(size,tol);
     
-    if (status == GSL_SUCCESS)
-      if (fp) 
-       fprintf(fp,"Minimum found using %s at:\n",
-               gsl_multimin_fminimizer_name(s));
+        if (status == GSL_SUCCESS)
+            if (fp) 
+                fprintf(fp,"Minimum found using %s at:\n",
+                        gsl_multimin_fminimizer_name(s));
   
-    if (fp) {
-      fprintf(fp,"%5d", iter);
-      for(i=0; (i<my_func.n); i++) 
-       fprintf(fp," %12.4e",gsl_vector_get (s->x,i));
-      fprintf (fp," %12.4e %12.4e\n",size,d2);
+        if (fp) {
+            fprintf(fp,"%5d", iter);
+            for(i=0; (i<my_func.n); i++) 
+                fprintf(fp," %12.4e",gsl_vector_get (s->x,i));
+            fprintf (fp," %12.4e %12.4e\n",size,d2);
+        }
     }
-  }
-  while ((status == GSL_CONTINUE) && (iter < maxiter));
+    while ((status == GSL_CONTINUE) && (iter < maxiter));
   
-  gsl_multimin_fminimizer_free (s);
+    gsl_multimin_fminimizer_free (s);
   
-  return d2;
+    return d2;
 }
 
 static real quality_of_fit(real chi2,int N)
 {
-  return gsl_sf_gamma_inc_Q((N-2)/2.0,chi2/2.0);
+    return gsl_sf_gamma_inc_Q((N-2)/2.0,chi2/2.0);
 }
 
 #else
 static real optimize_luzar_parameters(FILE *fp,t_luzar *tl,int maxiter,
-                                     real tol)
+                                      real tol)
 {
-  fprintf(stderr,"This program needs the GNU scientific library to work.\n");
+    fprintf(stderr,"This program needs the GNU scientific library to work.\n");
   
-  return -1;
+    return -1;
 }
 static real quality_of_fit(real chi2,int N)
 {
-  fprintf(stderr,"This program needs the GNU scientific library to work.\n");
+    fprintf(stderr,"This program needs the GNU scientific library to work.\n");
   
-  return -1;
+    return -1;
 }
 
 #endif
 
 static real compute_weighted_rates(int n,real t[],real ct[],real nt[],
-                                  real kt[],real sigma_ct[],real sigma_nt[],
-                                  real sigma_kt[],real *k,real *kp,
-                                  real *sigma_k,real *sigma_kp,
-                                  real fit_start)
+                                   real kt[],real sigma_ct[],real sigma_nt[],
+                                   real sigma_kt[],real *k,real *kp,
+                                   real *sigma_k,real *sigma_kp,
+                                   real fit_start)
 {
 #define NK 10
-  int      i,j;
-  t_luzar  tl;
-  real     kkk=0,kkp=0,kk2=0,kp2=0,chi2;
-  
-  *sigma_k  = 0;
-  *sigma_kp = 0;
-  
-  for(i=0; (i<n); i++) {
-    if (t[i] >= fit_start)
-      break;
-  }
-  tl.n0      = i;
-  tl.n1      = n;
-  tl.nparams = 2;
-  tl.ndelta  = 1;
-  tl.t  = t;
-  tl.ct = ct;
-  tl.nt = nt;
-  tl.kt = kt;
-  tl.sigma_ct = sigma_ct;
-  tl.sigma_nt = sigma_nt;
-  tl.sigma_kt = sigma_kt;
-  tl.kkk[0] = *k;
-  tl.kkk[1] = *kp;
-  
-  chi2 = optimize_luzar_parameters(debug,&tl,1000,1e-3);
-  *k  = tl.kkk[0];
-  *kp = tl.kkk[1] = *kp;
-  tl.ndelta = NK;
-  for(j=0; (j<NK); j++) {
-    (void) optimize_luzar_parameters(debug,&tl,1000,1e-3);
-    kkk += tl.kkk[0];
-    kkp += tl.kkk[1];
-    kk2 += sqr(tl.kkk[0]);
-    kp2 += sqr(tl.kkk[1]);
-    tl.n0++;
-  }
-  *sigma_k  = sqrt(kk2/NK - sqr(kkk/NK));
-  *sigma_kp = sqrt(kp2/NK - sqr(kkp/NK));
-  
-  return chi2;
+    int      i,j;
+    t_luzar  tl;
+    real     kkk=0,kkp=0,kk2=0,kp2=0,chi2;
+  
+    *sigma_k  = 0;
+    *sigma_kp = 0;
+  
+    for(i=0; (i<n); i++) {
+        if (t[i] >= fit_start)
+            break;
+    }
+    tl.n0      = i;
+    tl.n1      = n;
+    tl.nparams = 2;
+    tl.ndelta  = 1;
+    tl.t  = t;
+    tl.ct = ct;
+    tl.nt = nt;
+    tl.kt = kt;
+    tl.sigma_ct = sigma_ct;
+    tl.sigma_nt = sigma_nt;
+    tl.sigma_kt = sigma_kt;
+    tl.kkk[0] = *k;
+    tl.kkk[1] = *kp;
+  
+    chi2 = optimize_luzar_parameters(debug,&tl,1000,1e-3);
+    *k  = tl.kkk[0];
+    *kp = tl.kkk[1] = *kp;
+    tl.ndelta = NK;
+    for(j=0; (j<NK); j++) {
+        (void) optimize_luzar_parameters(debug,&tl,1000,1e-3);
+        kkk += tl.kkk[0];
+        kkp += tl.kkk[1];
+        kk2 += sqr(tl.kkk[0]);
+        kp2 += sqr(tl.kkk[1]);
+        tl.n0++;
+    }
+    *sigma_k  = sqrt(kk2/NK - sqr(kkk/NK));
+    *sigma_kp = sqrt(kp2/NK - sqr(kkp/NK));
+  
+    return chi2;
 }
 
 static void smooth_tail(int n,real t[],real c[],real sigma_c[],real start,
                         const output_env_t oenv)
 {
-  FILE *fp;
-  real e_1,fitparm[4];
-  int  i;
-  
-  e_1 = exp(-1);
-  for(i=0; (i<n); i++)
-    if (c[i] < e_1)
-      break;
-  if (i < n)
-    fitparm[0] = t[i];
-  else
-    fitparm[0] = 10;
-  fitparm[1] = 0.95;
-  do_lmfit(n,c,sigma_c,0,t,start,t[n-1],oenv,bDebugMode(),effnEXP2,fitparm,0);
+    FILE *fp;
+    real e_1,fitparm[4];
+    int  i;
+  
+    e_1 = exp(-1);
+    for(i=0; (i<n); i++)
+        if (c[i] < e_1)
+            break;
+    if (i < n)
+        fitparm[0] = t[i];
+    else
+        fitparm[0] = 10;
+    fitparm[1] = 0.95;
+    do_lmfit(n,c,sigma_c,0,t,start,t[n-1],oenv,bDebugMode(),effnEXP2,fitparm,0);
 }
 
 void analyse_corr(int n,real t[],real ct[],real nt[],real kt[],
-                 real sigma_ct[],real sigma_nt[],real sigma_kt[],
-                 real fit_start,real temp,real smooth_tail_start,
+                  real sigma_ct[],real sigma_nt[],real sigma_kt[],
+                  real fit_start,real temp,real smooth_tail_start,
                   const output_env_t oenv)
 {
-  int    i0,i;
-  real   k=1,kp=1,kow=1;
-  real   Q=0,chi22,chi2,dg,dgp,tau_hb,dtau,tau_rlx,e_1,dt,sigma_k,sigma_kp,ddg;
-  double tmp,sn2=0,sc2=0,sk2=0,scn=0,sck=0,snk=0;
-  bool   bError = (sigma_ct != NULL) && (sigma_nt != NULL) && (sigma_kt != NULL);
-  
-  if (smooth_tail_start >= 0) {
-    smooth_tail(n,t,ct,sigma_ct,smooth_tail_start,oenv);
-    smooth_tail(n,t,nt,sigma_nt,smooth_tail_start,oenv);
-    smooth_tail(n,t,kt,sigma_kt,smooth_tail_start,oenv);
-  }
-  for(i0=0; (i0<n-2) && ((t[i0]-t[0]) < fit_start); i0++)
-    ;
-  if (i0 < n-2) { 
-    for(i=i0; (i<n); i++) {
-      sc2 += sqr(ct[i]);
-      sn2 += sqr(nt[i]);
-      sk2 += sqr(kt[i]);
-      sck += ct[i]*kt[i];
-      snk += nt[i]*kt[i];
-      scn += ct[i]*nt[i];
-    }
-    printf("Hydrogen bond thermodynamics at T = %g K\n",temp);
-    tmp = (sn2*sc2-sqr(scn));
-    if ((tmp > 0) && (sn2 > 0)) {
-      k    = (sn2*sck-scn*snk)/tmp;
-      kp   = (k*scn-snk)/sn2;
-      if (bError) {
-       chi2 = 0;
-       for(i=i0; (i<n); i++) {
-         chi2 += sqr(k*ct[i]-kp*nt[i]-kt[i]);
-       }
-       chi22 = compute_weighted_rates(n,t,ct,nt,kt,sigma_ct,sigma_nt,
-                                      sigma_kt,&k,&kp,
-                                      &sigma_k,&sigma_kp,fit_start);
-       Q = quality_of_fit(chi2,2);
-       ddg = BOLTZ*temp*sigma_k/k;
-       printf("Fitting paramaters chi^2 = %10g, Quality of fit = %10g\n",
-              chi2,Q);
-       printf("The Rate and Delta G are followed by an error estimate\n");
-       printf("----------------------------------------------------------\n"
-              "Type      Rate (1/ps)  Sigma Time (ps)  DG (kJ/mol)  Sigma\n");
-       printf("Forward    %10.3f %6.2f   %8.3f  %10.3f %6.2f\n",
-              k,sigma_k,1/k,calc_dg(1/k,temp),ddg);
-       ddg = BOLTZ*temp*sigma_kp/kp;
-       printf("Backward   %10.3f %6.2f   %8.3f  %10.3f %6.2f\n",
-              kp,sigma_kp,1/kp,calc_dg(1/kp,temp),ddg);
-      }
-      else {
-       chi2 = 0;
-       for(i=i0; (i<n); i++) {
-         chi2 += sqr(k*ct[i]-kp*nt[i]-kt[i]);
-       }
-       printf("Fitting parameters chi^2 = %10g\nQ = %10g\n",
-              chi2,Q);
-       printf("--------------------------------------------------\n"
-              "Type      Rate (1/ps) Time (ps)  DG (kJ/mol)  Chi^2\n");
-       printf("Forward    %10.3f   %8.3f  %10.3f  %10g\n",
-              k,1/k,calc_dg(1/k,temp),chi2);
-       printf("Backward   %10.3f   %8.3f  %10.3f\n",
-              kp,1/kp,calc_dg(1/kp,temp));
-      }
-    }
-    if (sc2 > 0) {
-      kow  = 2*sck/sc2;
-      printf("One-way    %10.3f   %s%8.3f  %10.3f\n",
-            kow,bError ? "       " : "",1/kow,calc_dg(1/kow,temp));
-    }
-    else 
-      printf(" - Numerical problems computing HB thermodynamics:\n"
-            "sc2 = %g  sn2 = %g  sk2 = %g sck = %g snk = %g scn = %g\n",
-            sc2,sn2,sk2,sck,snk,scn);
-    /* Determine integral of the correlation function */
-    tau_hb = evaluate_integral(n,t,ct,NULL,(t[n-1]-t[0])/2,&dtau);
-    printf("Integral   %10.3f   %s%8.3f  %10.3f\n",1/tau_hb,
-          bError ? "       " : "",tau_hb,calc_dg(tau_hb,temp));
-    e_1 = exp(-1);
-    for(i=0; (i<n-2); i++) {
-      if ((ct[i] > e_1) && (ct[i+1] <= e_1)) {
-       break;
-      }
+    int    i0,i;
+    real   k=1,kp=1,kow=1;
+    real   Q=0,chi22,chi2,dg,dgp,tau_hb,dtau,tau_rlx,e_1,dt,sigma_k,sigma_kp,ddg;
+    double tmp,sn2=0,sc2=0,sk2=0,scn=0,sck=0,snk=0;
+    bool   bError = (sigma_ct != NULL) && (sigma_nt != NULL) && (sigma_kt != NULL);
+  
+    if (smooth_tail_start >= 0) {
+        smooth_tail(n,t,ct,sigma_ct,smooth_tail_start,oenv);
+        smooth_tail(n,t,nt,sigma_nt,smooth_tail_start,oenv);
+        smooth_tail(n,t,kt,sigma_kt,smooth_tail_start,oenv);
     }
-    if (i < n-2) {
-      /* Determine tau_relax from linear interpolation */
-      tau_rlx = t[i]-t[0] + (e_1-ct[i])*(t[i+1]-t[i])/(ct[i+1]-ct[i]);
-      printf("Relaxation %10.3f   %8.3f  %s%10.3f\n",1/tau_rlx,
-            tau_rlx,bError ? "       " : "",
-            calc_dg(tau_rlx,temp));
+    for(i0=0; (i0<n-2) && ((t[i0]-t[0]) < fit_start); i0++)
+        ;
+    if (i0 < n-2) { 
+        for(i=i0; (i<n); i++) {
+            sc2 += sqr(ct[i]);
+            sn2 += sqr(nt[i]);
+            sk2 += sqr(kt[i]);
+            sck += ct[i]*kt[i];
+            snk += nt[i]*kt[i];
+            scn += ct[i]*nt[i];
+        }
+        printf("Hydrogen bond thermodynamics at T = %g K\n",temp);
+        tmp = (sn2*sc2-sqr(scn));
+        if ((tmp > 0) && (sn2 > 0)) {
+            k    = (sn2*sck-scn*snk)/tmp;
+            kp   = (k*scn-snk)/sn2;
+            if (bError) {
+                chi2 = 0;
+                for(i=i0; (i<n); i++) {
+                    chi2 += sqr(k*ct[i]-kp*nt[i]-kt[i]);
+                }
+                chi22 = compute_weighted_rates(n,t,ct,nt,kt,sigma_ct,sigma_nt,
+                                               sigma_kt,&k,&kp,
+                                               &sigma_k,&sigma_kp,fit_start);
+                Q = quality_of_fit(chi2,2);
+                ddg = BOLTZ*temp*sigma_k/k;
+                printf("Fitting paramaters chi^2 = %10g, Quality of fit = %10g\n",
+                       chi2,Q);
+                printf("The Rate and Delta G are followed by an error estimate\n");
+                printf("----------------------------------------------------------\n"
+                       "Type      Rate (1/ps)  Sigma Time (ps)  DG (kJ/mol)  Sigma\n");
+                printf("Forward    %10.3f %6.2f   %8.3f  %10.3f %6.2f\n",
+                       k,sigma_k,1/k,calc_dg(1/k,temp),ddg);
+                ddg = BOLTZ*temp*sigma_kp/kp;
+                printf("Backward   %10.3f %6.2f   %8.3f  %10.3f %6.2f\n",
+                       kp,sigma_kp,1/kp,calc_dg(1/kp,temp),ddg);
+            }
+            else {
+                chi2 = 0;
+                for(i=i0; (i<n); i++) {
+                    chi2 += sqr(k*ct[i]-kp*nt[i]-kt[i]);
+                }
+                printf("Fitting parameters chi^2 = %10g\nQ = %10g\n",
+                       chi2,Q);
+                printf("--------------------------------------------------\n"
+                       "Type      Rate (1/ps) Time (ps)  DG (kJ/mol)  Chi^2\n");
+                printf("Forward    %10.3f   %8.3f  %10.3f  %10g\n",
+                       k,1/k,calc_dg(1/k,temp),chi2);
+                printf("Backward   %10.3f   %8.3f  %10.3f\n",
+                       kp,1/kp,calc_dg(1/kp,temp));
+            }
+        }
+        if (sc2 > 0) {
+            kow  = 2*sck/sc2;
+            printf("One-way    %10.3f   %s%8.3f  %10.3f\n",
+                   kow,bError ? "       " : "",1/kow,calc_dg(1/kow,temp));
+        }
+        else 
+            printf(" - Numerical problems computing HB thermodynamics:\n"
+                   "sc2 = %g  sn2 = %g  sk2 = %g sck = %g snk = %g scn = %g\n",
+                   sc2,sn2,sk2,sck,snk,scn);
+        /* Determine integral of the correlation function */
+        tau_hb = evaluate_integral(n,t,ct,NULL,(t[n-1]-t[0])/2,&dtau);
+        printf("Integral   %10.3f   %s%8.3f  %10.3f\n",1/tau_hb,
+               bError ? "       " : "",tau_hb,calc_dg(tau_hb,temp));
+        e_1 = exp(-1);
+        for(i=0; (i<n-2); i++) {
+            if ((ct[i] > e_1) && (ct[i+1] <= e_1)) {
+                break;
+            }
+        }
+        if (i < n-2) {
+            /* Determine tau_relax from linear interpolation */
+            tau_rlx = t[i]-t[0] + (e_1-ct[i])*(t[i+1]-t[i])/(ct[i+1]-ct[i]);
+            printf("Relaxation %10.3f   %8.3f  %s%10.3f\n",1/tau_rlx,
+                   tau_rlx,bError ? "       " : "",
+                   calc_dg(tau_rlx,temp));
+        }
     }
-  }
-  else 
-    printf("Correlation functions too short to compute thermodynamics\n");
+    else 
+        printf("Correlation functions too short to compute thermodynamics\n");
 }
 
 void compute_derivative(int nn,real x[],real y[],real dydx[])
 {
-  int j;
+    int j;
   
-  /* Compute k(t) = dc(t)/dt */
-  for(j=1; (j<nn-1); j++)
-    dydx[j] = (y[j+1]-y[j-1])/(x[j+1]-x[j-1]);
-  /* Extrapolate endpoints */
-  dydx[0]    = 2*dydx[1]   -  dydx[2];
-  dydx[nn-1] = 2*dydx[nn-2] - dydx[nn-3];
+    /* Compute k(t) = dc(t)/dt */
+    for(j=1; (j<nn-1); j++)
+        dydx[j] = (y[j+1]-y[j-1])/(x[j+1]-x[j-1]);
+    /* Extrapolate endpoints */
+    dydx[0]    = 2*dydx[1]   -  dydx[2];
+    dydx[nn-1] = 2*dydx[nn-2] - dydx[nn-3];
+}
+
+static void parallel_print(int *data, int nThreads)
+{
+    /* This prints the donors on which each tread is currently working. */
+    int i;
+
+    fprintf(stderr, "\r");
+    for (i=0; i<nThreads; i++)
+        fprintf(stderr, "%-7i",data[i]);
+}
+
+static void normalizeACF(real *ct, real *gt, int len)
+{
+    real ct_fac, gt_fac;
+    int i;
+
+    /* Xu and Berne use the same normalization constant */
+
+    ct_fac = 1.0/ct[0];
+    gt_fac = (gt!=NULL && gt[0]!=0) ? 1.0/gt[0] : 0;
+    printf("Normalization for c(t) = %g for gh(t) = %g\n",ct_fac,gt_fac);
+    for (i=0; i<len; i++)
+    {
+        ct[i] *= ct_fac;
+        if (gt != NULL)
+            gt[i] *= gt_fac;
+    }
 }
 
 /* Added argument bContact in do_hbac(...). Also
@@ -1576,1118 +2258,2021 @@ void compute_derivative(int nn,real x[],real y[],real dydx[])
  * - Erik Marklund, June 29, 2006
  */
 static void do_hbac(const char *fn,t_hbdata *hb,real aver_nhb,real aver_dist,
-                   int nDump,bool bMerge,bool bContact,real fit_start,
-                    real temp,bool R2,real smooth_tail_start,
-                    const output_env_t oenv)
+                    int nDump,bool bMerge,bool bContact, real fit_start,
+                    real temp,bool R2,real smooth_tail_start, const output_env_t oenv,
+                    t_gemParams *params, const char *gemType, int nThreads,
+                    const int NN, const bool bBallistic, const bool bGemFit)
 {
-  FILE *fp;
-  char *leg[] = { "Ac\\sfin sys\\v{}\\z{}(t)", "Ac(t)", "Cc\\scontact,hb\\v{}\\z{}(t)", "-dAc\\sfs\\v{}\\z{}/dt" };
-  int  i,j,k,m,n,nd,ihb,idist,n2,nn;
-  bool bNorm=FALSE;
-  double nhb = 0;
-  real *rhbex,*ht,*gt,*ght,*dght,*kt;
-  real *ct,tail,tail2,dtail,ct_fac,ght_fac,*cct;
-  const real tol = 1e-3;
-  int   nframes = hb->nframes,nf;
-  unsigned int **h,**g;
-  int   nh,nhbonds,nhydro,ngh;
-  t_hbond *hbh;
-
-  /* build hbexist matrix in reals for autocorr */
-  /* Allocate memory for computing ACF (rhbex) and aggregating the ACF (ct) */
-  n2=1;
-  while (n2 < nframes)
-    n2*=2;
-  snew(rhbex,2*n2);
-  snew(ct,2*n2);
-  snew(gt,2*n2);
-  snew(ht,2*n2);
-  snew(ght,2*n2);
-  snew(dght,2*n2);
-  
-  nn = nframes/2;
-  snew(kt,nn);
-  snew(cct,nn);
-  
-  snew(h,hb->maxhydro);
-  snew(g,hb->maxhydro);
-
-  /* Dump hbonds for debugging */
-  dump_ac(hb,bMerge||bContact,nDump);
-  
-  /* Total number of hbonds analyzed here */
-  nhbonds = 0;
-  ngh     = 0;
-  for(i=0; (i<hb->d.nrd); i++) {
-    for(k=0; (k<hb->a.nra); k++) {
-      nhydro = 0;
-      hbh = hb->hbmap[i][k];
-      if (hbh) {
-       if (bMerge || bContact) {
-         if (ISHB(hbh->history[0])) {
-           h[0] = hbh->h[0];
-           g[0] = hbh->g[0];
-           nhydro = 1;
-         }
-       }
-       else {
-         for(m=0; (m<hb->maxhydro); m++)
-           if (bContact ? ISDIST(hbh->history[m]) : ISHB(hbh->history[m])) {
-             g[nhydro] = hbh->g[m];
-             h[nhydro] = hbh->h[m];
-             nhydro++;
-           }
-       }
-       nf = hbh->nframes;
-       for(nh=0; (nh<nhydro); nh++) {
-         int nrint = bContact ? hb->nrdist : hb->nrhb;
-         if ((((nhbonds+1) % 10) == 0) || (nhbonds+1 == nrint))
-           fprintf(stderr,"\rACF %d/%d",nhbonds+1,nrint);
-         nhbonds++;
-         for(j=0; (j<nframes); j++) {
-           /* Changed '<' into '<=' below, just like I did in
-              the hbm-output-loop in the gmx_hbond() block.
-              - Erik Marklund, May 31, 2006 */
-           if (j <= nf) {
-             ihb   = is_hb(h[nh],j);
-             idist = is_hb(g[nh],j);
-           }
-           else {
-             ihb = idist = 0;
-           }
-           rhbex[j] = ihb-aver_nhb;
-           /* For contacts: if a second cut-off is provided, use it,
-            * otherwise use g(t) = 1-h(t) */
-           if (!R2 && bContact)
-             gt[j]  = 1-ihb;
-           else
-             gt[j]  = idist*(1-ihb); 
-           ht[j]    = rhbex[j];
-           nhb     += ihb;
-         }
+    FILE *fp;
+    int  i,j,k,m,n,o,nd,ihb,idist,n2,nn,iter,nSets;
+    static char *legNN[]   = { "Ac(t)",
+                               "Ac'(t)"};
+    static char **legGem;
+                             
+    static char *legLuzar[] = { "Ac\\sfin sys\\v{}\\z{}(t)",
+                                "Ac(t)",
+                                "Cc\\scontact,hb\\v{}\\z{}(t)",
+                                "-dAc\\sfs\\v{}\\z{}/dt" };
+    bool bNorm=FALSE;
+    double nhb = 0;
+    int nhbi=0;
+    real *rhbex=NULL,*ht,*gt,*ght,*dght,*kt;
+    real *ct,*p_ct,tail,tail2,dtail,ct_fac,ght_fac,*cct;
+    const real tol = 1e-3;
+    int   nframes = hb->nframes,nf;
+    unsigned int **h,**g;
+    int   nh,nhbonds,nhydro,ngh;
+    t_hbond *hbh;
+    PSTYPE p, *pfound = NULL, np;
+    t_pShift *pHist;
+    int *ptimes=NULL, *poff=NULL, anhb, n0, mMax=INT_MIN;
+    real **rHbExGem = NULL;
+    bool c;
+    int acType;
+    t_E *E;
+    double *ctdouble, *timedouble, *fittedct;
+    double fittolerance=0.1;
+
+    enum {AC_NONE, AC_NN, AC_GEM, AC_LUZAR};
+
+
+#ifdef HAVE_OPENMP
+    int *dondata=NULL, thisThread;
+#endif
+
+
+    printf("Doing autocorrelation ");
+
+    /* Decide what kind of ACF calculations to do. */
+    if (NN > NN_NONE && NN < NN_NR) {
+#ifdef HAVE_NN_LOOPS
+        acType = AC_NN;
+        printf("using the energy estimate.\n");
+#else
+        acType = AC_NONE;
+        printf("Can't do the NN-loop. Yet.\n");
+#endif
+    } else if (hb->bGem) {
+        acType = AC_GEM;
+        printf("according to the reversible geminate recombination model by Omer Markowitch.\n");
+
+        nSets = 1 + (bBallistic ? 1:0) + (bGemFit ? 1:0);
+        snew(legGem, nSets);
+        for (i=0;i<nSets;i++)
+            snew(legGem[i], 128);
+        sprintf(legGem[0], "Ac\\s%s\\v{}\\z{}(t)", gemType);
+        if (bBallistic)
+            sprintf(legGem[1], "Ac'(t)");
+        if (bGemFit)
+            sprintf(legGem[(bBallistic ? 3:2)], "Ac\\s%s,fit\\v{}\\z{}(t)", gemType);
+
+    } else {
+        acType = AC_LUZAR;
+        printf("according to the theory of Luzar and Chandler.\n");
+    }
+    fflush(stdout);
+
+    /* build hbexist matrix in reals for autocorr */
+    /* Allocate memory for computing ACF (rhbex) and aggregating the ACF (ct) */
+    n2=1;
+    while (n2 < nframes)
+        n2*=2;
+  
+    nn = nframes/2;
+  
+    if (acType != AC_NN ||
+#ifndef HAVE_OPENMP
+        TRUE
+#else
+        FALSE
+#endif
+        ) {
+        snew(h,hb->maxhydro);
+        snew(g,hb->maxhydro);
+    }
+
+    /* Dump hbonds for debugging */
+    dump_ac(hb,bMerge||bContact,nDump);
+  
+    /* Total number of hbonds analyzed here */
+    nhbonds = 0;
+    ngh     = 0;
+    anhb    = 0;
+
+    /* ------------------------------------------------
+     * I got tired of waiting for the acf calculations
+     * and parallelized it with openMP
+     * set environment variable CFLAGS = "-fopenmp" when running
+     * configure and define DOUSEOPENMP to make use of it.
+     */
+
+#ifdef HAVE_OPENMP  /* ================================================= \
+                     * Set up the OpenMP stuff,                           |
+                     * like the number of threads and such                |
+                     */
+    if (acType != AC_LUZAR)
+    {
+#if (_OPENMP >= 200805) /* =====================\ */
+        nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_thread_limit());
+#else
+        nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_num_procs());
+#endif /* _OPENMP >= 200805 ====================/ */
+
+        omp_set_num_threads(nThreads);
+        snew(dondata, nThreads);
+        for (i=0; i<nThreads; i++)
+            dondata[i] = -1;
+        printf("ACF calculations parallelized with OpenMP using %i threads.\n"
+               "Expect close to linear scaling over this donor-loop.\n", nThreads);
+        fflush(stdout);
+        fprintf(stderr, "Donors: [thread no]\n");
+        {
+            char tmpstr[7];
+            for (i=0;i<nThreads;i++) {
+                snprintf(tmpstr, 7, "[%i]", i);
+                fprintf(stderr, "%-7s", tmpstr);
+            }
+        }
+        fprintf(stderr, "\n"); /*                                         | */
+    }  /*                                                                 | */
+#endif /* HAVE_OPENMP ===================================================/  */
+
+
+    /* Build the ACF according to acType */
+    switch (acType)
+    {
+      
+    case AC_NN:
+#ifdef HAVE_NN_LOOPS
+        /* Here we're using the estimated energy for the hydrogen bonds. */
+        snew(ct,nn);
+#ifdef HAVE_OPENMP /* ==================================\ */      
+#pragma omp parallel                            \
+    private(i, j, k, nh, E, rhbex, thisThread),        \
+    default(shared)
+        {
+#pragma omp barrier
+            thisThread = omp_get_thread_num();
+            rhbex = NULL;
+#endif /* ==============================================/ */
+
+            snew(rhbex, n2);
+            memset(rhbex, 0, n2*sizeof(real)); /* Trust no-one, not even malloc()! */
+
+#ifdef HAVE_OPENMP /* ################################################## \
+                    *                                                    #
+                    *                                                    #
+                    */
+#pragma omp barrier
+#pragma omp for schedule (dynamic)
+#endif
+            for (i=0; i<hb->d.nrd; i++) /* loop over donors */
+            {
+#ifdef HAVE_OPENMP /* ====== Write some output ======\ */
+#pragma omp critical
+                {
+                    dondata[thisThread] = i;
+                    parallel_print(dondata, nThreads);
+                }
+#else
+                fprintf(stderr, "\r %i", i);
+#endif /* ===========================================/ */
+
+                for (j=0; j<hb->a.nra; j++) /* loop over acceptors */
+                {
+                    for (nh=0; nh<hb->d.nhydro[i]; nh++) /* loop over donors' hydrogens */
+                    {
+                        E = hb->hbE.E[i][j][nh];
+                        if (E != NULL)
+                        {
+                            for (k=0; k<nframes; k++)
+                            {
+                                if (E[k] != NONSENSE_E)
+                                    rhbex[k] = (real)E[k];
+                            }
+                     
+                            low_do_autocorr(NULL,oenv,NULL,nframes,1,-1,&(rhbex),hb->time[1]-hb->time[0],
+                                            eacNormal,1,FALSE,bNorm,FALSE,0,-1,0,1);
+#ifdef HAVE_OPENMP
+#pragma omp critical
+#endif
+                            {
+                                for(k=0; (k<nn); k++)
+                                    ct[k] += rhbex[k];
+                            }
+                        }
+                    }   /* k loop */
+                }       /* j loop */
+            }           /* i loop */
+            sfree(rhbex);
+#pragma omp barrier
+#ifdef HAVE_OPENMP 
+            /*                                                           # */
+        } /* End of parallel block                                       # */
+        /* ##############################################################/ */
+        sfree(dondata);
+#endif
+        normalizeACF(ct, NULL, nn);
+        snew(ctdouble, nn);
+        snew(timedouble, nn);
+        for (j=0; j<nn; j++)
+        {
+            timedouble[j]=(double)(hb->time[j]);
+            ctdouble[j]=(double)(ct[j]);
+        }
+
+        /* Remove ballistic term */
+        /* Ballistic component removal and fitting to the reversible geminate recombination model
+         * will be taken out for the time being. First of all, one can remove the ballistic
+         * component with g_analyze afterwards. Secondly, and more importantly, there are still
+         * problems with the robustness of the fitting to the model. More work is needed.
+         * A third reason is that we're currently using gsl for this and wish to reduce dependence
+         * on external libraries. There are Levenberg-Marquardt and nsimplex solvers that come with
+         * a BSD-licence that can do the job.
+         *
+         * - Erik Marklund, June 18 2010. 
+         */
+/*         if (params->ballistic/params->tDelta >= params->nExpFit*2+1) */
+/*             takeAwayBallistic(ctdouble, timedouble, nn, params->ballistic, params->nExpFit, params->bDt); */
+/*         else */
+/*             printf("\nNumber of data points is less than the number of parameters to fit\n." */
+/*                    "The system is underdetermined, hence no ballistic term can be found.\n\n"); */
+
+        fp = xvgropen(fn, "Hydrogen Bond Autocorrelation","Time (ps)","C(t)");
+        xvgr_legend(fp,asize(legNN),legNN);
+      
+        for(j=0; (j<nn); j++)
+            fprintf(fp,"%10g  %10g %10g\n",
+                    hb->time[j]-hb->time[0],
+                    ct[j],
+                    ctdouble[j]);
+        fclose(fp);
+        sfree(ct);
+        sfree(ctdouble);
+        sfree(timedouble);
+#endif /* HAVE_NN_LOOPS */
+        break; /* case AC_NN */
+
+    case AC_GEM:
+        snew(ct,2*n2);
+        memset(ct,0,2*n2*sizeof(real));
+#ifndef HAVE_OPENMP
+        fprintf(stderr, "Donor:\n");
+#define __ACDATA ct
+#else
+#define __ACDATA p_ct
+#endif
+
+#ifdef HAVE_OPENMP /*  =========================================\
+                    *                                          */
+#pragma omp parallel default(none)                              \
+    private(i, k, nh, hbh, pHist, h, g, n0, nf, np, j, m,              \
+            pfound, poff, rHbExGem, p, ihb, mMax,               \
+            thisThread, p_ct)                                   \
+    shared(hb, dondata, ct, nn, nThreads, n2, stderr, bNorm,    \
+           nframes, bMerge, bContact)
+        { /* ##########  THE START OF THE ENORMOUS PARALLELIZED BLOCK!  ########## */
+            h = NULL;
+            g = NULL;
+            thisThread = omp_get_thread_num();
+            snew(h,hb->maxhydro);
+            snew(g,hb->maxhydro);
+            mMax = INT_MIN;
+            rHbExGem = NULL;
+            poff = NULL;
+            pfound = NULL;
+            p_ct = NULL;
+            snew(p_ct,2*n2);
+            memset(p_ct,0,2*n2*sizeof(real));
+
+            /* I'm using a chunk size of 1, since I expect      \
+             * the overhead to be really small compared         \
+             * to the actual calculations                       \ */
+#pragma omp for schedule(dynamic,1) nowait /*                   \ */
+#endif /* HAVE_OPENMP  =========================================/ */
+      
+            for (i=0; i<hb->d.nrd; i++) {
+#ifdef HAVE_OPENMP
+#pragma omp critical
+                {
+                    dondata[thisThread] = i;
+                    parallel_print(dondata, nThreads);
+                }
+#else
+                fprintf(stderr, "\r %i", i);
+#endif
+       
+                for (k=0; k<hb->a.nra; k++) {
+                    for (nh=0; nh < ((bMerge || bContact) ? 1 : hb->d.nhydro[i]); nh++) {
+                        hbh = hb->hbmap[i][k];
+                        if (hbh) {
+                            /* Note that if hb->per->gemtype==gemDD, then distances will be stored in
+                             * hb->hbmap[d][a].h array anyway, because the contact flag will be set.
+                             * hence, it's only with the gemAD mode that hb->hbmap[d][a].g will be used. */
+                            pHist = &(hb->per->pHist[i][k]);
+                            if (ISHB(hbh->history[nh]) && pHist->len != 0) {
+
+/* No need for a critical section */
+/* #ifdef HAVE_OPENMP */
+/* #pragma omp critical */
+/* #endif */
+                                {
+                                    h[nh] = hbh->h[nh];
+                                    g[nh] = hb->per->gemtype==gemAD ? hbh->g[nh] : NULL;
+                                }
+                                n0 = hbh->n0;
+                                nf = hbh->nframes;
+                                /* count the number of periodic shifts encountered and store
+                                 * them in separate arrays. */
+                                np = 0;
+                                for (j=0; j<pHist->len; j++)
+                                {
+                                    p = pHist->p[j];
+                                    for (m=0; m<=np; m++) {
+                                        if (m == np) { /* p not recognized in list. Add it and set up new array. */ 
+                                            np++;
+                                            if (np>hb->per->nper)
+                                                gmx_fatal(FARGS, "Too many pshifts. Something's utterly wrong here.");
+                                            if (m>=mMax) { /* Extend the arrays.
+                                                            * Doing it like this, using mMax to keep track of the sizes,
+                                                            * eleviates the need for freeing and re-allocating the arrays
+                                                            * when taking on the next donor-acceptor pair */
+                                                mMax = m;
+                                                srenew(pfound,np);   /* The list of found periodic shifts. */
+                                                srenew(rHbExGem,np); /* The hb existence functions (-aver_hb). */
+                                                snew(rHbExGem[m],2*n2);
+                                                srenew(poff,np);
+                                            }
+
+/* This shouldn't have to be critical, right? */
+/* #ifdef HAVE_OPENMP */
+/* #pragma omp critical */
+/* #endif */
+                                            {
+                                                if (rHbExGem != NULL && rHbExGem[m] != NULL) {
+                                                    /* This must be done, as this array was most likey
+                                                     * used to store stuff in some previous iteration. */                          
+                                                    memset(rHbExGem[m], 0, (sizeof(real)) * (2*n2));
+                                                }
+                                                else
+                                                    fprintf(stderr, "rHbExGem not initialized! m = %i\n", m);
+                                            }
+                                            pfound[m] = p;
+                                            poff[m] = -1;
+                     
+                                            break;
+                                        } /* m==np */
+                                        if (p == pfound[m])
+                                            break;
+                                    } /* m: Loop over found shifts */
+                                }   /* j: Loop over shifts */
+
+                                /* Now unpack and disentangle the existence funtions. */
+                                for (j=0; j<nf; j++) {
+                                    /* i:       donor,
+                                     * k:       acceptor
+                                     * nh:      hydrogen
+                                     * j:       time
+                                     * p:       periodic shift
+                                     * pfound:  list of periodic shifts found for this pair.
+                                     * poff:    list of frame offsets; that is, the first
+                                     *          frame a hbond has a particular periodic shift. */
+                                    p = getPshift(*pHist, j+n0);
+                                    if (p != -1)
+                                    {
+                                        for (m=0; m<np; m++)
+                                        {
+                                            if (pfound[m] == p)
+                                                break;
+                                            if (m==(np-1))
+                                                gmx_fatal(FARGS,"Shift not found, but must be there.");
+                                        }
+
+                                        ihb = is_hb(h[nh],j) || ((hb->per->gemtype!=gemAD || j==0) ? FALSE : is_hb(g[nh],j));
+                                        if (ihb)
+                                        {
+                                            if (poff[m] == -1)
+                                                poff[m] = j; /* Here's where the first hbond with shift p is,
+                                                              * relative to the start of h[0].*/
+                                            if (j<poff[m])
+                                                gmx_fatal(FARGS, "j<poff[m]");
+                                            rHbExGem[m][j-poff[m]] += 1;
+                                        }
+                                    }
+                                }
+
+                                /* Now, build ac. */
+                                for (m=0; m<np; m++) {
+                                    if (rHbExGem[m][0]>0  && n0+poff[m]<nn/*  && m==0 */) {
+                                        low_do_autocorr(NULL,oenv,NULL,nframes,1,-1,&(rHbExGem[m]),hb->time[1]-hb->time[0],
+                                                        eacNormal,1,FALSE,bNorm,FALSE,0,-1,0,1);
+                                        for(j=0; (j<nn); j++)
+                                            __ACDATA[j] += rHbExGem[m][j];
+                                    }
+                                } /* Building of ac. */
+                            } /* if (ISHB(...*/
+                        } /* if (hbh) */
+                    } /* hydrogen loop */
+                } /* acceptor loop */
+            } /* donor loop */
+
+            for (m=0; m<=mMax; m++) {
+                sfree(rHbExGem[m]);
+            }
+            sfree(pfound);
+            sfree(poff);
+            sfree(rHbExGem);
+
+            sfree(h);
+            sfree(g);
+#ifdef HAVE_OPENMP /* =======================================\ */
+#pragma omp critical
+            {
+                for (i=0; i<nn; i++)
+                    ct[i] += p_ct[i];
+            }
+            sfree(p_ct);
+
+        } /* ########## THE END OF THE ENORMOUS PARALLELIZED BLOCK ########## */
+        sfree(dondata);
+#endif /* HAVE_OPENMP =======================================/ */
+
+        normalizeACF(ct, NULL, nn);
+
+        fprintf(stderr, "\n\nACF successfully calculated.\n");
+
+        /* Use this part to fit to geminate recombination - JCP 129, 84505 (2008) */
+      
+        snew(ctdouble, nn);
+        snew(timedouble, nn);
+        snew(fittedct, nn);
+    
+        for (j=0;j<nn;j++){
+            timedouble[j]=(double)(hb->time[j]);
+            ctdouble[j]=(double)(ct[j]);
+        }
+
+        /* Remove ballistic term */
+        /* Ballistic component removal and fitting to the reversible geminate recombination model
+         * will be taken out for the time being. First of all, one can remove the ballistic
+         * component with g_analyze afterwards. Secondly, and more importantly, there are still
+         * problems with the robustness of the fitting to the model. More work is needed.
+         * A third reason is that we're currently using gsl for this and wish to reduce dependence
+         * on external libraries. There are Levenberg-Marquardt and nsimplex solvers that come with
+         * a BSD-licence that can do the job.
+         *
+         * - Erik Marklund, June 18 2010. 
+         */
+/*         if (bBallistic) { */
+/*             if (params->ballistic/params->tDelta >= params->nExpFit*2+1) */
+/*                 takeAwayBallistic(ctdouble, timedouble, nn, params->ballistic, params->nExpFit, params->bDt); */
+/*             else */
+/*                 printf("\nNumber of data points is less than the number of parameters to fit\n." */
+/*                        "The system is underdetermined, hence no ballistic term can be found.\n\n"); */
+/*         } */
+/*         if (bGemFit) */
+/*             fitGemRecomb(ctdouble, timedouble, &fittedct, nn, params); */
+    
+
+        if (bContact)
+            fp = xvgropen(fn, "Contact Autocorrelation","Time (ps)","C(t)",oenv);
+        else
+            fp = xvgropen(fn, "Hydrogen Bond Autocorrelation","Time (ps)","C(t)",oenv);
+        xvgr_legend(fp,asize(legGem),legGem,oenv);
+
+        for(j=0; (j<nn); j++)
+        {
+            fprintf(fp, "%10g  %10g", hb->time[j]-hb->time[0],ct[j]);
+            if (bBallistic)
+                fprintf(fp,"  %10g", ctdouble[j]);
+            if (bGemFit)
+                fprintf(fp,"  %10g", fittedct[j]);
+            fprintf(fp,"\n");
+        }
+        fclose(fp);
+
+        sfree(ctdouble);
+        sfree(timedouble);
+        sfree(fittedct);
+        sfree(ct);
+
+        break; /* case AC_GEM */
+
+    case AC_LUZAR:
+        snew(rhbex,2*n2);
+        snew(ct,2*n2);
+        snew(gt,2*n2);
+        snew(ht,2*n2);
+        snew(ght,2*n2);
+        snew(dght,2*n2);
+
+        snew(kt,nn);
+        snew(cct,nn);
+    
+        for(i=0; (i<hb->d.nrd); i++) {
+            for(k=0; (k<hb->a.nra); k++) {
+                nhydro = 0;
+                hbh = hb->hbmap[i][k];
+   
+                if (hbh) {
+                    if (bMerge || bContact) {
+                        if (ISHB(hbh->history[0])) {
+                            h[0] = hbh->h[0];
+                            g[0] = hbh->g[0];
+                            nhydro = 1;
+                        }
+                    }
+                    else {
+                        for(m=0; (m<hb->maxhydro); m++)
+                            if (bContact ? ISDIST(hbh->history[m]) : ISHB(hbh->history[m])) {
+                                g[nhydro] = hbh->g[m];
+                                h[nhydro] = hbh->h[m];
+                                nhydro++;
+                            }
+                    }
+       
+                    nf = hbh->nframes;
+                    for(nh=0; (nh<nhydro); nh++) {
+                        int nrint = bContact ? hb->nrdist : hb->nrhb;
+                        if ((((nhbonds+1) % 10) == 0) || (nhbonds+1 == nrint))
+                            fprintf(stderr,"\rACF %d/%d",nhbonds+1,nrint);
+                        nhbonds++;
+                        for(j=0; (j<nframes); j++) {
+                            /* Changed '<' into '<=' below, just like I did in
+                               the hbm-output-loop in the gmx_hbond() block.
+                               - Erik Marklund, May 31, 2006 */
+                            if (j <= nf) {
+                                ihb   = is_hb(h[nh],j);
+                                idist = is_hb(g[nh],j);
+                            }
+                            else {
+                                ihb = idist = 0;
+                            }
+                            rhbex[j] = ihb-aver_nhb;
+                            /* For contacts: if a second cut-off is provided, use it,
+                             * otherwise use g(t) = 1-h(t) */
+                            if (!R2 && bContact)
+                                gt[j]  = 1-ihb;
+                            else
+                                gt[j]  = idist*(1-ihb); 
+                            ht[j]    = rhbex[j];
+                            nhb     += ihb;
+                        }
          
-         /* The autocorrelation function is normalized after summation only */
-         low_do_autocorr(NULL,oenv,NULL,nframes,1,-1,&rhbex,
-                          hb->time[1]-hb->time[0],
-                         eacNormal,1,FALSE,bNorm,FALSE,0,-1,0,1);
+
+                        /* The autocorrelation function is normalized after summation only */
+                        low_do_autocorr(NULL,oenv,NULL,nframes,1,-1,&rhbex,hb->time[1]-hb->time[0],
+                                        eacNormal,1,FALSE,bNorm,FALSE,0,-1,0,1);
          
-         /* Cross correlation analysis for thermodynamics */
-         for(j=nframes; (j<n2); j++) {
-           ht[j] = 0;
-           gt[j] = 0;
-         }
+                        /* Cross correlation analysis for thermodynamics */
+                        for(j=nframes; (j<n2); j++) {
+                            ht[j] = 0;
+                            gt[j] = 0;
+                        }
 
-         cross_corr(n2,ht,gt,dght);
+                        cross_corr(n2,ht,gt,dght);
          
-         for(j=0; (j<nn); j++) {
-           ct[j]  += rhbex[j];
-           ght[j] += dght[j];
-         }
-       }
-      }
-    }
-  }
-  fprintf(stderr,"\n");
-  
-  /* Normalize */
-  ct_fac  = 1.0/ct[0];
-  ght_fac = 1.0/nhb;
-  printf("Normalization for c(t) = %g for gh(t) = %g\n",ct_fac,ght_fac);
-  for(j=0; (j<nn); j++) {
-    ct[j]  *= ct_fac;
-    ght[j] *= ght_fac; 
-    /* Xu and Berne use the same normalization constant */
-  }
-  
-  /* Determine tail value for statistics */
-  tail  = 0;
-  tail2 = 0;
-  for(j=nn/2; (j<nn); j++) {
-    tail  += ct[j];
-    tail2 += ct[j]*ct[j];
-  }
-  tail  /= (nn - nn/2);
-  tail2 /= (nn - nn/2);
-  dtail  = sqrt(tail2-tail*tail);
-  
-  /* Check whether the ACF is long enough */
-  if (dtail > tol) {
-    printf("\nWARNING: Correlation function is probably not long enough\n"
-          "because the standard deviation in the tail of C(t) > %g\n"
-          "Tail value (average C(t) over second half of acf): %g +/- %g\n",
-          tol,tail,dtail);
-  }
-  for(j=0; (j<nn); j++) {
-    cct[j] = ct[j];
-    ct[j]  = (cct[j]-tail)/(1-tail); 
-  }
-  /* Compute negative derivative k(t) = -dc(t)/dt */
-  compute_derivative(nn,hb->time,ct,kt);
-  for(j=0; (j<nn); j++)
-    kt[j] = -kt[j];
-
-  if (bContact)
-    fp = xvgropen(fn, "Contact Autocorrelation","Time (ps)","C(t)",oenv);
-  else
-    fp = xvgropen(fn, "Hydrogen Bond Autocorrelation","Time (ps)","C(t)",oenv);
-  xvgr_legend(fp,asize(leg),leg,oenv);
-
-  for(j=0; (j<nn); j++)
-    fprintf(fp,"%10g  %10g  %10g  %10g  %10g\n",
-           hb->time[j]-hb->time[0],ct[j],cct[j],ght[j],kt[j]);
-  ffclose(fp);
-  
-  analyse_corr(nn,hb->time,ct,ght,kt,NULL,NULL,NULL,
-              fit_start,temp,smooth_tail_start,oenv);
-  
-  do_view(oenv,fn,NULL);
-  sfree(rhbex);
-  sfree(ct);
-  sfree(gt);
-  sfree(ht);
-  sfree(ght);
-  sfree(dght);
-  sfree(cct);
-  sfree(kt);
-  sfree(h);
-  sfree(g);
+                        for(j=0; (j<nn); j++) {
+                            ct[j]  += rhbex[j];
+                            ght[j] += dght[j];
+                        }
+                    }
+                }
+            }
+        }
+        fprintf(stderr,"\n");
+        sfree(h);
+        sfree(g);
+        normalizeACF(ct, gt, nn);
+
+        /* Determine tail value for statistics */
+        tail  = 0;
+        tail2 = 0;
+        for(j=nn/2; (j<nn); j++) {
+            tail  += ct[j];
+            tail2 += ct[j]*ct[j];
+        }
+        tail  /= (nn - nn/2);
+        tail2 /= (nn - nn/2);
+        dtail  = sqrt(tail2-tail*tail);
+  
+        /* Check whether the ACF is long enough */
+        if (dtail > tol) {
+            printf("\nWARNING: Correlation function is probably not long enough\n"
+                   "because the standard deviation in the tail of C(t) > %g\n"
+                   "Tail value (average C(t) over second half of acf): %g +/- %g\n",
+                   tol,tail,dtail);
+        }
+        for(j=0; (j<nn); j++) {
+            cct[j] = ct[j];
+            ct[j]  = (cct[j]-tail)/(1-tail); 
+        }
+        /* Compute negative derivative k(t) = -dc(t)/dt */
+        compute_derivative(nn,hb->time,ct,kt);
+        for(j=0; (j<nn); j++)
+            kt[j] = -kt[j];
+
+
+        if (bContact)
+            fp = xvgropen(fn, "Contact Autocorrelation","Time (ps)","C(t)",oenv);
+        else
+            fp = xvgropen(fn, "Hydrogen Bond Autocorrelation","Time (ps)","C(t)",oenv);
+        xvgr_legend(fp,asize(legLuzar),legLuzar, oenv);
+
+      
+        for(j=0; (j<nn); j++)
+            fprintf(fp,"%10g  %10g  %10g  %10g  %10g\n",
+                    hb->time[j]-hb->time[0],ct[j],cct[j],ght[j],kt[j]);
+        ffclose(fp);
+
+        analyse_corr(nn,hb->time,ct,ght,kt,NULL,NULL,NULL,
+                     fit_start,temp,smooth_tail_start,oenv);
+  
+        do_view(oenv,fn,NULL);
+        sfree(rhbex);
+        sfree(ct);
+        sfree(gt);
+        sfree(ht);
+        sfree(ght);
+        sfree(dght);
+        sfree(cct);
+        sfree(kt);
+        /* sfree(h); */
+/*         sfree(g); */
+
+        break; /* case AC_LUZAR */
+
+    default:
+        gmx_fatal(FARGS, "Unrecognized type of ACF-calulation. acType = %i.", acType);
+    } /* switch (acType) */
 }
 
 static void init_hbframe(t_hbdata *hb,int nframes,real t)
 {
-  int i,j,m;
-  
-  hb->time[nframes]   = t;
-  hb->nhb[nframes]    = 0;
-  hb->ndist[nframes]  = 0;
-  for (i=0; (i<max_hx); i++)
-    hb->nhx[nframes][i]=0;
-  /* Loop invalidated */
-  if (hb->bHBmap && 0)
-    for (i=0; (i<hb->d.nrd); i++)
-      for (j=0; (j<hb->a.nra); j++)
-       for (m=0; (m<hb->maxhydro); m++)
-         if (hb->hbmap[i][j] && hb->hbmap[i][j]->h[m])
-           set_hb(hb,i,m,j,nframes,HB_NO);
-  /*set_hb(hb->hbmap[i][j]->h[m],nframes-hb->hbmap[i][j]->n0,HB_NO);*/
+    int i,j,m;
+  
+    hb->time[nframes]   = t;
+    hb->nhb[nframes]    = 0;
+    hb->ndist[nframes]  = 0;
+    for (i=0; (i<max_hx); i++)
+        hb->nhx[nframes][i]=0;
+    /* Loop invalidated */
+    if (hb->bHBmap && 0)
+        for (i=0; (i<hb->d.nrd); i++)
+            for (j=0; (j<hb->a.nra); j++)
+                for (m=0; (m<hb->maxhydro); m++)
+                    if (hb->hbmap[i][j] && hb->hbmap[i][j]->h[m])
+                        set_hb(hb,i,m,j,nframes,HB_NO);
+    /*set_hb(hb->hbmap[i][j]->h[m],nframes-hb->hbmap[i][j]->n0,HB_NO);*/
 }
 
 static void analyse_donor_props(const char *fn,t_hbdata *hb,int nframes,real t,
                                 const output_env_t oenv)
 {
-  static FILE *fp = NULL;
-  char *leg[] = { "Nbound", "Nfree" };
-  int i,j,k,nbound,nb,nhtot;
+    static FILE *fp = NULL;
+    char *leg[] = { "Nbound", "Nfree" };
+    int i,j,k,nbound,nb,nhtot;
   
-  if (!fn)
-    return;
-  if (!fp) {
-    fp = xvgropen(fn,"Donor properties","Time (ps)","Number",oenv);
-    xvgr_legend(fp,asize(leg),leg,oenv);
-  }
-  nbound = 0;
-  nhtot  = 0;
-  for(i=0; (i<hb->d.nrd); i++) {
-    for(k=0; (k<hb->d.nhydro[i]); k++) {
-      nb = 0;
-      nhtot ++;
-      for(j=0; (j<hb->a.nra) && (nb == 0); j++) {
-       if (hb->hbmap[i][j] && hb->hbmap[i][j]->h[k] && 
-           is_hb(hb->hbmap[i][j]->h[k],nframes)) 
-         nb = 1;
-      }
-      nbound += nb;
-    }
-  }
-  fprintf(fp,"%10.3e  %6d  %6d\n",t,nbound,nhtot-nbound);
+    if (!fn)
+        return;
+    if (!fp) {
+        fp = xvgropen(fn,"Donor properties","Time (ps)","Number",oenv);
+        xvgr_legend(fp,asize(leg),leg,oenv);
+    }
+    nbound = 0;
+    nhtot  = 0;
+    for(i=0; (i<hb->d.nrd); i++) {
+        for(k=0; (k<hb->d.nhydro[i]); k++) {
+            nb = 0;
+            nhtot ++;
+            for(j=0; (j<hb->a.nra) && (nb == 0); j++) {
+                if (hb->hbmap[i][j] && hb->hbmap[i][j]->h[k] && 
+                    is_hb(hb->hbmap[i][j]->h[k],nframes)) 
+                    nb = 1;
+            }
+            nbound += nb;
+        }
+    }
+    fprintf(fp,"%10.3e  %6d  %6d\n",t,nbound,nhtot-nbound);
 }
 
 static void dump_hbmap(t_hbdata *hb,
-                      int nfile,t_filenm fnm[],bool bTwo,bool bInsert,
-                      bool bContact, int isize[],int *index[],char *grpnames[],
-                      t_atoms *atoms)
+                       int nfile,t_filenm fnm[],bool bTwo,bool bInsert,
+                       bool bContact, int isize[],int *index[],char *grpnames[],
+                       t_atoms *atoms)
 {
-  FILE *fp,*fplog;
-  int  ddd,hhh,aaa,i,j,k,m,grp;
-  char ds[32],hs[32],as[32];
-  bool first;
-  
-  fp = opt2FILE("-hbn",nfile,fnm,"w");
-  if (opt2bSet("-g",nfile,fnm)) {
-    fplog = ffopen(opt2fn("-g",nfile,fnm),"w");
-    if (bContact)
-      fprintf(fplog,"# %10s  %12s  %12s\n","Donor","Hydrogen","Acceptor");
+    FILE *fp,*fplog;
+    int  ddd,hhh,aaa,i,j,k,m,grp;
+    char ds[32],hs[32],as[32];
+    bool first;
+  
+    fp = opt2FILE("-hbn",nfile,fnm,"w");
+    if (opt2bSet("-g",nfile,fnm)) {
+        fplog = ffopen(opt2fn("-g",nfile,fnm),"w");
+        if (bContact)
+            fprintf(fplog,"# %10s  %12s  %12s\n","Donor","Hydrogen","Acceptor");
+        else
+            fprintf(fplog,"# %10s  %12s  %12s\n","Donor","Hydrogen","Acceptor");
+    }
     else
-      fprintf(fplog,"# %10s  %12s  %12s\n","Donor","Hydrogen","Acceptor");
-  }
-  else
-    fplog = NULL;
-  for (grp=gr0; grp<=(bTwo?gr1:gr0); grp++) {
-    fprintf(fp,"[ %s ]",grpnames[grp]);
-    for (i=0; i<isize[grp]; i++) {
-      fprintf(fp,(i%15)?" ":"\n");
-      fprintf(fp," %4u",index[grp][i]+1);
+        fplog = NULL;
+    for (grp=gr0; grp<=(bTwo?gr1:gr0); grp++) {
+        fprintf(fp,"[ %s ]",grpnames[grp]);
+        for (i=0; i<isize[grp]; i++) {
+            fprintf(fp,(i%15)?" ":"\n");
+            fprintf(fp," %4u",index[grp][i]+1);
+        }
+        fprintf(fp,"\n");
+        /*
+          Added -contact support below.
+          - Erik Marklund, May 29, 2006
+        */
+        if (!bContact) {
+            fprintf(fp,"[ donors_hydrogens_%s ]\n",grpnames[grp]);
+            for (i=0; (i<hb->d.nrd); i++) {
+                if (hb->d.grp[i] == grp) { 
+                    for(j=0; (j<hb->d.nhydro[i]); j++)
+                        fprintf(fp," %4u %4u",hb->d.don[i]+1,
+                                hb->d.hydro[i][j]+1);
+                    fprintf(fp,"\n");
+                }
+            }
+            first = TRUE;
+            fprintf(fp,"[ acceptors_%s ]",grpnames[grp]);
+            for (i=0; (i<hb->a.nra); i++) {
+                if (hb->a.grp[i] == grp) { 
+                    fprintf(fp,(i%15 && !first)?" ":"\n");
+                    fprintf(fp," %4u",hb->a.acc[i]+1);
+                    first = FALSE;
+                }
+            }
+            fprintf(fp,"\n");
+        }
     }
-    fprintf(fp,"\n");
-    /*
-      Added -contact support below.
-      - Erik Marklund, May 29, 2006
-     */
-    if (!bContact) {
-      fprintf(fp,"[ donors_hydrogens_%s ]\n",grpnames[grp]);
-      for (i=0; (i<hb->d.nrd); i++) {
-       if (hb->d.grp[i] == grp) { 
-         for(j=0; (j<hb->d.nhydro[i]); j++)
-           fprintf(fp," %4u %4u",hb->d.don[i]+1,
-                   hb->d.hydro[i][j]+1);
-         fprintf(fp,"\n");
-       }
-      }
-      first = TRUE;
-      fprintf(fp,"[ acceptors_%s ]",grpnames[grp]);
-      for (i=0; (i<hb->a.nra); i++) {
-       if (hb->a.grp[i] == grp) { 
-         fprintf(fp,(i%15 && !first)?" ":"\n");
-         fprintf(fp," %4u",hb->a.acc[i]+1);
-         first = FALSE;
-       }
-      }
-      fprintf(fp,"\n");
-    }
-  }
-  if (bTwo)
-    fprintf(fp,bContact ? "[ contacts_%s-%s ]\n" :
-           "[ hbonds_%s-%s ]\n",grpnames[0],grpnames[1]);
-  else
-    fprintf(fp,bContact ? "[ contacts_%s ]" : "[ hbonds_%s ]\n",grpnames[0]);
-  
-  for(i=0; (i<hb->d.nrd); i++) {
-    ddd = hb->d.don[i];
-    for(k=0; (k<hb->a.nra); k++) {
-      aaa = hb->a.acc[k];
-      for(m=0; (m<hb->d.nhydro[i]); m++) {
-       if (hb->hbmap[i][k] && ISHB(hb->hbmap[i][k]->history[m])) {
-         sprintf(ds,"%s",mkatomname(atoms,ddd));
-         sprintf(as,"%s",mkatomname(atoms,aaa));
-         if (bContact) {
-           fprintf(fp," %6u %6u\n",ddd+1,aaa+1);
-           if (fplog) 
-             fprintf(fplog,"%12s  %12s\n",ds,as);
-         } else {
-           hhh = hb->d.hydro[i][m];
-           sprintf(hs,"%s",mkatomname(atoms,hhh));
-           fprintf(fp," %6u %6u %6u\n",ddd+1,hhh+1,aaa+1);
-           if (fplog) 
-             fprintf(fplog,"%12s  %12s  %12s\n",ds,hs,as);
-         }
-       }
-      }
-    }
-  }
-  if (bInsert) {
     if (bTwo)
-      fprintf(fp,"[ insert_%s->%s-%s ]",
-             grpnames[2],grpnames[0],grpnames[1]);
+        fprintf(fp,bContact ? "[ contacts_%s-%s ]\n" :
+                "[ hbonds_%s-%s ]\n",grpnames[0],grpnames[1]);
     else
-      fprintf(fp,"[ insert_%s->%s ]",grpnames[2],grpnames[0]);
-    j=0;
+        fprintf(fp,bContact ? "[ contacts_%s ]" : "[ hbonds_%s ]\n",grpnames[0]);
+  
+    for(i=0; (i<hb->d.nrd); i++) {
+        ddd = hb->d.don[i];
+        for(k=0; (k<hb->a.nra); k++) {
+            aaa = hb->a.acc[k];
+            for(m=0; (m<hb->d.nhydro[i]); m++) {
+                if (hb->hbmap[i][k] && ISHB(hb->hbmap[i][k]->history[m])) {
+                    sprintf(ds,"%s",mkatomname(atoms,ddd));
+                    sprintf(as,"%s",mkatomname(atoms,aaa));
+                    if (bContact) {
+                        fprintf(fp," %6u %6u\n",ddd+1,aaa+1);
+                        if (fplog) 
+                            fprintf(fplog,"%12s  %12s\n",ds,as);
+                    } else {
+                        hhh = hb->d.hydro[i][m];
+                        sprintf(hs,"%s",mkatomname(atoms,hhh));
+                        fprintf(fp," %6u %6u %6u\n",ddd+1,hhh+1,aaa+1);
+                        if (fplog) 
+                            fprintf(fplog,"%12s  %12s  %12s\n",ds,hs,as);
+                    }
+                }
+            }
+        }
+    }
+    if (bInsert) {
+        if (bTwo)
+            fprintf(fp,"[ insert_%s->%s-%s ]",
+                    grpnames[2],grpnames[0],grpnames[1]);
+        else
+            fprintf(fp,"[ insert_%s->%s ]",grpnames[2],grpnames[0]);
+        j=0;
     
-    /* for(i=0; (i<hb->nrhb); i++) {
-       if (hb->hb[i].bInsert) {
-       fprintf(fp,(j%15)?" ":"\n");
-       fprintf(fp,"%4d",i+1);
-       j++;
-       }
-       }*/
-    fprintf(fp,"\n");
-  }
-  ffclose(fp);
-  if (fplog)
-    ffclose(fplog);
+        /*     for(i=0; (i<hb->nrhb); i++) {
+            if (hb->hb[i].bInsert) {
+            fprintf(fp,(j%15)?" ":"\n");
+            fprintf(fp,"%4d",i+1);
+            j++;
+            }
+            }*/
+        fprintf(fp,"\n");
+    }
+    ffclose(fp);
+    if (fplog)
+        ffclose(fplog);
 }
 
+#ifdef HAVE_OPENMP
+/* sync_hbdata() updates the parallel t_hbdata p_hb using hb as template.
+ * It mimics add_frames() and init_frame() to some extent. */
+static void sync_hbdata(t_hbdata *hb, t_hbdata *p_hb,
+                        int nframes, real t)
+{
+    int i;
+    if (nframes >= p_hb->max_frames)
+    {
+        p_hb->max_frames += 4096;
+        srenew(p_hb->nhb,   p_hb->max_frames);
+        srenew(p_hb->ndist, p_hb->max_frames);
+        srenew(p_hb->n_bound, p_hb->max_frames);
+        srenew(p_hb->nhx, p_hb->max_frames);
+        if (p_hb->bDAnr)
+            srenew(p_hb->danr, p_hb->max_frames);
+        memset(&(p_hb->nhb[nframes]),   0, sizeof(int) * (p_hb->max_frames-nframes));
+        memset(&(p_hb->ndist[nframes]), 0, sizeof(int) * (p_hb->max_frames-nframes));
+        p_hb->nhb[nframes] = 0;
+        p_hb->ndist[nframes] = 0;
+
+    }
+    p_hb->nframes = nframes;
+/*     for (i=0;) */
+/*     { */
+/*         p_hb->nhx[nframes][i] */
+/*     } */
+    memset(&(p_hb->nhx[nframes]), 0 ,sizeof(int)*max_hx); /* zero the helix count for this frame */
+
+    /* hb->per will remain constant througout the frame loop,
+     * even though the data its members point to will change,
+     * hence no need for re-syncing. */
+}
+#endif
+
 int gmx_hbond(int argc,char *argv[])
 {
-  const char *desc[] = {
-    "g_hbond computes and analyzes hydrogen bonds. Hydrogen bonds are",
-    "determined based on cutoffs for the angle Acceptor - Donor - Hydrogen",
-    "(zero is extended) and the distance Hydrogen - Acceptor.",
-    "OH and NH groups are regarded as donors, O is an acceptor always,",
-    "N is an acceptor by default, but this can be switched using",
-    "[TT]-nitacc[tt]. Dummy hydrogen atoms are assumed to be connected",
-    "to the first preceding non-hydrogen atom.[PAR]",
+    const char *desc[] = {
+        "g_hbond computes and analyzes hydrogen bonds. Hydrogen bonds are",
+        "determined based on cutoffs for the angle Acceptor - Donor - Hydrogen",
+        "(zero is extended) and the distance Hydrogen - Acceptor.",
+        "OH and NH groups are regarded as donors, O is an acceptor always,",
+        "N is an acceptor by default, but this can be switched using",
+        "[TT]-nitacc[tt]. Dummy hydrogen atoms are assumed to be connected",
+        "to the first preceding non-hydrogen atom.[PAR]",
     
-    "You need to specify two groups for analysis, which must be either",
-    "identical or non-overlapping. All hydrogen bonds between the two",
-    "groups are analyzed.[PAR]",
+        "You need to specify two groups for analysis, which must be either",
+        "identical or non-overlapping. All hydrogen bonds between the two",
+        "groups are analyzed.[PAR]",
     
-    "If you set -shell, you will be asked for an additional index group",
-    "which should contain exactly one atom. In this case, only hydrogen",
-    "bonds between atoms within the shell distance from the one atom are",
-    "considered.[PAR]"
+        "If you set -shell, you will be asked for an additional index group",
+        "which should contain exactly one atom. In this case, only hydrogen",
+        "bonds between atoms within the shell distance from the one atom are",
+        "considered.[PAR]",
     
-    /*    "It is also possible to analyse specific hydrogen bonds with",
-    "[TT]-sel[tt]. This index file must contain a group of atom triplets",
-    "Donor Hydrogen Acceptor, in the following way:[PAR]",
-    */
-    "[TT]",
-    "[ selected ][BR]",
-    "     20    21    24[BR]",
-    "     25    26    29[BR]",
-    "      1     3     6[BR]",
-    "[tt][BR]",
-    "Note that the triplets need not be on separate lines.",
-    "Each atom triplet specifies a hydrogen bond to be analyzed,",
-    "note also that no check is made for the types of atoms.[PAR]",
+        /*    "It is also possible to analyse specific hydrogen bonds with",
+              "[TT]-sel[tt]. This index file must contain a group of atom triplets",
+              "Donor Hydrogen Acceptor, in the following way:[PAR]",
+        */
+        "[TT]",
+        "[ selected ][BR]",
+        "     20    21    24[BR]",
+        "     25    26    29[BR]",
+        "      1     3     6[BR]",
+        "[tt][BR]",
+        "Note that the triplets need not be on separate lines.",
+        "Each atom triplet specifies a hydrogen bond to be analyzed,",
+        "note also that no check is made for the types of atoms.[PAR]",
     
-    "[TT]-ins[tt] turns on computing solvent insertion into hydrogen bonds.",
-    "In this case an additional group must be selected, specifying the",
-    "solvent molecules.[PAR]",
+        "[TT]-ins[tt] turns on computing solvent insertion into hydrogen bonds.",
+        "In this case an additional group must be selected, specifying the",
+        "solvent molecules.[PAR]",
     
-    "[BB]Output:[bb][BR]",
-    "[TT]-num[tt]:  number of hydrogen bonds as a function of time.[BR]",
-    "[TT]-ac[tt]:   average over all autocorrelations of the existence",
-    "functions (either 0 or 1) of all hydrogen bonds.[BR]",
-    "[TT]-dist[tt]: distance distribution of all hydrogen bonds.[BR]",
-    "[TT]-ang[tt]:  angle distribution of all hydrogen bonds.[BR]",
-    "[TT]-hx[tt]:   the number of n-n+i hydrogen bonds as a function of time",
-    "where n and n+i stand for residue numbers and i ranges from 0 to 6.",
-    "This includes the n-n+3, n-n+4 and n-n+5 hydrogen bonds associated",
-    "with helices in proteins.[BR]",
-    "[TT]-hbn[tt]:  all selected groups, donors, hydrogens and acceptors",
-    "for selected groups, all hydrogen bonded atoms from all groups and",
-    "all solvent atoms involved in insertion.[BR]",
-    "[TT]-hbm[tt]:  existence matrix for all hydrogen bonds over all",
-    "frames, this also contains information on solvent insertion",
-    "into hydrogen bonds. Ordering is identical to that in [TT]-hbn[tt]",
-    "index file.[BR]",
-    "[TT]-dan[tt]: write out the number of donors and acceptors analyzed for",
-    "each timeframe. This is especially usefull when using [TT]-shell[tt].[BR]",
-    "[TT]-nhbdist[tt]: compute the number of HBonds per hydrogen in order to",
-    "compare results to Raman Spectroscopy.",
-    "[PAR]",
-    "Note: options [TT]-ac[tt], [TT]-life[tt], [TT]-hbn[tt] and [TT]-hbm[tt]",
-    "require an amount of memory proportional to the total numbers of donors",
-    "times the total number of acceptors in the selected group(s)."
-  };
-  
-  static real acut=30, abin=1, rcut=0.35, r2cut=0, rbin=0.005, rshell=-1;
-  static real maxnhb=0,fit_start=1,temp=298.15,smooth_tail_start=-1;
-  static bool bNitAcc=TRUE,bInsert=FALSE,bDA=TRUE,bMerge=TRUE;
-  static int  nDump=0;
-  static bool bContact=FALSE;
-  /* options */
-  t_pargs pa [] = {
-    { "-ins",  FALSE,  etBOOL, {&bInsert},
-      "Analyze solvent insertion" },
-    { "-a",    FALSE,  etREAL, {&acut},
-      "Cutoff angle (degrees, Acceptor - Donor - Hydrogen)" },
-    { "-r",    FALSE,  etREAL, {&rcut},
-      "Cutoff radius (nm, X - Acceptor, see next option)" },
-    { "-da",   FALSE,  etBOOL, {&bDA},
-      "Use distance Donor-Acceptor (if TRUE) or Hydrogen-Acceptor (FALSE)" },
-    { "-r2",   FALSE,  etREAL, {&r2cut},
-      "Second cutoff radius. Mainly useful with -contact and -ac"},
-    { "-abin", FALSE,  etREAL, {&abin},
-      "Binwidth angle distribution (degrees)" },
-    { "-rbin", FALSE,  etREAL, {&rbin},
-      "Binwidth distance distribution (nm)" },
-    { "-nitacc",FALSE, etBOOL, {&bNitAcc},
-      "Regard nitrogen atoms as acceptors" },
-    { "-contact",FALSE,etBOOL, {&bContact},
-      "Do not look for hydrogen bonds, but merely for contacts within the cut-off distance" },
-    { "-shell", FALSE, etREAL, {&rshell},
-      "when > 0, only calculate hydrogen bonds within # nm shell around "
-      "one particle" },
-    { "-fitstart", FALSE, etREAL, {&fit_start},
-      "Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation" }, 
-    { "-temp",  FALSE, etREAL, {&temp},
-      "Temperature (K) for computing the Gibbs energy corresponding to HB breaking and reforming" },
-    { "-smooth",FALSE, etREAL, {&smooth_tail_start},
-      "If >= 0, the tail of the ACF will be smoothed by fitting it to an exponential function: y = A exp(-x/tau)" },
-    { "-dump",  FALSE, etINT, {&nDump},
-      "Dump the first N hydrogen bond ACFs in a single xvg file for debugging" },
-    { "-max_hb",FALSE, etREAL, {&maxnhb},
-      "Theoretical maximum number of hydrogen bonds used for normalizing HB autocorrelation function. Can be useful in case the program estimates it wrongly" },
-    { "-merge", FALSE, etBOOL, {&bMerge},
-      "H-bonds between the same donor and acceptor, but with different hydrogen are treated as a single H-bond. Mainly important for the ACF." }
-  };
-  const char *bugs[] = {
-    "The option [TT]-sel[tt] that used to work on selected hbonds is out of order, and therefore not available for the time being."
-  };
-  t_filenm fnm[] = {
-    { efTRX, "-f",   NULL,     ffREAD  },
-    { efTPX, NULL,   NULL,     ffREAD  },
-    { efNDX, NULL,   NULL,     ffOPTRD },
-    /*    { efNDX, "-sel", "select", ffOPTRD },*/
-    { efXVG, "-num", "hbnum",  ffWRITE },
-    { efLOG, "-g",   "hbond",  ffOPTWR },
-    { efXVG, "-ac",  "hbac",   ffOPTWR },
-    { efXVG, "-dist","hbdist", ffOPTWR },
-    { efXVG, "-ang", "hbang",  ffOPTWR },
-    { efXVG, "-hx",  "hbhelix",ffOPTWR },
-    { efNDX, "-hbn", "hbond",  ffOPTWR },
-    { efXPM, "-hbm", "hbmap",  ffOPTWR },
-    { efXVG, "-don", "donor",  ffOPTWR },
-    { efXVG, "-dan", "danum",  ffOPTWR },
-    { efXVG, "-life","hblife", ffOPTWR },
-    { efXVG, "-nhbdist", "nhbdist",ffOPTWR }
+        "[BB]Output:[bb][BR]",
+        "[TT]-num[tt]:  number of hydrogen bonds as a function of time.[BR]",
+        "[TT]-ac[tt]:   average over all autocorrelations of the existence",
+        "functions (either 0 or 1) of all hydrogen bonds.[BR]",
+        "[TT]-dist[tt]: distance distribution of all hydrogen bonds.[BR]",
+        "[TT]-ang[tt]:  angle distribution of all hydrogen bonds.[BR]",
+        "[TT]-hx[tt]:   the number of n-n+i hydrogen bonds as a function of time",
+        "where n and n+i stand for residue numbers and i ranges from 0 to 6.",
+        "This includes the n-n+3, n-n+4 and n-n+5 hydrogen bonds associated",
+        "with helices in proteins.[BR]",
+        "[TT]-hbn[tt]:  all selected groups, donors, hydrogens and acceptors",
+        "for selected groups, all hydrogen bonded atoms from all groups and",
+        "all solvent atoms involved in insertion.[BR]",
+        "[TT]-hbm[tt]:  existence matrix for all hydrogen bonds over all",
+        "frames, this also contains information on solvent insertion",
+        "into hydrogen bonds. Ordering is identical to that in [TT]-hbn[tt]",
+        "index file.[BR]",
+        "[TT]-dan[tt]: write out the number of donors and acceptors analyzed for",
+        "each timeframe. This is especially useful when using [TT]-shell[tt].[BR]",
+        "[TT]-nhbdist[tt]: compute the number of HBonds per hydrogen in order to",
+        "compare results to Raman Spectroscopy.",
+        "[PAR]",
+        "Note: options [TT]-ac[tt], [TT]-life[tt], [TT]-hbn[tt] and [TT]-hbm[tt]",
+        "require an amount of memory proportional to the total numbers of donors",
+        "times the total number of acceptors in the selected group(s)."
+    };
+  
+    static real acut=30, abin=1, rcut=0.35, r2cut=0, rbin=0.005, rshell=-1;
+    static real maxnhb=0,fit_start=1,fit_end=60,temp=298.15,smooth_tail_start=-1, D=-1;
+    static bool bNitAcc=TRUE,bInsert=FALSE,bDA=TRUE,bMerge=TRUE;
+    static int  nDump=0, nFitPoints=100;
+    static int nThreads = 0, nBalExp=4;
+
+    static bool bContact=FALSE, bBallistic=FALSE, bBallisticDt=FALSE, bGemFit=FALSE;
+    static real logAfterTime = 10, gemBallistic = 0.2; /* ps */
+    static const char *NNtype[] = {NULL, "none", "binary", "oneOverR3", "dipole", NULL};
+
+    /* options */
+    t_pargs pa [] = {
+        { "-ins",  FALSE,  etBOOL, {&bInsert},
+          "Analyze solvent insertion" },
+        { "-a",    FALSE,  etREAL, {&acut},
+          "Cutoff angle (degrees, Acceptor - Donor - Hydrogen)" },
+        { "-r",    FALSE,  etREAL, {&rcut},
+          "Cutoff radius (nm, X - Acceptor, see next option)" },
+        { "-da",   FALSE,  etBOOL, {&bDA},
+          "Use distance Donor-Acceptor (if TRUE) or Hydrogen-Acceptor (FALSE)" },
+        { "-r2",   FALSE,  etREAL, {&r2cut},
+          "Second cutoff radius. Mainly useful with -contact and -ac"},
+        { "-abin", FALSE,  etREAL, {&abin},
+          "Binwidth angle distribution (degrees)" },
+        { "-rbin", FALSE,  etREAL, {&rbin},
+          "Binwidth distance distribution (nm)" },
+        { "-nitacc",FALSE, etBOOL, {&bNitAcc},
+          "Regard nitrogen atoms as acceptors" },
+        { "-contact",FALSE,etBOOL, {&bContact},
+          "Do not look for hydrogen bonds, but merely for contacts within the cut-off distance" },
+        { "-shell", FALSE, etREAL, {&rshell},
+          "when > 0, only calculate hydrogen bonds within # nm shell around "
+          "one particle" },
+        { "-fitstart", FALSE, etREAL, {&fit_start},
+          "Time (ps) from which to start fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation. With -gemfit we suggest -fitstart 0" },
+        { "-fitstart", FALSE, etREAL, {&fit_start},
+          "Time (ps) to which to stop fitting the correlation functions in order to obtain the forward and backward rate constants for HB breaking and formation (only with -gemfit)" },
+        { "-temp",  FALSE, etREAL, {&temp},
+          "Temperature (K) for computing the Gibbs energy corresponding to HB breaking and reforming" },
+        { "-smooth",FALSE, etREAL, {&smooth_tail_start},
+          "If >= 0, the tail of the ACF will be smoothed by fitting it to an exponential function: y = A exp(-x/tau)" },
+        { "-dump",  FALSE, etINT, {&nDump},
+          "Dump the first N hydrogen bond ACFs in a single xvg file for debugging" },
+        { "-max_hb",FALSE, etREAL, {&maxnhb},
+          "Theoretical maximum number of hydrogen bonds used for normalizing HB autocorrelation function. Can be useful in case the program estimates it wrongly" },
+        { "-merge", FALSE, etBOOL, {&bMerge},
+          "H-bonds between the same donor and acceptor, but with different hydrogen are treated as a single H-bond. Mainly important for the ACF." },
+        { "-geminate", FALSE, etENUM, {gemType},
+          "Use reversible geminate recombination for the kinetics/thermodynamics calclations. See Markovitch et al., J. Chem. Phys 129, 084505 (2008) for details."},
+        { "-diff", FALSE, etREAL, {&D},
+          "Dffusion coefficient to use in the rev. gem. recomb. kinetic model. If non-positive, then it will be fitted to the ACF along with ka and kd."},
+#ifdef HAVE_OPENMP
+        { "-nthreads", FALSE, etINT, {&nThreads},
+          "Number of threads used for the parallel loop over autocorrelations. nThreads <= 0 means maximum number of threads. Requires linking with OpenMP. The number of threads is limited by the number of processors (before OpenMP v.3 ) or environment variable OMP_THREAD_LIMIT (OpenMP v.3)"},
+#endif
+        /* The ballistic/geminate fitting will be taken away temporarily sue to problems with stability. */
+/*         { "-NN", FALSE, etENUM, {NNtype}, */
+/*           "HIDDENDo a full all vs all loop and estimate the interaction energy instead of having a binary existence function for hydrogen bonds. NOT FULLY TESTED YET! DON'T USE IT!"}, */
+/*         { "-gemfit", FALSE, etBOOL, {&bGemFit}, */
+/*           "With -gemainate != none: fit ka and kd to the ACF"}, */
+/*         { "-gemlogstart", FALSE, etREAL, {&logAfterTime}, */
+/*           "HIDDENWith -gemfit: After this time (ps) the data points fitted to will be equidistant in log-time."}, */
+/*         { "-gemnp", FALSE, etINT, {&nFitPoints}, */
+/*           "HIDDENNuber of points in the ACF used to fit rev. gem. recomb. model"}, */
+/*         { "-ballistic", FALSE, etBOOL, {&bBallistic}, */
+/*           "Calculate and remove ultrafast \"ballistic\" component in the ACF"}, */
+/*         { "-ballisticlen", FALSE, etREAL, {&gemBallistic}, */
+/*           "HIDDENFitting interval for the ultrafast \"ballistic\" component in ACF"}, */
+/*         { "-nbalexp", FALSE, etINT, {&nBalExp}, */
+/*           "HIDDENNumber of exponentials to fit when removing the ballistic component"}, */
+/*         { "-ballisticDt", FALSE, etBOOL, {&bBallisticDt}, */
+/*           "HIDDENIf TRUE, finding of the fastest ballistic component will be based on the time derivative at t=0, " */
+/*           "while if FALSE, it will be based on the exponent alone (like in Markovitch 2008)"} */
+    };
+    const char *bugs[] = {
+        "The option [TT]-sel[tt] that used to work on selected hbonds is out of order, and therefore not available for the time being."
+    };
+    t_filenm fnm[] = {
+        { efTRX, "-f",   NULL,     ffREAD  },
+        { efTPX, NULL,   NULL,     ffREAD  },
+        { efNDX, NULL,   NULL,     ffOPTRD },
+        /*    { efNDX, "-sel", "select", ffOPTRD },*/
+        { efXVG, "-num", "hbnum",  ffWRITE },
+        { efLOG, "-g",   "hbond",  ffOPTWR },
+        { efXVG, "-ac",  "hbac",   ffOPTWR },
+        { efXVG, "-dist","hbdist", ffOPTWR },
+        { efXVG, "-ang", "hbang",  ffOPTWR },
+        { efXVG, "-hx",  "hbhelix",ffOPTWR },
+        { efNDX, "-hbn", "hbond",  ffOPTWR },
+        { efXPM, "-hbm", "hbmap",  ffOPTWR },
+        { efXVG, "-don", "donor",  ffOPTWR },
+        { efXVG, "-dan", "danum",  ffOPTWR },
+        { efXVG, "-life","hblife", ffOPTWR },
+        { efXVG, "-nhbdist", "nhbdist",ffOPTWR }
     
-  };
+    };
 #define NFILE asize(fnm)
   
-  char  hbmap [HB_NR]={ ' ',    'o',      '-',       '*' };
-  char *hbdesc[HB_NR]={ "None", "Present", "Inserted", "Present & Inserted" };
-  t_rgb hbrgb [HB_NR]={ {1,1,1},{1,0,0},   {0,0,1},    {1,0,1} };
-  
-  int     status;
-  t_topology top;
-  t_inputrec ir;
-  t_pargs *ppa;
-  int     npargs,natoms,nframes=0,shatom;
-  int     *isize;
-  char    **grpnames;
-  atom_id **index;
-  rvec    *x,hbox;
-  matrix  box;
-  real    t,ccut,dist,ang;
-  double  max_nhb,aver_nhb,aver_dist;
-  int     h,i,j,k,l,start,end,id,ja,ogrp,nsel;
-  int     xi,yi,zi,ai;
-  int     xj,yj,zj,aj,xjj,yjj,zjj;
-  int     xk,yk,zk,ak,xkk,ykk,zkk;
-  bool    bSelected,bHBmap,bStop,bTwo,was,bBox,bTric;
-  int     *adist,*rdist;
-  int        grp,nabin,nrbin,bin,resdist,ihb;
-  char       **leg;
-  t_hbdata   *hb;
-  FILE       *fp,*fpins=NULL,*fpnhb=NULL;
-  t_gridcell ***grid;
-  t_ncell    *icell,*jcell,*kcell;
-  ivec       ngrid;
-  unsigned char        *datable;
-  output_env_t oenv;
+    char  hbmap [HB_NR]={ ' ',    'o',      '-',       '*' };
+    const char *hbdesc[HB_NR]={ "None", "Present", "Inserted", "Present & Inserted" };
+    t_rgb hbrgb [HB_NR]={ {1,1,1},{1,0,0},   {0,0,1},    {1,0,1} };
+
+    t_trxstatus *status;
+    int trrStatus=1;
+    t_topology top;
+    t_inputrec ir;
+    t_pargs *ppa;
+    int     npargs,natoms,nframes=0,shatom;
+    int     *isize;
+    char    **grpnames;
+    atom_id **index;
+    rvec    *x,hbox;
+    matrix  box;
+    real    t,ccut,dist,ang;
+    double  max_nhb,aver_nhb,aver_dist;
+    int     h,i,j,k=0,l,start,end,id,ja,ogrp,nsel;
+    int     xi,yi,zi,ai;
+    int     xj,yj,zj,aj,xjj,yjj,zjj;
+    int     xk,yk,zk,ak,xkk,ykk,zkk;
+    bool    bSelected,bHBmap,bStop,bTwo,was,bBox,bTric;
+    int     *adist,*rdist;
+    int        grp,nabin,nrbin,bin,resdist,ihb;
+    char       **leg;
+    t_hbdata   *hb;
+    FILE       *fp,*fpins=NULL,*fpnhb=NULL;
+    t_gridcell ***grid;
+    t_ncell    *icell,*jcell,*kcell;
+    ivec       ngrid;
+    unsigned char        *datable;
+    output_env_t oenv;
+    int     gemmode, NN;
+    PSTYPE  peri=0;
+    t_E     E;
+    int     ii, jj, hh, actual_nThreads;
+    int     threadNr=0;
+    bool    bGem, bNN, bParallel;
+    t_gemParams *params=NULL;
     
-  CopyRight(stdout,argv[0]);
+    CopyRight(stdout,argv[0]);
 
-  npargs = asize(pa);  
-  ppa    = add_acf_pargs(&npargs,pa);
+    npargs = asize(pa);  
+    ppa    = add_acf_pargs(&npargs,pa);
   
-  parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE,NFILE,fnm,npargs,
-                   ppa,asize(desc),desc,asize(bugs),bugs,&oenv);
+    parse_common_args(&argc,argv,PCA_CAN_TIME | PCA_BE_NICE,NFILE,fnm,npargs,
+                      ppa,asize(desc),desc,asize(bugs),bugs,&oenv);
+
+    /* NN-loop? If so, what estimator to use ?*/
+    NN = 1;
+    while (NN < NN_NR && strcasecmp(NNtype[0], NNtype[NN])!=0)
+        NN++;
+    if (NN == NN_NR)
+        gmx_fatal(FARGS, "Invalid NN-loop type.");
 
-  /* process input */
-  bSelected = opt2bSet("-sel",NFILE,fnm);
-  ccut = cos(acut*DEG2RAD);
+    bNN = FALSE;
+    for (i=2; bNN==FALSE && i<NN_NR; i++)
+        bNN = bNN || NN == i;
+
+    if (NN > NN_NONE && bMerge)
+        bMerge = FALSE;
+
+    /* geminate recombination? If so, which flavor? */
+    gemmode = 1;
+    while (gemmode < gemNR && strcasecmp(gemType[0], gemType[gemmode])!=0)
+        gemmode++;
+    if (gemmode == gemNR)
+        gmx_fatal(FARGS, "Invalid recombination type.");
   
-  if (bContact) {
-    if (bSelected)
-      gmx_fatal(FARGS,"Can not analyze selected contacts: turn off -sel");
-    if (bInsert)
-      gmx_fatal(FARGS,"Can not analyze inserted contacts: turn off -ins");
-    if (!bDA) {
-      gmx_fatal(FARGS,"Can not analyze contact between H and A: turn off -noda");
-    }
-  }
-  
-  /* Initiate main data structure! */
-  bHBmap = (opt2bSet("-ac",NFILE,fnm) ||
-           opt2bSet("-life",NFILE,fnm) ||
-           opt2bSet("-hbn",NFILE,fnm) || 
-           opt2bSet("-hbm",NFILE,fnm));
-  
-  if (opt2bSet("-nhbdist",NFILE,fnm)) {
-    char *leg[MAXHH+1] = { "0 HBs", "1 HB", "2 HBs", "3 HBs", "Total" };
-    fpnhb = xvgropen(opt2fn("-nhbdist",NFILE,fnm),
-                    "Number of donor-H with N HBs","Time (ps)","N",oenv);
-    xvgr_legend(fpnhb,asize(leg),leg,oenv);
-  }
-  
-  hb = mk_hbdata(bHBmap,opt2bSet("-dan",NFILE,fnm),bMerge || bContact);
-  
-  /* get topology */
-  read_tpx_top(ftp2fn(efTPX,NFILE,fnm),&ir,box,&natoms,NULL,NULL,NULL,&top);
-  
-  snew(grpnames,grNR);
-  snew(index,grNR);
-  snew(isize,grNR);
-  /* Make Donor-Acceptor table */
-  snew(datable, top.atoms.nr);
-  gen_datable(index[0],isize[0],datable,top.atoms.nr);
-  
-  if (bSelected) {
-    /* analyze selected hydrogen bonds */
-    printf("Select group with selected atoms:\n");
-    get_index(&(top.atoms),opt2fn("-sel",NFILE,fnm),
-             1,&nsel,index,grpnames);
-    if (nsel % 3)
-      gmx_fatal(FARGS,"Number of atoms in group '%s' not a multiple of 3\n"
-                 "and therefore cannot contain triplets of "
-                 "Donor-Hydrogen-Acceptor",grpnames[0]);
-    bTwo=FALSE;
+    bGem = FALSE;
+    for (i=2; bGem==FALSE && i<gemNR; i++)
+        bGem = bGem || gemmode == i;
+  
+    if (bGem) {
+        printf("Geminate recombination: %s\n" ,gemType[gemmode]);
+#ifndef HAVE_LIBGSL
+        printf("Note that some aspects of reversible geminate recombination won't work without gsl.\n");
+#endif
+        if (bContact) {
+            if (gemmode != gemDD) {
+                printf("Turning off -contact option...\n");
+                bContact = FALSE;
+            }
+        } else {
+            if (gemmode == gemDD) {
+                printf("Turning on -contact option...\n");
+                bContact = TRUE;
+            }
+        }
+        if (bMerge) {
+            if (gemmode == gemAA) {
+                printf("Turning off -merge option...\n");
+                bMerge = FALSE;
+            }
+        } else {
+            if (gemmode != gemAA) {
+                printf("Turning on -merge option...\n");
+                bMerge = TRUE;
+            }
+        }
+    } else
+        printf("No geminate recombination.\n");
+
+    /* process input */
+    bSelected = opt2bSet("-sel",NFILE,fnm);
+    ccut = cos(acut*DEG2RAD);
+  
+    if (bContact) {
+        if (bSelected)
+            gmx_fatal(FARGS,"Can not analyze selected contacts: turn off -sel");
+        if (bInsert)
+            gmx_fatal(FARGS,"Can not analyze inserted contacts: turn off -ins");
+        if (!bDA) {
+            gmx_fatal(FARGS,"Can not analyze contact between H and A: turn off -noda");
+        }
+    }
+
+#ifndef HAVE_LIBGSL
+    printf("NO GSL! Can't find and take away ballistic term in ACF without GSL\n.");
+#endif
+  
+    /* Initiate main data structure! */
+    bHBmap = (opt2bSet("-ac",NFILE,fnm) ||
+              opt2bSet("-life",NFILE,fnm) ||
+              opt2bSet("-hbn",NFILE,fnm) || 
+              opt2bSet("-hbm",NFILE,fnm) ||
+              bGem);
+  
+#ifdef HAVE_OPENMP
+    printf("Compiled with OpenMP (%i)\n", _OPENMP);
+#endif
+
+    /*   if (bContact && bGem) */
+    /*     gmx_fatal(FARGS, "Can't do reversible geminate recombination with -contact yet."); */
+
+    if (opt2bSet("-nhbdist",NFILE,fnm)) {
+        char *leg[MAXHH+1] = { "0 HBs", "1 HB", "2 HBs", "3 HBs", "Total" };
+        fpnhb = xvgropen(opt2fn("-nhbdist",NFILE,fnm),
+                         "Number of donor-H with N HBs","Time (ps)","N",oenv);
+        xvgr_legend(fpnhb,asize(leg),leg,oenv);
+    }
+  
+    hb = mk_hbdata(bHBmap,opt2bSet("-dan",NFILE,fnm),bMerge || bContact, bGem, gemmode);
+
+    /* get topology */
+    read_tpx_top(ftp2fn(efTPX,NFILE,fnm),&ir,box,&natoms,NULL,NULL,NULL,&top);
+  
+    snew(grpnames,grNR);
+    snew(index,grNR);
+    snew(isize,grNR);
+    /* Make Donor-Acceptor table */
+    snew(datable, top.atoms.nr);
+    gen_datable(index[0],isize[0],datable,top.atoms.nr);
+  
+    if (bSelected) {
+        /* analyze selected hydrogen bonds */
+        printf("Select group with selected atoms:\n");
+        get_index(&(top.atoms),opt2fn("-sel",NFILE,fnm),
+                  1,&nsel,index,grpnames);
+        if (nsel % 3)
+            gmx_fatal(FARGS,"Number of atoms in group '%s' not a multiple of 3\n"
+                      "and therefore cannot contain triplets of "
+                      "Donor-Hydrogen-Acceptor",grpnames[0]);
+        bTwo=FALSE;
     
-    for(i=0; (i<nsel); i+=3) {
-      int dd = index[0][i];
-      int hh = index[0][i+1];
-      int aa = index[0][i+2];
-      add_dh (&hb->d,dd,hh,i,datable);
-      add_acc(&hb->a,aa,i);
-      /* Should this be here ? */
-      snew(hb->d.dptr,top.atoms.nr);
-      snew(hb->a.aptr,top.atoms.nr);
-      add_hbond(hb,dd,aa,hh,gr0,gr0,0,FALSE,bMerge,0,bContact);
-    }
-    printf("Analyzing %d selected hydrogen bonds from '%s'\n",
-          isize[0],grpnames[0]);
-  } 
-  else {
-    /* analyze all hydrogen bonds: get group(s) */
-    printf("Specify 2 groups to analyze:\n");
-    get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
-             2,isize,index,grpnames);
+        for(i=0; (i<nsel); i+=3) {
+            int dd = index[0][i];
+            int aa = index[0][i+2];
+            /* int */ hh = index[0][i+1];
+            add_dh (&hb->d,dd,hh,i,datable);
+            add_acc(&hb->a,aa,i);
+            /* Should this be here ? */
+            snew(hb->d.dptr,top.atoms.nr);
+            snew(hb->a.aptr,top.atoms.nr);
+            add_hbond(hb,dd,aa,hh,gr0,gr0,0,FALSE,bMerge,0,bContact,peri);
+        }
+        printf("Analyzing %d selected hydrogen bonds from '%s'\n",
+               isize[0],grpnames[0]);
+    
+    else {
+        /* analyze all hydrogen bonds: get group(s) */
+        printf("Specify 2 groups to analyze:\n");
+        get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
+                  2,isize,index,grpnames);
     
-    /* check if we have two identical or two non-overlapping groups */
-    bTwo = isize[0] != isize[1];
-    for (i=0; (i<isize[0]) && !bTwo; i++)
-      bTwo = index[0][i] != index[1][i];
-    if (bTwo) {
-      printf("Checking for overlap in atoms between %s and %s\n",
-            grpnames[0],grpnames[1]);
-      for (i=0; i<isize[1];i++)
-       if (ISINGRP(datable[index[1][i]]))
-         gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
-                   grpnames[0],grpnames[1]);
-      /*
-      printf("Checking for overlap in atoms between %s and %s\n",
-            grpnames[0],grpnames[1]);
-      for (i=0; i<isize[0]; i++)
-       for (j=0; j<isize[1]; j++)
-         if (index[0][i] == index[1][j]) 
-           gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
-                       grpnames[0],grpnames[1]);
-      */
+        /* check if we have two identical or two non-overlapping groups */
+        bTwo = isize[0] != isize[1];
+        for (i=0; (i<isize[0]) && !bTwo; i++)
+            bTwo = index[0][i] != index[1][i];
+        if (bTwo) {
+            printf("Checking for overlap in atoms between %s and %s\n",
+                   grpnames[0],grpnames[1]);
+            for (i=0; i<isize[1];i++)
+                if (ISINGRP(datable[index[1][i]]))
+                    gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
+                              grpnames[0],grpnames[1]);
+            /*
+              printf("Checking for overlap in atoms between %s and %s\n",
+              grpnames[0],grpnames[1]);
+              for (i=0; i<isize[0]; i++)
+              for (j=0; j<isize[1]; j++)
+              if (index[0][i] == index[1][j]) 
+              gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
+              grpnames[0],grpnames[1]);
+            */
+        }
+        if (bTwo)
+            printf("Calculating %s "
+                   "between %s (%d atoms) and %s (%d atoms)\n",
+                   bContact ? "contacts" : "hydrogen bonds",
+                   grpnames[0],isize[0],grpnames[1],isize[1]);
+        else
+            fprintf(stderr,"Calculating %s in %s (%d atoms)\n",
+                    bContact?"contacts":"hydrogen bonds",grpnames[0],isize[0]);
     }
-    if (bTwo)
-      printf("Calculating %s "
-            "between %s (%d atoms) and %s (%d atoms)\n",
-            bContact ? "contacts" : "hydrogen bonds",
-            grpnames[0],isize[0],grpnames[1],isize[1]);
-    else
-      fprintf(stderr,"Calculating %s in %s (%d atoms)\n",
-             bContact?"contacts":"hydrogen bonds",grpnames[0],isize[0]);
-  }
-  sfree(datable);
-  if (bInsert) {
-    printf("Specify group for insertion analysis:\n");
-    get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
-             1,&(isize[grI]),&(index[grI]),&(grpnames[grI]));
-    printf("Checking for overlap...\n");
-    for (i=0; i<isize[grI]; i++)
-      for (grp=0; grp<(bTwo?2:1); grp++)
-       for (j=0; j<isize[grp]; j++)
-         if (index[grI][i] == index[grp][j]) 
-           gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
-                       grpnames[grp],grpnames[grI]);
-    fpins=ffopen("insert.dat","w");
-    fprintf(fpins,"%4s: %15s -> %15s (%7s) - %15s (%7s)\n",
-           "time","insert","donor","distang","acceptor","distang");
-  }
-  
-  /* search donors and acceptors in groups */
-  snew(datable, top.atoms.nr);
-  for (i=0; (i<grNR); i++)
-    if ( ((i==gr0) && !bSelected ) ||
-        ((i==gr1) && bTwo ) ||
-        ((i==grI) && bInsert ) ) {
-      gen_datable(index[i],isize[i],datable,top.atoms.nr);
-      if (bContact) {
-       search_acceptors(&top,isize[i],index[i],&hb->a,i,
-                        bNitAcc,TRUE,(bTwo && (i==gr0)) || !bTwo, datable);
-       search_donors   (&top,isize[i],index[i],&hb->d,i,
-                        TRUE,(bTwo && (i==gr1)) || !bTwo, datable);
-      }
-      else {
-       search_acceptors(&top,isize[i],index[i],&hb->a,i,bNitAcc,FALSE,TRUE, datable);
-       search_donors   (&top,isize[i],index[i],&hb->d,i,FALSE,TRUE, datable);
-      }
-      if (bTwo)
-       clear_datable_grp(datable,top.atoms.nr);
-    }
-  sfree(datable);
-  printf("Found %d donors and %d acceptors\n",hb->d.nrd,hb->a.nra);
-  /*if (bSelected)
-    snew(donors[gr0D], dons[gr0D].nrd);*/
-
-  if (bHBmap) {
-    printf("Making hbmap structure...");
-    /* Generate hbond data structure */
-    mk_hbmap(hb,bTwo,bInsert);
-    printf("done.\n");
-  }
-  
-  /* check input */
-  bStop=FALSE;
-  if (hb->d.nrd + hb->a.nra == 0) {
-    printf("No Donors or Acceptors found\n");
-    bStop=TRUE;
-  }
-  if (!bStop) {
-    if (hb->d.nrd == 0) {
-      printf("No Donors found\n");
-      bStop=TRUE;
-    }
-    if (hb->a.nra == 0) {
-      printf("No Acceptors found\n");
-      bStop=TRUE;
-    }
-  }
-  if (bStop)
-    gmx_fatal(FARGS,"Nothing to be done");
-
-  shatom=0;
-  if (rshell > 0) {
-    int shisz;
-    atom_id *shidx;
-    char *shgrpnm;
-    /* get index group with atom for shell */
-    do {
-      printf("Select atom for shell (1 atom):\n");
-      get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
-               1,&shisz,&shidx,&shgrpnm);
-      if (shisz != 1)
-       printf("group contains %d atoms, should be 1 (one)\n",shisz);
-    } while(shisz != 1);
-    shatom = shidx[0];
-    printf("Will calculate hydrogen bonds within a shell "
-          "of %g nm around atom %i\n",rshell,shatom+1);
-  }
-
-  /* Analyze trajectory */
-  natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
-  if ( natoms > top.atoms.nr )
-    gmx_fatal(FARGS,"Topology (%d atoms) does not match trajectory (%d atoms)",
-             top.atoms.nr,natoms);
+    sfree(datable);
+    if (bInsert) {
+        printf("Specify group for insertion analysis:\n");
+        get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
+                  1,&(isize[grI]),&(index[grI]),&(grpnames[grI]));
+        printf("Checking for overlap...\n");
+        for (i=0; i<isize[grI]; i++)
+            for (grp=0; grp<(bTwo?2:1); grp++)
+                for (j=0; j<isize[grp]; j++)
+                    if (index[grI][i] == index[grp][j]) 
+                        gmx_fatal(FARGS,"Partial overlap between groups '%s' and '%s'",
+                                  grpnames[grp],grpnames[grI]);
+        fpins=ffopen("insert.dat","w");
+        fprintf(fpins,"%4s: %15s -> %15s (%7s) - %15s (%7s)\n",
+                "time","insert","donor","distang","acceptor","distang");
+    }
+  
+    /* search donors and acceptors in groups */
+    snew(datable, top.atoms.nr);
+    for (i=0; (i<grNR); i++)
+        if ( ((i==gr0) && !bSelected ) ||
+             ((i==gr1) && bTwo ) ||
+             ((i==grI) && bInsert ) ) {
+            gen_datable(index[i],isize[i],datable,top.atoms.nr);
+            if (bContact) {
+                search_acceptors(&top,isize[i],index[i],&hb->a,i,
+                                 bNitAcc,TRUE,(bTwo && (i==gr0)) || !bTwo, datable);
+                search_donors   (&top,isize[i],index[i],&hb->d,i,
+                                 TRUE,(bTwo && (i==gr1)) || !bTwo, datable);
+            }
+            else {
+                search_acceptors(&top,isize[i],index[i],&hb->a,i,bNitAcc,FALSE,TRUE, datable);
+                search_donors   (&top,isize[i],index[i],&hb->d,i,FALSE,TRUE, datable);
+            }
+            if (bTwo)
+                clear_datable_grp(datable,top.atoms.nr);
+        }
+    sfree(datable);
+    printf("Found %d donors and %d acceptors\n",hb->d.nrd,hb->a.nra);
+    /*if (bSelected)
+      snew(donors[gr0D], dons[gr0D].nrd);*/
+
+    if (bHBmap) {
+        printf("Making hbmap structure...");
+        /* Generate hbond data structure */
+        mk_hbmap(hb,bTwo,bInsert);
+        printf("done.\n");
+    }
+
+#ifdef HAVE_NN_LOOPS
+    if (bNN)
+        mk_hbEmap(hb, 0);
+#endif
+
+    if (bGem) {
+        printf("Making per structure...");
+        /* Generate hbond data structure */
+        mk_per(hb);
+        printf("done.\n");
+    }
+  
+    /* check input */
+    bStop=FALSE;
+    if (hb->d.nrd + hb->a.nra == 0) {
+        printf("No Donors or Acceptors found\n");
+        bStop=TRUE;
+    }
+    if (!bStop) {
+        if (hb->d.nrd == 0) {
+            printf("No Donors found\n");
+            bStop=TRUE;
+        }
+        if (hb->a.nra == 0) {
+            printf("No Acceptors found\n");
+            bStop=TRUE;
+        }
+    }
+    if (bStop)
+        gmx_fatal(FARGS,"Nothing to be done");
+
+    shatom=0;
+    if (rshell > 0) {
+        int shisz;
+        atom_id *shidx;
+        char *shgrpnm;
+        /* get index group with atom for shell */
+        do {
+            printf("Select atom for shell (1 atom):\n");
+            get_index(&(top.atoms),ftp2fn_null(efNDX,NFILE,fnm),
+                      1,&shisz,&shidx,&shgrpnm);
+            if (shisz != 1)
+                printf("group contains %d atoms, should be 1 (one)\n",shisz);
+        } while(shisz != 1);
+        shatom = shidx[0];
+        printf("Will calculate hydrogen bonds within a shell "
+               "of %g nm around atom %i\n",rshell,shatom+1);
+    }
+
+    /* Analyze trajectory */
+    natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
+    if ( natoms > top.atoms.nr )
+        gmx_fatal(FARGS,"Topology (%d atoms) does not match trajectory (%d atoms)",
+                  top.atoms.nr,natoms);
                
-  bBox  = ir.ePBC!=epbcNONE;
-  grid  = init_grid(bBox, box, (rcut>r2cut)?rcut:r2cut, ngrid);
-  nabin = acut/abin;
-  nrbin = rcut/rbin;
-  snew(adist,nabin+1);
-  snew(rdist,nrbin+1);
-  
-  do {
-    bTric = bBox && TRICLINIC(box);
-    build_grid(hb,x,x[shatom], bBox,box,hbox, (rcut>r2cut)?rcut:r2cut, 
-               rshell, ngrid,grid);
-    
-    reset_nhbonds(&(hb->d));
+    bBox  = ir.ePBC!=epbcNONE;
+    grid  = init_grid(bBox, box, (rcut>r2cut)?rcut:r2cut, ngrid);
+    nabin = acut/abin;
+    nrbin = rcut/rbin;
+    snew(adist,nabin+1);
+    snew(rdist,nrbin+1);
 
-    if (debug && bDebug)
-      dump_grid(debug, ngrid, grid);
-    
-    add_frames(hb,nframes);
-    init_hbframe(hb,nframes,t);
+    if (bGem && !bBox)
+        gmx_fatal(FARGS, "Can't do geminate recombination without periodic box.");
 
-    if (hb->bDAnr)
-      count_da_grid(ngrid, grid, hb->danr[nframes]);
-      
-    if (bSelected) {
-      int ii;
-      
-      for(ii=0; (ii<nsel); ii++) {
-       int dd = index[0][i];
-       int hh = index[0][i+1];
-       int aa = index[0][i+2];
-       ihb = is_hbond(hb,ii,ii,dd,aa,rcut,r2cut,ccut,x,bBox,box,
-                      hbox,&dist,&ang,bDA,&h,bContact);
-       
-       if (ihb) {
-         /* add to index if not already there */
-         /* Add a hbond */
-         add_hbond(hb,dd,aa,hh,ii,ii,nframes,FALSE,bMerge,ihb,bContact);
-       }
-      }
+    bParallel = FALSE;
+
+#ifndef HAVE_OPENMP
+#define __ADIST adist
+#define __RDIST rdist
+#define __HBDATA hb
+#else /* HAVE_OPENMP ==================================================        \
+       * Set up the OpenMP stuff,                                       |
+       * like the number of threads and such                            |
+       * Also start the parallel loop.                                  |
+       */
+#define __ADIST p_adist[threadNr]
+#define __RDIST p_rdist[threadNr]
+#define __HBDATA p_hb[threadNr]
+
+    bParallel = !bSelected && !bInsert;
+
+    if (bParallel)
+    {
+#if (_OPENMP > 200805)
+        actual_nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_thread_limit());
+#else
+        actual_nThreads = min((nThreads <= 0) ? INT_MAX : nThreads, omp_get_num_procs());
+#endif
+        omp_set_num_threads(actual_nThreads);
+        printf("Frame loop parallelized with OpenMP using %i threads.\n", actual_nThreads);
+        fflush(stdout);
     }
-    else {
-      /* loop over all gridcells (xi,yi,zi)      */
-      /* Removed confusing macro, DvdS 27/12/98  */
-      for(xi=0; (xi<ngrid[XX]); xi++)
-       for(yi=0; (yi<ngrid[YY]); yi++)
-         for(zi=0; (zi<ngrid[ZZ]); zi++) {
-           
-           /* loop over donor groups gr0 (always) and gr1 (if necessary) */
-           for (grp=gr0; (grp <= (bTwo?gr1:gr0)); grp++) {
-             icell=&(grid[zi][yi][xi].d[grp]);
-             
-             if (bTwo)
-               ogrp = 1-grp;
-             else
-               ogrp = grp;
+    else
+    {
+        actual_nThreads = 1;
+    }
+
+    t_hbdata **p_hb;          /* one per thread, then merge after the frame loop */
+    int **p_adist, **p_rdist; /* a histogram for each thread. */
+    snew(p_hb,    actual_nThreads);
+    snew(p_adist, actual_nThreads);
+    snew(p_rdist, actual_nThreads);
+    for (i=0; i<actual_nThreads; i++)
+    {
+        snew(p_hb[i], 1);
+        snew(p_adist[i], nabin+1);
+        snew(p_rdist[i], nrbin+1);
+
+        p_hb[i]->max_frames = 0;
+        p_hb[i]->nhb = NULL;
+        p_hb[i]->ndist = NULL;
+        p_hb[i]->n_bound = NULL;
+        p_hb[i]->time = NULL;
+        p_hb[i]->nhx = NULL;
+
+        p_hb[i]->bHBmap     = hb->bHBmap;
+        p_hb[i]->bDAnr      = hb->bDAnr;
+        p_hb[i]->bGem       = hb->bGem;
+        p_hb[i]->wordlen    = hb->wordlen;
+        p_hb[i]->nframes    = hb->nframes;
+        p_hb[i]->maxhydro   = hb->maxhydro;
+        p_hb[i]->danr       = hb->danr;
+        p_hb[i]->d          = hb->d;
+        p_hb[i]->a          = hb->a;
+        p_hb[i]->hbmap      = hb->hbmap;
+        p_hb[i]->time       = hb->time; /* This may need re-syncing at every frame. */
+        p_hb[i]->per        = hb->per;
+
+#ifdef HAVE_NN_LOOPS
+        p_hb[i]->hbE = hb->hbE;
+#endif
+
+        p_hb[i]->nrhb   = 0;
+        p_hb[i]->nrdist = 0;
+    }
+  
+    /* Make a thread pool here,
+     * instead of forking anew at every frame. */
+  
+#pragma omp parallel                                    \
+    private(i, j, h, ii, jj, hh, E,                     \
+            xi, yi, zi, xj, yj, zj, threadNr,           \
+            dist, ang, peri, icell, jcell,              \
+            grp, ogrp, ai, aj, xjj, yjj, zjj,           \
+            xk, yk, zk, ihb, id,  resdist,              \
+            xkk, ykk, zkk, kcell, ak, k, bTric)         \
+    default(none)                                       \
+    shared(hb, p_hb, p_adist, p_rdist, actual_nThreads, \
+           x, bBox, box, hbox, rcut, r2cut, rshell,     \
+           shatom, ngrid, grid, nframes, t,             \
+           bParallel, bNN, index, bMerge, bContact,     \
+           bTwo, bDA,ccut, abin, rbin, top,             \
+           bInsert, bSelected, bDebug, stderr, nsel,    \
+           bGem, oenv, fnm, fpnhb, trrStatus, natoms,   \
+           status, nabin, nrbin, adist, rdist, debug)
+    {    /* Start of parallel region */
+        threadNr = omp_get_thread_num();
+#endif /* HAVE_OPENMP ================================================= */
+        do
+        {
+            bTric = bBox && TRICLINIC(box);
+
+#ifdef HAVE_OPENMP
+            sync_hbdata(hb, p_hb[threadNr], nframes, t);
+#pragma omp single
+#endif
+            {
+                build_grid(hb,x,x[shatom], bBox,box,hbox, (rcut>r2cut)?rcut:r2cut, 
+                           rshell, ngrid,grid);
+                reset_nhbonds(&(hb->d));
+       
+                if (debug && bDebug)
+                    dump_grid(debug, ngrid, grid);
+                
+                add_frames(hb,nframes);
+                init_hbframe(hb,nframes,t);
+       
+                if (hb->bDAnr)
+                    count_da_grid(ngrid, grid, hb->danr[nframes]);
+            } /* omp single */
+
+#ifdef HAVE_OPENMP
+            p_hb[threadNr]->time = hb->time; /* This pointer may have changed. */
+#endif
+            if (bNN)
+            {
+#ifdef HAVE_NN_LOOPS /* Unlock this feature when testing */
+                /* Loop over all atom pairs and estimate interaction energy */
+#ifdef HAVE_OPENMP /* ------- */
+#pragma omp single
+#endif /* HAVE_OPENMP ------- */
+                {
+                    addFramesNN(hb, nframes);
+                }
+#ifdef HAVE_OPENMP /* ---------------- */
+#pragma omp barrier
+#pragma omp for schedule(dynamic)
+#endif /* HAVE_OPENMP ---------------- */
+                for (i=0; i<hb->d.nrd; i++)
+                {
+                    for(j=0;j<hb->a.nra; j++)
+                    {
+                        for (h=0;
+                             h < (bContact ? 1 : hb->d.nhydro[i]);
+                             h++)
+                        {
+                            if (i==hb->d.nrd || j==hb->a.nra)
+                                gmx_fatal(FARGS, "out of bounds");
+
+                            /* Get the real atom ids */
+                            ii = hb->d.don[i];
+                            jj = hb->a.acc[j];
+                            hh = hb->d.hydro[i][h];
+                   
+                            /* Estimate the energy from the geometry */
+                            E = calcHbEnergy(ii, jj, hh, x, NN, box, hbox, &(hb->d));
+                            /* Store the energy */
+                            storeHbEnergy(hb, i, j, h, E, nframes);
+                        }
+                    }
+                }
+#endif /* HAVE_NN_LOOPS */
+            } /* if (bNN)*/
+            else
+            {
+                if (bSelected)
+                {
+#ifdef HAVE_OPENMP
+#pragma omp single
+#endif
+                    {
+                        /* Do not parallelize this just yet. */
+                        /* int ii; */
+                        for(ii=0; (ii<nsel); ii++) {
+                            int dd = index[0][i];
+                            int aa = index[0][i+2];
+                            /* int */ hh = index[0][i+1];
+                            ihb = is_hbond(hb,ii,ii,dd,aa,rcut,r2cut,ccut,x,bBox,box,
+                                           hbox,&dist,&ang,bDA,&h,bContact,bMerge,&peri);
+         
+                            if (ihb) {
+                                /* add to index if not already there */
+                                /* Add a hbond */
+                                add_hbond(hb,dd,aa,hh,ii,ii,nframes,FALSE,bMerge,ihb,bContact,peri);
+                            }
+                        }
+                    } /* omp single */
+                } /* if (bSelected) */
+                else
+                {
+#ifdef HAVE_OPENMP
+#pragma omp single
+                    {
+#endif
+                    if (bGem)
+                        calcBoxProjection(box, hb->per->P);
+
+                    /* loop over all gridcells (xi,yi,zi)      */
+                    /* Removed confusing macro, DvdS 27/12/98  */
+#ifdef HAVE_OPENMP
+                    }
+                    /* The outer grid loop will have to do for now. */
+#pragma omp for schedule(dynamic)
+#endif
+                    for(xi=0; (xi<ngrid[XX]); xi++)
+                        for(yi=0; (yi<ngrid[YY]); yi++)
+                            for(zi=0; (zi<ngrid[ZZ]); zi++) {
              
-             /* loop over all hydrogen atoms from group (grp) 
-              * in this gridcell (icell) 
-              */
-             for (ai=0; (ai<icell->nr); ai++) {
-               i  = icell->atoms[ai];
+                                /* loop over donor groups gr0 (always) and gr1 (if necessary) */
+                                for (grp=gr0; (grp <= (bTwo?gr1:gr0)); grp++) {
+                                    icell=&(grid[zi][yi][xi].d[grp]);
+               
+                                    if (bTwo)
+                                        ogrp = 1-grp;
+                                    else
+                                        ogrp = grp;
+               
+                                    /* loop over all hydrogen atoms from group (grp) 
+                                     * in this gridcell (icell) 
+                                     */
+                                    for (ai=0; (ai<icell->nr); ai++) {
+                                        i  = icell->atoms[ai];
                
-               /* loop over all adjacent gridcells (xj,yj,zj) */
-               /* This is a macro!!! */
-               LOOPGRIDINNER(xj,yj,zj,xjj,yjj,zjj,xi,yi,zi,ngrid,bTric) {
-                 jcell=&(grid[zj][yj][xj].a[ogrp]);
-                 /* loop over acceptor atoms from other group (ogrp) 
-                  * in this adjacent gridcell (jcell) 
-                  */
-                 for (aj=0; (aj<jcell->nr); aj++) {
-                   j = jcell->atoms[aj];
+                                        /* loop over all adjacent gridcells (xj,yj,zj) */
+                                        /* This is a macro!!! */
+                                        LOOPGRIDINNER(xj,yj,zj,xjj,yjj,zjj,xi,yi,zi,ngrid,bTric) {
+                                            jcell=&(grid[zj][yj][xj].a[ogrp]);
+                                            /* loop over acceptor atoms from other group (ogrp) 
+                                             * in this adjacent gridcell (jcell) 
+                                             */
+                                            for (aj=0; (aj<jcell->nr); aj++) {
+                                                j = jcell->atoms[aj];
                  
-                   /* check if this once was a h-bond */
-                   ihb = is_hbond(hb,grp,ogrp,i,j,rcut,r2cut,ccut,x,bBox,box,
-                                  hbox,&dist,&ang,bDA,&h,bContact);
+                                                /* check if this once was a h-bond */
+                                                peri = -1;
+                                                ihb = is_hbond(__HBDATA,grp,ogrp,i,j,rcut,r2cut,ccut,x,bBox,box,
+                                                               hbox,&dist,&ang,bDA,&h,bContact,bMerge,&peri);
                    
-                   if (ihb) {
-                     /* add to index if not already there */
-                     /* Add a hbond */
-                     add_hbond(hb,i,j,h,grp,ogrp,nframes,FALSE,bMerge,ihb,bContact);
+                                                if (ihb) {
+                                                    /* add to index if not already there */
+                                                    /* Add a hbond */
+                                                    add_hbond(__HBDATA,i,j,h,grp,ogrp,nframes,FALSE,bMerge,ihb,bContact,peri);
                      
-                     /* make angle and distance distributions */
-                     if (ihb == hbHB && !bContact) {
-                       if (dist>rcut)
-                         gmx_fatal(FARGS,"distance is higher than what is allowed for an hbond: %f",dist);
-                       ang*=RAD2DEG;
-                       adist[(int)( ang/abin)]++;
-                       rdist[(int)(dist/rbin)]++;
-                       
-                       if (!bTwo) {
-                         int id,ia;
-                         if ((id = donor_index(&hb->d,grp,i)) == NOTSET)
-                           gmx_fatal(FARGS,"Invalid donor %d",i);
-                         if ((ia = acceptor_index(&hb->a,ogrp,j)) == NOTSET)
-                           gmx_fatal(FARGS,"Invalid acceptor %d",j);
-                         resdist=abs(top.atoms.atom[i].resind-
-                                     top.atoms.atom[j].resind);
-                         if (resdist >= max_hx) 
-                           resdist = max_hx-1;
-                         hb->nhx[nframes][resdist]++;
-                       }
-                     }
-                     if (bInsert && bSelected) {
-                       /* this has been a h-bond, or we are analyzing 
-                          selected bonds: check for inserted */
-                       bool ins_d, ins_a;
-                       real ins_d_dist, ins_d_ang, ins_a_dist, ins_a_ang;
-                       int  ins_d_k=0,ins_a_k=0;
+                                                    /* make angle and distance distributions */
+                                                    if (ihb == hbHB && !bContact) {
+                                                        if (dist>rcut)
+                                                            gmx_fatal(FARGS,"distance is higher than what is allowed for an hbond: %f",dist);
+                                                        ang*=RAD2DEG;
+                                                        __ADIST[(int)( ang/abin)]++;
+                                                        __RDIST[(int)(dist/rbin)]++;
+                                                        if (!bTwo) {
+                                                            int id,ia;
+                                                            if ((id = donor_index(&hb->d,grp,i)) == NOTSET)
+                                                                gmx_fatal(FARGS,"Invalid donor %d",i);
+                                                            if ((ia = acceptor_index(&hb->a,ogrp,j)) == NOTSET)
+                                                                gmx_fatal(FARGS,"Invalid acceptor %d",j);
+                                                            resdist=abs(top.atoms.atom[i].resind-
+                                                                        top.atoms.atom[j].resind);
+                                                            if (resdist >= max_hx)
+                                                                resdist = max_hx-1;
+                                                            __HBDATA->nhx[nframes][resdist]++;
+                                                        }
+                                                    }
+
+                                                    if (bInsert && bSelected && MASTER_THREAD_ONLY(threadNr)) {
+                                                        /* this has been a h-bond, or we are analyzing 
+                                                           selected bonds: check for inserted */
+                                                        bool ins_d, ins_a;
+                                                        real ins_d_dist, ins_d_ang, ins_a_dist, ins_a_ang;
+                                                        int  ins_d_k=0,ins_a_k=0;
                        
-                       ins_d=ins_a=FALSE;
-                       ins_d_dist=ins_d_ang=ins_a_dist=ins_a_ang=1e6;
+                                                        ins_d=ins_a=FALSE;
+                                                        ins_d_dist=ins_d_ang=ins_a_dist=ins_a_ang=1e6;
                        
-                       /* loop over gridcells adjacent to i (xk,yk,zk) */
-                       LOOPGRIDINNER(xk,yk,zk,xkk,ykk,zkk,xi,yi,zi,ngrid,bTric){
-                         kcell=&(grid[zk][yk][xk].a[grI]);
-                         /* loop over acceptor atoms from ins group 
-                            in this adjacent gridcell (kcell) */
-                         for (ak=0; (ak<kcell->nr); ak++) {
-                           k=kcell->atoms[ak];
-                           ihb = is_hbond(hb,grp,grI,i,k,rcut,r2cut,ccut,x,
-                                          bBox,box,hbox,&dist,&ang,bDA,&h,
-                                          bContact);
-                           if (ihb == hbHB) {
-                             if (dist < ins_d_dist) {
-                               ins_d=TRUE;
-                               ins_d_dist=dist;
-                               ins_d_ang =ang ;
-                               ins_d_k   =k   ;
-                             }
-                           }
-                         }
-                       }
-                       ENDLOOPGRIDINNER;
-                       /* loop over gridcells adjacent to j (xk,yk,zk) */
-                       LOOPGRIDINNER(xk,yk,zk,xkk,ykk,zkk,xj,yj,zj,ngrid,bTric){
-                         kcell=&grid[zk][yk][xk].d[grI];
-                         /* loop over hydrogen atoms from ins group 
-                            in this adjacent gridcell (kcell) */
-                         for (ak=0; ak<kcell->nr; ak++) {
-                           k   = kcell->atoms[ak];
-                           ihb = is_hbond(hb,grI,ogrp,k,j,rcut,r2cut,ccut,x,
-                                          bBox,box,hbox,&dist,&ang,bDA,&h,
-                                          bContact);
-                           if (ihb == hbHB) {
-                             if (dist<ins_a_dist) {
-                               ins_a=TRUE;
-                               ins_a_dist=dist;
-                               ins_a_ang =ang ;
-                               ins_a_k   =k   ;
-                             }
-                           }
-                         }
-                       }
-                       ENDLOOPGRIDINNER;
+                                                        /* loop over gridcells adjacent to i (xk,yk,zk) */
+                                                        LOOPGRIDINNER(xk,yk,zk,xkk,ykk,zkk,xi,yi,zi,ngrid,bTric){
+                                                            kcell=&(grid[zk][yk][xk].a[grI]);
+                                                            /* loop over acceptor atoms from ins group 
+                                                               in this adjacent gridcell (kcell) */
+                                                            for (ak=0; (ak<kcell->nr); ak++) {
+                                                                k=kcell->atoms[ak];
+                                                                ihb = is_hbond(hb,grp,grI,i,k,rcut,r2cut,ccut,x,
+                                                                               bBox,box,hbox,&dist,&ang,bDA,&h,
+                                                                               bContact,bMerge,&peri);
+                                                                if (ihb == hbHB) {
+                                                                    if (dist < ins_d_dist) {
+                                                                        ins_d=TRUE;
+                                                                        ins_d_dist=dist;
+                                                                        ins_d_ang =ang ;
+                                                                        ins_d_k   =k   ;
+                                                                    }
+                                                                }
+                                                            }
+                                                        }
+                                                        ENDLOOPGRIDINNER;
+                                                        /* loop over gridcells adjacent to j (xk,yk,zk) */
+                                                        LOOPGRIDINNER(xk,yk,zk,xkk,ykk,zkk,xj,yj,zj,ngrid,bTric){
+                                                            kcell=&grid[zk][yk][xk].d[grI];
+                                                            /* loop over hydrogen atoms from ins group 
+                                                               in this adjacent gridcell (kcell) */
+                                                            for (ak=0; ak<kcell->nr; ak++) {
+                                                                k   = kcell->atoms[ak];
+                                                                ihb = is_hbond(hb,grI,ogrp,k,j,rcut,r2cut,ccut,x,
+                                                                               bBox,box,hbox,&dist,&ang,bDA,&h,
+                                                                               bContact,bMerge,&peri);
+                                                                if (ihb == hbHB) {
+                                                                    if (dist<ins_a_dist) {
+                                                                        ins_a=TRUE;
+                                                                        ins_a_dist=dist;
+                                                                        ins_a_ang =ang ;
+                                                                        ins_a_k   =k   ;
+                                                                    }
+                                                                }
+                                                            }
+                                                        }
+                                                        ENDLOOPGRIDINNER;
                        
-                       {
-                         ihb = is_hbond(hb,grI,grI,ins_d_k,ins_a_k,rcut,r2cut,ccut,x,
-                                        bBox,box,hbox,&dist,&ang,bDA,&h,bContact);
-                         if (ins_d && ins_a && ihb) {
-                           /* add to hbond index if not already there */
-                           add_hbond(hb,ins_d_k,ins_a_k,h,grI,ogrp,
-                                     nframes,TRUE,bMerge,ihb,bContact);
+                                                        {
+                                                            ihb = is_hbond(hb,grI,grI,ins_d_k,ins_a_k,rcut,r2cut,ccut,x,
+                                                                           bBox,box,hbox,&dist,&ang,bDA,&h,bContact,bMerge,&peri);
+                                                            if (ins_d && ins_a && ihb) {
+                                                                /* add to hbond index if not already there */
+                                                                add_hbond(hb,ins_d_k,ins_a_k,h,grI,ogrp,
+                                                                          nframes,TRUE,bMerge,ihb,bContact,peri);
                            
-                           /* print insertion info to file */
-                           /*fprintf(fpins,
-                             "%4g: %4u:%3.3s%4d%3.3s -> "
-                             "%4u:%3.3s%4d%3.3s (%4.2f,%2.0f) - "
-                             "%4u:%3.3s%4d%3.3s (%4.2f,%2.0f)\n",t,
-                             a[grIA][ins_d_k]+1,
-                             *top.atoms.resname[top.atoms.atom[a[grIA][ins_d_k]].resnr],
-                             top.atoms.atom[a[grIA][ins_d_k]].resnr+1,
-                             *top.atoms.atomname[a[grIA][ins_d_k]],
-                             a[grp+grD][i]+1,
-                             *top.atoms.resname[top.atoms.atom[a[grp+grD][i]].resnr],
-                             top.atoms.atom[a[grp+grD][i]].resnr+1,
-                             *top.atoms.atomname[a[grp+grD][i]],
-                             ins_d_dist,ins_d_ang*RAD2DEG,
-                             a[ogrp+grA][j]+1,
-                             *top.atoms.resname[top.atoms.atom[a[ogrp+grA][j]].resnr],
-                             top.atoms.atom[a[ogrp+grA][j]].resnr+1,
-                             *top.atoms.atomname[a[ogrp+grA][j]],
-                             ins_a_dist,ins_a_ang*RAD2DEG);*/
-                         }
-                       }
-                     }
-                   }
-                 } /* for aj  */
-               }
-               ENDLOOPGRIDINNER;
-             } /* for ai  */
-           } /* for grp */
-         } /* for xi,yi,zi */
-    }
-    analyse_donor_props(opt2fn_null("-don",NFILE,fnm),hb,nframes,t,oenv);
-    if (fpnhb)
-      do_nhb_dist(fpnhb,hb,t);
+                                                                /* print insertion info to file */
+                                                                /*fprintf(fpins,
+                                                                  "%4g: %4u:%3.3s%4d%3.3s -> "
+                                                                  "%4u:%3.3s%4d%3.3s (%4.2f,%2.0f) - "
+                                                                  "%4u:%3.3s%4d%3.3s (%4.2f,%2.0f)\n",t,
+                                                                  a[grIA][ins_d_k]+1,
+                                                                  *top.atoms.resname[top.atoms.atom[a[grIA][ins_d_k]].resnr],
+                                                                  top.atoms.atom[a[grIA][ins_d_k]].resnr+1,
+                                                                  *top.atoms.atomname[a[grIA][ins_d_k]],
+                                                                  a[grp+grD][i]+1,
+                                                                  *top.atoms.resname[top.atoms.atom[a[grp+grD][i]].resnr],
+                                                                  top.atoms.atom[a[grp+grD][i]].resnr+1,
+                                                                  *top.atoms.atomname[a[grp+grD][i]],
+                                                                  ins_d_dist,ins_d_ang*RAD2DEG,
+                                                                  a[ogrp+grA][j]+1,
+                                                                  *top.atoms.resname[top.atoms.atom[a[ogrp+grA][j]].resnr],
+                                                                  top.atoms.atom[a[ogrp+grA][j]].resnr+1,
+                                                                  *top.atoms.atomname[a[ogrp+grA][j]],
+                                                                  ins_a_dist,ins_a_ang*RAD2DEG);*/
+                                                            }
+                                                        }
+                                                    } /* if (bInsert && bSelected), omp single */
+                                                }
+                                            } /* for aj  */
+                                        }
+                                        ENDLOOPGRIDINNER;
+                                    } /* for ai  */
+                                } /* for grp */
+                            } /* for xi,yi,zi */
+                } /* if (bSelected) {...} else */ 
+
+#ifdef HAVE_OPENMP /* ---------------------------- */
+                /* Better wait for all threads to finnish using x[] before updating it. */
+                k = nframes;            /*         */
+#pragma omp barrier                     /*         */
+#pragma omp critical                    /*         */
+                {                       /*         */
+                    /* Sum up histograms and counts from p_hb[] into hb */
+                    {                   /*         */
+                        hb->nhb[k]   += p_hb[threadNr]->nhb[k];
+                        hb->ndist[k] += p_hb[threadNr]->ndist[k];
+                        for (j=0; j<max_hx; j++) /**/
+                            hb->nhx[k][j]  += p_hb[threadNr]->nhx[k][j];
+                    }                   /*         */
+                }                       /*         */
+                /*                                 */
+                /* Here are a handful of single constructs
+                 * to share the workload a bit. The most
+                 * important one is of course the last one,
+                 * where there's a potential bottleneck in form
+                 * of slow I/O.                    */
+#pragma omp single /* ++++++++++++++++,            */
+#endif /* HAVE_OPENMP ----------------+------------*/
+                { /*                  +   */
+                    if (hb != NULL)  /*   */
+                    { /*              +   */
+                        analyse_donor_props(opt2fn_null("-don",NFILE,fnm),hb,k,t,oenv);
+                    } /*              +   */
+                } /*                  +   */
+#ifdef HAVE_OPENMP /*                 +   */
+#pragma omp single /* +++           +++   */
+#endif       /*                       +   */
+                {  /*                 +   */
+                    if (fpnhb)  /*    +   */
+                        do_nhb_dist(fpnhb,hb,t);
+                }  /*                 +   */
+            } /* if (bNN) {...} else  +   */
+#ifdef HAVE_OPENMP /*                 +   */
+#pragma omp single /* +++           +++   */
+#endif       /*                       +   */
+            {      /*                 +   */
+                trrStatus = (read_next_x(oenv,status,&t,natoms,x,box));
+                nframes++;      /*    +   */
+            }      /*                 +   */
+#ifdef HAVE_OPENMP /* ++++++++++++++++�   */
+#pragma omp barrier
+#endif
+        } while (trrStatus);
+
+#ifdef HAVE_OPENMP
+#pragma omp critical
+        {
+            hb->nrhb += p_hb[threadNr]->nrhb;
+            hb->nrdist += p_hb[threadNr]->nrdist;
+        }
+        /* Free parallel datastructures */
+        sfree(p_hb[threadNr]->nhb);
+        sfree(p_hb[threadNr]->ndist);
+        sfree(p_hb[threadNr]->nhx);
+
+#pragma omp for
+        for (i=0; i<nabin; i++)
+            for (j=0; j<actual_nThreads; j++)
+
+                adist[i] += p_adist[j][i];
+#pragma omp for
+        for (i=0; i<=nrbin; i++)
+            for (j=0; j<actual_nThreads; j++)
+                rdist[i] += p_rdist[j][i];
     
-    nframes++;
-  } while (read_next_x(oenv,status,&t,natoms,x,box));
+        sfree(p_adist[threadNr]);
+        sfree(p_rdist[threadNr]);
+    } /* End of parallel region */
+    sfree(p_adist);
+    sfree(p_rdist);
+#endif
+  
   
-  free_grid(ngrid,&grid);
+    free_grid(ngrid,&grid);
   
-  close_trj(status);
-  if (bInsert)
-    ffclose(fpins);
-  if (fpnhb)
-    ffclose(fpnhb);
+    close_trj(status);
+    if (bInsert)
+        ffclose(fpins);
+    if (fpnhb)
+        ffclose(fpnhb);
     
-  /* Compute maximum possible number of different hbonds */
-  if (maxnhb > 0)
-    max_nhb = maxnhb;
-  else {
-    max_nhb = 0.5*(hb->d.nrd*hb->a.nra);
-  }
-  /* Added support for -contact below.
-   * - Erik Marklund, May 29-31, 2006 */
-  /* Changed contact code.
-   * - Erik Marklund, June 29, 2006 */
-  if (bHBmap) {
-    if (hb->nrhb==0) {
-      printf("No %s found!!\n", bContact ? "contacts" : "hydrogen bonds");
-    } else {
-       printf("Found %d different %s in trajectory\n"
-              "Found %d different atom-pairs within %s distance\n",
-              hb->nrhb, bContact?"contacts":"hydrogen bonds",
-              hb->nrdist,(r2cut>0)?"second cut-off":"hydrogen bonding");
-
-       if (bMerge)
-         merge_hb(hb,bTwo,bContact);
-
-       if (opt2bSet("-hbn",NFILE,fnm)) 
-         dump_hbmap(hb,NFILE,fnm,bTwo,bInsert,bContact,isize,index,grpnames,&top.atoms);
-
-       /* Moved the call to merge_hb() to a line BEFORE dump_hbmap
-        * to make the -hbn and -hmb output match eachother. 
-        * - Erik Marklund, May 30, 2006 */
-    }
-  }
-  /* Print out number of hbonds and distances */
-  aver_nhb  = 0;    
-  aver_dist = 0;
-  fp = xvgropen(opt2fn("-num",NFILE,fnm),bContact ? "Contacts" :
-               "Hydrogen Bonds","Time","Number",oenv);
-  snew(leg,2);
-  snew(leg[0],STRLEN);
-  snew(leg[1],STRLEN);
-  sprintf(leg[0],"%s",bContact?"Contacts":"Hydrogen bonds");
-  sprintf(leg[1],"Pairs within %g nm",(r2cut>0)?r2cut:rcut);
-  xvgr_legend(fp,2,leg,oenv);
-  sfree(leg[1]);
-  sfree(leg[0]);
-  sfree(leg);
-  for(i=0; (i<nframes); i++) {
-    fprintf(fp,"%10g  %10d  %10d\n",hb->time[i],hb->nhb[i],hb->ndist[i]);
-    aver_nhb  += hb->nhb[i];
-    aver_dist += hb->ndist[i];
-  }
-  ffclose(fp);
-  aver_nhb  /= nframes;
-  aver_dist /= nframes;
-  /* Print HB distance distribution */
-  if (opt2bSet("-dist",NFILE,fnm)) {
-    long sum;
+    /* Compute maximum possible number of different hbonds */
+    if (maxnhb > 0)
+        max_nhb = maxnhb;
+    else {
+        max_nhb = 0.5*(hb->d.nrd*hb->a.nra);
+    }
+    /* Added support for -contact below.
+     * - Erik Marklund, May 29-31, 2006 */
+    /* Changed contact code.
+     * - Erik Marklund, June 29, 2006 */
+    if (bHBmap && !bNN) {
+        if (hb->nrhb==0) {
+            printf("No %s found!!\n", bContact ? "contacts" : "hydrogen bonds");
+        } else {
+            printf("Found %d different %s in trajectory\n"
+                   "Found %d different atom-pairs within %s distance\n",
+                   hb->nrhb, bContact?"contacts":"hydrogen bonds",
+                   hb->nrdist,(r2cut>0)?"second cut-off":"hydrogen bonding");
+
+            /*Control the pHist.*/
+
+            if (bMerge)
+                merge_hb(hb,bTwo,bContact);
+
+            if (opt2bSet("-hbn",NFILE,fnm)) 
+                dump_hbmap(hb,NFILE,fnm,bTwo,bInsert,bContact,isize,index,grpnames,&top.atoms);
+
+            /* Moved the call to merge_hb() to a line BEFORE dump_hbmap
+             * to make the -hbn and -hmb output match eachother. 
+             * - Erik Marklund, May 30, 2006 */
+        }
+    }
+    /* Print out number of hbonds and distances */
+    aver_nhb  = 0;    
+    aver_dist = 0;
+    fp = xvgropen(opt2fn("-num",NFILE,fnm),bContact ? "Contacts" :
+                  "Hydrogen Bonds","Time","Number",oenv);
+    snew(leg,2);
+    snew(leg[0],STRLEN);
+    snew(leg[1],STRLEN);
+    sprintf(leg[0],"%s",bContact?"Contacts":"Hydrogen bonds");
+    sprintf(leg[1],"Pairs within %g nm",(r2cut>0)?r2cut:rcut);
+    xvgr_legend(fp,2,leg,oenv);
+    sfree(leg[1]);
+    sfree(leg[0]);
+    sfree(leg);
+    for(i=0; (i<nframes); i++) {
+        fprintf(fp,"%10g  %10d  %10d\n",hb->time[i],hb->nhb[i],hb->ndist[i]);
+        aver_nhb  += hb->nhb[i];
+        aver_dist += hb->ndist[i];
+    }
+    ffclose(fp);
+    aver_nhb  /= nframes;
+    aver_dist /= nframes;
+    /* Print HB distance distribution */
+    if (opt2bSet("-dist",NFILE,fnm)) {
+        long sum;
     
-    sum=0;
-    for(i=0; i<nrbin; i++)
-      sum+=rdist[i];
+        sum=0;
+        for(i=0; i<nrbin; i++)
+            sum+=rdist[i];
     
-    fp = xvgropen(opt2fn("-dist",NFILE,fnm),
-                 "Hydrogen Bond Distribution",
-                 "Hydrogen - Acceptor Distance (nm)","",oenv);
-    for(i=0; i<nrbin; i++)
-      fprintf(fp,"%10g %10g\n",(i+0.5)*rbin,rdist[i]/(rbin*(real)sum));
-    ffclose(fp);
-  }
+        fp = xvgropen(opt2fn("-dist",NFILE,fnm),
+                      "Hydrogen Bond Distribution",
+                      "Hydrogen - Acceptor Distance (nm)","",oenv);
+        for(i=0; i<nrbin; i++)
+            fprintf(fp,"%10g %10g\n",(i+0.5)*rbin,rdist[i]/(rbin*(real)sum));
+        ffclose(fp);
+    }
   
-  /* Print HB angle distribution */
-  if (opt2bSet("-ang",NFILE,fnm)) {
-    long sum;
+    /* Print HB angle distribution */
+    if (opt2bSet("-ang",NFILE,fnm)) {
+        long sum;
     
-    sum=0;
-    for(i=0; i<nabin; i++)
-      sum+=adist[i];
+        sum=0;
+        for(i=0; i<nabin; i++)
+            sum+=adist[i];
     
-    fp = xvgropen(opt2fn("-ang",NFILE,fnm),
-                 "Hydrogen Bond Distribution",
-                 "Donor - Hydrogen - Acceptor Angle (\\SO\\N)","",oenv);
-    for(i=0; i<nabin; i++)
-      fprintf(fp,"%10g %10g\n",(i+0.5)*abin,adist[i]/(abin*(real)sum));
-    ffclose(fp);
-  }
+        fp = xvgropen(opt2fn("-ang",NFILE,fnm),
+                      "Hydrogen Bond Distribution",
+                      "Donor - Hydrogen - Acceptor Angle (\\SO\\N)","",oenv);
+        for(i=0; i<nabin; i++)
+            fprintf(fp,"%10g %10g\n",(i+0.5)*abin,adist[i]/(abin*(real)sum));
+        ffclose(fp);
+    }
     
-  /* Print HB in alpha-helix */
-  if (opt2bSet("-hx",NFILE,fnm)) {
-    fp = xvgropen(opt2fn("-hx",NFILE,fnm),
-                 "Hydrogen Bonds","Time(ps)","Count",oenv);
-    xvgr_legend(fp,NRHXTYPES,hxtypenames,oenv);
-    for(i=0; i<nframes; i++) {
-      fprintf(fp,"%10g",hb->time[i]);
-      for (j=0; j<max_hx; j++)
-       fprintf(fp," %6d",hb->nhx[i][j]);
-      fprintf(fp,"\n");
+    /* Print HB in alpha-helix */
+    if (opt2bSet("-hx",NFILE,fnm)) {
+        fp = xvgropen(opt2fn("-hx",NFILE,fnm),
+                      "Hydrogen Bonds","Time(ps)","Count",oenv);
+        xvgr_legend(fp,NRHXTYPES,hxtypenames,oenv);
+        for(i=0; i<nframes; i++) {
+            fprintf(fp,"%10g",hb->time[i]);
+            for (j=0; j<max_hx; j++)
+                fprintf(fp," %6d",hb->nhx[i][j]);
+            fprintf(fp,"\n");
+        }
+        ffclose(fp);
     }
-    ffclose(fp);
-  }
-  printf("Average number of %s per timeframe %.3f out of %g possible\n",
-        bContact ? "contacts" : "hbonds",
-        bContact ? aver_dist : aver_nhb, max_nhb);
+    if (!bNN)
+        printf("Average number of %s per timeframe %.3f out of %g possible\n",
+               bContact ? "contacts" : "hbonds",
+               bContact ? aver_dist : aver_nhb, max_nhb);
         
-  /* Do Autocorrelation etc. */
-  if (hb->bHBmap) {
-    /* 
-       Added support for -contact in ac and hbm calculations below.
-       - Erik Marklund, May 29, 2006
-     */
+    /* Do Autocorrelation etc. */
+    if (hb->bHBmap) {
+        /* 
+           Added support for -contact in ac and hbm calculations below.
+           - Erik Marklund, May 29, 2006
+        */
+        ivec itmp;
+        rvec rtmp;
+        if (opt2bSet("-ac",NFILE,fnm) || opt2bSet("-life",NFILE,fnm))
+            please_cite(stdout,"Spoel2006b");
+        if (opt2bSet("-ac",NFILE,fnm)) {
+            char *gemstring=NULL;
 
-    if (opt2bSet("-ac",NFILE,fnm) || opt2bSet("-life",NFILE,fnm))
-      please_cite(stdout,"Spoel2006b");
-    if (opt2bSet("-ac",NFILE,fnm)) 
-      do_hbac(opt2fn("-ac",NFILE,fnm),hb,aver_nhb/max_nhb,aver_dist,nDump,
-             bMerge,bContact,fit_start,temp,r2cut>0,smooth_tail_start,oenv);
-    if (opt2bSet("-life",NFILE,fnm))
-      do_hblife(opt2fn("-life",NFILE,fnm),hb,bMerge,bContact,oenv);
-    if (opt2bSet("-hbm",NFILE,fnm)) {
-      t_matrix mat;
-      int id,ia,hh,x,y;
+            if (bGem || bNN) {
+                params = init_gemParams(rcut, D, hb->time, hb->nframes/2, nFitPoints, fit_start, fit_end,
+                                        gemBallistic, nBalExp, bBallisticDt);
+                if (params == NULL)
+                    gmx_fatal(FARGS, "Could not initiate t_gemParams params.");
+            }
+            gemstring = strdup(gemType[hb->per->gemtype]);
+            do_hbac(opt2fn("-ac",NFILE,fnm),hb,aver_nhb/max_nhb,aver_dist,nDump,
+                    bMerge,bContact,fit_start,temp,r2cut>0,smooth_tail_start,oenv,
+                    params, gemstring, nThreads, NN, bBallistic, bGemFit);
+        }
+        if (opt2bSet("-life",NFILE,fnm))
+            do_hblife(opt2fn("-life",NFILE,fnm),hb,bMerge,bContact,oenv);
+        if (opt2bSet("-hbm",NFILE,fnm)) {
+            t_matrix mat;
+            int id,ia,hh,x,y;
       
-      mat.nx=nframes;
-      mat.ny=(bContact ? hb->nrdist : hb->nrhb);
-
-      snew(mat.matrix,mat.nx);
-      for(x=0; (x<mat.nx); x++) 
-       snew(mat.matrix[x],mat.ny);
-      y=0;
-      for(id=0; (id<hb->d.nrd); id++) 
-       for(ia=0; (ia<hb->a.nra); ia++) {
-         for(hh=0; (hh<hb->maxhydro); hh++) {
-           if (hb->hbmap[id][ia]) {
-             if (ISHB(hb->hbmap[id][ia]->history[hh])) {
-               /* Changed '<' into '<=' in the for-statement below.
-                * It fixed the previously undiscovered bug that caused
-                * the last occurance of an hbond/contact to not be
-                * set in mat.matrix. Have a look at any old -hbm-output
-                * and you will notice that the last column is allways empty.
-                * - Erik Marklund May 30, 2006
-                */
-               for(x=0; (x<=hb->hbmap[id][ia]->nframes); x++) {
-                 int nn0 = hb->hbmap[id][ia]->n0;
-                 range_check(y,0,mat.ny);
-                 mat.matrix[x+nn0][y] = is_hb(hb->hbmap[id][ia]->h[hh],x);
-               }
-               y++;
-             }
-           }
-         }
-       }
-      mat.axis_x=hb->time;
-      snew(mat.axis_y,mat.ny);
-      for(j=0; j<mat.ny; j++)
-       mat.axis_y[j]=j;
-      sprintf(mat.title,bContact ? "Contact Existence Map":
-             "Hydrogen Bond Existence Map");
-      sprintf(mat.legend,bContact ? "Contacts" : "Hydrogen Bonds");
-      sprintf(mat.label_x,"Time (ps)");
-      sprintf(mat.label_y, bContact ? "Contact Index" : "Hydrogen Bond Index");
-      mat.bDiscrete=TRUE;
-      if (bInsert)
-       mat.nmap=HB_NR;
-      else
-       mat.nmap=2;
-      snew(mat.map,mat.nmap);
-      for(i=0; i<mat.nmap; i++) {
-       mat.map[i].code.c1=hbmap[i];
-       mat.map[i].desc=hbdesc[i];
-       mat.map[i].rgb=hbrgb[i];
-      }
-      fp = opt2FILE("-hbm",NFILE,fnm,"w");
-      write_xpm_m(fp, mat);
-      ffclose(fp);
-      for(x=0; x<mat.nx; x++)
-       sfree(mat.matrix[x]);
-      sfree(mat.axis_y);
-      sfree(mat.matrix);
-      sfree(mat.map);
-    }
-  }
+            mat.nx=nframes;
+            mat.ny=(bContact ? hb->nrdist : hb->nrhb);
+
+            snew(mat.matrix,mat.nx);
+            for(x=0; (x<mat.nx); x++) 
+                snew(mat.matrix[x],mat.ny);
+            y=0;
+            for(id=0; (id<hb->d.nrd); id++) 
+                for(ia=0; (ia<hb->a.nra); ia++) {
+                    for(hh=0; (hh<hb->maxhydro); hh++) {
+                        if (hb->hbmap[id][ia]) {
+                            if (ISHB(hb->hbmap[id][ia]->history[hh])) {
+                                /* Changed '<' into '<=' in the for-statement below.
+                                 * It fixed the previously undiscovered bug that caused
+                                 * the last occurance of an hbond/contact to not be
+                                 * set in mat.matrix. Have a look at any old -hbm-output
+                                 * and you will notice that the last column is allways empty.
+                                 * - Erik Marklund May 30, 2006
+                                 */
+                                for(x=0; (x<=hb->hbmap[id][ia]->nframes); x++) {
+                                    int nn0 = hb->hbmap[id][ia]->n0;
+                                    range_check(y,0,mat.ny);
+                                    mat.matrix[x+nn0][y] = is_hb(hb->hbmap[id][ia]->h[hh],x);
+                                }
+                                y++;
+                            }
+                        }
+                    }
+                }
+            mat.axis_x=hb->time;
+            snew(mat.axis_y,mat.ny);
+            for(j=0; j<mat.ny; j++)
+                mat.axis_y[j]=j;
+            sprintf(mat.title,bContact ? "Contact Existence Map":
+                    "Hydrogen Bond Existence Map");
+            sprintf(mat.legend,bContact ? "Contacts" : "Hydrogen Bonds");
+            sprintf(mat.label_x,"Time (ps)");
+            sprintf(mat.label_y, bContact ? "Contact Index" : "Hydrogen Bond Index");
+            mat.bDiscrete=TRUE;
+            if (bInsert)
+                mat.nmap=HB_NR;
+            else
+                mat.nmap=2;
+            snew(mat.map,mat.nmap);
+            for(i=0; i<mat.nmap; i++) {
+                mat.map[i].code.c1=hbmap[i];
+                mat.map[i].desc=hbdesc[i];
+                mat.map[i].rgb=hbrgb[i];
+            }
+            fp = opt2FILE("-hbm",NFILE,fnm,"w");
+            write_xpm_m(fp, mat);
+            ffclose(fp);
+            for(x=0; x<mat.nx; x++)
+                sfree(mat.matrix[x]);
+            sfree(mat.axis_y);
+            sfree(mat.matrix);
+            sfree(mat.map);
+        }
+    }
+
+    if (bGem) {
+        fprintf(stderr, "There were %i periodic shifts\n", hb->per->nper);
+        fprintf(stderr, "Freeing pHist for all donors...\n");
+        for (i=0; i<hb->d.nrd; i++) {
+            fprintf(stderr, "\r%i",i);
+            if (hb->per->pHist[i] != NULL) {
+                for (j=0; j<hb->a.nra; j++)
+                    clearPshift(&(hb->per->pHist[i][j]));
+                sfree(hb->per->pHist[i]);
+            }
+        }
+        sfree(hb->per->pHist);
+        sfree(hb->per->p2i);
+        sfree(hb->per);
+        fprintf(stderr, "...done.\n");
+    }
+
+#ifdef HAVE_NN_LOOPS
+    if (bNN)
+        free_hbEmap(hb);
+#endif
     
-  if (hb->bDAnr) {
-    int  i,j,nleg;
-    char **legnames;
-    char buf[STRLEN];
+    if (hb->bDAnr) {
+        int  i,j,nleg;
+        char **legnames;
+        char buf[STRLEN];
     
 #define USE_THIS_GROUP(j) ( (j == gr0) || (bTwo && (j == gr1)) || (bInsert && (j == grI)) )
     
-    fp = xvgropen(opt2fn("-dan",NFILE,fnm),
-                 "Donors and Acceptors","Time(ps)","Count",oenv);
-    nleg = (bTwo?2:1)*2 + (bInsert?2:0);
-    snew(legnames,nleg);
-    i=0;
-    for(j=0; j<grNR; j++)
-      if ( USE_THIS_GROUP(j) ) {
-       sprintf(buf,"Donors %s",grpnames[j]);
-       legnames[i++] = strdup(buf);
-       sprintf(buf,"Acceptors %s",grpnames[j]);
-       legnames[i++] = strdup(buf);
-      }
-    if (i != nleg)
-      gmx_incons("number of legend entries");
-    xvgr_legend(fp,nleg,legnames,oenv);
-    for(i=0; i<nframes; i++) {
-      fprintf(fp,"%10g",hb->time[i]);
-      for (j=0; (j<grNR); j++)
-       if ( USE_THIS_GROUP(j) )
-         fprintf(fp," %6d",hb->danr[i][j]);
-      fprintf(fp,"\n");
+        fp = xvgropen(opt2fn("-dan",NFILE,fnm),
+                      "Donors and Acceptors","Time(ps)","Count",oenv);
+        nleg = (bTwo?2:1)*2 + (bInsert?2:0);
+        snew(legnames,nleg);
+        i=0;
+        for(j=0; j<grNR; j++)
+            if ( USE_THIS_GROUP(j) ) {
+                sprintf(buf,"Donors %s",grpnames[j]);
+                legnames[i++] = strdup(buf);
+                sprintf(buf,"Acceptors %s",grpnames[j]);
+                legnames[i++] = strdup(buf);
+            }
+        if (i != nleg)
+            gmx_incons("number of legend entries");
+        xvgr_legend(fp,nleg,legnames,oenv);
+        for(i=0; i<nframes; i++) {
+            fprintf(fp,"%10g",hb->time[i]);
+            for (j=0; (j<grNR); j++)
+                if ( USE_THIS_GROUP(j) )
+                    fprintf(fp," %6d",hb->danr[i][j]);
+            fprintf(fp,"\n");
+        }
+        ffclose(fp);
     }
-    ffclose(fp);
-  }
   
-  thanx(stdout);
+    thanx(stdout);
   
-  return 0;
+    return 0;
 }
index 7a19935ec24a6d2aec00d334f7fb298564d47aba..92e207906e01a6b496e3bce20a38eb6df656ed75 100644 (file)
@@ -211,7 +211,7 @@ int gmx_helix(int argc,char *argv[])
   output_env_t oenv;
   FILE       *otrj;
   char       buf[54],prop[256];
-  int        status;
+  t_trxstatus *status;
   int        natoms,nre,nres;
   t_bb       *bb;
   int        i,j,ai,m,nall,nbb,nca,teller,nSel=0;
@@ -222,6 +222,7 @@ int gmx_helix(int argc,char *argv[])
   real       t;
   real       rms,fac;
   matrix     box;
+  gmx_rmpbc_t  gpbc=NULL;
   bool       bRange;
   t_filenm  fnm[] = {
     { efTPX, NULL,  NULL,   ffREAD  },
@@ -289,12 +290,15 @@ int gmx_helix(int argc,char *argv[])
     pr_bb(stdout,nres,bb);
   }
   
+  gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
+
   snew(xav,natoms);
   teller=0;
   do {
     if ((teller++ % 10) == 0)
       fprintf(stderr,"\rt=%.2f",t);
-    rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x,x);
+    gmx_rmpbc(gpbc,box,x,x);
+
     
     calc_hxprops(nres,bb,x,box);
     if (bCheck)
@@ -334,6 +338,8 @@ int gmx_helix(int argc,char *argv[])
   } while (read_next_x(oenv,status,&t,natoms,x,box));
   fprintf(stderr,"\n");
   
+  gmx_rmpbc_done(gpbc);
+
   close_trj(status);
 
   if (otrj) {
index 2fd5289339f3b690de50e500bdffbda00c70fd03..09280de96de8c4d121b36f359d8ae966758ae83d 100644 (file)
 int gmx_helixorient(int argc,char *argv[])
 {
   const char *desc[] = {
-    "g_helixorient calculates coordinates and direction of the average",
+    "g_helixorient calculates the coordinates and direction of the average",
     "axis inside an alpha helix, and the direction/vectors of both the",
     "alpha carbon and (optionally) a sidechain atom relative to the axis.[PAR]",
     "As input, you need to specify an index group with alpha carbon atoms",
     "corresponding to an alpha helix of continuous residues. Sidechain",
     "directions require a second index group of the same size, containing",
-    "the heavy atom in each residue that should represent the sidechain.[PAR]"
+    "the heavy atom in each residue that should represent the sidechain.[PAR]",
     "Note that this program does not do any fitting of structures.[PAR]",
     "We need four Calpha coordinates to define the local direction of the helix",
-    "axis.[PAR]"
+    "axis.[PAR]",
     "The tilt/rotation is calculated from Euler rotations, where we define",
     "the helix axis as the local X axis, the residues/CA-vector as Y, and the",
     "Z axis from their cross product. We use the Euler Y-Z-X rotation, meaning",
@@ -80,7 +80,7 @@ int gmx_helixorient(int argc,char *argv[])
     real t;
     rvec *x=NULL,dx;
     matrix box;
-    int status;
+    t_trxstatus *status;
     int natoms;
     real theta1,theta2,theta3;
 
@@ -135,6 +135,7 @@ int gmx_helixorient(int argc,char *argv[])
     int ePBC;
 
     output_env_t oenv;
+    gmx_rmpbc_t  gpbc=NULL;
 
     static  bool bSC=FALSE;
     static bool bIncremental = FALSE;
@@ -249,12 +250,14 @@ int gmx_helixorient(int argc,char *argv[])
     unitaxes[1][1]=1;
     unitaxes[2][2]=1;
 
+    gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
+
   do 
   {
       /* initialisation for correct distance calculations */
     set_pbc(&pbc,ePBC,box);
       /* make molecules whole again */
-    rm_pbc(&top->idef,ePBC,natoms,box,x,x);
+    gmx_rmpbc(gpbc,box,x,x);
       
       /* copy coords to our smaller arrays */
       for(i=0;i<iCA;i++)
@@ -499,7 +502,9 @@ int gmx_helixorient(int argc,char *argv[])
       
       teller++;
   } while (read_next_x(oenv,status,&t,natoms,x,box));
-    
+        
+    gmx_rmpbc_done(gpbc);
+
     ffclose(fpaxis);
     ffclose(fpcenter);
     ffclose(fptilt);
index 649e5ee041d095cedd83677f71235d842df95482..b498f803e872a2d0314482fa84a6827242ef868f 100644 (file)
@@ -669,13 +669,13 @@ int gmx_kinetics(int argc,char *argv[])
 {
   const char *desc[] = {
     "g_kinetics reads two xvg files, each one containing data for N replicas.",
-    "The first file contains the temperature of each replica at each timestep,"
+    "The first file contains the temperature of each replica at each timestep,",
     "and the second contains real values that can be interpreted as",
     "an indicator for folding. If the value in the file is larger than",
     "the cutoff it is taken to be unfolded and the other way around.[PAR]",
     "From these data an estimate of the forward and backward rate constants",
-    "for folding is made at a reference temperature. In addition,"
-    "a theoretical melting curve and free energy as a function of temperature"
+    "for folding is made at a reference temperature. In addition,",
+    "a theoretical melting curve and free energy as a function of temperature",
     "are printed in an xvg file.[PAR]",
     "The user can give a max value to be regarded as intermediate",
     "([TT]-ucut[tt]), which, when given will trigger the use of an intermediate state",
index ab3af2fe3a89b434a684d7d9353500016734e6fa..2cd9c1d26f6f2437e7bb65486dd87901c7e11804 100644 (file)
@@ -190,7 +190,8 @@ int gmx_mdmat(int argc,char *argv[])
   char       *grpname;
   int        *rndx,*natm,prevres,newres;
   
-  int        i,j,status,nres,natoms,nframes,it,trxnat;
+  int        i,j,nres,natoms,nframes,it,trxnat;
+  t_trxstatus *status;
   int        nr0;
   bool       bCalcN,bFrames;
   real       t,ratio;
@@ -203,6 +204,7 @@ int gmx_mdmat(int argc,char *argv[])
   int        *tot_n;
   matrix     box;
   output_env_t oenv;
+  gmx_rmpbc_t  gpbc=NULL;
   
   CopyRight(stderr,argv[0]);
 
@@ -275,10 +277,13 @@ int gmx_mdmat(int argc,char *argv[])
   
   rlo.r=1.0, rlo.g=1.0, rlo.b=1.0;
   rhi.r=0.0, rhi.g=0.0, rhi.b=0.0;
+
+  gpbc = gmx_rmpbc_init(&top.idef,ePBC,trxnat,box);
+
   if (bFrames)
     out=opt2FILE("-frames",NFILE,fnm,"w");
   do {
-    rm_pbc(&top.idef,ePBC,trxnat,box,x,x);
+    gmx_rmpbc(gpbc,box,x,x);
     nframes++;
     calc_mat(nres,natoms,rndx,x,index,truncate,mdmat,nmat,ePBC,box);
     for (i=0; (i<nres); i++)
@@ -296,6 +301,7 @@ int gmx_mdmat(int argc,char *argv[])
   } while (read_next_x(oenv,status,&t,trxnat,x,box));
   fprintf(stderr,"\n");
   close_trj(status);
+  gmx_rmpbc_done(gpbc);
   if (bFrames)
     ffclose(out);
   
diff --git a/src/tools/gmx_membed.c b/src/tools/gmx_membed.c
new file mode 100644 (file)
index 0000000..1e2b085
--- /dev/null
@@ -0,0 +1,4660 @@
+/*
+ * $Id: mdrun.c,v 1.139.2.9 2009/05/04 16:13:29 hess Exp $
+ *
+ *                This source code is part of
+ *
+ *                 G   R   O   M   A   C   S
+ *
+ *          GROningen MAchine for Chemical Simulations
+ *
+ *                        VERSION 3.2.0
+ * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
+ * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
+ * Copyright (c) 2001-2004, The GROMACS development team,
+ * check out http://www.gromacs.org for more information.
+
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * If you want to redistribute modifications, please consider that
+ * scientific software is very special. Version control is crucial -
+ * bugs must be traceable. We will be happy to consider code for
+ * inclusion in the official distribution, but derived work must not
+ * be called official GROMACS. Details are found in the README & COPYING
+ * files - if they are missing, get the official version at www.gromacs.org.
+ *
+ * To help us fund GROMACS development, we humbly ask that you cite
+ * the papers on the package - you can find them in the top README file.
+ *
+ * For more info, check our website at http://www.gromacs.org
+ *
+ * And Hey:
+ * Gallium Rubidium Oxygen Manganese Argon Carbon Silicon
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <signal.h>
+#include <stdlib.h>
+#include "typedefs.h"
+#include "smalloc.h"
+#include "sysstuff.h"
+#include "vec.h"
+#include "statutil.h"
+#include "macros.h"
+#include "copyrite.h"
+#include "main.h"
+#include "futil.h"
+#include "edsam.h"
+#include "checkpoint.h"
+#include "vcm.h"
+#include "mdebin.h"
+#include "nrnb.h"
+#include "calcmu.h"
+#include "index.h"
+#include "vsite.h"
+#include "update.h"
+#include "ns.h"
+#include "trnio.h"
+#include "xtcio.h"
+#include "mdrun.h"
+#include "confio.h"
+#include "network.h"
+#include "pull.h"
+#include "xvgr.h"
+#include "physics.h"
+#include "names.h"
+#include "disre.h"
+#include "orires.h"
+#include "dihre.h"
+#include "pppm.h"
+#include "pme.h"
+#include "mdatoms.h"
+#include "qmmm.h"
+#include "mpelogging.h"
+#include "domdec.h"
+#include "partdec.h"
+#include "topsort.h"
+#include "coulomb.h"
+#include "constr.h"
+#include "shellfc.h"
+#include "mvdata.h"
+#include "checkpoint.h"
+#include "mtop_util.h"
+#include "tpxio.h"
+#include "string2.h"
+#include "sighandler.h"
+#include "gmx_ana.h"
+
+#ifdef GMX_LIB_MPI
+#include <mpi.h>
+#endif
+#ifdef GMX_THREADS
+#include "tmpi.h"
+#endif
+
+/* afm stuf */
+#include "pull.h"
+
+/* We use the same defines as in mvdata.c here */
+#define  block_bc(cr,   d) gmx_bcast(     sizeof(d),     &(d),(cr))
+#define nblock_bc(cr,nr,d) gmx_bcast((nr)*sizeof((d)[0]), (d),(cr))
+#define   snew_bc(cr,d,nr) { if (!MASTER(cr)) snew((d),(nr)); }
+
+/* The following two variables and the signal_handler function
+ * is used from pme.c as well
+ */
+
+typedef struct {
+       t_state s;
+       rvec    *f;
+       real    epot;
+       real    fnorm;
+       real    fmax;
+       int     a_fmax;
+} em_state_t;
+
+typedef struct {
+       int    it_xy;
+       int    it_z;
+       int    xy_step;
+       int    z_step;
+       rvec    xmin;
+       rvec    xmax;
+       rvec    *geom_cent;
+       int    pieces;
+       int    *nidx;
+       atom_id **subindex;
+} pos_ins_t;
+
+typedef struct {
+       int             id;
+       char    *name;
+       int     nr;
+       int     natoms;     /*nr of atoms per lipid*/
+       int     mol1;       /*id of the first lipid molecule*/
+       real    area;
+} lip_t;
+
+typedef struct {
+       char    *name;
+       t_block mem_at;
+       int             *mol_id;
+       int             nmol;
+       real    lip_area;
+       real    zmin;
+       real    zmax;
+       real    zmed;
+} mem_t;
+
+typedef struct {
+       int             *mol;
+       int             *block;
+       int     nr;
+} rm_t;
+
+int search_string(char *s,int ng,char ***gn)
+{
+       int i;
+
+       for(i=0; (i<ng); i++)
+               if (strcasecmp(s,*gn[i]) == 0)
+                       return i;
+
+       gmx_fatal(FARGS,"Group %s not found in indexfile.\nMaybe you have non-default groups in your mdp file, while not using the '-n' option of grompp.\nIn that case use the '-n' option.\n",s);
+
+       return -1;
+}
+
+int get_mol_id(int at,int nmblock,gmx_molblock_t *mblock, int *type, int *block)
+{
+       int mol_id=0;
+       int i;
+
+       for(i=0;i<nmblock;i++)
+       {
+               if(at<(mblock[i].nmol*mblock[i].natoms_mol))
+               {
+                       mol_id+=at/mblock[i].natoms_mol;
+                       *type = mblock[i].type;
+                       *block = i;
+                       return mol_id;
+               } else {
+                       at-= mblock[i].nmol*mblock[i].natoms_mol;
+                       mol_id+=mblock[i].nmol;
+               }
+       }
+
+       gmx_fatal(FARGS,"Something is wrong in mol ids, at %d, mol_id %d",at,mol_id);
+
+       return -1;
+}
+
+int get_block(int mol_id,int nmblock,gmx_molblock_t *mblock)
+{
+       int i;
+       int nmol=0;
+
+       for(i=0;i<nmblock;i++)
+       {
+               nmol+=mblock[i].nmol;
+               if(mol_id<nmol)
+                       return i;
+       }
+
+       gmx_fatal(FARGS,"mol_id %d larger than total number of molecules %d.\n",mol_id,nmol);
+
+       return -1;
+}
+
+int get_tpr_version(const char *infile)
+{
+       char    buf[STRLEN];
+       bool    bDouble;
+       int     precision,fver;
+        t_fileio *fio;
+
+       fio = open_tpx(infile,"r");
+       gmx_fio_checktype(fio);
+
+       precision = sizeof(real);
+
+       gmx_fio_do_string(fio,buf);
+       if (strncmp(buf,"VERSION",7))
+               gmx_fatal(FARGS,"Can not read file %s,\n"
+                               "             this file is from a Gromacs version which is older than 2.0\n"
+                               "             Make a new one with grompp or use a gro or pdb file, if possible",
+                               gmx_fio_getname(fio));
+       gmx_fio_do_int(fio,precision);
+       bDouble = (precision == sizeof(double));
+       if ((precision != sizeof(float)) && !bDouble)
+               gmx_fatal(FARGS,"Unknown precision in file %s: real is %d bytes "
+                               "instead of %d or %d",
+                               gmx_fio_getname(fio),precision,sizeof(float),sizeof(double));
+       gmx_fio_setprecision(fio,bDouble);
+       fprintf(stderr,"Reading file %s, %s (%s precision)\n",
+                       gmx_fio_getname(fio),buf,bDouble ? "double" : "single");
+
+       gmx_fio_do_int(fio,fver);
+
+       close_tpx(fio);
+
+       return fver;
+}
+
+void set_inbox(int natom, rvec *x)
+{
+       rvec tmp;
+       int  i;
+
+       tmp[XX]=tmp[YY]=tmp[ZZ]=0.0;
+       for(i=0;i<natom;i++)
+       {
+               if(x[i][XX]<tmp[XX])            tmp[XX]=x[i][XX];
+               if(x[i][YY]<tmp[YY])            tmp[YY]=x[i][YY];
+               if(x[i][ZZ]<tmp[ZZ])            tmp[ZZ]=x[i][ZZ];
+       }
+
+       for(i=0;i<natom;i++)
+                       rvec_inc(x[i],tmp);
+}
+
+int get_mtype_list(t_block *at, gmx_mtop_t *mtop, t_block *tlist)
+{
+       int i,j,nr,mol_id;
+        int type=0,block=0;
+       bool bNEW;
+
+       nr=0;
+       snew(tlist->index,at->nr);
+       for (i=0;i<at->nr;i++)
+       {
+               bNEW=TRUE;
+               mol_id = get_mol_id(at->index[i],mtop->nmolblock,mtop->molblock,&type,&block);
+               for(j=0;j<nr;j++)
+               {
+                       if(tlist->index[j]==type)
+                                               bNEW=FALSE;
+               }
+               if(bNEW==TRUE)
+               {
+                       tlist->index[nr]=type;
+                       nr++;
+               }
+       }
+
+       srenew(tlist->index,nr);
+       return nr;
+}
+
+void check_types(t_block *ins_at,t_block *rest_at,gmx_mtop_t *mtop)
+{
+       t_block         *ins_mtype,*rest_mtype;
+       int                     i,j;
+
+       snew(ins_mtype,1);
+       snew(rest_mtype,1);
+    ins_mtype->nr  = get_mtype_list(ins_at , mtop, ins_mtype );
+    rest_mtype->nr = get_mtype_list(rest_at, mtop, rest_mtype);
+
+    for(i=0;i<ins_mtype->nr;i++)
+    {
+       for(j=0;j<rest_mtype->nr;j++)
+       {
+               if(ins_mtype->index[i]==rest_mtype->index[j])
+                       gmx_fatal(FARGS,"Moleculetype %s is found both in the group to insert and the rest of the system.\n"
+                                       "Because we need to exclude all interactions between the atoms in the group to\n"
+                                       "insert, the same moleculetype can not be used in both groups. Change the\n"
+                                       "moleculetype of the molecules %s in the inserted group. Do not forget to provide\n"
+                                       "an appropriate *.itp file",*(mtop->moltype[rest_mtype->index[j]].name),
+                                       *(mtop->moltype[rest_mtype->index[j]].name));
+       }
+    }
+
+    sfree(ins_mtype->index);
+    sfree(rest_mtype->index);
+    sfree(ins_mtype);
+    sfree(rest_mtype);
+}
+
+int init_ins_at(t_block *ins_at,t_block *rest_at,t_state *state, pos_ins_t *pos_ins,gmx_groups_t *groups,int ins_grp_id, real xy_max)
+{
+       int i,gid,c=0;
+       real x,xmin,xmax,y,ymin,ymax,z,zmin,zmax;
+
+       snew(rest_at->index,state->natoms);
+
+       xmin=xmax=state->x[ins_at->index[0]][XX];
+       ymin=ymax=state->x[ins_at->index[0]][YY];
+       zmin=zmax=state->x[ins_at->index[0]][ZZ];
+
+       for(i=0;i<state->natoms;i++)
+       {
+               gid = groups->grpnr[egcFREEZE][i];
+               if(groups->grps[egcFREEZE].nm_ind[gid]==ins_grp_id)
+               {
+                       x=state->x[i][XX];
+                       if (x<xmin)                     xmin=x;
+                       if (x>xmax)                     xmax=x;
+                       y=state->x[i][YY];
+                       if (y<ymin)                             ymin=y;
+                       if (y>ymax)                             ymax=y;
+                       z=state->x[i][ZZ];
+                       if (z<zmin)                             zmin=z;
+                       if (z>zmax)                             zmax=z;
+               } else {
+                       rest_at->index[c]=i;
+                       c++;
+               }
+       }
+
+       rest_at->nr=c;
+       srenew(rest_at->index,c);
+
+       if(xy_max>1.000001)
+       {
+               pos_ins->xmin[XX]=xmin-((xmax-xmin)*xy_max-(xmax-xmin))/2;
+               pos_ins->xmin[YY]=ymin-((ymax-ymin)*xy_max-(ymax-ymin))/2;
+
+               pos_ins->xmax[XX]=xmax+((xmax-xmin)*xy_max-(xmax-xmin))/2;
+               pos_ins->xmax[YY]=ymax+((ymax-ymin)*xy_max-(ymax-ymin))/2;
+       } else {
+               pos_ins->xmin[XX]=xmin;
+               pos_ins->xmin[YY]=ymin;
+
+               pos_ins->xmax[XX]=xmax;
+               pos_ins->xmax[YY]=ymax;
+       }
+
+       /* 6.0 is estimated thickness of bilayer */
+       if( (zmax-zmin) < 6.0 )
+       {
+               pos_ins->xmin[ZZ]=zmin+(zmax-zmin)/2.0-3.0;
+               pos_ins->xmax[ZZ]=zmin+(zmax-zmin)/2.0+3.0;
+       } else {
+               pos_ins->xmin[ZZ]=zmin;
+               pos_ins->xmax[ZZ]=zmax;
+       }
+
+       return c;
+}
+
+real est_prot_area(pos_ins_t *pos_ins,rvec *r,t_block *ins_at, mem_t *mem_p)
+{
+       real x,y,dx=0.15,dy=0.15,area=0.0;
+       real add;
+       int c,at;
+
+       for(x=pos_ins->xmin[XX];x<pos_ins->xmax[XX];x+=dx)
+       {
+               for(y=pos_ins->xmin[YY];y<pos_ins->xmax[YY];y+=dy)
+               {
+                       c=0;
+                       add=0.0;
+                       do
+                       {
+                               at=ins_at->index[c];
+                               if ( (r[at][XX]>=x) && (r[at][XX]<x+dx) &&
+                                               (r[at][YY]>=y) && (r[at][YY]<y+dy) &&
+                                               (r[at][ZZ]>mem_p->zmin+1.0) && (r[at][ZZ]<mem_p->zmax-1.0) )
+                                       add=1.0;
+                               c++;
+                       } while ( (c<ins_at->nr) && (add<0.5) );
+                       area+=add;
+               }
+       }
+       area=area*dx*dy;
+
+       return area;
+}
+
+void init_lip(matrix box, gmx_mtop_t *mtop, lip_t *lip)
+{
+       int i;
+       real mem_area;
+       int mol1=0;
+
+       mem_area = box[XX][XX]*box[YY][YY]-box[XX][YY]*box[YY][XX];
+       for(i=0;i<mtop->nmolblock;i++)
+       {
+               if(mtop->molblock[i].type == lip->id)
+               {
+                       lip->nr=mtop->molblock[i].nmol;
+                       lip->natoms=mtop->molblock[i].natoms_mol;
+               }
+       }
+       lip->area=2.0*mem_area/(double)lip->nr;
+
+       for (i=0;i<lip->id;i++)
+               mol1+=mtop->molblock[i].nmol;
+       lip->mol1=mol1;
+}
+
+int init_mem_at(mem_t *mem_p, gmx_mtop_t *mtop, rvec *r, matrix box, pos_ins_t *pos_ins)
+{
+       int i,j,at,mol,nmol,nmolbox,count;
+       t_block *mem_a;
+       real z,zmin,zmax,mem_area;
+       bool bNew;
+       atom_id *mol_id;
+       int type=0,block=0;
+
+       nmol=count=0;
+       mem_a=&(mem_p->mem_at);
+       snew(mol_id,mem_a->nr);
+/*     snew(index,mem_a->nr); */
+       zmin=pos_ins->xmax[ZZ];
+       zmax=pos_ins->xmin[ZZ];
+       for(i=0;i<mem_a->nr;i++)
+       {
+               at=mem_a->index[i];
+               if(     (r[at][XX]>pos_ins->xmin[XX]) && (r[at][XX]<pos_ins->xmax[XX]) &&
+                       (r[at][YY]>pos_ins->xmin[YY]) && (r[at][YY]<pos_ins->xmax[YY]) &&
+                       (r[at][ZZ]>pos_ins->xmin[ZZ]) && (r[at][ZZ]<pos_ins->xmax[ZZ]) )
+               {
+                       mol = get_mol_id(at,mtop->nmolblock,mtop->molblock,&type,&block);
+
+                       bNew=TRUE;
+                       for(j=0;j<nmol;j++)
+                               if(mol == mol_id[j])
+                                       bNew=FALSE;
+
+                       if(bNew)
+                       {
+                               mol_id[nmol]=mol;
+                               nmol++;
+                       }
+
+                       z=r[at][ZZ];
+                       if(z<zmin)                                      zmin=z;
+                       if(z>zmax)                                      zmax=z;
+
+/*                     index[count]=at;*/
+                       count++;
+               }
+       }
+
+       mem_p->nmol=nmol;
+       srenew(mol_id,nmol);
+       mem_p->mol_id=mol_id;
+/*     srenew(index,count);*/
+/*     mem_p->mem_at.nr=count;*/
+/*     sfree(mem_p->mem_at.index);*/
+/*     mem_p->mem_at.index=index;*/
+
+       if((zmax-zmin)>(box[ZZ][ZZ]-0.5))
+               gmx_fatal(FARGS,"Something is wrong with your membrane. Max and min z values are %f and %f.\n"
+                               "Maybe your membrane is not centered in the box, but located at the box edge in the z-direction,\n"
+                               "so that one membrane is distributed over two periodic box images. Another possibility is that\n"
+                               "your water layer is not thick enough.\n",zmax,zmin);
+       mem_p->zmin=zmin;
+       mem_p->zmax=zmax;
+       mem_p->zmed=(zmax-zmin)/2+zmin;
+
+       /*number of membrane molecules in protein box*/
+       nmolbox = count/mtop->molblock[block].natoms_mol;
+       /*mem_area = box[XX][XX]*box[YY][YY]-box[XX][YY]*box[YY][XX];
+       mem_p->lip_area = 2.0*mem_area/(double)mem_p->nmol;*/
+       mem_area = (pos_ins->xmax[XX]-pos_ins->xmin[XX])*(pos_ins->xmax[YY]-pos_ins->xmin[YY]);
+       mem_p->lip_area = 2.0*mem_area/(double)nmolbox;
+
+       return mem_p->mem_at.nr;
+}
+
+void init_resize(t_block *ins_at,rvec *r_ins,pos_ins_t *pos_ins,mem_t *mem_p,rvec *r, bool bALLOW_ASYMMETRY)
+{
+       int i,j,at,c,outsidesum,gctr=0;
+    int idxsum=0;
+
+    /*sanity check*/
+    for (i=0;i<pos_ins->pieces;i++)
+          idxsum+=pos_ins->nidx[i];
+    if (idxsum!=ins_at->nr)
+          gmx_fatal(FARGS,"Piecewise sum of inserted atoms not same as size of group selected to insert.");
+
+    snew(pos_ins->geom_cent,pos_ins->pieces);
+    for (i=0;i<pos_ins->pieces;i++)
+    {
+       c=0;
+       outsidesum=0;
+       for(j=0;j<DIM;j++)
+               pos_ins->geom_cent[i][j]=0;
+
+       for(j=0;j<DIM;j++)
+               pos_ins->geom_cent[i][j]=0;
+       for (j=0;j<pos_ins->nidx[i];j++)
+       {
+               at=pos_ins->subindex[i][j];
+               copy_rvec(r[at],r_ins[gctr]);
+               if( (r_ins[gctr][ZZ]<mem_p->zmax) && (r_ins[gctr][ZZ]>mem_p->zmin) )
+               {
+                       rvec_inc(pos_ins->geom_cent[i],r_ins[gctr]);
+                       c++;
+               }
+               else
+                       outsidesum++;
+               gctr++;
+       }
+       if (c>0)
+               svmul(1/(double)c,pos_ins->geom_cent[i],pos_ins->geom_cent[i]);
+       if (!bALLOW_ASYMMETRY)
+               pos_ins->geom_cent[i][ZZ]=mem_p->zmed;
+
+       fprintf(stderr,"Embedding piece %d with center of geometry: %f %f %f\n",i,pos_ins->geom_cent[i][XX],pos_ins->geom_cent[i][YY],pos_ins->geom_cent[i][ZZ]);
+    }
+    fprintf(stderr,"\n");
+}
+
+void resize(t_block *ins_at, rvec *r_ins, rvec *r, pos_ins_t *pos_ins,rvec fac)
+{
+       int i,j,k,at,c=0;
+       for (k=0;k<pos_ins->pieces;k++)
+               for(i=0;i<pos_ins->nidx[k];i++)
+               {
+                       at=pos_ins->subindex[k][i];
+                       for(j=0;j<DIM;j++)
+                               r[at][j]=pos_ins->geom_cent[k][j]+fac[j]*(r_ins[c][j]-pos_ins->geom_cent[k][j]);
+                       c++;
+               }
+}
+
+int gen_rm_list(rm_t *rm_p,t_block *ins_at,t_block *rest_at,t_pbc *pbc, gmx_mtop_t *mtop,
+               rvec *r, rvec *r_ins, mem_t *mem_p, pos_ins_t *pos_ins, real probe_rad, int low_up_rm, bool bALLOW_ASYMMETRY)
+{
+       int i,j,k,l,at,at2,mol_id;
+        int type=0,block=0;
+       int nrm,nupper,nlower;
+       real r_min_rad,z_lip,min_norm;
+       bool bRM;
+       rvec dr,dr_tmp;
+       real *dist;
+       int *order;
+
+       r_min_rad=probe_rad*probe_rad;
+       snew(rm_p->mol,mtop->mols.nr);
+       snew(rm_p->block,mtop->mols.nr);
+       nrm=nupper=0;
+       nlower=low_up_rm;
+       for(i=0;i<ins_at->nr;i++)
+       {
+               at=ins_at->index[i];
+               for(j=0;j<rest_at->nr;j++)
+               {
+                       at2=rest_at->index[j];
+                       pbc_dx(pbc,r[at],r[at2],dr);
+
+                       if(norm2(dr)<r_min_rad)
+                       {
+                               mol_id = get_mol_id(at2,mtop->nmolblock,mtop->molblock,&type,&block);
+                               bRM=TRUE;
+                               for(l=0;l<nrm;l++)
+                                       if(rm_p->mol[l]==mol_id)
+                                               bRM=FALSE;
+                               if(bRM)
+                               {
+                                       /*fprintf(stderr,"%d wordt toegevoegd\n",mol_id);*/
+                                       rm_p->mol[nrm]=mol_id;
+                                       rm_p->block[nrm]=block;
+                                       nrm++;
+                                       z_lip=0.0;
+                                       for(l=0;l<mem_p->nmol;l++)
+                                       {
+                                               if(mol_id==mem_p->mol_id[l])
+                                               {
+                                                       for(k=mtop->mols.index[mol_id];k<mtop->mols.index[mol_id+1];k++)
+                                                               z_lip+=r[k][ZZ];
+                                                       z_lip/=mtop->molblock[block].natoms_mol;
+                                                       if(z_lip<mem_p->zmed)
+                                                               nlower++;
+                                                       else
+                                                               nupper++;
+                                               }
+                                       }
+                               }
+                       }
+               }
+       }
+
+       /*make sure equal number of lipids from upper and lower layer are removed */
+       if( (nupper!=nlower) && (!bALLOW_ASYMMETRY) )
+       {
+               snew(dist,mem_p->nmol);
+               snew(order,mem_p->nmol);
+               for(i=0;i<mem_p->nmol;i++)
+               {
+                       at = mtop->mols.index[mem_p->mol_id[i]];
+                       pbc_dx(pbc,r[at],pos_ins->geom_cent[0],dr);
+                       if (pos_ins->pieces>1)
+                       {
+                               /*minimum dr value*/
+                               min_norm=norm2(dr);
+                               for (k=1;k<pos_ins->pieces;k++)
+                               {
+                                       pbc_dx(pbc,r[at],pos_ins->geom_cent[k],dr_tmp);
+                                       if (norm2(dr_tmp) < min_norm)
+                                       {
+                                               min_norm=norm2(dr_tmp);
+                                               copy_rvec(dr_tmp,dr);
+                                       }
+                               }
+                       }
+                       dist[i]=dr[XX]*dr[XX]+dr[YY]*dr[YY];
+                       j=i-1;
+                       while (j>=0 && dist[i]<dist[order[j]])
+                       {
+                               order[j+1]=order[j];
+                               j--;
+                       }
+                       order[j+1]=i;
+               }
+
+               i=0;
+               while(nupper!=nlower)
+               {
+                       mol_id=mem_p->mol_id[order[i]];
+                       block=get_block(mol_id,mtop->nmolblock,mtop->molblock);
+
+                       bRM=TRUE;
+                       for(l=0;l<nrm;l++)
+                               if(rm_p->mol[l]==mol_id)
+                                       bRM=FALSE;
+                       if(bRM)
+                       {
+                               z_lip=0;
+                               for(k=mtop->mols.index[mol_id];k<mtop->mols.index[mol_id+1];k++)
+                                       z_lip+=r[k][ZZ];
+                               z_lip/=mtop->molblock[block].natoms_mol;
+                               if(nupper>nlower && z_lip<mem_p->zmed)
+                               {
+                                       rm_p->mol[nrm]=mol_id;
+                                       rm_p->block[nrm]=block;
+                                       nrm++;
+                                       nlower++;
+                               }
+                               else if (nupper<nlower && z_lip>mem_p->zmed)
+                               {
+                                       rm_p->mol[nrm]=mol_id;
+                                       rm_p->block[nrm]=block;
+                                       nrm++;
+                                       nupper++;
+                               }
+                       }
+                       i++;
+
+                       if(i>mem_p->nmol)
+                               gmx_fatal(FARGS,"Trying to remove more lipid molecules than there are in the membrane");
+               }
+               sfree(dist);
+               sfree(order);
+       }
+
+       rm_p->nr=nrm;
+       srenew(rm_p->mol,nrm);
+       srenew(rm_p->block,nrm);
+
+       return nupper+nlower;
+}
+
+void rm_group(t_inputrec *ir, gmx_groups_t *groups, gmx_mtop_t *mtop, rm_t *rm_p, t_state *state, t_block *ins_at, pos_ins_t *pos_ins)
+{
+       int i,j,k,n,rm,mol_id,at,block;
+       rvec *x_tmp,*v_tmp;
+       atom_id *list,*new_mols;
+       unsigned char  *new_egrp[egcNR];
+       bool bRM;
+
+       snew(list,state->natoms);
+       n=0;
+       for(i=0;i<rm_p->nr;i++)
+       {
+               mol_id=rm_p->mol[i];
+               at=mtop->mols.index[mol_id];
+               block =rm_p->block[i];
+               mtop->molblock[block].nmol--;
+               for(j=0;j<mtop->molblock[block].natoms_mol;j++)
+               {
+                       list[n]=at+j;
+                       n++;
+               }
+
+               mtop->mols.index[mol_id]=-1;
+       }
+
+       mtop->mols.nr-=rm_p->nr;
+       mtop->mols.nalloc_index-=rm_p->nr;
+       snew(new_mols,mtop->mols.nr);
+       for(i=0;i<mtop->mols.nr+rm_p->nr;i++)
+       {
+               j=0;
+               if(mtop->mols.index[i]!=-1)
+               {
+                       new_mols[j]=mtop->mols.index[i];
+                       j++;
+               }
+       }
+       sfree(mtop->mols.index);
+       mtop->mols.index=new_mols;
+
+
+       mtop->natoms-=n;
+       state->natoms-=n;
+       state->nalloc=state->natoms;
+       snew(x_tmp,state->nalloc);
+       snew(v_tmp,state->nalloc);
+
+       for(i=0;i<egcNR;i++)
+       {
+               if(groups->grpnr[i]!=NULL)
+               {
+                       groups->ngrpnr[i]=state->natoms;
+                       snew(new_egrp[i],state->natoms);
+               }
+       }
+
+       rm=0;
+       for (i=0;i<state->natoms+n;i++)
+       {
+               bRM=FALSE;
+               for(j=0;j<n;j++)
+               {
+                       if(i==list[j])
+                       {
+                               bRM=TRUE;
+                               rm++;
+                       }
+               }
+
+               if(!bRM)
+               {
+                       for(j=0;j<egcNR;j++)
+                       {
+                               if(groups->grpnr[j]!=NULL)
+                               {
+                                       new_egrp[j][i-rm]=groups->grpnr[j][i];
+                               }
+                       }
+                       copy_rvec(state->x[i],x_tmp[i-rm]);
+                       copy_rvec(state->v[i],v_tmp[i-rm]);
+                       for(j=0;j<ins_at->nr;j++)
+                       {
+                               if (i==ins_at->index[j])
+                                       ins_at->index[j]=i-rm;
+                       }
+                       for(j=0;j<pos_ins->pieces;j++)
+                       {
+                               for(k=0;k<pos_ins->nidx[j];k++)
+                               {
+                                       if (i==pos_ins->subindex[j][k])
+                                               pos_ins->subindex[j][k]=i-rm;
+                               }
+                       }
+               }
+       }
+       sfree(state->x);
+       state->x=x_tmp;
+       sfree(state->v);
+       state->v=v_tmp;
+
+       for(i=0;i<egcNR;i++)
+       {
+               if(groups->grpnr[i]!=NULL)
+               {
+                       sfree(groups->grpnr[i]);
+                       groups->grpnr[i]=new_egrp[i];
+               }
+       }
+}
+
+int rm_bonded(t_block *ins_at, gmx_mtop_t *mtop)
+{
+       int i,j,m;
+       int type,natom,nmol,at,atom1=0,rm_at=0;
+       bool *bRM,bINS;
+       /*this routine lives dangerously by assuming that all molecules of a given type are in order in the structure*/
+       /*this routine does not live as dangerously as it seems. There is namely a check in mdrunner_membed to make
+         *sure that g_membed exits with a warning when there are molecules of the same type not in the 
+        *ins_at index group. MGWolf 050710 */
+
+
+       snew(bRM,mtop->nmoltype);
+       for (i=0;i<mtop->nmoltype;i++)
+       {
+               bRM[i]=TRUE;
+       }
+
+       for (i=0;i<mtop->nmolblock;i++) 
+       {
+           /*loop over molecule blocks*/
+               type        =mtop->molblock[i].type;
+               natom       =mtop->molblock[i].natoms_mol;
+               nmol            =mtop->molblock[i].nmol;
+
+               for(j=0;j<natom*nmol && bRM[type]==TRUE;j++) 
+               {
+                   /*loop over atoms in the block*/
+                       at=j+atom1; /*atom index = block index + offset*/
+                       bINS=FALSE;
+
+                       for (m=0;(m<ins_at->nr) && (bINS==FALSE);m++)
+                       {
+                           /*loop over atoms in insertion index group to determine if we're inserting one*/
+                               if(at==ins_at->index[m])
+                               {
+                                       bINS=TRUE;
+                               }
+                       }
+                       bRM[type]=bINS;
+               }
+               atom1+=natom*nmol; /*update offset*/
+               if(bRM[type])
+               {
+                       rm_at+=natom*nmol; /*increment bonded removal counter by # atoms in block*/
+               }
+       }
+
+       for(i=0;i<mtop->nmoltype;i++)
+       {
+               if(bRM[i])
+               {
+                       for(j=0;j<F_LJ;j++)
+                       {
+                               mtop->moltype[i].ilist[j].nr=0;
+                       }
+                       for(j=F_POSRES;j<=F_VSITEN;j++)
+                       {
+                               mtop->moltype[i].ilist[j].nr=0;
+                       }
+               }
+       }
+       sfree(bRM);
+
+       return rm_at;
+}
+
+void top_update(const char *topfile, char *ins, rm_t *rm_p, gmx_mtop_t *mtop)
+{
+#define TEMP_FILENM "temp.top"
+       int     bMolecules=0;
+       FILE    *fpin,*fpout;
+       char    buf[STRLEN],buf2[STRLEN],*temp;
+       int             i,*nmol_rm,nmol,line;
+
+       fpin  = ffopen(topfile,"r");
+       fpout = ffopen(TEMP_FILENM,"w");
+
+       snew(nmol_rm,mtop->nmoltype);
+       for(i=0;i<rm_p->nr;i++)
+               nmol_rm[rm_p->block[i]]++;
+
+       line=0;
+       while(fgets(buf,STRLEN,fpin))
+       {
+               line++;
+               if(buf[0]!=';')
+               {
+                       strcpy(buf2,buf);
+                       if ((temp=strchr(buf2,'\n')) != NULL)
+                               temp[0]='\0';
+                       ltrim(buf2);
+
+                       if (buf2[0]=='[')
+                       {
+                               buf2[0]=' ';
+                               if ((temp=strchr(buf2,'\n')) != NULL)
+                                       temp[0]='\0';
+                               rtrim(buf2);
+                               if (buf2[strlen(buf2)-1]==']')
+                               {
+                                       buf2[strlen(buf2)-1]='\0';
+                                       ltrim(buf2);
+                                       rtrim(buf2);
+                                       if (strcasecmp(buf2,"molecules")==0)
+                                               bMolecules=1;
+                               }
+                               fprintf(fpout,"%s",buf);
+                       } else if (bMolecules==1)
+                       {
+                               for(i=0;i<mtop->nmolblock;i++)
+                               {
+                                       nmol=mtop->molblock[i].nmol;
+                                       sprintf(buf,"%-15s %5d\n",*(mtop->moltype[mtop->molblock[i].type].name),nmol);
+                                       fprintf(fpout,"%s",buf);
+                               }
+                               bMolecules=2;
+                       } else if (bMolecules==2)
+                       {
+                               /* print nothing */
+                       } else 
+                       {
+                               fprintf(fpout,"%s",buf);
+                       }
+               } else 
+               {
+                       fprintf(fpout,"%s",buf);
+               }
+       }
+
+       fclose(fpout);
+       /* use ffopen to generate backup of topinout */
+       fpout=ffopen(topfile,"w");
+       fclose(fpout);
+       rename(TEMP_FILENM,topfile);
+#undef TEMP_FILENM
+}
+
+void md_print_warning(const t_commrec *cr,FILE *fplog,const char *buf)
+{
+    if (MASTER(cr))
+    {
+        fprintf(stderr,"\n%s\n",buf);
+    }
+    if (fplog)
+    {
+        fprintf(fplog,"\n%s\n",buf);
+    }
+}
+
+/*  simulation conditions to transmit. Keep in mind that they are
+    transmitted to other nodes through an MPI_Reduce after
+    casting them to a real (so the signals can be sent together with other
+    data). This means that the only meaningful values are positive,
+    negative or zero. */
+enum { eglsNABNSB, eglsCHKPT, eglsSTOPCOND, eglsRESETCOUNTERS, eglsNR };
+/* Is the signal in one simulation independent of other simulations? */
+bool gs_simlocal[eglsNR] = { TRUE, FALSE, FALSE, TRUE };
+
+typedef struct {
+    int nstms;       /* The frequency for intersimulation communication */
+    int sig[eglsNR]; /* The signal set by one process in do_md */
+    int set[eglsNR]; /* The communicated signal, equal for all processes */
+} globsig_t;
+
+
+static int multisim_min(const gmx_multisim_t *ms,int nmin,int n)
+{
+    int  *buf;
+    bool bPos,bEqual;
+    int  s,d;
+
+    snew(buf,ms->nsim);
+    buf[ms->sim] = n;
+    gmx_sumi_sim(ms->nsim,buf,ms);
+    bPos   = TRUE;
+    bEqual = TRUE;
+    for(s=0; s<ms->nsim; s++)
+    {
+        bPos   = bPos   && (buf[s] > 0);
+        bEqual = bEqual && (buf[s] == buf[0]);
+    }
+    if (bPos)
+    {
+        if (bEqual)
+        {
+            nmin = min(nmin,buf[0]);
+        }
+        else
+        {
+            /* Find the least common multiple */
+            for(d=2; d<nmin; d++)
+            {
+                s = 0;
+                while (s < ms->nsim && d % buf[s] == 0)
+                {
+                    s++;
+                }
+                if (s == ms->nsim)
+                {
+                    /* We found the LCM and it is less than nmin */
+                    nmin = d;
+                    break;
+                }
+            }
+        }
+    }
+    sfree(buf);
+
+    return nmin;
+}
+
+static int multisim_nstsimsync(const t_commrec *cr,
+                               const t_inputrec *ir,int repl_ex_nst)
+{
+    int nmin;
+
+    if (MASTER(cr))
+    {
+        nmin = INT_MAX;
+        nmin = multisim_min(cr->ms,nmin,ir->nstlist);
+        nmin = multisim_min(cr->ms,nmin,ir->nstcalcenergy);
+        nmin = multisim_min(cr->ms,nmin,repl_ex_nst);
+        if (nmin == INT_MAX)
+        {
+            gmx_fatal(FARGS,"Can not find an appropriate interval for inter-simulation communication, since nstlist, nstcalcenergy and -replex are all <= 0");
+        }
+        /* Avoid inter-simulation communication at every (second) step */
+        if (nmin <= 2)
+        {
+            nmin = 10;
+        }
+    }
+
+    gmx_bcast(sizeof(int),&nmin,cr);
+
+    return nmin;
+}
+
+static void init_global_signals(globsig_t *gs,const t_commrec *cr,
+                                const t_inputrec *ir,int repl_ex_nst)
+{
+    int i;
+
+    if (MULTISIM(cr))
+    {
+        gs->nstms = multisim_nstsimsync(cr,ir,repl_ex_nst);
+        if (debug)
+        {
+            fprintf(debug,"Syncing simulations for checkpointing and termination every %d steps\n",gs->nstms);
+        }
+    }
+    else
+    {
+        gs->nstms = 1;
+    }
+
+    for(i=0; i<eglsNR; i++)
+    {
+        gs->sig[i] = 0;
+        gs->set[i] = 0;
+    }
+}
+
+static void copy_coupling_state(t_state *statea,t_state *stateb,
+                                gmx_ekindata_t *ekinda,gmx_ekindata_t *ekindb, t_grpopts* opts)
+{
+
+    /* MRS note -- might be able to get rid of some of the arguments.  Look over it when it's all debugged */
+
+    int i,j,nc;
+
+    /* Make sure we have enough space for x and v */
+    if (statea->nalloc > stateb->nalloc)
+    {
+        stateb->nalloc = statea->nalloc;
+        srenew(stateb->x,stateb->nalloc);
+        srenew(stateb->v,stateb->nalloc);
+    }
+
+    stateb->natoms     = statea->natoms;
+    stateb->ngtc       = statea->ngtc;
+    stateb->nnhpres    = statea->nnhpres;
+    stateb->veta       = statea->veta;
+    if (ekinda)
+    {
+        copy_mat(ekinda->ekin,ekindb->ekin);
+        for (i=0; i<stateb->ngtc; i++)
+        {
+            ekindb->tcstat[i].T = ekinda->tcstat[i].T;
+            ekindb->tcstat[i].Th = ekinda->tcstat[i].Th;
+            copy_mat(ekinda->tcstat[i].ekinh,ekindb->tcstat[i].ekinh);
+            copy_mat(ekinda->tcstat[i].ekinf,ekindb->tcstat[i].ekinf);
+            ekindb->tcstat[i].ekinscalef_nhc =  ekinda->tcstat[i].ekinscalef_nhc;
+            ekindb->tcstat[i].ekinscaleh_nhc =  ekinda->tcstat[i].ekinscaleh_nhc;
+            ekindb->tcstat[i].vscale_nhc =  ekinda->tcstat[i].vscale_nhc;
+        }
+    }
+    copy_rvecn(statea->x,stateb->x,0,stateb->natoms);
+    copy_rvecn(statea->v,stateb->v,0,stateb->natoms);
+    copy_mat(statea->box,stateb->box);
+    copy_mat(statea->box_rel,stateb->box_rel);
+    copy_mat(statea->boxv,stateb->boxv);
+
+    for (i = 0; i<stateb->ngtc; i++)
+    {
+        nc = i*opts->nhchainlength;
+        for (j=0; j<opts->nhchainlength; j++)
+        {
+            stateb->nosehoover_xi[nc+j]  = statea->nosehoover_xi[nc+j];
+            stateb->nosehoover_vxi[nc+j] = statea->nosehoover_vxi[nc+j];
+        }
+    }
+    if (stateb->nhpres_xi != NULL)
+    {
+        for (i = 0; i<stateb->nnhpres; i++)
+        {
+            nc = i*opts->nhchainlength;
+            for (j=0; j<opts->nhchainlength; j++)
+            {
+                stateb->nhpres_xi[nc+j]  = statea->nhpres_xi[nc+j];
+                stateb->nhpres_vxi[nc+j] = statea->nhpres_vxi[nc+j];
+            }
+        }
+    }
+}
+
+static void compute_globals(FILE *fplog, gmx_global_stat_t gstat, t_commrec *cr, t_inputrec *ir,
+                            t_forcerec *fr, gmx_ekindata_t *ekind,
+                            t_state *state, t_state *state_global, t_mdatoms *mdatoms,
+                            t_nrnb *nrnb, t_vcm *vcm, gmx_wallcycle_t wcycle,
+                            gmx_enerdata_t *enerd,tensor force_vir, tensor shake_vir, tensor total_vir,
+                            tensor pres, rvec mu_tot, gmx_constr_t constr,
+                            globsig_t *gs,bool bInterSimGS,
+                            matrix box, gmx_mtop_t *top_global, real *pcurr,
+                            int natoms, bool *bSumEkinhOld, int flags)
+{
+    int  i,gsi;
+    real gs_buf[eglsNR];
+    tensor corr_vir,corr_pres;
+    bool bEner,bPres,bTemp;
+    bool bRerunMD, bStopCM, bGStat, bNEMD, bIterate,
+        bFirstIterate,bReadEkin,bEkinAveVel,bScaleEkin, bConstrain;
+    real prescorr,enercorr,dvdlcorr;
+
+    /* translate CGLO flags to booleans */
+    bRerunMD = flags & CGLO_RERUNMD;
+    bStopCM = flags & CGLO_STOPCM;
+    bGStat = flags & CGLO_GSTAT;
+    bNEMD = flags & CGLO_NEMD;
+    bReadEkin = flags & CGLO_READEKIN;
+    bScaleEkin = flags & CGLO_SCALEEKIN;
+    bEner = flags & CGLO_ENERGY;
+    bTemp = flags & CGLO_TEMPERATURE;
+    bPres  = flags & CGLO_PRESSURE;
+    bConstrain = flags & CGLO_CONSTRAINT;
+    bIterate = flags & CGLO_ITERATE;
+    bFirstIterate = flags & CGLO_FIRSTITERATE;
+
+    /* we calculate a full state kinetic energy either with full-step velocity verlet
+       or half step where we need the pressure */
+    bEkinAveVel = (ir->eI==eiVV || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir) && bPres) || bReadEkin);
+
+    /* in initalization, it sums the shake virial in vv, and to
+       sums ekinh_old in leapfrog (or if we are calculating ekinh_old for other reasons */
+
+    /* ########## Kinetic energy  ############## */
+
+    if (bTemp)
+    {
+        /* Non-equilibrium MD: this is parallellized, but only does communication
+         * when there really is NEMD.
+         */
+
+        if (PAR(cr) && (bNEMD))
+        {
+            accumulate_u(cr,&(ir->opts),ekind);
+        }
+        debug_gmx();
+        if (bReadEkin)
+        {
+            restore_ekinstate_from_state(cr,ekind,&state_global->ekinstate);
+        }
+        else
+        {
+
+            calc_ke_part(state,&(ir->opts),mdatoms,ekind,nrnb,bEkinAveVel,bIterate);
+        }
+
+        debug_gmx();
+
+        /* Calculate center of mass velocity if necessary, also parallellized */
+        if (bStopCM && !bRerunMD && bEner)
+        {
+            calc_vcm_grp(fplog,mdatoms->start,mdatoms->homenr,mdatoms,
+                         state->x,state->v,vcm);
+        }
+    }
+
+    if (bTemp || bPres || bEner || bConstrain)
+    {
+        if (!bGStat)
+        {
+            /* We will not sum ekinh_old,
+             * so signal that we still have to do it.
+             */
+            *bSumEkinhOld = TRUE;
+
+        }
+        else
+        {
+            if (gs != NULL)
+            {
+                for(i=0; i<eglsNR; i++)
+                {
+                    gs_buf[i] = gs->sig[i];
+                }
+            }
+            if (PAR(cr))
+            {
+                wallcycle_start(wcycle,ewcMoveE);
+                GMX_MPE_LOG(ev_global_stat_start);
+                global_stat(fplog,gstat,cr,enerd,force_vir,shake_vir,mu_tot,
+                            ir,ekind,constr,vcm,
+                            gs != NULL ? eglsNR : 0,gs_buf,
+                            top_global,state,
+                            *bSumEkinhOld,flags);
+                GMX_MPE_LOG(ev_global_stat_finish);
+                wallcycle_stop(wcycle,ewcMoveE);
+            }
+            if (gs != NULL)
+            {
+                if (MULTISIM(cr) && bInterSimGS)
+                {
+                    if (MASTER(cr))
+                    {
+                        /* Communicate the signals between the simulations */
+                        gmx_sum_sim(eglsNR,gs_buf,cr->ms);
+                    }
+                    /* Communicate the signals form the master to the others */
+                    gmx_bcast(eglsNR*sizeof(gs_buf[0]),gs_buf,cr);
+                }
+                for(i=0; i<eglsNR; i++)
+                {
+                    if (bInterSimGS || gs_simlocal[i])
+                    {
+                        /* Set the communicated signal only when it is non-zero,
+                         * since signals might not be processed at each MD step.
+                         */
+                        gsi = (gs_buf[i] >= 0 ?
+                               (int)(gs_buf[i] + 0.5) :
+                               (int)(gs_buf[i] - 0.5));
+                        if (gsi != 0)
+                        {
+                            gs->set[i] = gsi;
+                        }
+                        /* Turn off the local signal */
+                        gs->sig[i] = 0;
+                    }
+                }
+            }
+            *bSumEkinhOld = FALSE;
+        }
+    }
+
+    if (!bNEMD && debug && bTemp && (vcm->nr > 0))
+    {
+        correct_ekin(debug,
+                     mdatoms->start,mdatoms->start+mdatoms->homenr,
+                     state->v,vcm->group_p[0],
+                     mdatoms->massT,mdatoms->tmass,ekind->ekin);
+    }
+
+    if (bEner) {
+        /* Do center of mass motion removal */
+        if (bStopCM && !bRerunMD) /* is this correct?  Does it get called too often with this logic? */
+        {
+            check_cm_grp(fplog,vcm,ir,1);
+            do_stopcm_grp(fplog,mdatoms->start,mdatoms->homenr,mdatoms->cVCM,
+                          state->x,state->v,vcm);
+            inc_nrnb(nrnb,eNR_STOPCM,mdatoms->homenr);
+        }
+    }
+
+    if (bTemp)
+    {
+        /* Sum the kinetic energies of the groups & calc temp */
+        /* compute full step kinetic energies if vv, or if vv-avek and we are computing the pressure with IR_NPT_TROTTER */
+        /* three maincase:  VV with AveVel (md-vv), vv with AveEkin (md-vv-avek), leap with AveEkin (md).
+           Leap with AveVel is also an option for the future but not supported now.
+           bEkinAveVel: If TRUE, we simply multiply ekin by ekinscale to get a full step kinetic energy.
+           If FALSE, we average ekinh_old and ekinh*ekinscale_nhc to get an averaged half step kinetic energy.
+           bSaveEkinOld: If TRUE (in the case of iteration = bIterate is TRUE), we don't reset the ekinscale_nhc.
+           If FALSE, we go ahead and erase over it.
+        */
+        enerd->term[F_TEMP] = sum_ekin(&(ir->opts),ekind,&(enerd->term[F_DKDL]),
+                                       bEkinAveVel,bIterate,bScaleEkin);
+
+        enerd->term[F_EKIN] = trace(ekind->ekin);
+    }
+
+    /* ##########  Long range energy information ###### */
+
+    if (bEner || bPres || bConstrain)
+    {
+        calc_dispcorr(fplog,ir,fr,0,top_global->natoms,box,state->lambda,
+                      corr_pres,corr_vir,&prescorr,&enercorr,&dvdlcorr);
+    }
+
+    if (bEner && bFirstIterate)
+    {
+        enerd->term[F_DISPCORR] = enercorr;
+        enerd->term[F_EPOT] += enercorr;
+        enerd->term[F_DVDL] += dvdlcorr;
+        if (fr->efep != efepNO) {
+            enerd->dvdl_lin += dvdlcorr;
+        }
+    }
+
+    /* ########## Now pressure ############## */
+    if (bPres || bConstrain)
+    {
+
+        m_add(force_vir,shake_vir,total_vir);
+
+        /* Calculate pressure and apply LR correction if PPPM is used.
+         * Use the box from last timestep since we already called update().
+         */
+
+        enerd->term[F_PRES] = calc_pres(fr->ePBC,ir->nwall,box,ekind->ekin,total_vir,pres,
+                                        (fr->eeltype==eelPPPM)?enerd->term[F_COUL_RECIP]:0.0);
+
+        /* Calculate long range corrections to pressure and energy */
+        /* this adds to enerd->term[F_PRES] and enerd->term[F_ETOT],
+           and computes enerd->term[F_DISPCORR].  Also modifies the
+           total_vir and pres tesors */
+
+        m_add(total_vir,corr_vir,total_vir);
+        m_add(pres,corr_pres,pres);
+        enerd->term[F_PDISPCORR] = prescorr;
+        enerd->term[F_PRES] += prescorr;
+        *pcurr = enerd->term[F_PRES];
+        /* calculate temperature using virial */
+        enerd->term[F_VTEMP] = calc_temp(trace(total_vir),ir->opts.nrdf[0]);
+
+    }
+}
+
+
+/* Definitions for convergence of iterated constraints */
+
+/* iterate constraints up to 50 times  */
+#define MAXITERCONST       50
+
+/* data type */
+typedef struct
+{
+    real f,fprev,x,xprev;
+    int iter_i;
+    bool bIterate;
+    real allrelerr[MAXITERCONST+2];
+    int num_close; /* number of "close" violations, caused by limited precision. */
+} gmx_iterate_t;
+
+#ifdef GMX_DOUBLE
+#define CONVERGEITER  0.000000001
+#define CLOSE_ENOUGH  0.000001000
+#else
+#define CONVERGEITER  0.0001
+#define CLOSE_ENOUGH  0.0050
+#endif
+
+/* we want to keep track of the close calls.  If there are too many, there might be some other issues.
+   so we make sure that it's either less than some predetermined number, or if more than that number,
+   only some small fraction of the total. */
+#define MAX_NUMBER_CLOSE        50
+#define FRACTION_CLOSE       0.001
+
+/* maximum length of cyclic traps to check, emerging from limited numerical precision  */
+#define CYCLEMAX            20
+
+static void gmx_iterate_init(gmx_iterate_t *iterate,bool bIterate)
+{
+    int i;
+
+    iterate->iter_i = 0;
+    iterate->bIterate = bIterate;
+    iterate->num_close = 0;
+    for (i=0;i<MAXITERCONST+2;i++)
+    {
+        iterate->allrelerr[i] = 0;
+    }
+}
+
+static bool done_iterating(const t_commrec *cr,FILE *fplog, int nsteps, gmx_iterate_t *iterate, bool bFirstIterate, real fom, real *newf)
+{
+    /* monitor convergence, and use a secant search to propose new
+       values.
+                                                                  x_{i} - x_{i-1}
+       The secant method computes x_{i+1} = x_{i} - f(x_{i}) * ---------------------
+                                                                f(x_{i}) - f(x_{i-1})
+
+       The function we are trying to zero is fom-x, where fom is the
+       "figure of merit" which is the pressure (or the veta value) we
+       would get by putting in an old value of the pressure or veta into
+       the incrementor function for the step or half step.  I have
+       verified that this gives the same answer as self consistent
+       iteration, usually in many fewer steps, especially for small tau_p.
+
+       We could possibly eliminate an iteration with proper use
+       of the value from the previous step, but that would take a bit
+       more bookkeeping, especially for veta, since tests indicate the
+       function of veta on the last step is not sufficiently close to
+       guarantee convergence this step. This is
+       good enough for now.  On my tests, I could use tau_p down to
+       0.02, which is smaller that would ever be necessary in
+       practice. Generally, 3-5 iterations will be sufficient */
+
+    real relerr,err;
+    char buf[256];
+    int i;
+    bool incycle;
+
+    if (bFirstIterate)
+    {
+        iterate->x = fom;
+        iterate->f = fom-iterate->x;
+        iterate->xprev = 0;
+        iterate->fprev = 0;
+        *newf = fom;
+    }
+    else
+    {
+        iterate->f = fom-iterate->x; /* we want to zero this difference */
+        if ((iterate->iter_i > 1) && (iterate->iter_i < MAXITERCONST))
+        {
+            if (iterate->f==iterate->fprev)
+            {
+                *newf = iterate->f;
+            }
+            else
+            {
+                *newf = iterate->x - (iterate->x-iterate->xprev)*(iterate->f)/(iterate->f-iterate->fprev);
+            }
+        }
+        else
+        {
+            /* just use self-consistent iteration the first step to initialize, or
+               if it's not converging (which happens occasionally -- need to investigate why) */
+            *newf = fom;
+        }
+    }
+    /* Consider a slight shortcut allowing us to exit one sooner -- we check the
+       difference between the closest of x and xprev to the new
+       value. To be 100% certain, we should check the difference between
+       the last result, and the previous result, or
+
+       relerr = (fabs((x-xprev)/fom));
+
+       but this is pretty much never necessary under typical conditions.
+       Checking numerically, it seems to lead to almost exactly the same
+       trajectories, but there are small differences out a few decimal
+       places in the pressure, and eventually in the v_eta, but it could
+       save an interation.
+
+       if (fabs(*newf-x) < fabs(*newf - xprev)) { xmin = x;} else { xmin = xprev;}
+       relerr = (fabs((*newf-xmin) / *newf));
+    */
+
+    err = fabs((iterate->f-iterate->fprev));
+    relerr = fabs(err/fom);
+
+    iterate->allrelerr[iterate->iter_i] = relerr;
+
+    if (iterate->iter_i > 0)
+    {
+        if (debug)
+        {
+            fprintf(debug,"Iterating NPT constraints: %6i %20.12f%14.6g%20.12f\n",
+                    iterate->iter_i,fom,relerr,*newf);
+        }
+
+        if ((relerr < CONVERGEITER) || (err < CONVERGEITER) || (fom==0) || ((iterate->x == iterate->xprev) && iterate->iter_i > 1))
+        {
+            iterate->bIterate = FALSE;
+            if (debug)
+            {
+                fprintf(debug,"Iterating NPT constraints: CONVERGED\n");
+            }
+            return TRUE;
+        }
+        if (iterate->iter_i > MAXITERCONST)
+        {
+            if (relerr < CLOSE_ENOUGH)
+            {
+                incycle = FALSE;
+                for (i=1;i<CYCLEMAX;i++) {
+                    if ((iterate->allrelerr[iterate->iter_i-(1+i)] == iterate->allrelerr[iterate->iter_i-1]) &&
+                        (iterate->allrelerr[iterate->iter_i-(1+i)] == iterate->allrelerr[iterate->iter_i-(1+2*i)])) {
+                        incycle = TRUE;
+                        if (debug)
+                        {
+                            fprintf(debug,"Exiting from an NPT iterating cycle of length %d\n",i);
+                        }
+                        break;
+                    }
+                }
+
+                if (incycle) {
+                    /* step 1: trapped in a numerical attractor */
+                    /* we are trapped in a numerical attractor, and can't converge any more, and are close to the final result.
+                       Better to give up convergence here than have the simulation die.
+                    */
+                    iterate->num_close++;
+                    return TRUE;
+                }
+                else
+                {
+                    /* Step #2: test if we are reasonably close for other reasons, then monitor the number.  If not, die */
+
+                    /* how many close calls have we had?  If less than a few, we're OK */
+                    if (iterate->num_close < MAX_NUMBER_CLOSE)
+                    {
+                        sprintf(buf,"Slight numerical convergence deviation with NPT at step %d, relative error only %10.5g, likely not a problem, continuing\n",nsteps,relerr);
+                        md_print_warning(cr,fplog,buf);
+                        iterate->num_close++;
+                        return TRUE;
+                        /* if more than a few, check the total fraction.  If too high, die. */
+                    } else if (iterate->num_close/(double)nsteps > FRACTION_CLOSE) {
+                        gmx_fatal(FARGS,"Could not converge NPT constraints, too many exceptions (%d%%\n",iterate->num_close/(double)nsteps);
+                    }
+                }
+            }
+            else
+            {
+                gmx_fatal(FARGS,"Could not converge NPT constraints\n");
+            }
+        }
+    }
+
+    iterate->xprev = iterate->x;
+    iterate->x = *newf;
+    iterate->fprev = iterate->f;
+    iterate->iter_i++;
+
+    return FALSE;
+}
+
+static void check_nst_param(FILE *fplog,t_commrec *cr,
+                            const char *desc_nst,int nst,
+                            const char *desc_p,int *p)
+{
+    char buf[STRLEN];
+
+    if (*p > 0 && *p % nst != 0)
+    {
+        /* Round up to the next multiple of nst */
+        *p = ((*p)/nst + 1)*nst;
+        sprintf(buf,"NOTE: %s changes %s to %d\n",desc_nst,desc_p,*p);
+        md_print_warning(cr,fplog,buf);
+    }
+}
+
+static void reset_all_counters(FILE *fplog,t_commrec *cr,
+                               gmx_large_int_t step,
+                               gmx_large_int_t *step_rel,t_inputrec *ir,
+                               gmx_wallcycle_t wcycle,t_nrnb *nrnb,
+                               gmx_runtime_t *runtime)
+{
+    char buf[STRLEN],sbuf[STEPSTRSIZE];
+
+    /* Reset all the counters related to performance over the run */
+    sprintf(buf,"Step %s: resetting all time and cycle counters\n",
+            gmx_step_str(step,sbuf));
+    md_print_warning(cr,fplog,buf);
+
+    wallcycle_stop(wcycle,ewcRUN);
+    wallcycle_reset_all(wcycle);
+    if (DOMAINDECOMP(cr))
+    {
+        reset_dd_statistics_counters(cr->dd);
+    }
+    init_nrnb(nrnb);
+    ir->init_step += *step_rel;
+    ir->nsteps    -= *step_rel;
+    *step_rel = 0;
+    wallcycle_start(wcycle,ewcRUN);
+    runtime_start(runtime);
+    print_date_and_time(fplog,cr->nodeid,"Restarted time",runtime);
+}
+
+static int check_nstglobalcomm(FILE *fplog,t_commrec *cr,
+                               int nstglobalcomm,t_inputrec *ir)
+{
+    char buf[STRLEN];
+
+    if (!EI_DYNAMICS(ir->eI))
+    {
+        nstglobalcomm = 1;
+    }
+
+    if (nstglobalcomm == -1)
+    {
+        if (ir->nstcalcenergy == 0 && ir->nstlist == 0)
+        {
+            nstglobalcomm = 10;
+            if (ir->nstenergy > 0 && ir->nstenergy < nstglobalcomm)
+            {
+                nstglobalcomm = ir->nstenergy;
+            }
+        }
+        else
+        {
+            /* We assume that if nstcalcenergy > nstlist,
+             * nstcalcenergy is a multiple of nstlist.
+             */
+            if (ir->nstcalcenergy == 0 ||
+                (ir->nstlist > 0 && ir->nstlist < ir->nstcalcenergy))
+            {
+                nstglobalcomm = ir->nstlist;
+            }
+            else
+            {
+                nstglobalcomm = ir->nstcalcenergy;
+            }
+        }
+    }
+    else
+    {
+        if (ir->nstlist > 0 &&
+            nstglobalcomm > ir->nstlist && nstglobalcomm % ir->nstlist != 0)
+        {
+            nstglobalcomm = (nstglobalcomm / ir->nstlist)*ir->nstlist;
+            sprintf(buf,"WARNING: nstglobalcomm is larger than nstlist, but not a multiple, setting it to %d\n",nstglobalcomm);
+            md_print_warning(cr,fplog,buf);
+        }
+        if (nstglobalcomm > ir->nstcalcenergy)
+        {
+            check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
+                            "nstcalcenergy",&ir->nstcalcenergy);
+        }
+
+        check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
+                        "nstenergy",&ir->nstenergy);
+
+        check_nst_param(fplog,cr,"-gcom",nstglobalcomm,
+                        "nstlog",&ir->nstlog);
+    }
+
+    if (ir->comm_mode != ecmNO && ir->nstcomm < nstglobalcomm)
+    {
+        sprintf(buf,"WARNING: Changing nstcomm from %d to %d\n",
+                ir->nstcomm,nstglobalcomm);
+        md_print_warning(cr,fplog,buf);
+        ir->nstcomm = nstglobalcomm;
+    }
+
+    return nstglobalcomm;
+}
+
+void check_ir_old_tpx_versions(t_commrec *cr,FILE *fplog,
+                               t_inputrec *ir,gmx_mtop_t *mtop)
+{
+    /* Check required for old tpx files */
+    if (IR_TWINRANGE(*ir) && ir->nstlist > 1 &&
+        ir->nstcalcenergy % ir->nstlist != 0)
+    {
+        md_print_warning(cr,fplog,"Old tpr file with twin-range settings: modifying energy calculation and/or T/P-coupling frequencies");
+
+        if (gmx_mtop_ftype_count(mtop,F_CONSTR) +
+            gmx_mtop_ftype_count(mtop,F_CONSTRNC) > 0 &&
+            ir->eConstrAlg == econtSHAKE)
+        {
+            md_print_warning(cr,fplog,"With twin-range cut-off's and SHAKE the virial and pressure are incorrect");
+            if (ir->epc != epcNO)
+            {
+                gmx_fatal(FARGS,"Can not do pressure coupling with twin-range cut-off's and SHAKE");
+            }
+        }
+        check_nst_param(fplog,cr,"nstlist",ir->nstlist,
+                        "nstcalcenergy",&ir->nstcalcenergy);
+       check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+                       "nstenergy",&ir->nstenergy);
+        check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+                        "nstlog",&ir->nstlog);
+        if (ir->efep != efepNO)
+        {
+            check_nst_param(fplog,cr,"nstcalcenergy",ir->nstcalcenergy,
+                            "nstdhdl",&ir->nstdhdl);
+        }
+    }
+}
+
+typedef struct {
+    bool       bGStatEveryStep;
+    gmx_large_int_t step_ns;
+    gmx_large_int_t step_nscheck;
+    gmx_large_int_t nns;
+    matrix     scale_tot;
+    int        nabnsb;
+    double     s1;
+    double     s2;
+    double     ab;
+    double     lt_runav;
+    double     lt_runav2;
+} gmx_nlheur_t;
+
+static void reset_nlistheuristics(gmx_nlheur_t *nlh,gmx_large_int_t step)
+{
+    nlh->lt_runav  = 0;
+    nlh->lt_runav2 = 0;
+    nlh->step_nscheck = step;
+}
+
+static void init_nlistheuristics(gmx_nlheur_t *nlh,
+                                 bool bGStatEveryStep,gmx_large_int_t step)
+{
+    nlh->bGStatEveryStep = bGStatEveryStep;
+    nlh->nns       = 0;
+    nlh->nabnsb    = 0;
+    nlh->s1        = 0;
+    nlh->s2        = 0;
+    nlh->ab        = 0;
+
+    reset_nlistheuristics(nlh,step);
+}
+
+static void update_nliststatistics(gmx_nlheur_t *nlh,gmx_large_int_t step)
+{
+    gmx_large_int_t nl_lt;
+    char sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
+
+    /* Determine the neighbor list life time */
+    nl_lt = step - nlh->step_ns;
+    if (debug)
+    {
+        fprintf(debug,"%d atoms beyond ns buffer, updating neighbor list after %s steps\n",nlh->nabnsb,gmx_step_str(nl_lt,sbuf));
+    }
+    nlh->nns++;
+    nlh->s1 += nl_lt;
+    nlh->s2 += nl_lt*nl_lt;
+    nlh->ab += nlh->nabnsb;
+    if (nlh->lt_runav == 0)
+    {
+        nlh->lt_runav  = nl_lt;
+        /* Initialize the fluctuation average
+         * such that at startup we check after 0 steps.
+         */
+        nlh->lt_runav2 = sqr(nl_lt/2.0);
+    }
+    /* Running average with 0.9 gives an exp. history of 9.5 */
+    nlh->lt_runav2 = 0.9*nlh->lt_runav2 + 0.1*sqr(nlh->lt_runav - nl_lt);
+    nlh->lt_runav  = 0.9*nlh->lt_runav  + 0.1*nl_lt;
+    if (nlh->bGStatEveryStep)
+    {
+        /* Always check the nlist validity */
+        nlh->step_nscheck = step;
+    }
+    else
+    {
+        /* We check after:  <life time> - 2*sigma
+         * The factor 2 is quite conservative,
+         * but we assume that with nstlist=-1 the user
+         * prefers exact integration over performance.
+         */
+        nlh->step_nscheck = step
+                  + (int)(nlh->lt_runav - 2.0*sqrt(nlh->lt_runav2)) - 1;
+    }
+    if (debug)
+    {
+        fprintf(debug,"nlist life time %s run av. %4.1f sig %3.1f check %s check with -gcom %d\n",
+                gmx_step_str(nl_lt,sbuf),nlh->lt_runav,sqrt(nlh->lt_runav2),
+                gmx_step_str(nlh->step_nscheck-step+1,sbuf2),
+                (int)(nlh->lt_runav - 2.0*sqrt(nlh->lt_runav2)));
+    }
+}
+
+static void set_nlistheuristics(gmx_nlheur_t *nlh,bool bReset,gmx_large_int_t step)
+{
+    int d;
+
+    if (bReset)
+    {
+        reset_nlistheuristics(nlh,step);
+    }
+    else
+    {
+        update_nliststatistics(nlh,step);
+    }
+
+    nlh->step_ns = step;
+    /* Initialize the cumulative coordinate scaling matrix */
+    clear_mat(nlh->scale_tot);
+    for(d=0; d<DIM; d++)
+    {
+        nlh->scale_tot[d][d] = 1.0;
+    }
+}
+
+double do_md_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
+             const output_env_t oenv, bool bVerbose,bool bCompact,
+             int nstglobalcomm,
+             gmx_vsite_t *vsite,gmx_constr_t constr,
+             int stepout,t_inputrec *ir,
+             gmx_mtop_t *top_global,
+             t_fcdata *fcd,
+             t_state *state_global,
+             t_mdatoms *mdatoms,
+             t_nrnb *nrnb,gmx_wallcycle_t wcycle,
+             gmx_edsam_t ed,t_forcerec *fr,
+             int repl_ex_nst,int repl_ex_seed,
+             real cpt_period,real max_hours,
+             const char *deviceOptions,
+             unsigned long Flags,
+             gmx_runtime_t *runtime,
+             rvec fac, rvec *r_ins, pos_ins_t *pos_ins, t_block *ins_at,
+             real xy_step, real z_step, int it_xy, int it_z)
+{
+    gmx_mdoutf_t *outf;
+    gmx_large_int_t step,step_rel;
+    double     run_time;
+    double     t,t0,lam0;
+    bool       bGStatEveryStep,bGStat,bNstEner,bCalcEnerPres;
+    bool       bNS,bNStList,bSimAnn,bStopCM,bRerunMD,bNotLastFrame=FALSE,
+               bFirstStep,bStateFromTPX,bInitStep,bLastStep,
+               bBornRadii,bStartingFromCpt;
+    bool       bDoDHDL=FALSE;
+    bool       bNEMD,do_ene,do_log,do_verbose,bRerunWarnNoV=TRUE,
+               bForceUpdate=FALSE,bCPT;
+    int        mdof_flags;
+    bool       bMasterState;
+    int        force_flags,cglo_flags;
+    tensor     force_vir,shake_vir,total_vir,tmp_vir,pres;
+    int        i,m;
+    t_trxstatus *status;
+    rvec       mu_tot;
+    t_vcm      *vcm;
+    t_state    *bufstate=NULL;
+    matrix     *scale_tot,pcoupl_mu,M,ebox;
+    gmx_nlheur_t nlh;
+    t_trxframe rerun_fr;
+/*    gmx_repl_ex_t repl_ex=NULL;*/
+    int        nchkpt=1;
+
+    gmx_localtop_t *top;
+    t_mdebin *mdebin=NULL;
+    t_state    *state=NULL;
+    rvec       *f_global=NULL;
+    int        n_xtc=-1;
+    rvec       *x_xtc=NULL;
+    gmx_enerdata_t *enerd;
+    rvec       *f=NULL;
+    gmx_global_stat_t gstat;
+    gmx_update_t upd=NULL;
+    t_graph    *graph=NULL;
+    globsig_t   gs;
+
+    bool        bFFscan;
+    gmx_groups_t *groups;
+    gmx_ekindata_t *ekind, *ekind_save;
+    gmx_shellfc_t shellfc;
+    int         count,nconverged=0;
+    real        timestep=0;
+    double      tcount=0;
+    bool        bIonize=FALSE;
+    bool        bTCR=FALSE,bConverged=TRUE,bOK,bSumEkinhOld,bExchanged;
+    bool        bAppend;
+    bool        bResetCountersHalfMaxH=FALSE;
+    bool        bVV,bIterations,bIterate,bFirstIterate,bTemp,bPres,bTrotter;
+    real        temp0,dvdl;
+    int         a0,a1,ii;
+    rvec        *xcopy=NULL,*vcopy=NULL,*cbuf=NULL;
+    matrix      boxcopy={{0}},lastbox;
+       real        veta_save,pcurr,scalevir,tracevir;
+       real        vetanew = 0;
+    double      cycles;
+       real        last_conserved = 0;
+    real        last_ekin = 0;
+       t_extmass   MassQ;
+    int         **trotter_seq;
+    char        sbuf[STEPSTRSIZE],sbuf2[STEPSTRSIZE];
+    int         handled_stop_condition=gmx_stop_cond_none; /* compare to get_stop_condition*/
+    gmx_iterate_t iterate;
+#ifdef GMX_FAHCORE
+    /* Temporary addition for FAHCORE checkpointing */
+    int chkpt_ret;
+#endif
+
+    /* Check for special mdrun options */
+    bRerunMD = (Flags & MD_RERUN);
+    bIonize  = (Flags & MD_IONIZE);
+    bFFscan  = (Flags & MD_FFSCAN);
+    bAppend  = (Flags & MD_APPENDFILES);
+    bGStatEveryStep = FALSE;
+    if (Flags & MD_RESETCOUNTERSHALFWAY)
+    {
+        if (ir->nsteps > 0)
+        {
+            /* Signal to reset the counters half the simulation steps. */
+            wcycle_set_reset_counters(wcycle,ir->nsteps/2);
+        }
+        /* Signal to reset the counters halfway the simulation time. */
+        bResetCountersHalfMaxH = (max_hours > 0);
+    }
+
+    /* md-vv uses averaged full step velocities for T-control
+       md-vv-avek uses averaged half step velocities for T-control (but full step ekin for P control)
+       md uses averaged half step kinetic energies to determine temperature unless defined otherwise by GMX_EKIN_AVE_VEL; */
+    bVV = EI_VV(ir->eI);
+    if (bVV) /* to store the initial velocities while computing virial */
+    {
+        snew(cbuf,top_global->natoms);
+    }
+    /* all the iteratative cases - only if there are constraints */
+    bIterations = ((IR_NPT_TROTTER(ir)) && (constr) && (!bRerunMD));
+    bTrotter = (bVV && (IR_NPT_TROTTER(ir) || (IR_NVT_TROTTER(ir))));
+
+    if (bRerunMD)
+    {
+        /* Since we don't know if the frames read are related in any way,
+         * rebuild the neighborlist at every step.
+         */
+        ir->nstlist       = 1;
+        ir->nstcalcenergy = 1;
+        nstglobalcomm     = 1;
+    }
+
+    check_ir_old_tpx_versions(cr,fplog,ir,top_global);
+
+    nstglobalcomm = check_nstglobalcomm(fplog,cr,nstglobalcomm,ir);
+    /*bGStatEveryStep = (nstglobalcomm == 1);*/
+    bGStatEveryStep = FALSE;
+
+    if (!bGStatEveryStep && ir->nstlist == -1 && fplog != NULL)
+    {
+        fprintf(fplog,
+                "To reduce the energy communication with nstlist = -1\n"
+                "the neighbor list validity should not be checked at every step,\n"
+                "this means that exact integration is not guaranteed.\n"
+                "The neighbor list validity is checked after:\n"
+                "  <n.list life time> - 2*std.dev.(n.list life time)  steps.\n"
+                "In most cases this will result in exact integration.\n"
+                "This reduces the energy communication by a factor of 2 to 3.\n"
+                "If you want less energy communication, set nstlist > 3.\n\n");
+    }
+
+    if (bRerunMD || bFFscan)
+    {
+        ir->nstxtcout = 0;
+    }
+    groups = &top_global->groups;
+
+    /* Initial values */
+    init_md(fplog,cr,ir,oenv,&t,&t0,&state_global->lambda,&lam0,
+            nrnb,top_global,&upd,
+            nfile,fnm,&outf,&mdebin,
+            force_vir,shake_vir,mu_tot,&bNEMD,&bSimAnn,&vcm,state_global,Flags);
+
+    clear_mat(total_vir);
+    clear_mat(pres);
+    /* Energy terms and groups */
+    snew(enerd,1);
+    init_enerdata(top_global->groups.grps[egcENER].nr,ir->n_flambda,enerd);
+    if (DOMAINDECOMP(cr))
+    {
+        f = NULL;
+    }
+    else
+    {
+        snew(f,top_global->natoms);
+    }
+
+    /* Kinetic energy data */
+    snew(ekind,1);
+    init_ekindata(fplog,top_global,&(ir->opts),ekind);
+    /* needed for iteration of constraints */
+    snew(ekind_save,1);
+    init_ekindata(fplog,top_global,&(ir->opts),ekind_save);
+    /* Copy the cos acceleration to the groups struct */
+    ekind->cosacc.cos_accel = ir->cos_accel;
+
+    gstat = global_stat_init(ir);
+    debug_gmx();
+
+    /* Check for polarizable models and flexible constraints */
+    shellfc = init_shell_flexcon(fplog,
+                                 top_global,n_flexible_constraints(constr),
+                                 (ir->bContinuation ||
+                                  (DOMAINDECOMP(cr) && !MASTER(cr))) ?
+                                 NULL : state_global->x);
+
+/*    if (DEFORM(*ir))
+    {
+#ifdef GMX_THREADS
+        tMPI_Thread_mutex_lock(&deform_init_box_mutex);
+#endif
+        set_deform_reference_box(upd,
+                                 deform_init_init_step_tpx,
+                                 deform_init_box_tpx);
+#ifdef GMX_THREADS
+        tMPI_Thread_mutex_unlock(&deform_init_box_mutex);
+#endif
+    }*/
+
+/*    {
+        double io = compute_io(ir,top_global->natoms,groups,mdebin->ebin->nener,1);
+        if ((io > 2000) && MASTER(cr))
+            fprintf(stderr,
+                    "\nWARNING: This run will generate roughly %.0f Mb of data\n\n",
+                    io);
+    }*/
+
+    if (DOMAINDECOMP(cr)) {
+        top = dd_init_local_top(top_global);
+
+        snew(state,1);
+        dd_init_local_state(cr->dd,state_global,state);
+
+        if (DDMASTER(cr->dd) && ir->nstfout) {
+            snew(f_global,state_global->natoms);
+        }
+    } else {
+        if (PAR(cr)) {
+            /* Initialize the particle decomposition and split the topology */
+            top = split_system(fplog,top_global,ir,cr);
+
+            pd_cg_range(cr,&fr->cg0,&fr->hcg);
+            pd_at_range(cr,&a0,&a1);
+        } else {
+            top = gmx_mtop_generate_local_top(top_global,ir);
+
+            a0 = 0;
+            a1 = top_global->natoms;
+        }
+
+        state = partdec_init_local_state(cr,state_global);
+        f_global = f;
+
+        atoms2md(top_global,ir,0,NULL,a0,a1-a0,mdatoms);
+
+        if (vsite) {
+            set_vsite_top(vsite,top,mdatoms,cr);
+        }
+
+        if (ir->ePBC != epbcNONE && !ir->bPeriodicMols) {
+            graph = mk_graph(fplog,&(top->idef),0,top_global->natoms,FALSE,FALSE);
+        }
+
+        if (shellfc) {
+            make_local_shells(cr,mdatoms,shellfc);
+        }
+
+        if (ir->pull && PAR(cr)) {
+            dd_make_local_pull_groups(NULL,ir->pull,mdatoms);
+        }
+    }
+
+    if (DOMAINDECOMP(cr))
+    {
+        /* Distribute the charge groups over the nodes from the master node */
+        dd_partition_system(fplog,ir->init_step,cr,TRUE,1,
+                            state_global,top_global,ir,
+                            state,&f,mdatoms,top,fr,
+                            vsite,shellfc,constr,
+                            nrnb,wcycle,FALSE);
+    }
+
+    update_mdatoms(mdatoms,state->lambda);
+
+    if (MASTER(cr))
+    {
+        /* Update mdebin with energy history if appending to output files */
+        if ( Flags & MD_APPENDFILES )
+        {
+            restore_energyhistory_from_state(mdebin,&state_global->enerhist);
+        }
+        /* Set the initial energy history in state to zero by updating once */
+        update_energyhistory(&state_global->enerhist,mdebin);
+    }
+
+    if ((state->flags & (1<<estLD_RNG)) && (Flags & MD_READ_RNG)) {
+        /* Set the random state if we read a checkpoint file */
+        set_stochd_state(upd,state);
+    }
+
+    /* Initialize constraints */
+    if (constr) {
+        if (!DOMAINDECOMP(cr))
+            set_constraints(constr,top,ir,mdatoms,cr);
+    }
+
+    /* Check whether we have to GCT stuff */
+ /*   bTCR = ftp2bSet(efGCT,nfile,fnm);
+    if (bTCR) {
+        if (MASTER(cr)) {
+            fprintf(stderr,"Will do General Coupling Theory!\n");
+        }
+        gnx = top_global->mols.nr;
+        snew(grpindex,gnx);
+        for(i=0; (i<gnx); i++) {
+            grpindex[i] = i;
+        }
+    }*/
+
+/*    if (repl_ex_nst > 0 && MASTER(cr))
+        repl_ex = init_replica_exchange(fplog,cr->ms,state_global,ir,
+                                        repl_ex_nst,repl_ex_seed);*/
+
+    if (!ir->bContinuation && !bRerunMD)
+    {
+        if (mdatoms->cFREEZE && (state->flags & (1<<estV)))
+        {
+            /* Set the velocities of frozen particles to zero */
+            for(i=mdatoms->start; i<mdatoms->start+mdatoms->homenr; i++)
+            {
+                for(m=0; m<DIM; m++)
+                {
+                    if (ir->opts.nFreeze[mdatoms->cFREEZE[i]][m])
+                    {
+                        state->v[i][m] = 0;
+                    }
+                }
+            }
+        }
+
+        if (constr)
+        {
+            /* Constrain the initial coordinates and velocities */
+            do_constrain_first(fplog,constr,ir,mdatoms,state,f,
+                               graph,cr,nrnb,fr,top,shake_vir);
+        }
+        if (vsite)
+        {
+            /* Construct the virtual sites for the initial configuration */
+            construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,NULL,
+                             top->idef.iparams,top->idef.il,
+                             fr->ePBC,fr->bMolPBC,graph,cr,state->box);
+        }
+    }
+
+    debug_gmx();
+
+    /* I'm assuming we need global communication the first time! MRS */
+    cglo_flags = (CGLO_TEMPERATURE | CGLO_GSTAT
+                  | (bVV ? CGLO_PRESSURE:0)
+                  | (bVV ? CGLO_CONSTRAINT:0)
+                  | (bRerunMD ? CGLO_RERUNMD:0)
+                  | ((Flags & MD_READ_EKIN) ? CGLO_READEKIN:0));
+
+    bSumEkinhOld = FALSE;
+    compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                    wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+                    constr,NULL,FALSE,state->box,
+                    top_global,&pcurr,top_global->natoms,&bSumEkinhOld,cglo_flags);
+    if (ir->eI == eiVVAK) {
+        /* a second call to get the half step temperature initialized as well */
+        /* we do the same call as above, but turn the pressure off -- internally, this
+           is recognized as a velocity verlet half-step kinetic energy calculation.
+           This minimized excess variables, but perhaps loses some logic?*/
+
+        compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                        wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+                        constr,NULL,FALSE,state->box,
+                        top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+                        cglo_flags &~ CGLO_PRESSURE);
+    }
+
+    /* Calculate the initial half step temperature, and save the ekinh_old */
+    if (!(Flags & MD_STARTFROMCPT))
+    {
+        for(i=0; (i<ir->opts.ngtc); i++)
+        {
+            copy_mat(ekind->tcstat[i].ekinh,ekind->tcstat[i].ekinh_old);
+        }
+    }
+    temp0 = enerd->term[F_TEMP];
+
+    /* if using an iterative algorithm, we need to create a working directory for the state. */
+    if (bIterations)
+    {
+            bufstate = init_bufstate(state);
+    }
+    if (bFFscan)
+    {
+        snew(xcopy,state->natoms);
+        snew(vcopy,state->natoms);
+        copy_rvecn(state->x,xcopy,0,state->natoms);
+        copy_rvecn(state->v,vcopy,0,state->natoms);
+        copy_mat(state->box,boxcopy);
+    }
+
+    /* need to make an initiation call to get the Trotter variables set, as well as other constants for non-trotter
+       temperature control */
+    trotter_seq = init_npt_vars(ir,state,&MassQ,bTrotter);
+
+    if (MASTER(cr))
+    {
+        if (constr && !ir->bContinuation && ir->eConstrAlg == econtLINCS)
+        {
+            fprintf(fplog,
+                    "RMS relative constraint deviation after constraining: %.2e\n",
+                    constr_rmsd(constr,FALSE));
+        }
+        if (bVV)
+        {
+            enerd->term[F_TEMP] *= 2; /* result of averages being done over previous and current step,
+                                         and there is no previous step */
+        }
+        fprintf(fplog,"Initial temperature: %g K\n",enerd->term[F_TEMP]);
+        if (bRerunMD)
+        {
+            fprintf(stderr,"starting md rerun '%s', reading coordinates from"
+                    " input trajectory '%s'\n\n",
+                    *(top_global->name),opt2fn("-rerun",nfile,fnm));
+            if (bVerbose)
+            {
+                fprintf(stderr,"Calculated time to finish depends on nsteps from "
+                        "run input file,\nwhich may not correspond to the time "
+                        "needed to process input trajectory.\n\n");
+            }
+        }
+        else
+        {
+            char tbuf[20];
+            fprintf(stderr,"starting mdrun '%s'\n",
+                    *(top_global->name));
+            if (ir->nsteps >= 0)
+            {
+                sprintf(tbuf,"%8.1f",(ir->init_step+ir->nsteps)*ir->delta_t);
+            }
+            else
+            {
+                sprintf(tbuf,"%s","infinite");
+            }
+            if (ir->init_step > 0)
+            {
+                fprintf(stderr,"%s steps, %s ps (continuing from step %s, %8.1f ps).\n",
+                        gmx_step_str(ir->init_step+ir->nsteps,sbuf),tbuf,
+                        gmx_step_str(ir->init_step,sbuf2),
+                        ir->init_step*ir->delta_t);
+            }
+            else
+            {
+                fprintf(stderr,"%s steps, %s ps.\n",
+                        gmx_step_str(ir->nsteps,sbuf),tbuf);
+            }
+        }
+        fprintf(fplog,"\n");
+    }
+
+    /* Set and write start time */
+    runtime_start(runtime);
+    print_date_and_time(fplog,cr->nodeid,"Started mdrun",runtime);
+    wallcycle_start(wcycle,ewcRUN);
+    if (fplog)
+        fprintf(fplog,"\n");
+
+    /* safest point to do file checkpointing is here.  More general point would be immediately before integrator call */
+/*#ifdef GMX_FAHCORE
+    chkpt_ret=fcCheckPointParallel( cr->nodeid,
+                                    NULL,0);
+    if ( chkpt_ret == 0 )
+        gmx_fatal( 3,__FILE__,__LINE__, "Checkpoint error on step %d\n", 0 );
+#endif*/
+
+    debug_gmx();
+    /***********************************************************
+     *
+     *             Loop over MD steps
+     *
+     ************************************************************/
+
+    /* if rerunMD then read coordinates and velocities from input trajectory */
+    if (bRerunMD)
+    {
+        if (getenv("GMX_FORCE_UPDATE"))
+        {
+            bForceUpdate = TRUE;
+        }
+
+        bNotLastFrame = read_first_frame(oenv,&status,
+                                         opt2fn("-rerun",nfile,fnm),
+                                         &rerun_fr,TRX_NEED_X | TRX_READ_V);
+        if (rerun_fr.natoms != top_global->natoms)
+        {
+            gmx_fatal(FARGS,
+                      "Number of atoms in trajectory (%d) does not match the "
+                      "run input file (%d)\n",
+                      rerun_fr.natoms,top_global->natoms);
+        }
+        if (ir->ePBC != epbcNONE)
+        {
+            if (!rerun_fr.bBox)
+            {
+                gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f does not contain a box, while pbc is used",rerun_fr.step,rerun_fr.time);
+            }
+            if (max_cutoff2(ir->ePBC,rerun_fr.box) < sqr(fr->rlistlong))
+            {
+                gmx_fatal(FARGS,"Rerun trajectory frame step %d time %f has too small box dimensions",rerun_fr.step,rerun_fr.time);
+            }
+
+            /* Set the shift vectors.
+             * Necessary here when have a static box different from the tpr box.
+             */
+            calc_shifts(rerun_fr.box,fr->shift_vec);
+        }
+    }
+
+    /* loop over MD steps or if rerunMD to end of input trajectory */
+    bFirstStep = TRUE;
+    /* Skip the first Nose-Hoover integration when we get the state from tpx */
+    bStateFromTPX = !opt2bSet("-cpi",nfile,fnm);
+    bInitStep = bFirstStep && (bStateFromTPX || bVV);
+    bStartingFromCpt = (Flags & MD_STARTFROMCPT) && bInitStep;
+    bLastStep    = FALSE;
+    bSumEkinhOld = FALSE;
+    bExchanged   = FALSE;
+
+    init_global_signals(&gs,cr,ir,repl_ex_nst);
+
+    step = ir->init_step;
+    step_rel = 0;
+
+    if (ir->nstlist == -1)
+    {
+        init_nlistheuristics(&nlh,bGStatEveryStep,step);
+    }
+
+    bLastStep = (bRerunMD || (ir->nsteps >= 0 && step_rel > ir->nsteps));
+    while (!bLastStep || (bRerunMD && bNotLastFrame)) {
+
+        wallcycle_start(wcycle,ewcSTEP);
+
+        GMX_MPE_LOG(ev_timestep1);
+
+        if (bRerunMD) {
+            if (rerun_fr.bStep) {
+                step = rerun_fr.step;
+                step_rel = step - ir->init_step;
+            }
+            if (rerun_fr.bTime) {
+                t = rerun_fr.time;
+            }
+            else
+            {
+                t = step;
+            }
+        }
+        else
+        {
+            bLastStep = (step_rel == ir->nsteps);
+            t = t0 + step*ir->delta_t;
+        }
+
+        if (ir->efep != efepNO)
+        {
+            if (bRerunMD && rerun_fr.bLambda && (ir->delta_lambda!=0))
+            {
+                state_global->lambda = rerun_fr.lambda;
+            }
+            else
+            {
+                state_global->lambda = lam0 + step*ir->delta_lambda;
+            }
+            state->lambda = state_global->lambda;
+            bDoDHDL = do_per_step(step,ir->nstdhdl);
+        }
+
+        if (bSimAnn)
+        {
+            update_annealing_target_temp(&(ir->opts),t);
+        }
+
+        if (bRerunMD)
+        {
+            if (!(DOMAINDECOMP(cr) && !MASTER(cr)))
+            {
+                for(i=0; i<state_global->natoms; i++)
+                {
+                    copy_rvec(rerun_fr.x[i],state_global->x[i]);
+                }
+                if (rerun_fr.bV)
+                {
+                    for(i=0; i<state_global->natoms; i++)
+                    {
+                        copy_rvec(rerun_fr.v[i],state_global->v[i]);
+                    }
+                }
+                else
+                {
+                    for(i=0; i<state_global->natoms; i++)
+                    {
+                        clear_rvec(state_global->v[i]);
+                    }
+                    if (bRerunWarnNoV)
+                    {
+                        fprintf(stderr,"\nWARNING: Some frames do not contain velocities.\n"
+                                "         Ekin, temperature and pressure are incorrect,\n"
+                                "         the virial will be incorrect when constraints are present.\n"
+                                "\n");
+                        bRerunWarnNoV = FALSE;
+                    }
+                }
+            }
+            copy_mat(rerun_fr.box,state_global->box);
+            copy_mat(state_global->box,state->box);
+
+            if (vsite && (Flags & MD_RERUN_VSITE))
+            {
+                if (DOMAINDECOMP(cr))
+                {
+                    gmx_fatal(FARGS,"Vsite recalculation with -rerun is not implemented for domain decomposition, use particle decomposition");
+                }
+                if (graph)
+                {
+                    /* Following is necessary because the graph may get out of sync
+                     * with the coordinates if we only have every N'th coordinate set
+                     */
+                    mk_mshift(fplog,graph,fr->ePBC,state->box,state->x);
+                    shift_self(graph,state->box,state->x);
+                }
+                construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,state->v,
+                                 top->idef.iparams,top->idef.il,
+                                 fr->ePBC,fr->bMolPBC,graph,cr,state->box);
+                if (graph)
+                {
+                    unshift_self(graph,state->box,state->x);
+                }
+            }
+        }
+
+        /* Stop Center of Mass motion */
+        bStopCM = (ir->comm_mode != ecmNO && do_per_step(step,ir->nstcomm));
+
+        /* Copy back starting coordinates in case we're doing a forcefield scan */
+        if (bFFscan)
+        {
+            for(ii=0; (ii<state->natoms); ii++)
+            {
+                copy_rvec(xcopy[ii],state->x[ii]);
+                copy_rvec(vcopy[ii],state->v[ii]);
+            }
+            copy_mat(boxcopy,state->box);
+        }
+
+        if (bRerunMD)
+        {
+            /* for rerun MD always do Neighbour Searching */
+            bNS = (bFirstStep || ir->nstlist != 0);
+            bNStList = bNS;
+        }
+        else
+        {
+            /* Determine whether or not to do Neighbour Searching and LR */
+            bNStList = (ir->nstlist > 0  && step % ir->nstlist == 0);
+
+            bNS = (bFirstStep || bExchanged || bNStList ||
+                   (ir->nstlist == -1 && nlh.nabnsb > 0));
+
+            if (bNS && ir->nstlist == -1)
+            {
+                set_nlistheuristics(&nlh,bFirstStep || bExchanged,step);
+            }
+        }
+
+        /* < 0 means stop at next step, > 0 means stop at next NS step */
+        if ( (gs.set[eglsSTOPCOND] < 0 ) ||
+             ( (gs.set[eglsSTOPCOND] > 0 ) && ( bNS || ir->nstlist==0)) )
+        {
+            bLastStep = TRUE;
+        }
+
+        /* Determine whether or not to update the Born radii if doing GB */
+        bBornRadii=bFirstStep;
+        if (ir->implicit_solvent && (step % ir->nstgbradii==0))
+        {
+            bBornRadii=TRUE;
+        }
+
+        do_log = do_per_step(step,ir->nstlog) || bFirstStep || bLastStep;
+        do_verbose = bVerbose &&
+                  (step % stepout == 0 || bFirstStep || bLastStep);
+
+        if (bNS && !(bFirstStep && ir->bContinuation && !bRerunMD))
+        {
+            if (bRerunMD)
+            {
+                bMasterState = TRUE;
+            }
+            else
+            {
+                bMasterState = FALSE;
+                /* Correct the new box if it is too skewed */
+                if (DYNAMIC_BOX(*ir))
+                {
+                    if (correct_box(fplog,step,state->box,graph))
+                    {
+                        bMasterState = TRUE;
+                    }
+                }
+                if (DOMAINDECOMP(cr) && bMasterState)
+                {
+                    dd_collect_state(cr->dd,state,state_global);
+                }
+            }
+
+            if (DOMAINDECOMP(cr))
+            {
+                /* Repartition the domain decomposition */
+                wallcycle_start(wcycle,ewcDOMDEC);
+                dd_partition_system(fplog,step,cr,
+                                    bMasterState,nstglobalcomm,
+                                    state_global,top_global,ir,
+                                    state,&f,mdatoms,top,fr,
+                                    vsite,shellfc,constr,
+                                    nrnb,wcycle,do_verbose);
+                wallcycle_stop(wcycle,ewcDOMDEC);
+                /* If using an iterative integrator, reallocate space to match the decomposition */
+            }
+        }
+
+        if (MASTER(cr) && do_log && !bFFscan)
+        {
+            print_ebin_header(fplog,step,t,state->lambda);
+        }
+
+        if (ir->efep != efepNO)
+        {
+            update_mdatoms(mdatoms,state->lambda);
+        }
+
+        if (bRerunMD && rerun_fr.bV)
+        {
+
+            /* We need the kinetic energy at minus the half step for determining
+             * the full step kinetic energy and possibly for T-coupling.*/
+            /* This may not be quite working correctly yet . . . . */
+            compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                            wcycle,enerd,NULL,NULL,NULL,NULL,mu_tot,
+                            constr,NULL,FALSE,state->box,
+                            top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+                            CGLO_RERUNMD | CGLO_GSTAT | CGLO_TEMPERATURE);
+        }
+        clear_mat(force_vir);
+
+        /* Ionize the atoms if necessary */
+/*        if (bIonize)
+        {
+            ionize(fplog,oenv,mdatoms,top_global,t,ir,state->x,state->v,
+                   mdatoms->start,mdatoms->start+mdatoms->homenr,state->box,cr);
+        }*/
+
+        /* Update force field in ffscan program */
+/*        if (bFFscan)
+        {
+            if (update_forcefield(fplog,
+                                  nfile,fnm,fr,
+                                  mdatoms->nr,state->x,state->box)) {
+                if (gmx_parallel_env_initialized())
+                {
+                    gmx_finalize();
+                }
+                exit(0);
+            }
+        }*/
+
+        GMX_MPE_LOG(ev_timestep2);
+
+        /* We write a checkpoint at this MD step when:
+         * either at an NS step when we signalled through gs,
+         * or at the last step (but not when we do not want confout),
+         * but never at the first step or with rerun.
+         */
+/*        bCPT = (((gs.set[eglsCHKPT] && bNS) ||
+                 (bLastStep && (Flags & MD_CONFOUT))) &&
+                step > ir->init_step && !bRerunMD);
+        if (bCPT)
+        {
+            gs.set[eglsCHKPT] = 0;
+        }*/
+
+        /* Determine the energy and pressure:
+         * at nstcalcenergy steps and at energy output steps (set below).
+         */
+        bNstEner = (bGStatEveryStep || do_per_step(step,ir->nstcalcenergy));
+        bCalcEnerPres = bNstEner;
+
+        /* Do we need global communication ? */
+        bGStat = (bCalcEnerPres || bStopCM ||
+                  (ir->nstlist == -1 && !bRerunMD && step >= nlh.step_nscheck));
+
+        do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
+
+        if (do_ene || do_log)
+        {
+            bCalcEnerPres = TRUE;
+            bGStat    = TRUE;
+        }
+
+        /* these CGLO_ options remain the same throughout the iteration */
+        cglo_flags = ((bRerunMD ? CGLO_RERUNMD : 0) |
+                      (bStopCM ? CGLO_STOPCM : 0) |
+                      (bGStat ? CGLO_GSTAT : 0) |
+                      (bNEMD ? CGLO_NEMD : 0)
+            );
+
+        force_flags = (GMX_FORCE_STATECHANGED |
+                       ((DYNAMIC_BOX(*ir) || bRerunMD) ? GMX_FORCE_DYNAMICBOX : 0) |
+                       GMX_FORCE_ALLFORCES |
+                       (bNStList ? GMX_FORCE_DOLR : 0) |
+                       GMX_FORCE_SEPLRF |
+                       (bCalcEnerPres ? GMX_FORCE_VIRIAL : 0) |
+                       (bDoDHDL ? GMX_FORCE_DHDL : 0)
+            );
+
+        if (shellfc)
+        {
+            /* Now is the time to relax the shells */
+            count=relax_shell_flexcon(fplog,cr,bVerbose,bFFscan ? step+1 : step,
+                                      ir,bNS,force_flags,
+                                      bStopCM,top,top_global,
+                                      constr,enerd,fcd,
+                                      state,f,force_vir,mdatoms,
+                                      nrnb,wcycle,graph,groups,
+                                      shellfc,fr,bBornRadii,t,mu_tot,
+                                      state->natoms,&bConverged,vsite,
+                                      outf->fp_field);
+            tcount+=count;
+
+            if (bConverged)
+            {
+                nconverged++;
+            }
+        }
+        else
+        {
+            /* The coordinates (x) are shifted (to get whole molecules)
+             * in do_force.
+             * This is parallellized as well, and does communication too.
+             * Check comments in sim_util.c
+             */
+
+            do_force(fplog,cr,ir,step,nrnb,wcycle,top,top_global,groups,
+                     state->box,state->x,&state->hist,
+                     f,force_vir,mdatoms,enerd,fcd,
+                     state->lambda,graph,
+                     fr,vsite,mu_tot,t,outf->fp_field,ed,bBornRadii,
+                     (bNS ? GMX_FORCE_NS : 0) | force_flags);
+        }
+
+        GMX_BARRIER(cr->mpi_comm_mygroup);
+
+ /*       if (bTCR)
+        {
+            mu_aver = calc_mu_aver(cr,state->x,mdatoms->chargeA,
+                                   mu_tot,&top_global->mols,mdatoms,gnx,grpindex);
+        }
+
+        if (bTCR && bFirstStep)
+        {
+            tcr=init_coupling(fplog,nfile,fnm,cr,fr,mdatoms,&(top->idef));
+            fprintf(fplog,"Done init_coupling\n");
+            fflush(fplog);
+        }*/
+
+        /*  ############### START FIRST UPDATE HALF-STEP ############### */
+
+        if (!bStartingFromCpt && !bRerunMD)
+        {
+            if (ir->eI == eiVV)
+            {
+                if (bInitStep)
+                {
+                    /* if using velocity verlet with full time step Ekin,
+                     * take the first half step only to compute the
+                     * virial for the first step. From there,
+                     * revert back to the initial coordinates
+                     * so that the input is actually the initial step.
+                     */
+                    copy_rvecn(state->v,cbuf,0,state->natoms); /* should make this better for parallelizing? */
+                }
+
+                /* this is for NHC in the Ekin(t+dt/2) version of vv */
+                if (!bInitStep)
+                {
+                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[1]);
+                }
+
+                update_coords(fplog,step,ir,mdatoms,state,
+                              f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+                              ekind,M,wcycle,upd,bInitStep,etrtVELOCITY,
+                              cr,nrnb,constr,&top->idef);
+
+                if (bIterations)
+                {
+                    gmx_iterate_init(&iterate,bIterations && !bInitStep);
+                }
+                /* for iterations, we save these vectors, as we will be self-consistently iterating
+                   the calculations */
+                /*#### UPDATE EXTENDED VARIABLES IN TROTTER FORMULATION */
+
+                /* save the state */
+                if (bIterations && iterate.bIterate) {
+                    copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
+                }
+            }
+
+            bFirstIterate = TRUE;
+            while (bFirstIterate || (bIterations && iterate.bIterate))
+            {
+                if (bIterations && iterate.bIterate)
+                {
+                    copy_coupling_state(bufstate,state,ekind_save,ekind,&(ir->opts));
+                    if (bFirstIterate && bTrotter)
+                    {
+                        /* The first time through, we need a decent first estimate
+                           of veta(t+dt) to compute the constraints.  Do
+                           this by computing the box volume part of the
+                           trotter integration at this time. Nothing else
+                           should be changed by this routine here.  If
+                           !(first time), we start with the previous value
+                           of veta.  */
+
+                        veta_save = state->veta;
+                        trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[0]);
+                        vetanew = state->veta;
+                        state->veta = veta_save;
+                    }
+                }
+
+                bOK = TRUE;
+                if ( !bRerunMD || rerun_fr.bV || bForceUpdate) {  /* Why is rerun_fr.bV here?  Unclear. */
+                    dvdl = 0;
+
+                    update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
+                                       &top->idef,shake_vir,NULL,
+                                       cr,nrnb,wcycle,upd,constr,
+                                       bInitStep,TRUE,bCalcEnerPres,vetanew);
+
+                    if (!bOK && !bFFscan)
+                    {
+                        gmx_fatal(FARGS,"Constraint error: Shake, Lincs or Settle could not solve the constrains");
+                    }
+
+                }
+                else if (graph)
+                { /* Need to unshift here if a do_force has been
+                     called in the previous step */
+                    unshift_self(graph,state->box,state->x);
+                }
+
+
+                if (bVV) {
+                    /* if VV, compute the pressure and constraints */
+                    /* if VV2, the pressure and constraints only if using pressure control.*/
+                    bPres = (ir->eI==eiVV || IR_NPT_TROTTER(ir));
+                    bTemp = ((ir->eI==eiVV &&(!bInitStep)) || (ir->eI==eiVVAK && IR_NPT_TROTTER(ir)));
+                    compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                                    wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+                                    constr,NULL,FALSE,state->box,
+                                    top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+                                    cglo_flags
+                                    | CGLO_ENERGY
+                                    | (bTemp ? CGLO_TEMPERATURE:0)
+                                    | (bPres ? CGLO_PRESSURE : 0)
+                                    | (bPres ? CGLO_CONSTRAINT : 0)
+                                    | (iterate.bIterate ? CGLO_ITERATE : 0)
+                                    | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
+                                    | CGLO_SCALEEKIN
+                        );
+                }
+                /* explanation of above:
+                   a) We compute Ekin at the full time step
+                   if 1) we are using the AveVel Ekin, and it's not the
+                   initial step, or 2) if we are using AveEkin, but need the full
+                   time step kinetic energy for the pressure.
+                   b) If we are using EkinAveEkin for the kinetic energy for the temperture control, we still feed in
+                   EkinAveVel because it's needed for the pressure */
+
+                /* temperature scaling and pressure scaling to produce the extended variables at t+dt */
+                if (bVV && !bInitStep)
+                {
+                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[2]);
+                }
+
+                if (bIterations &&
+                    done_iterating(cr,fplog,step,&iterate,bFirstIterate,
+                                   state->veta,&vetanew))
+                {
+                    break;
+                }
+                bFirstIterate = FALSE;
+            }
+
+            if (bTrotter && !bInitStep) {
+                copy_mat(shake_vir,state->svir_prev);
+                copy_mat(force_vir,state->fvir_prev);
+                if (IR_NVT_TROTTER(ir) && ir->eI==eiVV) {
+                    /* update temperature and kinetic energy now that step is over - this is the v(t+dt) point */
+                    enerd->term[F_TEMP] = sum_ekin(&(ir->opts),ekind,NULL,(ir->eI==eiVV),FALSE,FALSE);
+                    enerd->term[F_EKIN] = trace(ekind->ekin);
+                }
+            }
+            /* if it's the initial step, we performed this first step just to get the constraint virial */
+            if (bInitStep && ir->eI==eiVV) {
+                copy_rvecn(cbuf,state->v,0,state->natoms);
+            }
+
+            if (fr->bSepDVDL && fplog && do_log)
+            {
+                fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
+            }
+            enerd->term[F_DHDL_CON] += dvdl;
+
+            GMX_MPE_LOG(ev_timestep1);
+
+        }
+
+        /* MRS -- now done iterating -- compute the conserved quantity */
+        if (bVV) {
+            last_conserved = 0;
+            if (IR_NVT_TROTTER(ir) || IR_NPT_TROTTER(ir))
+            {
+                last_conserved =
+                    NPT_energy(ir,state,&MassQ);
+                if ((ir->eDispCorr != edispcEnerPres) && (ir->eDispCorr != edispcAllEnerPres))
+                {
+                    last_conserved -= enerd->term[F_DISPCORR];
+                }
+            }
+            if (ir->eI==eiVV) {
+                last_ekin = enerd->term[F_EKIN]; /* does this get preserved through checkpointing? */
+            }
+        }
+
+        /* ########  END FIRST UPDATE STEP  ############## */
+        /* ########  If doing VV, we now have v(dt) ###### */
+
+        /* ################## START TRAJECTORY OUTPUT ################# */
+
+        /* Now we have the energies and forces corresponding to the
+         * coordinates at time t. We must output all of this before
+         * the update.
+         * for RerunMD t is read from input trajectory
+         */
+        GMX_MPE_LOG(ev_output_start);
+
+        mdof_flags = 0;
+        if (do_per_step(step,ir->nstxout)) { mdof_flags |= MDOF_X; }
+        if (do_per_step(step,ir->nstvout)) { mdof_flags |= MDOF_V; }
+        if (do_per_step(step,ir->nstfout)) { mdof_flags |= MDOF_F; }
+        if (do_per_step(step,ir->nstxtcout)) { mdof_flags |= MDOF_XTC; }
+/*        if (bCPT) { mdof_flags |= MDOF_CPT; };*/
+
+#ifdef GMX_FAHCORE
+        if (MASTER(cr))
+            fcReportProgress( ir->nsteps, step );
+
+        if (bLastStep)
+        {
+            /* Enforce writing positions and velocities at end of run */
+            mdof_flags |= (MDOF_X | MDOF_V);
+        }
+        {
+            int nthreads=(cr->nthreads==0 ? 1 : cr->nthreads);
+            int nnodes=(cr->nnodes==0 ? 1 : cr->nnodes);
+
+            /*Gromacs drives checkpointing; no ||
+              fcCheckPointPendingThreads(cr->nodeid,
+              nthreads*nnodes);*/
+            /* sync bCPT and fc record-keeping */
+/*            if (bCPT && MASTER(cr))
+                fcRequestCheckPoint();*/
+        }
+#endif
+
+        if (mdof_flags != 0)
+        {
+            wallcycle_start(wcycle,ewcTRAJ);
+/*            if (bCPT)
+            {
+                if (state->flags & (1<<estLD_RNG))
+                {
+                    get_stochd_state(upd,state);
+                }
+                if (MASTER(cr))
+                {
+                    if (bSumEkinhOld)
+                    {
+                        state_global->ekinstate.bUpToDate = FALSE;
+                    }
+                    else
+                    {
+                        update_ekinstate(&state_global->ekinstate,ekind);
+                        state_global->ekinstate.bUpToDate = TRUE;
+                    }
+                    update_energyhistory(&state_global->enerhist,mdebin);
+                }
+            }*/
+            write_traj(fplog,cr,outf,mdof_flags,top_global,
+                       step,t,state,state_global,f,f_global,&n_xtc,&x_xtc);
+/*            if (bCPT)
+            {
+                nchkpt++;
+                bCPT = FALSE;
+            }*/
+            debug_gmx();
+            if (bLastStep && step_rel == ir->nsteps &&
+                (Flags & MD_CONFOUT) && MASTER(cr) &&
+                !bRerunMD && !bFFscan)
+            {
+                /* x and v have been collected in write_traj,
+                 * because a checkpoint file will always be written
+                 * at the last step.
+                 */
+                fprintf(stderr,"\nWriting final coordinates.\n");
+                if (ir->ePBC != epbcNONE && !ir->bPeriodicMols &&
+                    DOMAINDECOMP(cr))
+                {
+                    /* Make molecules whole only for confout writing */
+                    do_pbc_mtop(fplog,ir->ePBC,state->box,top_global,state_global->x);
+                }
+/*                write_sto_conf_mtop(ftp2fn(efSTO,nfile,fnm),
+                                    *top_global->name,top_global,
+                                    state_global->x,state_global->v,
+                                    ir->ePBC,state->box);*/
+                debug_gmx();
+            }
+            wallcycle_stop(wcycle,ewcTRAJ);
+        }
+        GMX_MPE_LOG(ev_output_finish);
+
+        /* kludge -- virial is lost with restart for NPT control. Must restart */
+        if (bStartingFromCpt && bVV)
+        {
+            copy_mat(state->svir_prev,shake_vir);
+            copy_mat(state->fvir_prev,force_vir);
+        }
+        /*  ################## END TRAJECTORY OUTPUT ################ */
+
+        /* Determine the pressure:
+         * always when we want exact averages in the energy file,
+         * at ns steps when we have pressure coupling,
+         * otherwise only at energy output steps (set below).
+         */
+
+        bNstEner = (bGStatEveryStep || do_per_step(step,ir->nstcalcenergy));
+        bCalcEnerPres = bNstEner;
+
+        /* Do we need global communication ? */
+        bGStat = (bGStatEveryStep || bStopCM || bNS ||
+                  (ir->nstlist == -1 && !bRerunMD && step >= nlh.step_nscheck));
+
+        do_ene = (do_per_step(step,ir->nstenergy) || bLastStep);
+
+        if (do_ene || do_log)
+        {
+            bCalcEnerPres = TRUE;
+            bGStat        = TRUE;
+        }
+
+        /* Determine the wallclock run time up till now */
+        run_time = gmx_gettime() - (double)runtime->real;
+
+        /* Check whether everything is still allright */
+        if (((int)gmx_get_stop_condition() > handled_stop_condition) &&
+            MASTERTHREAD(cr))
+        {
+            /* this is just make gs.sig compatible with the hack
+               of sending signals around by MPI_Reduce with together with
+               other floats */
+            if ( gmx_get_stop_condition() == gmx_stop_cond_next_ns )
+                gs.sig[eglsSTOPCOND]=1;
+            if ( gmx_get_stop_condition() == gmx_stop_cond_next )
+                gs.sig[eglsSTOPCOND]=-1;
+            /* < 0 means stop at next step, > 0 means stop at next NS step */
+            if (fplog)
+            {
+                fprintf(fplog,
+                        "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
+                        gmx_get_signal_name(),
+                        gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
+                fflush(fplog);
+            }
+            fprintf(stderr,
+                    "\n\nReceived the %s signal, stopping at the next %sstep\n\n",
+                    gmx_get_signal_name(),
+                    gs.sig[eglsSTOPCOND]==1 ? "NS " : "");
+            fflush(stderr);
+            handled_stop_condition=(int)gmx_get_stop_condition();
+        }
+        else if (MASTER(cr) && (bNS || ir->nstlist <= 0) &&
+                 (max_hours > 0 && run_time > max_hours*60.0*60.0*0.99) &&
+                 gs.sig[eglsSTOPCOND] == 0 && gs.set[eglsSTOPCOND] == 0)
+        {
+            /* Signal to terminate the run */
+            gs.sig[eglsSTOPCOND] = 1;
+            if (fplog)
+            {
+                fprintf(fplog,"\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
+            }
+            fprintf(stderr, "\nStep %s: Run time exceeded %.3f hours, will terminate the run\n",gmx_step_str(step,sbuf),max_hours*0.99);
+        }
+
+        if (bResetCountersHalfMaxH && MASTER(cr) &&
+            run_time > max_hours*60.0*60.0*0.495)
+        {
+            gs.sig[eglsRESETCOUNTERS] = 1;
+        }
+
+        if (ir->nstlist == -1 && !bRerunMD)
+        {
+            /* When bGStatEveryStep=FALSE, global_stat is only called
+             * when we check the atom displacements, not at NS steps.
+             * This means that also the bonded interaction count check is not
+             * performed immediately after NS. Therefore a few MD steps could
+             * be performed with missing interactions.
+             * But wrong energies are never written to file,
+             * since energies are only written after global_stat
+             * has been called.
+             */
+            if (step >= nlh.step_nscheck)
+            {
+                nlh.nabnsb = natoms_beyond_ns_buffer(ir,fr,&top->cgs,
+                                                     nlh.scale_tot,state->x);
+            }
+            else
+            {
+                /* This is not necessarily true,
+                 * but step_nscheck is determined quite conservatively.
+                 */
+                nlh.nabnsb = 0;
+            }
+        }
+
+        /* In parallel we only have to check for checkpointing in steps
+         * where we do global communication,
+         *  otherwise the other nodes don't know.
+         */
+        if (MASTER(cr) && ((bGStat || !PAR(cr)) &&
+                           cpt_period >= 0 &&
+                           (cpt_period == 0 ||
+                            run_time >= nchkpt*cpt_period*60.0)) &&
+            gs.set[eglsCHKPT] == 0)
+        {
+            gs.sig[eglsCHKPT] = 1;
+        }
+
+        if (bIterations)
+        {
+            gmx_iterate_init(&iterate,bIterations);
+        }
+
+        /* for iterations, we save these vectors, as we will be redoing the calculations */
+        if (bIterations && iterate.bIterate)
+        {
+            copy_coupling_state(state,bufstate,ekind,ekind_save,&(ir->opts));
+        }
+        bFirstIterate = TRUE;
+        while (bFirstIterate || (bIterations && iterate.bIterate))
+        {
+            /* We now restore these vectors to redo the calculation with improved extended variables */
+            if (bIterations)
+            {
+                copy_coupling_state(bufstate,state,ekind_save,ekind,&(ir->opts));
+            }
+
+            /* We make the decision to break or not -after- the calculation of Ekin and Pressure,
+               so scroll down for that logic */
+
+            /* #########   START SECOND UPDATE STEP ################# */
+            GMX_MPE_LOG(ev_update_start);
+            bOK = TRUE;
+            if (!bRerunMD || rerun_fr.bV || bForceUpdate)
+            {
+                wallcycle_start(wcycle,ewcUPDATE);
+                dvdl = 0;
+                /* Box is changed in update() when we do pressure coupling,
+                 * but we should still use the old box for energy corrections and when
+                 * writing it to the energy file, so it matches the trajectory files for
+                 * the same timestep above. Make a copy in a separate array.
+                 */
+                copy_mat(state->box,lastbox);
+                /* UPDATE PRESSURE VARIABLES IN TROTTER FORMULATION WITH CONSTRAINTS */
+                if (bTrotter)
+                {
+                    if (bIterations && iterate.bIterate)
+                    {
+                        if (bFirstIterate)
+                        {
+                            scalevir = 1;
+                        }
+                        else
+                        {
+                            /* we use a new value of scalevir to converge the iterations faster */
+                            scalevir = tracevir/trace(shake_vir);
+                        }
+                        msmul(shake_vir,scalevir,shake_vir);
+                        m_add(force_vir,shake_vir,total_vir);
+                        clear_mat(shake_vir);
+                    }
+                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[3]);
+                }
+                /* We can only do Berendsen coupling after we have summed
+                 * the kinetic energy or virial. Since the happens
+                 * in global_state after update, we should only do it at
+                 * step % nstlist = 1 with bGStatEveryStep=FALSE.
+                 */
+
+                update_extended(fplog,step,ir,mdatoms,state,ekind,pcoupl_mu,M,wcycle,
+                                upd,bInitStep,FALSE,&MassQ);
+
+                /* velocity (for VV) */
+                update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+                              ekind,M,wcycle,upd,FALSE,etrtVELOCITY,cr,nrnb,constr,&top->idef);
+
+                /* Above, initialize just copies ekinh into ekin,
+                 * it doesn't copy position (for VV),
+                 * and entire integrator for MD.
+                 */
+
+                if (ir->eI==eiVVAK)
+                {
+                    copy_rvecn(state->x,cbuf,0,state->natoms);
+                }
+
+                update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+                              ekind,M,wcycle,upd,bInitStep,etrtPOSITION,cr,nrnb,constr,&top->idef);
+                wallcycle_stop(wcycle,ewcUPDATE);
+
+                update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
+                                   &top->idef,shake_vir,force_vir,
+                                   cr,nrnb,wcycle,upd,constr,
+                                   bInitStep,FALSE,bCalcEnerPres,state->veta);
+
+                if (ir->eI==eiVVAK)
+                {
+                    /* erase F_EKIN and F_TEMP here? */
+                    /* just compute the kinetic energy at the half step to perform a trotter step */
+                    compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                                    wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+                                    constr,NULL,FALSE,lastbox,
+                                    top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+                                    cglo_flags | CGLO_TEMPERATURE | CGLO_CONSTRAINT
+                        );
+                    wallcycle_start(wcycle,ewcUPDATE);
+                    trotter_update(ir,step,ekind,enerd,state,total_vir,mdatoms,&MassQ,trotter_seq[4]);
+                    /* now we know the scaling, we can compute the positions again again */
+                    copy_rvecn(cbuf,state->x,0,state->natoms);
+
+                    update_coords(fplog,step,ir,mdatoms,state,f,fr->bTwinRange && bNStList,fr->f_twin,fcd,
+                                  ekind,M,wcycle,upd,bInitStep,etrtPOSITION,cr,nrnb,constr,&top->idef);
+                    wallcycle_stop(wcycle,ewcUPDATE);
+
+                    /* do we need an extra constraint here? just need to copy out of state->v to upd->xp? */
+                    /* are the small terms in the shake_vir here due
+                     * to numerical errors, or are they important
+                     * physically? I'm thinking they are just errors, but not completely sure.
+                     * For now, will call without actually constraining, constr=NULL*/
+                    update_constraints(fplog,step,&dvdl,ir,ekind,mdatoms,state,graph,f,
+                                       &top->idef,tmp_vir,force_vir,
+                                       cr,nrnb,wcycle,upd,NULL,
+                                       bInitStep,FALSE,bCalcEnerPres,state->veta);
+                }
+                if (!bOK && !bFFscan)
+                {
+                    gmx_fatal(FARGS,"Constraint error: Shake, Lincs or Settle could not solve the constrains");
+                }
+
+                if (fr->bSepDVDL && fplog && do_log)
+                {
+                    fprintf(fplog,sepdvdlformat,"Constraint",0.0,dvdl);
+                }
+                enerd->term[F_DHDL_CON] += dvdl;
+            }
+            else if (graph)
+            {
+                /* Need to unshift here */
+                unshift_self(graph,state->box,state->x);
+            }
+
+            GMX_BARRIER(cr->mpi_comm_mygroup);
+            GMX_MPE_LOG(ev_update_finish);
+
+            if (vsite != NULL)
+            {
+                wallcycle_start(wcycle,ewcVSITECONSTR);
+                if (graph != NULL)
+                {
+                    shift_self(graph,state->box,state->x);
+                }
+                construct_vsites(fplog,vsite,state->x,nrnb,ir->delta_t,state->v,
+                                 top->idef.iparams,top->idef.il,
+                                 fr->ePBC,fr->bMolPBC,graph,cr,state->box);
+
+                if (graph != NULL)
+                {
+                    unshift_self(graph,state->box,state->x);
+                }
+                wallcycle_stop(wcycle,ewcVSITECONSTR);
+            }
+
+            /* ############## IF NOT VV, Calculate globals HERE, also iterate constraints ############ */
+            if (ir->nstlist == -1 && bFirstIterate)
+            {
+                gs.sig[eglsNABNSB] = nlh.nabnsb;
+            }
+            compute_globals(fplog,gstat,cr,ir,fr,ekind,state,state_global,mdatoms,nrnb,vcm,
+                            wcycle,enerd,force_vir,shake_vir,total_vir,pres,mu_tot,
+                            constr,
+                            bFirstIterate ? &gs : NULL,(step % gs.nstms == 0),
+                            lastbox,
+                            top_global,&pcurr,top_global->natoms,&bSumEkinhOld,
+                            cglo_flags
+                            | (!EI_VV(ir->eI) ? CGLO_ENERGY : 0)
+                            | (!EI_VV(ir->eI) ? CGLO_TEMPERATURE : 0)
+                            | (!EI_VV(ir->eI) || bRerunMD ? CGLO_PRESSURE : 0)
+                            | (bIterations && iterate.bIterate ? CGLO_ITERATE : 0)
+                            | (bFirstIterate ? CGLO_FIRSTITERATE : 0)
+                            | CGLO_CONSTRAINT
+                );
+            if (ir->nstlist == -1 && bFirstIterate)
+            {
+                nlh.nabnsb = gs.set[eglsNABNSB];
+                gs.set[eglsNABNSB] = 0;
+            }
+            /* bIterate is set to keep it from eliminating the old ekin kinetic energy terms */
+            /* #############  END CALC EKIN AND PRESSURE ################# */
+
+            /* Note: this is OK, but there are some numerical precision issues with using the convergence of
+               the virial that should probably be addressed eventually. state->veta has better properies,
+               but what we actually need entering the new cycle is the new shake_vir value. Ideally, we could
+               generate the new shake_vir, but test the veta value for convergence.  This will take some thought. */
+
+            if (bIterations &&
+                done_iterating(cr,fplog,step,&iterate,bFirstIterate,
+                               trace(shake_vir),&tracevir))
+            {
+                break;
+            }
+            bFirstIterate = FALSE;
+        }
+
+        update_box(fplog,step,ir,mdatoms,state,graph,f,
+                   ir->nstlist==-1 ? &nlh.scale_tot : NULL,pcoupl_mu,nrnb,wcycle,upd,bInitStep,FALSE);
+
+        /* ################# END UPDATE STEP 2 ################# */
+        /* #### We now have r(t+dt) and v(t+dt/2)  ############# */
+
+        /* The coordinates (x) were unshifted in update */
+/*        if (bFFscan && (shellfc==NULL || bConverged))
+        {
+            if (print_forcefield(fplog,enerd->term,mdatoms->homenr,
+                                 f,NULL,xcopy,
+                                 &(top_global->mols),mdatoms->massT,pres))
+            {
+                if (gmx_parallel_env_initialized())
+                {
+                    gmx_finalize();
+                }
+                fprintf(stderr,"\n");
+                exit(0);
+            }
+        }*/
+        if (!bGStat)
+        {
+            /* We will not sum ekinh_old,
+             * so signal that we still have to do it.
+             */
+            bSumEkinhOld = TRUE;
+        }
+
+/*        if (bTCR)
+        {*/
+            /* Only do GCT when the relaxation of shells (minimization) has converged,
+             * otherwise we might be coupling to bogus energies.
+             * In parallel we must always do this, because the other sims might
+             * update the FF.
+             */
+
+            /* Since this is called with the new coordinates state->x, I assume
+             * we want the new box state->box too. / EL 20040121
+             */
+/*            do_coupling(fplog,oenv,nfile,fnm,tcr,t,step,enerd->term,fr,
+                        ir,MASTER(cr),
+                        mdatoms,&(top->idef),mu_aver,
+                        top_global->mols.nr,cr,
+                        state->box,total_vir,pres,
+                        mu_tot,state->x,f,bConverged);
+            debug_gmx();
+        }*/
+
+        /* #########  BEGIN PREPARING EDR OUTPUT  ###########  */
+
+        sum_dhdl(enerd,state->lambda,ir);
+        /* use the directly determined last velocity, not actually the averaged half steps */
+        if (bTrotter && ir->eI==eiVV)
+        {
+            enerd->term[F_EKIN] = last_ekin;
+        }
+        enerd->term[F_ETOT] = enerd->term[F_EPOT] + enerd->term[F_EKIN];
+
+        switch (ir->etc)
+        {
+        case etcNO:
+            break;
+        case etcBERENDSEN:
+            break;
+        case etcNOSEHOOVER:
+            if (IR_NVT_TROTTER(ir)) {
+                enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] + last_conserved;
+            } else {
+                enerd->term[F_ECONSERVED] = enerd->term[F_ETOT] +
+                    NPT_energy(ir,state,&MassQ);
+            }
+            break;
+        case etcVRESCALE:
+            enerd->term[F_ECONSERVED] =
+                enerd->term[F_ETOT] + vrescale_energy(&(ir->opts),
+                                                      state->therm_integral);
+            break;
+        default:
+            break;
+        }
+
+        /* Check for excessively large energies */
+/*        if (bIonize)
+        {
+#ifdef GMX_DOUBLE
+            real etot_max = 1e200;
+#else
+            real etot_max = 1e30;
+#endif
+            if (fabs(enerd->term[F_ETOT]) > etot_max)
+            {
+                fprintf(stderr,"Energy too large (%g), giving up\n",
+                        enerd->term[F_ETOT]);
+            }
+        }*/
+        /* #########  END PREPARING EDR OUTPUT  ###########  */
+
+        /* Time for performance */
+        if (((step % stepout) == 0) || bLastStep)
+        {
+            runtime_upd_proc(runtime);
+        }
+
+        /* Output stuff */
+        if (MASTER(cr))
+        {
+            bool do_dr,do_or;
+
+            if (!(bStartingFromCpt && (EI_VV(ir->eI))))
+            {
+                if (bNstEner)
+                {
+                    upd_mdebin(mdebin,bDoDHDL ? outf->fp_dhdl : NULL,TRUE,
+                               t,mdatoms->tmass,enerd,state,lastbox,
+                               shake_vir,force_vir,total_vir,pres,
+                               ekind,mu_tot,constr);
+                }
+                else
+                {
+                    upd_mdebin_step(mdebin);
+                }
+
+                do_dr  = do_per_step(step,ir->nstdisreout);
+                do_or  = do_per_step(step,ir->nstorireout);
+
+                print_ebin(outf->fp_ene,do_ene,do_dr,do_or,do_log?fplog:NULL,
+                           step,t,
+                           eprNORMAL,bCompact,mdebin,fcd,groups,&(ir->opts));
+            }
+            if (ir->ePull != epullNO)
+            {
+                pull_print_output(ir->pull,step,t);
+            }
+
+            if (do_per_step(step,ir->nstlog))
+            {
+                if(fflush(fplog) != 0)
+                {
+                    gmx_fatal(FARGS,"Cannot flush logfile - maybe you are out of quota?");
+                }
+            }
+        }
+
+
+        /* Remaining runtime */
+        if (MULTIMASTER(cr) && (do_verbose || gmx_got_usr_signal() ))
+        {
+            if (shellfc)
+            {
+                fprintf(stderr,"\n");
+            }
+            print_time(stderr,runtime,step,ir,cr);
+        }
+
+               /* Set new positions for the group to embed */
+               if(!bLastStep){
+                       if(step_rel<=it_xy)
+                       {
+                               fac[0]+=xy_step;
+                               fac[1]+=xy_step;
+                       } else if (step_rel<=(it_xy+it_z))
+                       {
+                               fac[2]+=z_step;
+                       }
+                       resize(ins_at,r_ins,state_global->x,pos_ins,fac);
+               }
+
+        /* Replica exchange */
+/*        bExchanged = FALSE;
+        if ((repl_ex_nst > 0) && (step > 0) && !bLastStep &&
+            do_per_step(step,repl_ex_nst))
+        {
+            bExchanged = replica_exchange(fplog,cr,repl_ex,
+                                          state_global,enerd->term,
+                                          state,step,t);
+        }
+        if (bExchanged && PAR(cr))
+        {
+            if (DOMAINDECOMP(cr))
+            {
+                dd_partition_system(fplog,step,cr,TRUE,1,
+                                    state_global,top_global,ir,
+                                    state,&f,mdatoms,top,fr,
+                                    vsite,shellfc,constr,
+                                    nrnb,wcycle,FALSE);
+            }
+            else
+            {
+                bcast_state(cr,state,FALSE);
+            }
+        }*/
+
+        bFirstStep = FALSE;
+        bInitStep = FALSE;
+        bStartingFromCpt = FALSE;
+
+        /* #######  SET VARIABLES FOR NEXT ITERATION IF THEY STILL NEED IT ###### */
+        /* Complicated conditional when bGStatEveryStep=FALSE.
+         * We can not just use bGStat, since then the simulation results
+         * would depend on nstenergy and nstlog or step_nscheck.
+         */
+        if (((state->flags & (1<<estPRES_PREV)) ||
+             (state->flags & (1<<estSVIR_PREV)) ||
+             (state->flags & (1<<estFVIR_PREV))) &&
+            (bGStatEveryStep ||
+             (ir->nstlist > 0 && step % ir->nstlist == 0) ||
+             (ir->nstlist < 0 && nlh.nabnsb > 0) ||
+             (ir->nstlist == 0 && bGStat)))
+        {
+            /* Store the pressure in t_state for pressure coupling
+             * at the next MD step.
+             */
+            if (state->flags & (1<<estPRES_PREV))
+            {
+                copy_mat(pres,state->pres_prev);
+            }
+        }
+
+        /* #######  END SET VARIABLES FOR NEXT ITERATION ###### */
+
+        if (bRerunMD)
+        {
+            /* read next frame from input trajectory */
+            bNotLastFrame = read_next_frame(oenv,status,&rerun_fr);
+        }
+
+        if (!bRerunMD || !rerun_fr.bStep)
+        {
+            /* increase the MD step number */
+            step++;
+            step_rel++;
+        }
+
+        cycles = wallcycle_stop(wcycle,ewcSTEP);
+        if (DOMAINDECOMP(cr) && wcycle)
+        {
+            dd_cycles_add(cr->dd,cycles,ddCyclStep);
+        }
+
+        if (step_rel == wcycle_get_reset_counters(wcycle) ||
+            gs.set[eglsRESETCOUNTERS] != 0)
+        {
+            /* Reset all the counters related to performance over the run */
+            reset_all_counters(fplog,cr,step,&step_rel,ir,wcycle,nrnb,runtime);
+            wcycle_set_reset_counters(wcycle,-1);
+            bResetCountersHalfMaxH = FALSE;
+            gs.set[eglsRESETCOUNTERS] = 0;
+        }
+    }
+    /* End of main MD loop */
+    debug_gmx();
+    write_sto_conf_mtop(ftp2fn(efSTO,nfile,fnm),
+                                        *top_global->name,top_global,
+                                        state_global->x,state_global->v,
+                                        ir->ePBC,state->box);
+
+    /* Stop the time */
+    runtime_end(runtime);
+
+    if (bRerunMD)
+    {
+        close_trj(status);
+    }
+
+    if (!(cr->duty & DUTY_PME))
+    {
+        /* Tell the PME only node to finish */
+        gmx_pme_finish(cr);
+    }
+
+    if (MASTER(cr))
+    {
+        if (ir->nstcalcenergy > 0 && !bRerunMD)
+        {
+            print_ebin(outf->fp_ene,FALSE,FALSE,FALSE,fplog,step,t,
+                       eprAVER,FALSE,mdebin,fcd,groups,&(ir->opts));
+        }
+    }
+
+    done_mdoutf(outf);
+
+    debug_gmx();
+
+    if (ir->nstlist == -1 && nlh.nns > 0 && fplog)
+    {
+        fprintf(fplog,"Average neighborlist lifetime: %.1f steps, std.dev.: %.1f steps\n",nlh.s1/nlh.nns,sqrt(nlh.s2/nlh.nns - sqr(nlh.s1/nlh.nns)));
+        fprintf(fplog,"Average number of atoms that crossed the half buffer length: %.1f\n\n",nlh.ab/nlh.nns);
+    }
+
+    if (shellfc && fplog)
+    {
+        fprintf(fplog,"Fraction of iterations that converged:           %.2f %%\n",
+                (nconverged*100.0)/step_rel);
+        fprintf(fplog,"Average number of force evaluations per MD step: %.2f\n\n",
+                tcount/step_rel);
+    }
+
+/*    if (repl_ex_nst > 0 && MASTER(cr))
+    {
+        print_replica_exchange_statistics(fplog,repl_ex);
+    }*/
+
+    runtime->nsteps_done = step_rel;
+
+    return 0;
+}
+
+
+int mdrunner_membed(FILE *fplog,t_commrec *cr,int nfile,const t_filenm fnm[],
+             const output_env_t oenv, bool bVerbose,bool bCompact,
+             int nstglobalcomm,
+             ivec ddxyz,int dd_node_order,real rdd,real rconstr,
+             const char *dddlb_opt,real dlb_scale,
+             const char *ddcsx,const char *ddcsy,const char *ddcsz,
+             int nstepout,int resetstep,int nmultisim,int repl_ex_nst,int repl_ex_seed,
+             real pforce,real cpt_period,real max_hours,
+             const char *deviceOptions,
+             unsigned long Flags,
+             real xy_fac, real xy_max, real z_fac, real z_max,
+             int it_xy, int it_z, real probe_rad, int low_up_rm,
+             int pieces, bool bALLOW_ASYMMETRY, int maxwarn)
+{
+    double     nodetime=0,realtime;
+    t_inputrec *inputrec;
+    t_state    *state=NULL;
+    matrix     box;
+    gmx_ddbox_t ddbox;
+    int        npme_major,npme_minor;
+    real       tmpr1,tmpr2;
+    t_nrnb     *nrnb;
+    gmx_mtop_t *mtop=NULL;
+    t_mdatoms  *mdatoms=NULL;
+    t_forcerec *fr=NULL;
+    t_fcdata   *fcd=NULL;
+    real       ewaldcoeff=0;
+    gmx_pme_t  *pmedata=NULL;
+    gmx_vsite_t *vsite=NULL;
+    gmx_constr_t constr;
+    int        i,m,nChargePerturbed=-1,status,nalloc;
+    char       *gro;
+    gmx_wallcycle_t wcycle;
+    bool       bReadRNG,bReadEkin;
+    int        list;
+    gmx_runtime_t runtime;
+    int        rc;
+    gmx_large_int_t reset_counters;
+    gmx_edsam_t ed=NULL;
+    t_commrec   *cr_old=cr;
+    int        nthreads=1,nthreads_requested=1;
+
+
+       char                    *ins;
+       int                     rm_bonded_at,fr_id,fr_i=0,tmp_id,warn=0;
+       int                     ng,j,max_lip_rm,ins_grp_id,ins_nat,mem_nat,ntype,lip_rm,tpr_version;
+       real                    xy_step=0,z_step=0;
+       real                    prot_area;
+       rvec                    *r_ins=NULL,fac;
+       t_block                 *ins_at,*rest_at;
+       pos_ins_t               *pos_ins;
+       mem_t                   *mem_p;
+       rm_t                    *rm_p;
+       gmx_groups_t            *groups;
+       bool                    bExcl=FALSE;
+       t_atoms                 atoms;
+       t_pbc                   *pbc;
+       char                    **piecename=NULL;
+
+    /* CAUTION: threads may be started later on in this function, so
+       cr doesn't reflect the final parallel state right now */
+    snew(inputrec,1);
+    snew(mtop,1);
+
+    if (bVerbose && SIMMASTER(cr))
+    {
+        fprintf(stderr,"Getting Loaded...\n");
+    }
+
+    if (Flags & MD_APPENDFILES)
+    {
+        fplog = NULL;
+    }
+
+    snew(state,1);
+    if (MASTER(cr))
+    {
+        /* Read (nearly) all data required for the simulation */
+        read_tpx_state(ftp2fn(efTPX,nfile,fnm),inputrec,state,NULL,mtop);
+
+        /* NOW the threads will be started: */
+#ifdef GMX_THREADS
+#endif
+    }
+    /* END OF CAUTION: cr is now reliable */
+
+    /* now make sure the state is initialized and propagated */
+    set_state_entries(state,inputrec,cr->nnodes);
+    if (PAR(cr))
+    {
+        /* now broadcast everything to the non-master nodes/threads: */
+        init_parallel(fplog, cr, inputrec, mtop, state);
+    }
+
+    if (can_use_allvsall(inputrec,mtop,TRUE,cr,fplog))
+    {
+        /* All-vs-all loops do not work with domain decomposition */
+        Flags |= MD_PARTDEC;
+    }
+
+    if (!EEL_PME(inputrec->coulombtype) || (Flags & MD_PARTDEC))
+    {
+        cr->npmenodes = 0;
+    }
+
+       snew(ins_at,1);
+       snew(pos_ins,1);
+       if(MASTER(cr))
+       {
+               tpr_version = get_tpr_version(ftp2fn(efTPX,nfile,fnm));
+               if (tpr_version<58)
+                       gmx_fatal(FARGS,"Version of *.tpr file to old (%d). Rerun grompp with gromacs VERSION 4.0.3 or newer.\n",tpr_version);
+
+               if( inputrec->eI != eiMD )
+                       gmx_input("Change integrator to md in mdp file.");
+
+               if(PAR(cr))
+                       gmx_input("Sorry, parallel g_membed is not yet fully functrional.");
+
+               groups=&(mtop->groups);
+
+               atoms=gmx_mtop_global_atoms(mtop);
+               snew(mem_p,1);
+               fprintf(stderr,"\nSelect a group to embed in the membrane:\n");
+               get_index(&atoms,ftp2fn_null(efNDX,nfile,fnm),1,&(ins_at->nr),&(ins_at->index),&ins);
+               ins_grp_id = search_string(ins,groups->ngrpname,(groups->grpname));
+               fprintf(stderr,"\nSelect a group to embed %s into (e.g. the membrane):\n",ins);
+               get_index(&atoms,ftp2fn_null(efNDX,nfile,fnm),1,&(mem_p->mem_at.nr),&(mem_p->mem_at.index),&(mem_p->name));
+
+               pos_ins->pieces=pieces;
+               snew(pos_ins->nidx,pieces);
+               snew(pos_ins->subindex,pieces);
+               snew(piecename,pieces); 
+               if (pieces>1)
+               {
+                       fprintf(stderr,"\nSelect pieces to embed:\n");
+                       get_index(&atoms,ftp2fn_null(efNDX,nfile,fnm),pieces,pos_ins->nidx,pos_ins->subindex,piecename);
+               }
+               else
+               {       
+                       /*use whole embedded group*/
+                       snew(pos_ins->nidx,1);
+                       snew(pos_ins->subindex,1);
+                       pos_ins->nidx[0]=ins_at->nr;
+                       pos_ins->subindex[0]=ins_at->index;
+               }
+
+               if(probe_rad<0.2199999)
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d:\nA probe radius (-rad) smaller than 0.2 can result in overlap between waters "
+                                       "and the group to embed, which will result in Lincs errors etc.\nIf you are sure, you can increase maxwarn.\n\n",warn);
+               }
+
+               if(xy_fac<0.09999999)
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d:\nThe initial size of %s is probably too smal.\n"
+                                       "If you are sure, you can increase maxwarn.\n\n",warn,ins);
+               }
+
+               if(it_xy<1000)
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d;\nThe number of steps used to grow the xy-coordinates of %s (%d) is probably too small.\n"
+                                       "Increase -nxy or, if you are sure, you can increase maxwarn.\n\n",warn,ins,it_xy);
+               }
+
+               if( (it_z<100) && ( z_fac<0.99999999 || z_fac>1.0000001) )
+                {
+                        warn++;
+                        fprintf(stderr,"\nWarning %d;\nThe number of steps used to grow the z-coordinate of %s (%d) is probably too small.\n"
+                                       "Increase -nz or, if you are sure, you can increase maxwarn.\n\n",warn,ins,it_z);
+                }
+
+               if(it_xy+it_z>inputrec->nsteps)
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d:\nThe number of growth steps (-nxy + -nz) is larger than the number of steps in the tpr.\n"
+                                       "If you are sure, you can increase maxwarn.\n\n",warn);
+               }
+
+               fr_id=-1;
+               if( inputrec->opts.ngfrz==1)
+                       gmx_fatal(FARGS,"You did not specify \"%s\" as a freezegroup.",ins);
+               for(i=0;i<inputrec->opts.ngfrz;i++)
+               {
+                       tmp_id = mtop->groups.grps[egcFREEZE].nm_ind[i];
+                       if(ins_grp_id==tmp_id)
+                       {
+                               fr_id=tmp_id;
+                               fr_i=i;
+                       }
+               }
+               if (fr_id == -1 )
+                       gmx_fatal(FARGS,"\"%s\" not as freezegroup defined in the mdp-file.",ins);
+
+               for(i=0;i<DIM;i++)
+                       if( inputrec->opts.nFreeze[fr_i][i] != 1)
+                               gmx_fatal(FARGS,"freeze dimensions for %s are not Y Y Y\n",ins);
+
+               ng = groups->grps[egcENER].nr;
+               if (ng == 1)
+                       gmx_input("No energy groups defined. This is necessary for energy exclusion in the freeze group");
+
+               for(i=0;i<ng;i++)
+               {
+                       for(j=0;j<ng;j++)
+                       {
+                               if (inputrec->opts.egp_flags[ng*i+j] == EGP_EXCL)
+                               {
+                                       bExcl = TRUE;
+                                       if ( (groups->grps[egcENER].nm_ind[i] != ins_grp_id) || (groups->grps[egcENER].nm_ind[j] != ins_grp_id) )
+                                               gmx_fatal(FARGS,"Energy exclusions \"%s\" and  \"%s\" do not match the group to embed \"%s\"",
+                                                               *groups->grpname[groups->grps[egcENER].nm_ind[i]],
+                                                               *groups->grpname[groups->grps[egcENER].nm_ind[j]],ins);
+                               }
+                       }
+               }
+               if (!bExcl)
+                       gmx_input("No energy exclusion groups defined. This is necessary for energy exclusion in the freeze group");
+
+               /* Set all atoms in box*/
+               /*set_inbox(state->natoms,state->x);*/
+
+               /* Guess the area the protein will occupy in the membrane plane  Calculate area per lipid*/
+               snew(rest_at,1);
+               ins_nat = init_ins_at(ins_at,rest_at,state,pos_ins,groups,ins_grp_id,xy_max);
+               /* Check moleculetypes in insertion group */
+               check_types(ins_at,rest_at,mtop);
+
+               mem_nat = init_mem_at(mem_p,mtop,state->x,state->box,pos_ins);
+
+               prot_area = est_prot_area(pos_ins,state->x,ins_at,mem_p);
+               if ( (prot_area>7.5) && ( (state->box[XX][XX]*state->box[YY][YY]-state->box[XX][YY]*state->box[YY][XX])<50) )
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d:\nThe xy-area is very small compared to the area of the protein.\n"
+                                       "This might cause pressure problems during the growth phase. Just try with\n"
+                                       "current setup (-maxwarn + 1), but if pressure problems occur, lower the\n"
+                                       "compressibility in the mdp-file or use no pressure coupling at all.\n\n",warn);
+               }
+               if(warn>maxwarn)
+                                       gmx_fatal(FARGS,"Too many warnings.\n");
+
+               printf("The estimated area of the protein in the membrane is %.3f nm^2\n",prot_area);
+               printf("\nThere are %d lipids in the membrane part that overlaps the protein.\nThe area per lipid is %.4f nm^2.\n",mem_p->nmol,mem_p->lip_area);
+
+               /* Maximum number of lipids to be removed*/
+               max_lip_rm=(int)(2*prot_area/mem_p->lip_area);
+               printf("Maximum number of lipids that will be removed is %d.\n",max_lip_rm);
+
+               printf("\nWill resize the protein by a factor of %.3f in the xy plane and %.3f in the z direction.\n"
+                               "This resizing will be done with respect to the geometrical center of all protein atoms\n"
+                               "that span the membrane region, i.e. z between %.3f and %.3f\n\n",xy_fac,z_fac,mem_p->zmin,mem_p->zmax);
+
+               /* resize the protein by xy and by z if necessary*/
+               snew(r_ins,ins_at->nr);
+               init_resize(ins_at,r_ins,pos_ins,mem_p,state->x,bALLOW_ASYMMETRY);
+               fac[0]=fac[1]=xy_fac;
+               fac[2]=z_fac;
+
+               xy_step =(xy_max-xy_fac)/(double)(it_xy);
+               z_step  =(z_max-z_fac)/(double)(it_z-1);
+
+               resize(ins_at,r_ins,state->x,pos_ins,fac);
+
+               /* remove overlapping lipids and water from the membrane box*/
+               /*mark molecules to be removed*/
+               snew(pbc,1);
+               set_pbc(pbc,inputrec->ePBC,state->box);
+
+               snew(rm_p,1);
+               lip_rm = gen_rm_list(rm_p,ins_at,rest_at,pbc,mtop,state->x, r_ins, mem_p,pos_ins,probe_rad,low_up_rm,bALLOW_ASYMMETRY);
+        lip_rm -= low_up_rm;
+
+               if(fplog)
+                       for(i=0;i<rm_p->nr;i++)
+                               fprintf(fplog,"rm mol %d\n",rm_p->mol[i]);
+
+               for(i=0;i<mtop->nmolblock;i++)
+               {
+                       ntype=0;
+                       for(j=0;j<rm_p->nr;j++)
+                               if(rm_p->block[j]==i)
+                                       ntype++;
+                       printf("Will remove %d %s molecules\n",ntype,*(mtop->moltype[mtop->molblock[i].type].name));
+               }
+
+               if(lip_rm>max_lip_rm)
+               {
+                       warn++;
+                       fprintf(stderr,"\nWarning %d:\nTrying to remove a larger lipid area than the estimated protein area\n"
+                                       "Try making the -xyinit resize factor smaller. If you are sure about this increase maxwarn.\n\n",warn);
+               }
+
+               /*remove all lipids and waters overlapping and update all important structures*/
+               rm_group(inputrec,groups,mtop,rm_p,state,ins_at,pos_ins);
+
+               rm_bonded_at = rm_bonded(ins_at,mtop);
+               if (rm_bonded_at != ins_at->nr)
+               {
+                       fprintf(stderr,"Warning: The number of atoms for which the bonded interactions are removed is %d, "
+                                       "while %d atoms are embedded. Make sure that the atoms to be embedded are not in the same"
+                                       "molecule type as atoms that are not to be embedded.\n",rm_bonded_at,ins_at->nr);
+               }
+
+               if(warn>maxwarn)
+                       gmx_fatal(FARGS,"Too many warnings.\nIf you are sure these warnings are harmless, you can increase -maxwarn");
+
+               if (MASTER(cr))
+               {
+                       if (ftp2bSet(efTOP,nfile,fnm))
+                               top_update(opt2fn("-p",nfile,fnm),ins,rm_p,mtop);
+               }
+
+               sfree(pbc);
+               sfree(rest_at);
+       }
+
+#ifdef GMX_FAHCORE
+    fcRegisterSteps(inputrec->nsteps,inputrec->init_step);
+#endif
+
+    /* NMR restraints must be initialized before load_checkpoint,
+     * since with time averaging the history is added to t_state.
+     * For proper consistency check we therefore need to extend
+     * t_state here.
+     * So the PME-only nodes (if present) will also initialize
+     * the distance restraints.
+     */
+    snew(fcd,1);
+
+    /* This needs to be called before read_checkpoint to extend the state */
+    init_disres(fplog,mtop,inputrec,cr,Flags & MD_PARTDEC,fcd,state);
+
+    if (gmx_mtop_ftype_count(mtop,F_ORIRES) > 0)
+    {
+        if (PAR(cr) && !(Flags & MD_PARTDEC))
+        {
+            gmx_fatal(FARGS,"Orientation restraints do not work (yet) with domain decomposition, use particle decomposition (mdrun option -pd)");
+        }
+        /* Orientation restraints */
+        if (MASTER(cr))
+        {
+            init_orires(fplog,mtop,state->x,inputrec,cr->ms,&(fcd->orires),
+                        state);
+        }
+    }
+
+    if (DEFORM(*inputrec))
+    {
+        /* Store the deform reference box before reading the checkpoint */
+        if (SIMMASTER(cr))
+        {
+            copy_mat(state->box,box);
+        }
+        if (PAR(cr))
+        {
+            gmx_bcast(sizeof(box),box,cr);
+        }
+        /* Because we do not have the update struct available yet
+         * in which the reference values should be stored,
+         * we store them temporarily in static variables.
+         * This should be thread safe, since they are only written once
+         * and with identical values.
+         */
+/*        deform_init_init_step_tpx = inputrec->init_step;*/
+/*        copy_mat(box,deform_init_box_tpx);*/
+    }
+
+    if (opt2bSet("-cpi",nfile,fnm))
+    {
+        /* Check if checkpoint file exists before doing continuation.
+         * This way we can use identical input options for the first and subsequent runs...
+         */
+        if( gmx_fexist_master(opt2fn_master("-cpi",nfile,fnm,cr),cr) )
+        {
+            load_checkpoint(opt2fn_master("-cpi",nfile,fnm,cr),&fplog,
+                            cr,Flags & MD_PARTDEC,ddxyz,
+                            inputrec,state,&bReadRNG,&bReadEkin,
+                            (Flags & MD_APPENDFILES));
+
+            if (bReadRNG)
+            {
+                Flags |= MD_READ_RNG;
+            }
+            if (bReadEkin)
+            {
+                Flags |= MD_READ_EKIN;
+            }
+        }
+    }
+
+    if ((MASTER(cr) || (Flags & MD_SEPPOT)) && (Flags & MD_APPENDFILES))
+    {
+        gmx_log_open(ftp2fn(efLOG,nfile,fnm),cr,!(Flags & MD_SEPPOT),
+                             Flags,&fplog);
+    }
+
+    if (SIMMASTER(cr))
+    {
+        copy_mat(state->box,box);
+    }
+
+    if (PAR(cr))
+    {
+        gmx_bcast(sizeof(box),box,cr);
+    }
+
+    if (bVerbose && SIMMASTER(cr))
+    {
+        fprintf(stderr,"Loaded with Money\n\n");
+    }
+
+    if (PAR(cr) && !((Flags & MD_PARTDEC) || EI_TPI(inputrec->eI)))
+    {
+        cr->dd = init_domain_decomposition(fplog,cr,Flags,ddxyz,rdd,rconstr,
+                                           dddlb_opt,dlb_scale,
+                                           ddcsx,ddcsy,ddcsz,
+                                           mtop,inputrec,
+                                           box,state->x,
+                                           &ddbox,&npme_major,&npme_minor);
+
+        make_dd_communicators(fplog,cr,dd_node_order);
+
+        /* Set overallocation to avoid frequent reallocation of arrays */
+        set_over_alloc_dd(TRUE);
+    }
+    else
+    {
+        /* PME, if used, is done on all nodes with 1D decomposition */
+        cr->npmenodes = 0;
+        cr->duty = (DUTY_PP | DUTY_PME);
+        npme_major = cr->nnodes;
+        npme_minor = 1;
+
+        if (inputrec->ePBC == epbcSCREW)
+        {
+            gmx_fatal(FARGS,
+                      "pbc=%s is only implemented with domain decomposition",
+                      epbc_names[inputrec->ePBC]);
+        }
+    }
+
+    if (PAR(cr))
+    {
+        /* After possible communicator splitting in make_dd_communicators.
+         * we can set up the intra/inter node communication.
+         */
+        gmx_setup_nodecomm(fplog,cr);
+    }
+
+    wcycle = wallcycle_init(fplog,resetstep,cr);
+    if (PAR(cr))
+    {
+        /* Master synchronizes its value of reset_counters with all nodes
+         * including PME only nodes */
+        reset_counters = wcycle_get_reset_counters(wcycle);
+        gmx_bcast_sim(sizeof(reset_counters),&reset_counters,cr);
+        wcycle_set_reset_counters(wcycle, reset_counters);
+    }
+
+
+    snew(nrnb,1);
+    if (cr->duty & DUTY_PP)
+    {
+        /* For domain decomposition we allocate dynamically
+         * in dd_partition_system.
+         */
+        if (DOMAINDECOMP(cr))
+        {
+            bcast_state_setup(cr,state);
+        }
+        else
+        {
+            if (PAR(cr))
+            {
+                if (!MASTER(cr))
+                {
+                    snew(state,1);
+                }
+                bcast_state(cr,state,TRUE);
+            }
+        }
+
+        /* Dihedral Restraints */
+        if (gmx_mtop_ftype_count(mtop,F_DIHRES) > 0)
+        {
+            init_dihres(fplog,mtop,inputrec,fcd);
+        }
+
+        /* Initiate forcerecord */
+        fr = mk_forcerec();
+        init_forcerec(fplog,oenv,fr,fcd,inputrec,mtop,cr,box,FALSE,
+                      opt2fn("-table",nfile,fnm),
+                      opt2fn("-tablep",nfile,fnm),
+                      opt2fn("-tableb",nfile,fnm),FALSE,pforce);
+
+        /* version for PCA_NOT_READ_NODE (see md.c) */
+        /*init_forcerec(fplog,fr,fcd,inputrec,mtop,cr,box,FALSE,
+          "nofile","nofile","nofile",FALSE,pforce);
+          */
+        fr->bSepDVDL = ((Flags & MD_SEPPOT) == MD_SEPPOT);
+
+        /* Initialize QM-MM */
+        if(fr->bQMMM)
+        {
+            init_QMMMrec(cr,box,mtop,inputrec,fr);
+        }
+
+        /* Initialize the mdatoms structure.
+         * mdatoms is not filled with atom data,
+         * as this can not be done now with domain decomposition.
+         */
+        mdatoms = init_mdatoms(fplog,mtop,inputrec->efep!=efepNO);
+
+        /* Initialize the virtual site communication */
+        vsite = init_vsite(mtop,cr);
+
+        calc_shifts(box,fr->shift_vec);
+
+        /* With periodic molecules the charge groups should be whole at start up
+         * and the virtual sites should not be far from their proper positions.
+         */
+        if (!inputrec->bContinuation && MASTER(cr) &&
+            !(inputrec->ePBC != epbcNONE && inputrec->bPeriodicMols))
+        {
+            /* Make molecules whole at start of run */
+            if (fr->ePBC != epbcNONE)
+            {
+                do_pbc_first_mtop(fplog,inputrec->ePBC,box,mtop,state->x);
+            }
+            if (vsite)
+            {
+                /* Correct initial vsite positions are required
+                 * for the initial distribution in the domain decomposition
+                 * and for the initial shell prediction.
+                 */
+                construct_vsites_mtop(fplog,vsite,mtop,state->x);
+            }
+        }
+
+        /* Initiate PPPM if necessary */
+        if (fr->eeltype == eelPPPM)
+        {
+            if (mdatoms->nChargePerturbed)
+            {
+                gmx_fatal(FARGS,"Free energy with %s is not implemented",
+                          eel_names[fr->eeltype]);
+            }
+            status = gmx_pppm_init(fplog,cr,oenv,FALSE,TRUE,box,
+                                   getenv("GMXGHAT"),inputrec, (Flags & MD_REPRODUCIBLE));
+            if (status != 0)
+            {
+                gmx_fatal(FARGS,"Error %d initializing PPPM",status);
+            }
+        }
+
+        if (EEL_PME(fr->eeltype))
+        {
+            ewaldcoeff = fr->ewaldcoeff;
+            pmedata = &fr->pmedata;
+        }
+        else
+        {
+            pmedata = NULL;
+        }
+    }
+    else
+    {
+        /* This is a PME only node */
+
+        /* We don't need the state */
+        done_state(state);
+
+        ewaldcoeff = calc_ewaldcoeff(inputrec->rcoulomb, inputrec->ewald_rtol);
+        snew(pmedata,1);
+    }
+
+    /* Initiate PME if necessary,
+     * either on all nodes or on dedicated PME nodes only. */
+    if (EEL_PME(inputrec->coulombtype))
+    {
+        if (mdatoms)
+        {
+            nChargePerturbed = mdatoms->nChargePerturbed;
+        }
+        if (cr->npmenodes > 0)
+        {
+            /* The PME only nodes need to know nChargePerturbed */
+            gmx_bcast_sim(sizeof(nChargePerturbed),&nChargePerturbed,cr);
+        }
+        if (cr->duty & DUTY_PME)
+        {
+            status = gmx_pme_init(pmedata,cr,npme_major,npme_minor,inputrec,
+                                  mtop ? mtop->natoms : 0,nChargePerturbed,
+                                  (Flags & MD_REPRODUCIBLE));
+            if (status != 0)
+            {
+                gmx_fatal(FARGS,"Error %d initializing PME",status);
+            }
+        }
+    }
+
+
+/*    if (integrator[inputrec->eI].func == do_md
+#ifdef GMX_OPENMM
+        ||
+        integrator[inputrec->eI].func == do_md_openmm
+#endif
+        )
+    {*/
+        /* Turn on signal handling on all nodes */
+        /*
+         * (A user signal from the PME nodes (if any)
+         * is communicated to the PP nodes.
+         */
+        signal_handler_install();
+/*    }*/
+
+    if (cr->duty & DUTY_PP)
+    {
+        if (inputrec->ePull != epullNO)
+        {
+            /* Initialize pull code */
+            init_pull(fplog,inputrec,nfile,fnm,mtop,cr,oenv,
+                      EI_DYNAMICS(inputrec->eI) && MASTER(cr),Flags);
+        }
+
+        constr = init_constraints(fplog,mtop,inputrec,ed,state,cr);
+
+        if (DOMAINDECOMP(cr))
+        {
+            dd_init_bondeds(fplog,cr->dd,mtop,vsite,constr,inputrec,
+                            Flags & MD_DDBONDCHECK,fr->cginfo_mb);
+
+            set_dd_parameters(fplog,cr->dd,dlb_scale,inputrec,fr,&ddbox);
+
+            setup_dd_grid(fplog,cr->dd);
+        }
+
+        /* Now do whatever the user wants us to do (how flexible...) */
+        do_md_membed(fplog,cr,nfile,fnm,
+                                      oenv,bVerbose,bCompact,
+                                      nstglobalcomm,
+                                      vsite,constr,
+                                      nstepout,inputrec,mtop,
+                                      fcd,state,
+                                      mdatoms,nrnb,wcycle,ed,fr,
+                                      repl_ex_nst,repl_ex_seed,
+                                      cpt_period,max_hours,
+                                      deviceOptions,
+                                      Flags,
+                                      &runtime,
+                                      fac, r_ins, pos_ins, ins_at,
+                                      xy_step, z_step, it_xy, it_z);
+
+        if (inputrec->ePull != epullNO)
+        {
+            finish_pull(fplog,inputrec->pull);
+        }
+    }
+    else
+    {
+        /* do PME only */
+        gmx_pmeonly(*pmedata,cr,nrnb,wcycle,ewaldcoeff,FALSE,inputrec);
+    }
+
+    if (EI_DYNAMICS(inputrec->eI) || EI_TPI(inputrec->eI))
+    {
+        /* Some timing stats */
+        if (MASTER(cr))
+        {
+            if (runtime.proc == 0)
+            {
+                runtime.proc = runtime.real;
+            }
+        }
+        else
+        {
+            runtime.real = 0;
+        }
+    }
+
+    wallcycle_stop(wcycle,ewcRUN);
+
+    /* Finish up, write some stuff
+     * if rerunMD, don't write last frame again
+     */
+    finish_run(fplog,cr,ftp2fn(efSTO,nfile,fnm),
+               inputrec,nrnb,wcycle,&runtime,
+               EI_DYNAMICS(inputrec->eI) && !MULTISIM(cr));
+
+    /* Does what it says */
+    print_date_and_time(fplog,cr->nodeid,"Finished mdrun",&runtime);
+
+    /* Close logfile already here if we were appending to it */
+    if (MASTER(cr) && (Flags & MD_APPENDFILES))
+    {
+        gmx_log_close(fplog);
+    }
+
+    if (pieces>1)
+    {
+       sfree(piecename);
+    }
+
+    rc=(int)gmx_get_stop_condition();
+
+    return rc;
+}
+
+int gmx_membed(int argc,char *argv[])
+{
+       const char *desc[] = {
+                       "g_membed embeds a membrane protein into an equilibrated lipid bilayer at the position",
+                       "and orientation specified by the user.\n",
+                       "\n",
+                       "SHORT MANUAL\n------------\n",
+                       "The user should merge the structure files of the protein and membrane (+solvent), creating a",
+                       "single structure file with the protein overlapping the membrane at the desired position and",
+                       "orientation. Box size should be taken from the membrane structure file. The corresponding topology",
+                       "files should also be merged. Consecutively, create a tpr file (input for g_membed) from these files,"
+                       "with the following options included in the mdp file.\n",
+                       " - integrator      = md\n",
+                       " - energygrp       = Protein (or other group that you want to insert)\n",
+                       " - freezegrps      = Protein\n",
+                       " - freezedim       = Y Y Y\n",
+                       " - energygrp_excl  = Protein Protein\n",
+                       "The output is a structure file containing the protein embedded in the membrane. If a topology",
+                       "file is provided, the number of lipid and ",
+                       "solvent molecules will be updated to match the new structure file.\n",
+                       "For a more extensive manual see Wolf et al, J Comp Chem 31 (2010) 2169-2174, Appendix.\n",
+                       "\n",
+                       "SHORT METHOD DESCRIPTION\n",
+                       "------------------------\n",
+                       "1. The protein is resized around its center of mass by a factor -xy in the xy-plane",
+                       "(the membrane plane) and a factor -z in the z-direction (if the size of the",
+                       "protein in the z-direction is the same or smaller than the width of the membrane, a",
+                       "-z value larger than 1 can prevent that the protein will be enveloped by the lipids).\n",
+                       "2. All lipid and solvent molecules overlapping with the resized protein are removed. All",
+                       "intraprotein interactions are turned off to prevent numerical issues for small values of -xy",
+                       " or -z\n",
+                       "3. One md step is performed.\n",
+                       "4. The resize factor (-xy or -z) is incremented by a small amount ((1-xy)/nxy or (1-z)/nz) and the",
+                       "protein is resized again around its center of mass. The resize factor for the xy-plane",
+                       "is incremented first. The resize factor for the z-direction is not changed until the -xy factor",
+                       "is 1 (thus after -nxy iteration).\n",
+                       "5. Repeat step 3 and 4 until the protein reaches its original size (-nxy + -nz iterations).\n",
+                       "For a more extensive method descrition see Wolf et al, J Comp Chem, 31 (2010) 2169-2174.\n",
+                       "\n",
+                       "NOTE\n----\n",
+                       " - Protein can be any molecule you want to insert in the membrane.\n",
+                       " - It is recommended to perform a short equilibration run after the embedding",
+                       "(see Wolf et al, J Comp Chem 31 (2010) 2169-2174, to re-equilibrate the membrane. Clearly",
+                       "protein equilibration might require longer.\n",
+                       "\n"
+       };
+       t_commrec    *cr;
+       t_filenm fnm[] = {
+                       { efTPX, "-f",      "into_mem", ffREAD },
+                       { efNDX, "-n",      "index",    ffOPTRD },
+                       { efTOP, "-p",      "topol",    ffOPTRW },
+                       { efTRN, "-o",      NULL,       ffWRITE },
+                       { efXTC, "-x",      NULL,       ffOPTWR },
+                       { efCPT, "-cpi",    NULL,       ffOPTRD },
+                       { efCPT, "-cpo",    NULL,       ffOPTWR },
+                       { efSTO, "-c",      "membedded",  ffWRITE },
+                       { efEDR, "-e",      "ener",     ffWRITE },
+                       { efLOG, "-g",      "md",       ffWRITE },
+                       { efEDI, "-ei",     "sam",      ffOPTRD },
+                       { efTRX, "-rerun",  "rerun",    ffOPTRD },
+                       { efXVG, "-table",  "table",    ffOPTRD },
+                       { efXVG, "-tablep", "tablep",   ffOPTRD },
+                       { efXVG, "-tableb", "table",    ffOPTRD },
+                       { efXVG, "-dhdl",   "dhdl",     ffOPTWR },
+                       { efXVG, "-field",  "field",    ffOPTWR },
+                       { efXVG, "-table",  "table",    ffOPTRD },
+                       { efXVG, "-tablep", "tablep",   ffOPTRD },
+                       { efXVG, "-tableb", "table",    ffOPTRD },
+                       { efTRX, "-rerun",  "rerun",    ffOPTRD },
+                       { efXVG, "-tpi",    "tpi",      ffOPTWR },
+                       { efXVG, "-tpid",   "tpidist",  ffOPTWR },
+                       { efEDI, "-ei",     "sam",      ffOPTRD },
+                       { efEDO, "-eo",     "sam",      ffOPTWR },
+                       { efGCT, "-j",      "wham",     ffOPTRD },
+                       { efGCT, "-jo",     "bam",      ffOPTWR },
+                       { efXVG, "-ffout",  "gct",      ffOPTWR },
+                       { efXVG, "-devout", "deviatie", ffOPTWR },
+                       { efXVG, "-runav",  "runaver",  ffOPTWR },
+                       { efXVG, "-px",     "pullx",    ffOPTWR },
+                       { efXVG, "-pf",     "pullf",    ffOPTWR },
+                       { efMTX, "-mtx",    "nm",       ffOPTWR },
+                       { efNDX, "-dn",     "dipole",   ffOPTWR }
+       };
+#define NFILE asize(fnm)
+
+       /* Command line options ! */
+       bool bCart        = FALSE;
+       bool bPPPME       = FALSE;
+       bool bPartDec     = FALSE;
+       bool bDDBondCheck = TRUE;
+       bool bDDBondComm  = TRUE;
+       bool bVerbose     = FALSE;
+       bool bCompact     = TRUE;
+       bool bSepPot      = FALSE;
+       bool bRerunVSite  = FALSE;
+       bool bIonize      = FALSE;
+       bool bConfout     = TRUE;
+       bool bReproducible = FALSE;
+
+       int  npme=-1;
+       int  nmultisim=0;
+       int  nstglobalcomm=-1;
+       int  repl_ex_nst=0;
+       int  repl_ex_seed=-1;
+       int  nstepout=100;
+       int  nthreads=0; /* set to determine # of threads automatically */
+       int  resetstep=-1;
+
+       rvec realddxyz={0,0,0};
+       const char *ddno_opt[ddnoNR+1] =
+       { NULL, "interleave", "pp_pme", "cartesian", NULL };
+       const char *dddlb_opt[] =
+       { NULL, "auto", "no", "yes", NULL };
+       real rdd=0.0,rconstr=0.0,dlb_scale=0.8,pforce=-1;
+       char *ddcsx=NULL,*ddcsy=NULL,*ddcsz=NULL;
+       real cpt_period=15.0,max_hours=-1;
+       bool bAppendFiles=TRUE,bAddPart=TRUE;
+       bool bResetCountersHalfWay=FALSE;
+       output_env_t oenv=NULL;
+       const char *deviceOptions = "";
+
+       real xy_fac = 0.5;
+       real xy_max = 1.0;
+       real z_fac = 1.0;
+       real z_max = 1.0;
+       int it_xy = 1000;
+       int it_z = 0;
+       real probe_rad = 0.22;
+       int low_up_rm = 0;
+       int maxwarn=0;
+       int pieces=1;
+    bool bALLOW_ASYMMETRY=FALSE;
+
+
+/* arguments relevant to OPENMM only*/
+#ifdef GMX_OPENMM
+    gmx_input("g_membed not functional in openmm");
+#endif
+
+       t_pargs pa[] = {
+                       { "-xyinit",   FALSE, etREAL,  {&xy_fac},       "Resize factor for the protein in the xy dimension before starting embedding" },
+                       { "-xyend",   FALSE, etREAL,  {&xy_max},                "Final resize factor in the xy dimension" },
+                       { "-zinit",    FALSE, etREAL,  {&z_fac},                "Resize factor for the protein in the z dimension before starting embedding" },
+                       { "-zend",    FALSE, etREAL,  {&z_max},                 "Final resize faction in the z dimension" },
+                       { "-nxy",     FALSE,  etINT,  {&it_xy},         "Number of iteration for the xy dimension" },
+                       { "-nz",      FALSE,  etINT,  {&it_z},          "Number of iterations for the z dimension" },
+                       { "-rad",     FALSE, etREAL,  {&probe_rad},     "Probe radius to check for overlap between the group to embed and the membrane"},
+                       { "-pieces",  FALSE,  etINT,  {&pieces},        "Perform piecewise resize. Select parts of the group to insert and resize these with respect to their own geometrical center." },
+            { "-asymmetry",FALSE, etBOOL,{&bALLOW_ASYMMETRY}, "Allow asymmetric insertion, i.e. the number of lipids removed from the upper and lower leaflet will not be checked." },
+            { "-ndiff" ,  FALSE, etINT, {&low_up_rm},       "Number of lipids that will additionally be removed from the lower (negative number) or upper (positive number) membrane leaflet." },
+                       { "-maxwarn", FALSE, etINT, {&maxwarn},                 "Maximum number of warning allowed" },
+  { "-pd",      FALSE, etBOOL,{&bPartDec},
+    "HIDDENUse particle decompostion" },
+  { "-dd",      FALSE, etRVEC,{&realddxyz},
+    "HIDDENDomain decomposition grid, 0 is optimize" },
+  { "-nt",      FALSE, etINT, {&nthreads},
+    "HIDDENNumber of threads to start (0 is guess)" },
+  { "-npme",    FALSE, etINT, {&npme},
+    "HIDDENNumber of separate nodes to be used for PME, -1 is guess" },
+  { "-ddorder", FALSE, etENUM, {ddno_opt},
+    "HIDDENDD node order" },
+  { "-ddcheck", FALSE, etBOOL, {&bDDBondCheck},
+    "HIDDENCheck for all bonded interactions with DD" },
+  { "-ddbondcomm", FALSE, etBOOL, {&bDDBondComm},
+    "HIDDENUse special bonded atom communication when -rdd > cut-off" },
+  { "-rdd",     FALSE, etREAL, {&rdd},
+    "HIDDENThe maximum distance for bonded interactions with DD (nm), 0 is determine from initial coordinates" },
+  { "-rcon",    FALSE, etREAL, {&rconstr},
+    "HIDDENMaximum distance for P-LINCS (nm), 0 is estimate" },
+  { "-dlb",     FALSE, etENUM, {dddlb_opt},
+    "HIDDENDynamic load balancing (with DD)" },
+  { "-dds",     FALSE, etREAL, {&dlb_scale},
+    "HIDDENMinimum allowed dlb scaling of the DD cell size" },
+  { "-ddcsx",   FALSE, etSTR, {&ddcsx},
+    "HIDDENThe DD cell sizes in x" },
+  { "-ddcsy",   FALSE, etSTR, {&ddcsy},
+    "HIDDENThe DD cell sizes in y" },
+  { "-ddcsz",   FALSE, etSTR, {&ddcsz},
+    "HIDDENThe DD cell sizes in z" },
+  { "-gcom",    FALSE, etINT,{&nstglobalcomm},
+    "HIDDENGlobal communication frequency" },
+  { "-compact", FALSE, etBOOL,{&bCompact},
+    "Write a compact log file" },
+  { "-seppot",  FALSE, etBOOL, {&bSepPot},
+    "HIDDENWrite separate V and dVdl terms for each interaction type and node to the log file(s)" },
+  { "-pforce",  FALSE, etREAL, {&pforce},
+    "HIDDENPrint all forces larger than this (kJ/mol nm)" },
+  { "-reprod",  FALSE, etBOOL,{&bReproducible},
+    "HIDDENTry to avoid optimizations that affect binary reproducibility" },
+  { "-multi",   FALSE, etINT,{&nmultisim},
+    "HIDDENDo multiple simulations in parallel" },
+  { "-replex",  FALSE, etINT, {&repl_ex_nst},
+    "HIDDENAttempt replica exchange every # steps" },
+  { "-reseed",  FALSE, etINT, {&repl_ex_seed},
+    "HIDDENSeed for replica exchange, -1 is generate a seed" },
+  { "-rerunvsite", FALSE, etBOOL, {&bRerunVSite},
+    "HIDDENRecalculate virtual site coordinates with -rerun" },
+  { "-ionize",  FALSE, etBOOL,{&bIonize},
+    "HIDDENDo a simulation including the effect of an X-Ray bombardment on your system" },
+  { "-confout", TRUE, etBOOL, {&bConfout},
+    "HIDDENWrite the last configuration with -c and force checkpointing at the last step" },
+  { "-stepout", FALSE, etINT, {&nstepout},
+    "HIDDENFrequency of writing the remaining runtime" },
+  { "-resetstep", FALSE, etINT, {&resetstep},
+    "HIDDENReset cycle counters after these many time steps" },
+  { "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
+    "HIDDENReset the cycle counters after half the number of steps or halfway -maxh" },
+  { "-v",       FALSE, etBOOL,{&bVerbose},
+    "Be loud and noisy" },
+  { "-maxh",   FALSE, etREAL, {&max_hours},
+    "HIDDENTerminate after 0.99 times this time (hours)" },
+  { "-cpt",     FALSE, etREAL, {&cpt_period},
+    "HIDDENCheckpoint interval (minutes)" },
+  { "-append",  FALSE, etBOOL, {&bAppendFiles},
+    "HIDDENAppend to previous output files when continuing from checkpoint" },
+  { "-addpart",  FALSE, etBOOL, {&bAddPart},
+    "HIDDENAdd the simulation part number to all output files when continuing from checkpoint" },
+       };
+       gmx_edsam_t  ed;
+       unsigned long Flags, PCA_Flags;
+       ivec     ddxyz;
+       int      dd_node_order;
+       bool     HaveCheckpoint;
+       FILE     *fplog,*fptest;
+       int      sim_part,sim_part_fn;
+       const char *part_suffix=".part";
+       char     suffix[STRLEN];
+       int      rc;
+
+
+       cr = init_par(&argc,&argv);
+
+       PCA_Flags = (PCA_KEEP_ARGS | PCA_NOEXIT_ON_ARGS | PCA_CAN_SET_DEFFNM
+                       | (MASTER(cr) ? 0 : PCA_QUIET));
+
+
+       /* Comment this in to do fexist calls only on master
+        * works not with rerun or tables at the moment
+        * also comment out the version of init_forcerec in md.c
+        * with NULL instead of opt2fn
+        */
+       /*
+   if (!MASTER(cr))
+   {
+   PCA_Flags |= PCA_NOT_READ_NODE;
+   }
+        */
+
+       parse_common_args(&argc,argv,PCA_Flags, NFILE,fnm,asize(pa),pa,
+                       asize(desc),desc,0,NULL, &oenv);
+
+       /* we set these early because they might be used in init_multisystem()
+   Note that there is the potential for npme>nnodes until the number of
+   threads is set later on, if there's thread parallelization. That shouldn't
+   lead to problems. */
+       dd_node_order = nenum(ddno_opt);
+       cr->npmenodes = npme;
+
+#ifdef GMX_THREADS
+       /* now determine the number of threads automatically. The threads are
+   only started at mdrunner_threads, though. */
+       if (nthreads<1)
+       {
+               nthreads=tMPI_Get_recommended_nthreads();
+       }
+#else
+       nthreads=1;
+#endif
+
+
+       if (repl_ex_nst != 0 && nmultisim < 2)
+               gmx_fatal(FARGS,"Need at least two replicas for replica exchange (option -multi)");
+
+       if (nmultisim > 1) {
+#ifndef GMX_THREADS
+               init_multisystem(cr,nmultisim,NFILE,fnm,TRUE);
+#else
+               gmx_fatal(FARGS,"mdrun -multi is not supported with the thread library.Please compile GROMACS with MPI support");
+#endif
+       }
+
+       /* Check if there is ANY checkpoint file available */
+       sim_part    = 1;
+       sim_part_fn = sim_part;
+       if (opt2bSet("-cpi",NFILE,fnm))
+       {
+               bAppendFiles =
+                       read_checkpoint_simulation_part(opt2fn_master("-cpi", NFILE,
+                                       fnm,cr),
+                                       &sim_part_fn,NULL,cr,
+                                       bAppendFiles,
+                                       part_suffix,&bAddPart);
+               if (sim_part_fn==0 && MASTER(cr))
+               {
+                       fprintf(stdout,"No previous checkpoint file present, assuming this is a new run.\n");
+               }
+               else
+               {
+                       sim_part = sim_part_fn + 1;
+               }
+       }
+       else
+       {
+               bAppendFiles = FALSE;
+       }
+
+       if (!bAppendFiles)
+       {
+               sim_part_fn = sim_part;
+       }
+
+       if (bAddPart && sim_part_fn > 1)
+       {
+               /* This is a continuation run, rename trajectory output files
+       (except checkpoint files) */
+               /* create new part name first (zero-filled) */
+               sprintf(suffix,"%s%04d",part_suffix,sim_part_fn);
+
+               add_suffix_to_output_names(fnm,NFILE,suffix);
+               fprintf(stdout,"Checkpoint file is from part %d, new output files will be suffixed '%s'.\n",sim_part-1,suffix);
+       }
+
+       Flags = opt2bSet("-rerun",NFILE,fnm) ? MD_RERUN : 0;
+       Flags = Flags | (bSepPot       ? MD_SEPPOT       : 0);
+       Flags = Flags | (bIonize       ? MD_IONIZE       : 0);
+       Flags = Flags | (bPartDec      ? MD_PARTDEC      : 0);
+       Flags = Flags | (bDDBondCheck  ? MD_DDBONDCHECK  : 0);
+       Flags = Flags | (bDDBondComm   ? MD_DDBONDCOMM   : 0);
+       Flags = Flags | (bConfout      ? MD_CONFOUT      : 0);
+       Flags = Flags | (bRerunVSite   ? MD_RERUN_VSITE  : 0);
+       Flags = Flags | (bReproducible ? MD_REPRODUCIBLE : 0);
+       Flags = Flags | (bAppendFiles  ? MD_APPENDFILES  : 0);
+       Flags = Flags | (sim_part>1    ? MD_STARTFROMCPT : 0);
+       Flags = Flags | (bResetCountersHalfWay ? MD_RESETCOUNTERSHALFWAY : 0);
+
+
+       /* We postpone opening the log file if we are appending, so we can
+   first truncate the old log file and append to the correct position
+   there instead.  */
+       if ((MASTER(cr) || bSepPot) && !bAppendFiles)
+       {
+               gmx_log_open(ftp2fn(efLOG,NFILE,fnm),cr,!bSepPot,Flags,&fplog);
+               CopyRight(fplog,argv[0]);
+               please_cite(fplog,"Hess2008b");
+               please_cite(fplog,"Spoel2005a");
+               please_cite(fplog,"Lindahl2001a");
+               please_cite(fplog,"Berendsen95a");
+       }
+       else
+       {
+               fplog = NULL;
+       }
+
+       ddxyz[XX] = (int)(realddxyz[XX] + 0.5);
+       ddxyz[YY] = (int)(realddxyz[YY] + 0.5);
+       ddxyz[ZZ] = (int)(realddxyz[ZZ] + 0.5);
+
+       /* even if nthreads = 1, we still call this one */
+
+       rc = mdrunner_membed(fplog, cr, NFILE, fnm, oenv, bVerbose, bCompact,
+                       nstglobalcomm,
+                       ddxyz, dd_node_order, rdd, rconstr, dddlb_opt[0], dlb_scale,
+                       ddcsx, ddcsy, ddcsz, nstepout, resetstep, nmultisim, repl_ex_nst,
+                       repl_ex_seed, pforce, cpt_period, max_hours, deviceOptions, Flags,
+                       xy_fac,xy_max,z_fac,z_max,
+                       it_xy,it_z,probe_rad,low_up_rm,
+                       pieces,bALLOW_ASYMMETRY,maxwarn);
+
+       if (gmx_parallel_env_initialized())
+               gmx_finalize();
+
+       if (MULTIMASTER(cr)) {
+               thanx(stderr);
+       }
+
+       /* Log file has to be closed in mdrunner if we are appending to it
+   (fplog not set here) */
+       fprintf(stderr,"Please cite:\nWolf et al, J Comp Chem 31 (2010) 2169-2174.\n");
+
+       if (MASTER(cr) && !bAppendFiles)
+       {
+               gmx_log_close(fplog);
+       }
+
+       return rc;
+}
index 641b63d9d5d5895a9583af5d5a839e049ece4627..16e3baf21fbfba80587c4c3e2da7c07b26a187de 100644 (file)
@@ -108,14 +108,15 @@ static void periodic_mindist_plot(const char *trxfn,const char *outfn,
 {
   FILE   *out;
   char *leg[5] = { "min per.","max int.","box1","box2","box3" };
-  int    status;
+  t_trxstatus *status;
   real   t;
   rvec   *x;
   matrix box;
   int    natoms,ind_min[2]={0,0},ind_mini=0,ind_minj=0;
   real   r,rmin,rmax,rmint,tmint;
   bool   bFirst;
-  
+  gmx_rmpbc_t  gpbc=NULL;
+
   natoms=read_first_x(oenv,&status,trxfn,&t,&x,box);
   
   check_index(NULL,n,index,NULL,natoms);
@@ -129,11 +130,14 @@ static void periodic_mindist_plot(const char *trxfn,const char *outfn,
   rmint = box[XX][XX];
   tmint = 0;
   
+  if (NULL != top)
+    gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
+
   bFirst=TRUE;  
   do {
-    if (top) {
-      rm_pbc(&(top->idef),ePBC,natoms,box,x,x);
-    }
+    if (NULL != top) 
+      gmx_rmpbc(gpbc,box,x,x);
+    
     periodic_dist(box,x,n,index,&rmin,&rmax,ind_min);
     if (rmin < rmint) {
       rmint = rmin;
@@ -147,6 +151,9 @@ static void periodic_mindist_plot(const char *trxfn,const char *outfn,
            output_env_conv_time(oenv,t),rmin,rmax,norm(box[0]),norm(box[1]),norm(box[2]));
     bFirst=FALSE;
   } while(read_next_x(oenv,status,&t,natoms,x,box));
+
+  if (NULL != top)
+    gmx_rmpbc_done(gpbc);
     
   ffclose(out);
   
@@ -252,11 +259,12 @@ void dist_plot(const char *fn,const char *afile,const char *dfile,
                const output_env_t oenv)
 {
   FILE         *atm,*dist,*num;
-  int          trxout;
+  t_trxstatus  *trxout;
   char         buf[256];
   char         **leg;
   real         t,dmin,dmax,**mindres=NULL,**maxdres=NULL;
-  int          nmin,nmax,status;
+  int          nmin,nmax;
+  t_trxstatus  *status;
   int          i=-1,j,k,natoms;
   int         min1,min2,max1,max2;
   atom_id      oindex[2];
@@ -274,7 +282,7 @@ void dist_plot(const char *fn,const char *afile,const char *dfile,
   sprintf(buf,"Number of Contacts %s %g nm",bMin ? "<" : ">",rcut);
   num = nfile ? xvgropen(nfile,buf,output_env_get_time_label(oenv),"Number",oenv) : NULL;
   atm = afile ? ffopen(afile,"w") : NULL;
-  trxout = xfile ? open_trx(xfile,"w") : NOTSET;
+  trxout = xfile ? open_trx(xfile,"w") : NULL;
   
   if (bMat) {
     if (ng == 1) {
@@ -385,7 +393,7 @@ void dist_plot(const char *fn,const char *afile,const char *dfile,
                output_env_conv_time(oenv,t),1+(bMin ? min1 : max1),
                                   1+(bMin ? min2 : max2));
     
-    if (trxout>=0) {
+    if (trxout) {
       oindex[0]=bMin?min1:max1;
       oindex[1]=bMin?min2:max2;
       write_trx(trxout,2,oindex,atoms,i,t,box,x0,NULL,NULL);
@@ -411,7 +419,7 @@ void dist_plot(const char *fn,const char *afile,const char *dfile,
   ffclose(dist);
   if (num) ffclose(num);
   if (atm) ffclose(atm);
-  if (trxout>=0) close_xtc(trxout);
+  if (trxout) close_trx(trxout);
   
   if(nres && !bEachResEachTime) {
     FILE *res;
@@ -481,7 +489,7 @@ int gmx_mindist(int argc,char *argv[])
     "with multiple atoms in the first group is counted as one contact",
     "instead of as multiple contacts.",
     "With [TT]-or[tt], minimum distances to each residue in the first",
-    "group are determined and plotted as a function of reisdue number.[PAR]",
+    "group are determined and plotted as a function of residue number.[PAR]",
     "With option [TT]-pi[tt] the minimum distance of a group to its",
     "periodic image is plotted. This is useful for checking if a protein",
     "has seen its periodic image during a simulation. Only one shift in",
index fb0e19ac9180f8f423b075720a964a7a570b1d04..ee0925ba0659aff37f0ab264fcc7fce5058661df 100644 (file)
@@ -73,7 +73,7 @@ int gmx_morph(int argc,char *argv[])
     "generic trajectory. The number of intermediates can be controlled with",
     "the -ninterm flag. The first and last flag correspond to the way of",
     "interpolating: 0 corresponds to input structure 1 while",
-    "1 corresponds to input strucutre 2.",
+    "1 corresponds to input structure 2.",
     "If you specify first < 0 or last > 1 extrapolation will be",
     "on the path from input structure x1 to x2. In general the coordinates",
     "of the intermediate x(i) out of N total intermidates correspond to:[PAR]",
@@ -85,7 +85,7 @@ int gmx_morph(int argc,char *argv[])
   t_filenm fnm[] = {
     { efSTX, "-f1", "conf1",  ffREAD },
     { efSTX, "-f2", "conf2",  ffREAD },
-    { efTRO, "-o",  "interm", ffWRITE },
+    { efTRX, "-o",  "interm", ffWRITE },
     { efXVG, "-or", "rms-interm", ffOPTWR },
     { efNDX, "-n",  "index",  ffOPTRD }
   };
@@ -106,7 +106,8 @@ int gmx_morph(int argc,char *argv[])
   };
   char *leg[] = { "Ref = 1\\Sst\\N conf", "Ref = 2\\Snd\\N conf" };
   FILE     *fp=NULL;
-  int      i,isize,is_lsq,status,nat1,nat2;
+  int      i,isize,is_lsq,nat1,nat2;
+  t_trxstatus *status;
   atom_id  *index,*index_lsq,*index_all,*dummy;
   t_atoms  atoms;
   rvec     *x1,*x2,*xx,*v;
index 0bd60f03ff0a0e3180a222caebbbb50428b4957a..357b5cd31c865d451a9b603d6567f2f0fbe56fea 100644 (file)
    coefficient in X,Y,Z direction. LATERAL is diffusion coefficient in
    plane perpendicular to axis
 */
-enum { NOT_USED, NORMAL, X, Y, Z, LATERAL };
+typedef enum { NOT_USED, NORMAL, X, Y, Z, LATERAL } msd_type;
 
 typedef struct {
-  real    t0,delta_t,beginfit,endfit,dim_factor;
-  real    **data,*time,*data_x,*data_y,*data_z,*data_xy,*mass;
+  real    t0;           /* start time and time increment between  */
+  real    delta_t;      /* time between restart points */
+  real    beginfit,     /* the begin/end time for fits as reals between */
+          endfit;       /* 0 and 1 */
+  real    dim_factor;   /* the dimensionality factor for the diffusion 
+                           constant */
+  real    **data;       /* the displacement data. First index is the group 
+                           number, second is frame number */
+  real    *time;        /* frame time */
+  real    *mass;        /* masses for mass-weighted msd */
   matrix  **datam;
-  rvec    **x0;
-  rvec    *com;
-  gmx_stats_t **lsq;
-  int     type,axis,ncoords,nrestart,nmol,nframes,nlast,ngrp;
-  int     *n_offs;
-  int     **ndata;
+  rvec    **x0;         /* original positions */
+  rvec    *com;         /* center of mass correction for each frame */
+  gmx_stats_t **lsq;    /* fitting stats for individual molecule msds */
+  msd_type type;        /* the type of msd to calculate (lateral, etc.)*/
+  int       axis;       /* the axis along which to calculate */
+  int       ncoords;
+  int       nrestart;   /* number of restart points */
+  int       nmol;       /* number of molecules (for bMol) */
+  int       nframes;    /* number of frames */ 
+  int       nlast;
+  int       ngrp;       /* number of groups to use for msd calculation */
+  int       *n_offs;
+  int       **ndata;    /* the number of msds (particles/mols) per data 
+                           point. */
 } t_corr;
 
 typedef real t_calc_func(t_corr *,int,atom_id[],int,rvec[],rvec,bool,matrix,
@@ -100,7 +116,7 @@ t_corr *init_corr(int nrgrp,int type,int axis,real dim_factor,
   int     i;
 
   snew(curr,1);
-  curr->type      = type;
+  curr->type      = (msd_type)type;
   curr->axis      = axis;
   curr->ngrp      = nrgrp;
   curr->nrestart  = 0;
@@ -217,7 +233,7 @@ static void calc_corr(t_corr *curr,int nr,int nx,atom_id index[],rvec xc[],
    */
   for(nx0=0; (nx0<curr->nlast); nx0++) {
     if (bRmCOMM) {
-      rvec_sub(curr->com[nx0],com,dcom);
+      rvec_sub(com,curr->com[nx0],dcom);
     } else {
       clear_rvec(dcom);
     }
@@ -234,6 +250,7 @@ static void calc_corr(t_corr *curr,int nr,int nx,atom_id index[],rvec xc[],
   }
 }
 
+/* the non-mass-weighted mean-squared displacement calcuation */
 static real calc1_norm(t_corr *curr,int nx,atom_id index[],int nx0,rvec xc[],
                      rvec dcom,bool bTen,matrix mat, const output_env_t oenv)
 {
@@ -250,7 +267,7 @@ static real calc1_norm(t_corr *curr,int nx,atom_id index[],int nx0,rvec xc[],
     switch (curr->type) {
     case NORMAL:
       for(m=0; (m<DIM); m++) {
-       rv[m] = curr->x0[nx0][ix][m] - xc[ix][m] - dcom[m];
+       rv[m] = xc[ix][m] - curr->x0[nx0][ix][m] - dcom[m];
        r2   += rv[m]*rv[m];
        if (bTen) {
          for(m2=0; m2<=m; m2++)
@@ -261,14 +278,14 @@ static real calc1_norm(t_corr *curr,int nx,atom_id index[],int nx0,rvec xc[],
     case X:
     case Y:
     case Z:
-      r = curr->x0[nx0][ix][curr->type-X] - xc[ix][curr->type-X]
-       - dcom[curr->type-X];
+      r = xc[ix][curr->type-X] - curr->x0[nx0][ix][curr->type-X] - 
+                dcom[curr->type-X];
       r2 += r*r;
       break;
     case LATERAL:
       for(m=0; (m<DIM); m++) {
        if (m != curr->axis) {
-         r   = curr->x0[nx0][ix][m] - xc[ix][m] - dcom[m];
+         r   = xc[ix][m] - curr->x0[nx0][ix][m] - dcom[m];
          r2 += r*r;
        }
       }
@@ -284,6 +301,7 @@ static real calc1_norm(t_corr *curr,int nx,atom_id index[],int nx0,rvec xc[],
   return g;
 }
 
+/* calculate the com of molecules in x and put it into xa */
 static void calc_mol_com(int nmol,int *molindex,t_block *mols,t_atoms *atoms,
                         rvec *x,rvec *xa)
 {
@@ -320,7 +338,7 @@ static real calc_one_mw(t_corr *curr,int ix,int nx0,rvec xc[],real *tm,
   switch (curr->type) {
   case NORMAL:
     for(m=0; (m<DIM); m++) {
-      rv[m] = curr->x0[nx0][ix][m] - xc[ix][m] - dcom[m];
+      rv[m] = xc[ix][m] - curr->x0[nx0][ix][m] - dcom[m];
       r2   += mm*rv[m]*rv[m];
       if (bTen) {
        for(m2=0; m2<=m; m2++)
@@ -331,14 +349,14 @@ static real calc_one_mw(t_corr *curr,int ix,int nx0,rvec xc[],real *tm,
   case X:
   case Y:
   case Z:
-    r  = curr->x0[nx0][ix][curr->type-X] - xc[ix][curr->type-X]
-      - dcom[curr->type-X];
+    r  = xc[ix][curr->type-X] - curr->x0[nx0][ix][curr->type-X] - 
+              dcom[curr->type-X];
     r2 = mm*r*r;
       break;
   case LATERAL:
     for(m=0; (m<DIM); m++) {
       if (m != curr->axis) {
-       r   = curr->x0[nx0][ix][m] - xc[ix][m] - dcom[m];
+       r   = xc[ix][m] - curr->x0[nx0][ix][m] - dcom[m];
        r2 += mm*r*r;
       }
     }
@@ -349,6 +367,7 @@ static real calc_one_mw(t_corr *curr,int ix,int nx0,rvec xc[],real *tm,
   return r2;
 }
 
+/* the normal, mass-weighted mean-squared displacement calcuation */
 static real calc1_mw(t_corr *curr,int nx,atom_id index[],int nx0,rvec xc[],
                     rvec dcom,bool bTen,matrix mat,const output_env_t oenv)
 {
@@ -367,79 +386,90 @@ static real calc1_mw(t_corr *curr,int nx,atom_id index[],int nx0,rvec xc[],
   return g;
 }
 
-static void remove_pbc(bool bMol,int nmol,int natoms,t_atoms *atoms,
-                      rvec xcur[],rvec xprev[],matrix box,
-                      rvec com)
+/* prepare the coordinates by removing periodic boundary crossings.
+   gnx = the number of atoms/molecules
+   index = the indices
+   xcur = the current coordinates
+   xprev = the previous coordinates
+   box = the box matrix */
+static void prep_data(bool bMol,int gnx,atom_id index[],
+                     rvec xcur[],rvec xprev[],matrix box)
 {
-  int  n,i,m;
-  rvec hbox;
-  real mass;
-  dvec sx;
-  double tmass;
+    int  i,m,ind;
+    rvec hbox;
 
-  if (bMol)
-    n = nmol;
-  else
-    n = natoms;
-
-  /* Remove periodicity */
-  for(m=0; (m<DIM); m++)
-    hbox[m] = 0.5*box[m][m];
-  clear_dvec(sx);
-  tmass = 0;
-  mass = 1;
-  for(i=0; i<n; i++) {
-    for(m=DIM-1; m>=0; m--) {
-      while(xcur[i][m]-xprev[i][m] <= -hbox[m])
-       rvec_inc(xcur[i],box[m]);
-      while(xcur[i][m]-xprev[i][m] >  hbox[m])
-       rvec_dec(xcur[i],box[m]);
+    /* Remove periodicity */
+    for(m=0; (m<DIM); m++)
+        hbox[m]=0.5*box[m][m];
+    
+    for(i=0; (i<gnx); i++) {
+        if (bMol)
+            ind = i;
+        else
+            ind = index[i];
+
+        for(m=DIM-1; m>=0; m--) 
+        {
+            while(xcur[ind][m]-xprev[ind][m] <= -hbox[m])
+                rvec_inc(xcur[ind],box[m]);
+            while(xcur[ind][m]-xprev[ind][m] >  hbox[m])
+                rvec_dec(xcur[ind],box[m]);
+        }      
     }
-    if (!bMol)
-      mass = atoms->atom[i].m;
-    for(m=0; m<DIM; m++)
-      sx[m] += mass*xcur[i][m];
-    tmass += mass;
-  }
-  for(m=0; m<DIM; m++)
-    com[m] = sx[m]/tmass;
 }
 
-static void prep_data(bool bMol,int gnx,atom_id index[],
-                     rvec xcur[],rvec xprev[],matrix box)
+/* calculate the center of mass for a group 
+   gnx = the number of atoms/molecules
+   index = the indices
+   xcur = the current coordinates
+   xprev = the previous coordinates
+   box = the box matrix
+   atoms = atom data (for mass)
+   com(output) = center of mass  */
+static void calc_com(bool bMol, int gnx, atom_id index[], 
+                     rvec xcur[],rvec xprev[],matrix box, t_atoms *atoms,
+                     rvec com)
 {
-  int  i,m,ind;
-  rvec hbox;
-
-  /* Remove periodicity */
-  for(m=0; (m<DIM); m++)
-    hbox[m]=0.5*box[m][m];
-  for(i=0; (i<gnx); i++) {
-    if (bMol)
-      ind = i;
-    else
-      ind = index[i];
-    for(m=DIM-1; m>=0; m--) {
-      while(xcur[ind][m]-xprev[ind][m] <= -hbox[m])
-       rvec_inc(xcur[ind],box[m]);
-      while(xcur[ind][m]-xprev[ind][m] >  hbox[m])
-       rvec_dec(xcur[ind],box[m]);
-    }      
-  }
+    int  i,m,ind;
+    real mass;
+    double tmass;
+    dvec sx;
+
+    clear_dvec(sx);
+    tmass = 0;
+    mass = 1;
+
+    prep_data(bMol, gnx, index, xcur, xprev, box);
+    for(i=0; (i<gnx); i++) 
+    {
+        if (bMol)
+            ind = i;
+        else
+            ind = index[i];
+
+
+        mass = atoms->atom[ind].m;
+        for(m=0; m<DIM; m++)
+            sx[m] += mass*xcur[ind][m];
+        tmass += mass;
+    }
+    for(m=0; m<DIM; m++)
+        com[m] = sx[m]/tmass;
 }
 
+
 static real calc1_mol(t_corr *curr,int nx,atom_id index[],int nx0,rvec xc[],
                      rvec dcom,bool bTen,matrix mat, const output_env_t oenv)
 {
   int  i;
-  real g,mm,gtot,tt;
+  real g,tm,gtot,tt;
 
   tt = curr->time[in_data(curr,nx0)];
   gtot = 0;
+  tm = 0;
   clear_mat(mat);
   for(i=0; (i<nx); i++) {
-    mm = 0;
-    g = calc_one_mw(curr,i,nx0,xc,&mm,dcom,bTen,mat);
+    g = calc_one_mw(curr,i,nx0,xc,&tm,dcom,bTen,mat);
     /* We don't need to normalize as the mass was set to 1 */
     gtot += g;
     if (tt >= curr->beginfit && (curr->endfit < 0 || tt <= curr->endfit))
@@ -455,10 +485,10 @@ void printmol(t_corr *curr,const char *fn,
              rvec *x,int ePBC,matrix box, const output_env_t oenv)
 {
 #define NDIST 100
-  FILE  *out,out_pdb;
+  FILE  *out;
   gmx_stats_t lsq1;
   int   i,j;
-  real  a,b,r,D,Dav,D2av,VarD,sqrtD,sqrtD_max,scale;
+  real  a,b,D,Dav,D2av,VarD,sqrtD,sqrtD_max,scale;
   t_pdbinfo *pdbinfo=NULL;
   int   *mol2a=NULL;
 
@@ -479,12 +509,7 @@ void printmol(t_corr *curr,const char *fn,
       real xx,yy,dx,dy;
       
       while(gmx_stats_get_point(curr->lsq[j][i],&xx,&yy,&dx,&dy) == estatsOK)
-       gmx_stats_add_point(lsq1,xx,yy,dx,dy);
-      /* lsq1.sx+=curr->lsq[j][i].sx;
-        lsq1.sy+=curr->lsq[j][i].sy;
-        lsq1.xx+=curr->lsq[j][i].xx;
-        lsq1.yx+=curr->lsq[j][i].yx;
-        lsq1.np+=curr->lsq[j][i].np; */
+          gmx_stats_add_point(lsq1,xx,yy,dx,dy);
     }
     gmx_stats_get_ab(lsq1,elsqWEIGHT_NONE,&a,&b,NULL,NULL,NULL,NULL);
     gmx_stats_done(lsq1);
@@ -531,21 +556,26 @@ void printmol(t_corr *curr,const char *fn,
  */
 int corr_loop(t_corr *curr,const char *fn,t_topology *top,int ePBC,
              bool bMol,int gnx[],atom_id *index[],
-             t_calc_func *calc1,bool bTen,bool bRmCOMM,real dt,
-             real t_pdb,rvec **x_pdb,matrix box_pdb, const output_env_t oenv)
+             t_calc_func *calc1,bool bTen, int *gnx_com, atom_id *index_com[],
+              real dt, real t_pdb,rvec **x_pdb,matrix box_pdb, 
+              const output_env_t oenv)
 {
-  rvec         *x[2],*xa[2],com={0};
+  rvec         *x[2]; /* the coordinates to read */
+  rvec         *xa[2]; /* the coordinates to calculate displacements for */
+  rvec         com={0};
   real         t,t_prev=0;
-  int          natoms,i,j,status,cur=0,maxframes=0;
+  int          natoms,i,j,cur=0,maxframes=0;
+  t_trxstatus *status;
 #define        prev (1-cur)
   matrix       box;
   bool         bFirst;
+  gmx_rmpbc_t  gpbc=NULL;
 
   natoms = read_first_x(oenv,&status,fn,&curr->t0,&(x[cur]),box);
 #ifdef DEBUG
   fprintf(stderr,"Read %d atoms for first frame\n",natoms);
 #endif
-  if (bRmCOMM && natoms < top->atoms.nr) {
+  if ((gnx_com!=NULL) && natoms < top->atoms.nr) {
     fprintf(stderr,"WARNING: The trajectory only contains part of the system (%d of %d atoms) and therefore the COM motion of only this part of the system will be removed\n",natoms,top->atoms.nr);
   }
 
@@ -565,19 +595,27 @@ int corr_loop(t_corr *curr,const char *fn,t_topology *top,int ePBC,
   t=curr->t0;
   if (x_pdb)
     *x_pdb = NULL;
-  do {
+
+  if (bMol)
+    gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
+
+  /* the loop over all frames */
+  do 
+  {
     if (x_pdb && ((bFirst && t_pdb < t) || 
                  (!bFirst && 
                   t_pdb > t - 0.5*(t - t_prev) && 
-                  t_pdb < t + 0.5*(t - t_prev)))) {
-      if (*x_pdb == NULL)
-       snew(*x_pdb,natoms);
-      for(i=0; i<natoms; i++)
-       copy_rvec(x[cur][i],(*x_pdb)[i]);
-      copy_mat(box,box_pdb);
+                  t_pdb < t + 0.5*(t - t_prev)))) 
+    {
+        if (*x_pdb == NULL)
+            snew(*x_pdb,natoms);
+        for(i=0; i<natoms; i++)
+            copy_rvec(x[cur][i],(*x_pdb)[i]);
+        copy_mat(box,box_pdb);
     }
       
 
+    /* check whether we've reached a restart point */
     if (bRmod(t,curr->t0,dt)) {
       curr->nrestart++;
   
@@ -587,10 +625,14 @@ int corr_loop(t_corr *curr,const char *fn,t_topology *top,int ePBC,
       srenew(curr->n_offs,curr->nrestart);
       srenew(curr->lsq,curr->nrestart);
       snew(curr->lsq[curr->nrestart-1],curr->nmol);
+      for(i=0;i<curr->nmol;i++)
+          curr->lsq[curr->nrestart-1][i]  = gmx_stats_init();
+
       if (debug)
        fprintf(debug,"Extended data structures because of new restart %d\n",
                curr->nrestart);
     }
+    /* create or extend the frame-based arrays */
     if (curr->nframes >= maxframes-1) {
       if (maxframes==0) {
        for(i=0; (i<curr->ngrp); i++) {
@@ -617,30 +659,43 @@ int corr_loop(t_corr *curr,const char *fn,t_topology *top,int ePBC,
       srenew(curr->time,maxframes);
     }
 
+    /* set the time */
     curr->time[curr->nframes] = t - curr->t0;
 
+    /* for the first frame, the previous frame is a copy of the first frame */
     if (bFirst) {
       memcpy(xa[prev],xa[cur],curr->ncoords*sizeof(xa[prev][0]));
       bFirst = FALSE;
     }
 
+    /* make the molecules whole */
     if (bMol)
-      rm_pbc(&top->idef,ePBC,natoms,box,x[cur],x[cur]);
+      gmx_rmpbc(gpbc,box,x[cur],x[cur]);
+
+    /* first remove the periodic boundary condition crossings */
+    for(i=0;i<curr->ngrp;i++)
+    {
+        prep_data(bMol, gnx[i], index[i], xa[cur], xa[prev], box);
+    }
 
-    if (bRmCOMM)
-      remove_pbc(bMol,curr->nmol,natoms,&top->atoms,xa[cur],xa[prev],box,com);
+    /* calculate the center of mass */
+    if (gnx_com)
+    {
+        prep_data(bMol, gnx_com[0], index_com[0], xa[cur], xa[prev], box);
+        calc_com(bMol, gnx_com[0], index_com[0], xa[cur], xa[prev], box,
+                 &top->atoms, com);
+    }
 
+    /* calculate the molecules' centers of masses and put them into xa */
     if (bMol)
-      calc_mol_com(gnx[0],index[0],&top->mols,&top->atoms,
-                  x[cur],xa[cur]);
+        calc_mol_com(gnx[0],index[0],&top->mols,&top->atoms, x[cur],xa[cur]);
     
     /* loop over all groups in index file */
-    for(i=0; (i<curr->ngrp); i++) {
-      /* nice for putting things in boxes and such */
-      if (!bRmCOMM)
-       prep_data(bMol,gnx[i],index[i],xa[cur],xa[prev],box);
+    for(i=0; (i<curr->ngrp); i++) 
+    {
       /* calculate something useful, like mean square displacements */
-      calc_corr(curr,i,gnx[i],index[i],xa[cur],bRmCOMM,com,calc1,bTen,oenv);
+      calc_corr(curr,i,gnx[i],index[i],xa[cur], (gnx_com!=NULL),com,
+                calc1,bTen,oenv);
     }
     cur=prev;
     t_prev = t;
@@ -650,8 +705,12 @@ int corr_loop(t_corr *curr,const char *fn,t_topology *top,int ePBC,
   fprintf(stderr,"\nUsed %d restart points spaced %g %s over %g %s\n\n", 
          curr->nrestart, 
          output_env_conv_time(oenv,dt), output_env_get_time_unit(oenv),
-         output_env_conv_time(oenv,curr->time[curr->nframes-1]), output_env_get_time_unit(oenv) );
+         output_env_conv_time(oenv,curr->time[curr->nframes-1]), 
+         output_env_get_time_unit(oenv) );
   
+  if (bMol)
+    gmx_rmpbc_done(gpbc);
+
   close_trj(status);
 
   return natoms;
@@ -692,20 +751,34 @@ void do_corr(const char *trx_file, const char *ndx_file, const char *msd_file,
             real dt,real beginfit,real endfit,const output_env_t oenv)
 {
   t_corr       *msd;
-  int          *gnx;
-  atom_id      **index;
-  char         **grpname;
+  int          *gnx; /* the selected groups' sizes */
+  atom_id      **index; /* selected groups' indices */
+  char         **grpname; 
   int          i,i0,i1,j,N,nat_trx;
   real         *DD,*SigmaD,a,a2,b,r,chi2;
   rvec         *x;
   matrix       box;
-  
+  int          *gnx_com=NULL; /* the COM removal group size  */
+  atom_id      **index_com=NULL; /* the COM removal group atom indices */
+  char         **grpname_com=NULL; /* the COM removal group name */
+
   snew(gnx,nrgrp);
   snew(index,nrgrp);
   snew(grpname,nrgrp);
-    
+   
+  fprintf(stderr, "\nSelect a group to calculate mean squared displacement for:\n");
   get_index(&top->atoms,ndx_file,nrgrp,gnx,index,grpname);
 
+  if (bRmCOMM)
+  {
+      snew(gnx_com,1);
+      snew(index_com,1);
+      snew(grpname_com,1);
+
+      fprintf(stderr, "\nNow select a group for center of mass removal:\n");
+      get_index(&top->atoms, ndx_file, 1, gnx_com, index_com, grpname_com);
+  }
+  
   if (mol_file)
     index_atom2mol(&gnx[0],index[0],&top->mols);
 
@@ -716,8 +789,9 @@ void do_corr(const char *trx_file, const char *ndx_file, const char *msd_file,
   nat_trx =
     corr_loop(msd,trx_file,top,ePBC,mol_file ? gnx[0] : 0,gnx,index,
              (mol_file!=NULL) ? calc1_mol : (bMW ? calc1_mw : calc1_norm),
-             bTen,bRmCOMM,dt,t_pdb,pdb_file ? &x : NULL,box,oenv);
-  
+             bTen, gnx_com, index_com, dt,t_pdb,
+              pdb_file ? &x : NULL,box,oenv);
+
   /* Correct for the number of points */
   for(j=0; (j<msd->ngrp); j++) {
     for(i=0; (i<msd->nframes); i++) {
@@ -774,8 +848,12 @@ void do_corr(const char *trx_file, const char *ndx_file, const char *msd_file,
       lsq_y_ax_b(N,&(msd->time[i0]),&(msd->data[j][i0]),&(DD[j]),&b,&r,&chi2);
       DD[j]     *= FACTOR/msd->dim_factor;
       SigmaD[j] *= FACTOR/msd->dim_factor;
-      fprintf(stdout,"D[%10s] %.4f (+/- %.4f) 1e-5 cm^2/s\n",
-             grpname[j],DD[j],SigmaD[j]);
+      if (DD[j] > 0.01 && DD[j] < 1e4)
+          fprintf(stdout,"D[%10s] %.4f (+/- %.4f) 1e-5 cm^2/s\n",
+                  grpname[j],DD[j],SigmaD[j]);
+      else
+          fprintf(stdout,"D[%10s] %.4g (+/- %.4g) 1e-5 cm^2/s\n",
+                  grpname[j],DD[j], SigmaD[j]);
     }
   }
   /* Print mean square displacement */
@@ -803,15 +881,18 @@ int gmx_msd(int argc,char *argv[])
     "types of mean square displacement: [TT]-type[tt], [TT]-lateral[tt]",
     "and [TT]-ten[tt]. Option [TT]-ten[tt] writes the full MSD tensor for",
     "each group, the order in the output is: trace xx yy zz yx zx zy.[PAR]",
-    "Option [TT]-mol[tt] plots the MSD for molecules, this implies",
-    "With option [TT]-rmcomm[tt] center of mass motion can be removed.",
-    "For trajectories produced with GROMACS this is usually not necessary",
+    "If [TT]-mol[tt] is set, g_msd plots the MSD for individual molecules: ",
+    "for each individual molecule a diffusion constant is computed for ",
+    "its center of mass. The chosen index group will be split into ",
+    "molecules.[PAR]",
+    "The default way to calculate a MSD is by using mass-weighted averages.",
+    "This can be turned off with [TT]-nomw[tt].[PAR]",
+    "With the option [TT]-rmcomm[tt], the center of mass motion of a ",
+    "specific group can be removed. For trajectories produced with ",
+    "GROMACS this is usually not necessary, ",
     "as mdrun usually already removes the center of mass motion.",
     "When you use this option be sure that the whole system is stored",
     "in the trajectory file.[PAR]",
-    "[TT]-mw[tt], i.e. for each individual molecule an diffusion constant",
-    "is computed for its center of mass. The chosen index group will",
-    "be split into molecules.",
     "The diffusion coefficient is determined by linear regression of the MSD,",
     "where, unlike for the normal output of D, the times are weighted",
     "according to the number of reference points, i.e. short times have",
@@ -884,7 +965,7 @@ int gmx_msd(int argc,char *argv[])
   CopyRight(stderr,argv[0]);
 
   parse_common_args(&argc,argv,
-                    PCA_CAN_VIEW | PCA_CAN_TIME | PCA_TIME_UNIT | PCA_BE_NICE,
+                    PCA_CAN_VIEW | PCA_CAN_BEGIN | PCA_CAN_END | PCA_TIME_UNIT | PCA_BE_NICE,
                    NFILE,fnm,asize(pa),pa,asize(desc),desc,0,NULL,&oenv);
   trx_file = ftp2fn_null(efTRX,NFILE,fnm);
   tps_file = ftp2fn_null(efTPS,NFILE,fnm);
index 9b00e1527927e698b2887dac35f6aecc43b8e549..4daa01b3eee29ed10cdf0de79e56b5816c62b05e 100644 (file)
@@ -628,6 +628,7 @@ void do_multipoles(char *trjfn,char *topfn,char *molndxfn,bool bFull)
   tensor3    *m3;
   tensor4    *m4;
   matrix     trans;
+  gmx_rmpbc_t  gpbc=NULL;
 
   top  = read_top(topfn);
   rd_index(molndxfn,1,&gnx,&grpindex,&grpname);
@@ -639,12 +640,13 @@ void do_multipoles(char *trjfn,char *topfn,char *molndxfn,bool bFull)
   snew(m2,gnx);
   snew(m3,gnx);
   snew(m4,gnx);
-  
+
+  gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
+
   /* Start while loop over frames */
   do {
     /* PvM, bug in rm_pbc??? Does not work for virtual sites ...
-    rm_pbc(&(top->idef),top->atoms.nr,box,x,x_s); */
-
+    gmx_rmpbc(gpbc,box,x,x_s); */
 
     /* Begin loop of all molecules in index file */
     for(i=0; (i<gnx); i++) {
@@ -673,6 +675,9 @@ void do_multipoles(char *trjfn,char *topfn,char *molndxfn,bool bFull)
     
     bCont = read_next_x(status,&t,natoms,x,box);
   } while(bCont);
+  gmx_rmpbc_done(gpbc);
+
+  
   
 }
 
index 160847727c98af651861c8bc8313bc1747e088c5..855dd02fecc3541a988a46f8dc89e6538250263f 100644 (file)
@@ -86,7 +86,7 @@ int gmx_nmens(int argc,char *argv[])
   };
 #define NPA asize(pa)
   
-  int        out;
+  t_trxstatus *out;
   int        status,trjout;
   t_topology top;
   int        ePBC;
index 3d05d3709b263667c9bda6c7fbd4cf5974366d4f..a3860e3de447ba17227ded9fec903f2b796e13e2 100644 (file)
@@ -96,7 +96,7 @@ int gmx_nmtraj(int argc,char *argv[])
     
 #define NPA asize(pa)
   
-  int        out;
+  t_trxstatus *out;
   t_topology top;
   int        ePBC;
   t_atoms    *atoms;
index 27262b04c3851ce710785cdeb9f233d66e0dcd4a..574796aefe6566232279ab5007310186a3227665 100644 (file)
@@ -75,7 +75,8 @@ static void find_nearest_neighbours(t_topology top, int ePBC,
                                    real time,
                                    real *sgmean, real *skmean,
                                    int nslice,int slice_dim,
-                                   real sgslice[],real skslice[])
+                                   real sgslice[],real skslice[],
+                                   gmx_rmpbc_t gpbc)
 {
   FILE    *fpoutdist;
   char    fnsgdist[32];
@@ -89,9 +90,7 @@ static void find_nearest_neighbours(t_topology top, int ePBC,
   int     m1,mm,sl_index;
   int    **nnb,*sl_count;
   real   onethird=1.0/3.0;
-  
   /*  dmat = init_mat(maxidx, FALSE); */
-
   box2 = box[XX][XX] * box[XX][XX];
   snew(sl_count,nslice);
   for (i=0; (i<4); i++) {
@@ -108,7 +107,8 @@ static void find_nearest_neighbours(t_topology top, int ePBC,
 
   /* Must init pbc every step because of pressure coupling */
   set_pbc(&pbc,ePBC,box);
-  rm_pbc(&(top.idef),ePBC,natoms,box,x,x);
+  
+  gmx_rmpbc(gpbc,box,x,x);
 
   nsgbin = 1 + 1/0.0005;
   snew(sgbin,nsgbin);
@@ -238,7 +238,7 @@ static void calc_tetra_order_parm(const char *fnNDX,const char *fnTPS,
   t_topology top;
   int        ePBC;
   char       title[STRLEN],fn[STRLEN],subtitle[STRLEN];
-  int        status;
+  t_trxstatus *status;
   int        natoms;
   real       t;
   rvec       *xtop,*x;
@@ -248,7 +248,9 @@ static void calc_tetra_order_parm(const char *fnNDX,const char *fnTPS,
   char       **grpname;
   int        i,*isize,ng,nframes;
   real       *sg_slice,*sg_slice_tot,*sk_slice,*sk_slice_tot;
-  
+  gmx_rmpbc_t  gpbc=NULL;
+
+
   read_tps_conf(fnTPS,title,&top,&ePBC,&xtop,NULL,box,FALSE);
 
   snew(sg_slice,nslice);
@@ -276,10 +278,11 @@ static void calc_tetra_order_parm(const char *fnNDX,const char *fnTPS,
                 oenv);
 
   /* loop over frames */
+  gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
   nframes = 0;
   do {
     find_nearest_neighbours(top,ePBC,natoms,box,x,isize[0],index[0],t,
-                           &sg,&sk,nslice,slice_dim,sg_slice,sk_slice);
+                           &sg,&sk,nslice,slice_dim,sg_slice,sk_slice,gpbc);
     for(i=0; (i<nslice); i++) {
       sg_slice_tot[i] += sg_slice[i];
       sk_slice_tot[i] += sk_slice[i];
@@ -289,7 +292,8 @@ static void calc_tetra_order_parm(const char *fnNDX,const char *fnTPS,
     nframes++;
   } while (read_next_x(oenv,status,&t,natoms,x,box));
   close_trj(status);
+  gmx_rmpbc_done(gpbc);
+
   sfree(grpname);
   sfree(index);
   sfree(isize);
@@ -348,7 +352,7 @@ void calc_order(const char *fn, atom_id *index, atom_id *a, rvec **order,
     *x1,             /* coordinates without pbc                        */
     dist;            /* vector between two atoms                       */
   matrix box;        /* box (3x3)                                      */
-  int   status;  
+  t_trxstatus *status;  
   rvec  cossum,      /* sum of vector angles for three axes            */
     Sx, Sy, Sz,      /* the three molecular axes                       */
     tmp1, tmp2,      /* temp. rvecs for calculating dot products       */
@@ -373,6 +377,7 @@ void calc_order(const char *fn, atom_id *index, atom_id *a, rvec **order,
    char *grpname=NULL;
    t_pbc pbc;
    real arcdist;
+   gmx_rmpbc_t  gpbc=NULL;
 
   /* PBC added for center-of-mass vector*/
   /* Initiate the pbc structure */
@@ -440,14 +445,15 @@ void calc_order(const char *fn, atom_id *index, atom_id *a, rvec **order,
 
   teller = 0; 
 
+  gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
   /*********** Start processing trajectory ***********/
   do {
     if (bSliced)
       *slWidth = box[axis][axis]/nslices;
     teller++;
     
-       set_pbc(&pbc,ePBC,box);
-    rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x0,x1);
+    set_pbc(&pbc,ePBC,box);
+    gmx_rmpbc(gpbc,box,x0,x1);
 
     /* Now loop over all groups. There are ngrps groups, the order parameter can
        be calculated for grp 1 to grp ngrps - 1. For each group, loop over all 
@@ -608,7 +614,8 @@ void calc_order(const char *fn, atom_id *index, atom_id *a, rvec **order,
   /*********** done with status file **********/
   
   fprintf(stderr,"\nRead trajectory. Printing parameters to file\n");
-  
+  gmx_rmpbc_done(gpbc);
+
   /* average over frames */
   for (i = 1; i < ngrps - 1; i++) {
     svmul(1.0/nr_frames, (*order)[i], (*order)[i]);
@@ -708,7 +715,7 @@ void write_bfactors(t_filenm  *fnm, int nfile, atom_id *index, atom_id *a, int n
 {
        /*function to write order parameters as B factors in PDB file using 
           first frame of trajectory*/
-       int status;
+       t_trxstatus *status;
        int natoms;
        t_trxframe fr, frout;
        t_atoms useatoms;
index 8f54eb3fe4bb55e42f1e8238f731c962f5e9fb91..a310644c8a21646bde76d802bdc0cb9d9244ac90 100644 (file)
@@ -109,10 +109,10 @@ int gmx_polystat(int argc,char *argv[])
     "gyration tensors are written.",
     "With option [TT]-i[tt] the mean square internal distances are",
     "written.[PAR]",
-    "With option [TT]-p[tt] the presistence length is determined.",
+    "With option [TT]-p[tt] the persistence length is determined.",
     "The chosen index group should consist of atoms that are",
     "consecutively bonded in the polymer mainchains.",
-    "The presistence length is then determined from the cosine of",
+    "The persistence length is then determined from the cosine of",
     "the angles between bonds with an index difference that is even,",
     "the odd pairs are not used, because straight polymer backbones",
     "are usually all trans and therefore only every second bond aligns.",
@@ -144,7 +144,7 @@ int gmx_polystat(int argc,char *argv[])
   int    ePBC;
   int    isize,*index,nmol,*molind,mol,nat_min=0,nat_max=0;
   char   *grpname;
-  int    status;
+  t_trxstatus *status;
   real   t;
   rvec   *x,*bond=NULL;
   matrix box;
@@ -162,6 +162,7 @@ int gmx_polystat(int argc,char *argv[])
                         "<R\\sg\\N> eig1", "<R\\sg\\N> eig2", "<R\\sg\\N> eig3",
                         "<R\\sg\\N eig1>", "<R\\sg\\N eig2>", "<R\\sg\\N eig3>" };
   char   **legp,buf[STRLEN];
+  gmx_rmpbc_t  gpbc=NULL;
 
   CopyRight(stderr,argv[0]);
   parse_common_args(&argc,argv,
@@ -253,8 +254,11 @@ int gmx_polystat(int argc,char *argv[])
   sum_eed2_tot = 0;
   sum_gyro_tot = 0;
   sum_pers_tot = 0;
+  
+  gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
+  
   do {
-    rm_pbc(&(top->idef),ePBC,natoms,box,x,x);
+    gmx_rmpbc(gpbc,box,x,x);
     
     sum_eed2 = 0;
     for(d=0; d<DIM; d++)
@@ -379,6 +383,8 @@ int gmx_polystat(int argc,char *argv[])
 
     frame++;
   } while (read_next_x(oenv,status,&t,natoms,x,box));
+  
+  gmx_rmpbc_done(gpbc);
 
   close_trx(status);
 
index e8a21bb0e807e66c5e74a1c378a7f1079dba08b5..48a836542ccd3fc4d31e1ef460ed2c930bc90f4d 100644 (file)
@@ -104,9 +104,9 @@ void calc_potential(const char *fn, atom_id **index, int gnx[],
 {
   rvec *x0;              /* coordinates without pbc */
   matrix box;            /* box (3x3) */
-  int natoms,            /* nr. atoms in trj */
-      status,
-      **slCount,         /* nr. of atoms in one slice for a group */
+  int natoms;            /* nr. atoms in trj */
+  t_trxstatus *status;
+  int **slCount,         /* nr. of atoms in one slice for a group */
       i,j,n,             /* loop indices */
       teller = 0,      
       ax1=0, ax2=0,
@@ -117,7 +117,8 @@ void calc_potential(const char *fn, atom_id **index, int gnx[],
   real t;
   double z;
   rvec xcm;
-  
+  gmx_rmpbc_t  gpbc=NULL;
+
   switch(axis)
   {
   case 0:
@@ -152,13 +153,15 @@ void calc_potential(const char *fn, atom_id **index, int gnx[],
     snew((*slPotential)[i], *nslices);
   }
 
+
+  gpbc = gmx_rmpbc_init(&top->idef,ePBC,top->atoms.nr,box);
+  
   /*********** Start processing trajectory ***********/
   do 
   {
     *slWidth = box[axis][axis]/(*nslices);
     teller++;
-    
-    rm_pbc(&(top->idef),ePBC,top->atoms.nr,box,x0,x0);
+    gmx_rmpbc(gpbc,box,x0,x0);
 
     /* calculate position of center of mass based on group 1 */
     calc_xcm(x0, gnx[0], index[0], top->atoms.atom, xcm, FALSE);
@@ -201,6 +204,8 @@ void calc_potential(const char *fn, atom_id **index, int gnx[],
     nr_frames++;
   } while (read_next_x(oenv,status,&t,natoms,x0,box));
 
+  gmx_rmpbc_done(gpbc);
+
   /*********** done with status file **********/
   close_trj(status);
   
@@ -375,14 +380,14 @@ void plot_potential(double *potential[], double *charge[], double *field[],
 int gmx_potential(int argc,char *argv[])
 {
   const char *desc[] = {
-    "Compute the electrostatical potential across the box. The potential is"
-    "calculated by first summing the charges per slice and then integrating"
-    "twice of this charge distribution. Periodic boundaries are not taken  "
-    "into account. Reference of potential is taken to be the left side of"
-    "the box. It's also possible to calculate the potential in spherical"
-    "coordinates as function of r by calculating a charge distribution in"
-    "spherical slices and twice integrating them. epsilon_r is taken as 1,"
-    "2 is more appropriate in many cases"
+    "Compute the electrostatical potential across the box. The potential is",
+    "calculated by first summing the charges per slice and then integrating",
+    "twice of this charge distribution. Periodic boundaries are not taken",
+    "into account. Reference of potential is taken to be the left side of",
+    "the box. It's also possible to calculate the potential in spherical",
+    "coordinates as function of r by calculating a charge distribution in",
+    "spherical slices and twice integrating them. epsilon_r is taken as 1,",
+    "2 is more appropriate in many cases."
   };
   output_env_t oenv;
   static int  axis = 2;                      /* normal to memb. default z  */
index 5cd9d72d7043e3745aaf86827044c1c57791429b..6721307a24a1e9bd7605293e0bee0f6fcb991e9b 100644 (file)
@@ -85,7 +85,7 @@ int gmx_principal(int argc,char *argv[])
   t_pargs pa[] = {
          { "-foo",      FALSE, etBOOL, {&foo}, "Dummy option to avoid empty array" }
   };
-  int        status;
+  t_trxstatus *status;
   t_topology top;
   int        ePBC;
   real       t;
@@ -102,6 +102,8 @@ int gmx_principal(int argc,char *argv[])
   FILE *     fmoi;
   matrix     axes,box;
   output_env_t oenv;
+  gmx_rmpbc_t  gpbc=NULL;
+
 
   t_filenm fnm[] = {
     { efTRX, "-f",   NULL,       ffREAD }, 
@@ -130,9 +132,12 @@ int gmx_principal(int argc,char *argv[])
 
   natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box); 
 
+  gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
+
   do
   {
-         rm_pbc(&(top.idef),ePBC,natoms,box,x,x);
+          gmx_rmpbc(gpbc,box,x,x);
+
          calc_principal_axes(&top,x,index,gnx,axes,moi);
 
          fprintf(axis1,"%15.10f     %15.10f  %15.10f  %15.10f\n",t,axes[XX][XX],axes[YY][XX],axes[ZZ][XX]);
@@ -142,6 +147,9 @@ int gmx_principal(int argc,char *argv[])
   }    
   while(read_next_x(oenv,status,&t,natoms,x,box));
        
+  gmx_rmpbc_done(gpbc);
+
+
   close_trj(status);
   ffclose(axis1);
   ffclose(axis2);
index 37cb094f0fcc4199de6507e5c340f1da031ee934..82818a857d7d605cb4d613cbf40f453eca201d1b 100644 (file)
@@ -53,7 +53,6 @@
 #include "physics.h"
 #include "index.h"
 #include "smalloc.h"
-#include "fftgrid.h"
 #include "calcgrid.h"
 #include "nrnb.h"
 #include "coulomb.h"
 #include "matio.h"
 #include "gmx_ana.h"
 #include "names.h"
+#include "sfactor.h"
 
 
-typedef struct
-{
-  const char *label;
-  int  elem,mass;
-  real a[4], b[4], c;
-} t_CM_table;
-
-/*
- * 
- * f0[k] = c + [SUM a_i*EXP(-b_i*(k^2)) ]
- *             i=1,4
- */
-
-const t_CM_table CM_t[] =
-{
-
-  { "H", 1,  1,   { 0.489918, 0.262003, 0.196767, 0.049879 },
-    { 20.6593, 7.74039, 49.5519, 2.20159 },
-    0.001305 },
-  { "C", 6,  12, { 2.26069, 1.56165, 1.05075, 0.839259 },
-    { 22.6907, 0.656665, 9.75618, 55.5949 },
-    0.286977 },
-  { "N", 7,  14,   { 12.2126, 3.13220, 2.01250, 1.16630 },     
-    { 0.005700, 9.89330, 28.9975, 0.582600 },
-    -11.529 },
-  { "O", 8,  16, { 3.04850, 2.28680, 1.54630, 0.867000 },  
-    { 13.2771, 5.70110, 0.323900, 32.9089 },
-    0.250800 },
-  { "Na", 11, 23,  { 3.25650, 3.93620, 1.39980, 1.00320 },       /*  Na 1+ */
-    { 2.66710, 6.11530, 0.200100, 14.0390 }, 
-    0.404000 }
-};
-
-#define NCMT asize(CM_t)
-
-typedef struct
-{
-  int     n_angles;
-  int     n_groups;
-  double  lambda;
-  double  energy;
-  double  momentum;
-  double  ref_k;
-  double  **F;
-  int     nSteps;
-  int     total_n_atoms;
-} structure_factor;
-
-typedef struct
-{
-  rvec x;
-  int  t;
-} reduced_atom;
-
 static void check_box_c(matrix box)
 {
   if (fabs(box[ZZ][XX]) > GMX_REAL_EPS*box[ZZ][ZZ] ||
@@ -218,7 +164,7 @@ static void do_rdf(const char *fnNDX,const char *fnTPS,const char *fnTRX,
                    const output_env_t oenv)
 {
   FILE       *fp;
-  int        status;
+  t_trxstatus *status;
   char       outf1[STRLEN],outf2[STRLEN];
   char       title[STRLEN],gtitle[STRLEN],refgt[30];
   int        g,natoms,i,ii,j,k,nbin,j0,j1,n,nframes;
@@ -245,7 +191,7 @@ static void do_rdf(const char *fnNDX,const char *fnTPS,const char *fnTRX,
   t_blocka   *excl;
   t_atom     *atom=NULL;
   t_pbc      pbc;
-
+  gmx_rmpbc_t  gpbc=NULL;
   int        *is=NULL,**coi=NULL,cur,mol,i1,res,a;
 
   excl=NULL;
@@ -407,12 +353,15 @@ static void do_rdf(const char *fnNDX,const char *fnTPS,const char *fnTRX,
   snew(x_i1,max_i);
   nframes = 0;
   invvol_sum = 0;
+  if (bPBC && (NULL != top))
+    gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
+
   do {
     /* Must init pbc every step because of pressure coupling */
     copy_mat(box,box_pbc);
     if (bPBC) {
       if (top != NULL)
-       rm_pbc(&top->idef,ePBC,natoms,box,x,x);
+       gmx_rmpbc(gpbc,box,x,x);
       if (bXY) {
        check_box_c(box);
        clear_rvec(box_pbc[ZZ]);
@@ -519,6 +468,9 @@ static void do_rdf(const char *fnNDX,const char *fnTPS,const char *fnTRX,
   } while (read_next_x(oenv,status,&t,natoms,x,box));
   fprintf(stderr,"\n");
   
+  if (bPBC && (NULL != top))
+    gmx_rmpbc_done(gpbc);
+
   close_trj(status);
   
   sfree(x);
@@ -666,366 +618,6 @@ static void do_rdf(const char *fnNDX,const char *fnTPS,const char *fnTRX,
   sfree(rdf);
 }
 
-t_complex *** rc_tensor_allocation(int x, int y, int z)
-{
-  t_complex ***t;
-  int i,j;
-  
-  snew(t,x);
-  t = (t_complex ***)calloc(x,sizeof(t_complex**));
-  if(!t) exit(fprintf(stderr,"\nallocation error"));
-  t[0] = (t_complex **)calloc(x*y,sizeof(t_complex*));
-  if(!t[0]) exit(fprintf(stderr,"\nallocation error"));
-  t[0][0] = (t_complex *)calloc(x*y*z,sizeof(t_complex));
-  if(!t[0][0]) exit(fprintf(stderr,"\nallocation error"));
-  
-  for( j = 1 ; j < y ; j++) 
-    t[0][j] = t[0][j-1] + z;
-  for( i = 1 ; i < x ; i++) {
-    t[i] = t[i-1] + y;
-    t[i][0] = t[i-1][0] + y*z;
-    for( j = 1 ; j < y ; j++) 
-      t[i][j] = t[i][j-1] + z;
-  }
-  return t;
-}
-    
-int return_atom_type (const char *name)
-{
-  typedef struct {
-    const char *name;
-    int  nh;
-  } t_united_h;
-  t_united_h uh[] = {
-    { "CH1", 1 }, { "CH2", 2 }, { "CH3", 3 }, 
-    { "CS1", 1 }, { "CS2", 2 }, { "CS3", 3 }, 
-    { "CP1", 1 }, { "CP2", 2 }, { "CP3", 3 }
-  };
-  int i;
-
-  for(i=0; (i<asize(uh)); i++) 
-    if (strcmp(name,uh[i].name) == 0)
-      return NCMT-1+uh[i].nh;
-      
-  for(i=0; (i<NCMT); i++)
-    if (strncmp (name, CM_t[i].label,strlen(CM_t[i].label)) == 0)
-      return i;
-  gmx_fatal(FARGS,"\nError: atom (%s) not in list (%d types checked)!\n", 
-           name,i);
-  
-  return 0;
-}
-
-double CMSF (int type,int nh,double lambda, double sin_theta)
-/* 
- * return Cromer-Mann fit for the atomic scattering factor:
- * sin_theta is the sine of half the angle between incoming and scattered
- * vectors. See g_sq.h for a short description of CM fit.
- */
-{
-  int i;
-  double tmp = 0.0, k2;
-  
-  /*
-   *  united atoms case
-   *  CH2 / CH3 groups  
-   */
-  if (nh > 0) {
-    tmp = (CMSF (return_atom_type ("C"),0,lambda, sin_theta) +
-          nh*CMSF (return_atom_type ("H"),0,lambda, sin_theta));
-  }
-  /* all atom case */
-  else {
-    k2 = (sqr (sin_theta) / sqr (10.0 * lambda));
-    tmp = CM_t[type].c;
-    for (i = 0; (i < 4); i++)
-      tmp += CM_t[type].a[i] * exp (-CM_t[type].b[i] * k2);
-  }
-  return tmp;
-}
-
-real **compute_scattering_factor_table (structure_factor * sf,int *nsftable)
-{
-/*
- *  this function build up a table of scattering factors for every atom
- *  type and for every scattering angle.
- */
-    int i, j;
-    double sin_theta,q,hc=1239.842;
-    real ** sf_table;
-
-    /* \hbar \omega \lambda = hc = 1239.842 eV * nm */
-    sf->momentum = ((double) (2. * 1000.0 * M_PI * sf->energy) / hc);
-    sf->lambda = hc / (1000.0 * sf->energy);
-    fprintf (stderr, "\nwavelenght = %f nm\n", sf->lambda);
-    *nsftable = NCMT+3;
-    snew (sf_table,*nsftable);
-    for (i = 0; (i < *nsftable); i++) {
-       snew (sf_table[i], sf->n_angles);
-       for (j = 0; j < sf->n_angles; j++) {
-           q = ((double) j * sf->ref_k);
-           /* theta is half the angle between incoming 
-              and scattered wavevectors. */
-           sin_theta = q / (2.0 * sf->momentum);
-           if (i < NCMT)
-             sf_table[i][j] = CMSF (i,0,sf->lambda, sin_theta);
-           else
-             sf_table[i][j] = CMSF (i,i-NCMT+1,sf->lambda, sin_theta);
-       }
-    }
-    return sf_table;
-}
-
-int * create_indexed_atom_type (reduced_atom * atm, int size)
-{
-/* 
- * create an index of the atom types found in a  group
- * i.e.: for water index_atp[0]=type_number_of_O and 
- *                 index_atp[1]=type_number_of_H
- * 
- * the last element is set to 0 
- */
-    int *index_atp, i, i_tmp, j;
-
-    snew (index_atp, 1);
-    i_tmp = 1;
-    index_atp[0] = atm[0].t;
-    for (i = 1; i < size; i++) {
-       for (j = 0; j < i_tmp; j++)
-           if (atm[i].t == index_atp[j])
-               break;
-       if (j == i_tmp) {       /* i.e. no indexed atom type is  == to atm[i].t */
-           i_tmp++;
-           srenew (index_atp, i_tmp * sizeof (int));
-           index_atp[i_tmp - 1] = atm[i].t;
-       }
-    }
-    i_tmp++;
-    srenew (index_atp, i_tmp * sizeof (int));
-    index_atp[i_tmp - 1] = 0;
-    return index_atp;
-}
-
-void rearrange_atoms (reduced_atom * positions, t_trxframe *fr, atom_id * index,
-                     int isize, t_topology * top, bool flag)
-/* given the group's index, return the (continuous) array of atoms */
-{
-  int i;
-  
-  if (flag)
-    for (i = 0; i < isize; i++)
-      positions[i].t =
-       return_atom_type (*(top->atoms.atomname[index[i]]));
-  for (i = 0; i < isize; i++)
-    copy_rvec (fr->x[index[i]], positions[i].x);
-}
-
-
-int atp_size (int *index_atp)
-{
-    int i = 0;
-
-    while (index_atp[i])
-       i++;
-    return i;
-}
-
-void compute_structure_factor (structure_factor * sf, matrix box,
-                              reduced_atom * red, int isize, real start_q,
-                              real end_q, int group,real **sf_table)
-{
-    t_complex ***tmpSF;
-    rvec k_factor;
-    real kdotx, asf, kx, ky, kz, krr;
-    int kr, maxkx, maxky, maxkz, i, j, k, p, *counter;
-
-
-    k_factor[XX] = 2 * M_PI / box[XX][XX];
-    k_factor[YY] = 2 * M_PI / box[YY][YY];
-    k_factor[ZZ] = 2 * M_PI / box[ZZ][ZZ];
-
-    maxkx = (int) (end_q / k_factor[XX] + 0.5);
-    maxky = (int) (end_q / k_factor[YY] + 0.5);
-    maxkz = (int) (end_q / k_factor[ZZ] + 0.5);
-
-    snew (counter, sf->n_angles);
-
-    tmpSF = rc_tensor_allocation(maxkx,maxky,maxkz);
-/*
- * The big loop...
- * compute real and imaginary part of the structure factor for every
- * (kx,ky,kz)) 
- */
-    fprintf(stderr,"\n");
-    for (i = 0; i < maxkx; i++) {
-       fprintf (stderr,"\rdone %3.1f%%     ", (double)(100.0*(i+1))/maxkx);
-       kx = i * k_factor[XX];
-       for (j = 0; j < maxky; j++) {
-           ky = j * k_factor[YY];
-           for (k = 0; k < maxkz; k++)
-               if (i != 0 || j != 0 || k != 0) {
-                   kz = k * k_factor[ZZ];
-                   krr = sqrt (sqr (kx) + sqr (ky) + sqr (kz));
-                   if (krr >= start_q && krr <= end_q) {
-                       kr = (int) (krr/sf->ref_k + 0.5);
-                       if (kr < sf->n_angles) {
-                           counter[kr]++;  /* will be used for the copmutation 
-                                              of the average*/
-                           for (p = 0; p < isize; p++) {
-                                   
-                               asf = sf_table[red[p].t][kr];
-
-                               kdotx = kx * red[p].x[XX] +
-                                   ky * red[p].x[YY] + kz * red[p].x[ZZ];
-                               
-                               tmpSF[i][j][k].re += cos (kdotx) * asf;
-                               tmpSF[i][j][k].im += sin (kdotx) * asf;
-                           }
-                       }
-                   }
-               }
-       }
-    }                          /* end loop on i */
-/*
- *  compute the square modulus of the structure factor, averaging on the surface
- *  kx*kx + ky*ky + kz*kz = krr*krr 
- *  note that this is correct only for a (on the macroscopic scale)
- *  isotropic system. 
- */
-    for (i = 0; i < maxkx; i++) {
-       kx = i * k_factor[XX]; for (j = 0; j < maxky; j++) {
-           ky = j * k_factor[YY]; for (k = 0; k < maxkz; k++) {
-               kz = k * k_factor[ZZ]; krr = sqrt (sqr (kx) + sqr (ky)
-               + sqr (kz)); if (krr >= start_q && krr <= end_q) {
-                   kr = (int) (krr / sf->ref_k + 0.5); 
-                       if (kr < sf->n_angles && counter[kr] != 0)
-                               sf->F[group][kr] +=
-                           (sqr (tmpSF[i][j][k].re) +
-                            sqr (tmpSF[i][j][k].im))/ counter[kr];
-               }
-           }
-       }
-    } sfree (counter); free(tmpSF[0][0]); free(tmpSF[0]); free(tmpSF);
-}
-
-void save_data (structure_factor * sf, const char *file, int ngrps, 
-                real start_q, real end_q, const output_env_t oenv)
-{
-
-    FILE *fp;
-    int i, g = 0;
-    double *tmp, polarization_factor, A;
-
-    fp = xvgropen (file, "Scattering Intensity", "q (1/nm)",
-                  "Intensity (a.u.)",oenv);
-
-    snew (tmp, ngrps);
-
-    for (g = 0; g < ngrps; g++)
-       for (i = 0; i < sf->n_angles; i++) {
-/*
- *          theta is half the angle between incoming and scattered vectors.
- *          
- *          polar. fact. = 0.5*(1+cos^2(2*theta)) = 1 - 0.5 * sin^2(2*theta)
- *          
- *          sin(theta) = q/(2k) := A  ->  sin^2(theta) = 4*A^2 (1-A^2) ->
- *          -> 0.5*(1+cos^2(2*theta)) = 1 - 2 A^2 (1-A^2)
- */
-           A = (double) (i * sf->ref_k) / (2.0 * sf->momentum);
-           polarization_factor = 1 - 2.0 * sqr (A) * (1 - sqr (A));
-           sf->F[g][i] *= polarization_factor;
-       }
-    for (i = 0; i < sf->n_angles; i++) {
-       if (i * sf->ref_k >= start_q && i * sf->ref_k <= end_q) {
-           fprintf (fp, "%10.5f  ", i * sf->ref_k);
-           for (g = 0; g < ngrps; g++)
-               fprintf (fp, "  %10.5f ", (sf->F[g][i]) /( sf->total_n_atoms*
-                                                         sf->nSteps));   
-           fprintf (fp, "\n");
-       }
-    }
-    ffclose (fp);
-}
-
-int do_scattering_intensity (const char* fnTPS, const char* fnNDX, 
-                             const char* fnXVG, const char *fnTRX, 
-                             real start_q,real end_q, 
-                             real energy,int ng,const output_env_t oenv)
-{
-    int i,*isize,status,flags = TRX_READ_X,**index_atp;
-    char **grpname,title[STRLEN];
-    atom_id **index;
-    t_topology top;
-    int ePBC;
-    t_trxframe fr;
-    reduced_atom **red;
-    structure_factor *sf;
-    rvec *xtop;
-    real **sf_table;
-    int nsftable;
-    matrix box;
-    double r_tmp;
-
-    snew (sf, 1);
-    sf->energy = energy;
-
-    /* Read the topology informations */
-    read_tps_conf (fnTPS, title, &top, &ePBC, &xtop, NULL, box, TRUE);
-    sfree (xtop);
-    
-    /* groups stuff... */
-    snew (isize, ng);
-    snew (index, ng);
-    snew (grpname, ng);
-
-    fprintf (stderr, "\nSelect %d group%s\n", ng,
-            ng == 1 ? "" : "s");
-    if (fnTPS)
-       get_index (&top.atoms, fnNDX, ng, isize, index, grpname);
-    else
-       rd_index (fnNDX, ng, isize, index, grpname);
-
-    /* The first time we read data is a little special */
-    read_first_frame (oenv,&status, fnTRX, &fr, flags);
-
-    sf->total_n_atoms = fr.natoms;
-    
-    snew (red, ng);
-    snew (index_atp, ng);
-
-    r_tmp = max (box[XX][XX], box[YY][YY]);
-    r_tmp = (double) max (box[ZZ][ZZ], r_tmp);
-
-    sf->ref_k = (2.0 * M_PI) / (r_tmp);
-    /* ref_k will be the reference momentum unit */
-    sf->n_angles = (int) (end_q / sf->ref_k + 0.5);
-
-    snew (sf->F, ng);
-    for (i = 0; i < ng; i++)
-       snew (sf->F[i], sf->n_angles);
-    for (i = 0; i < ng; i++) {
-       snew (red[i], isize[i]);
-       rearrange_atoms (red[i], &fr, index[i], isize[i], &top, TRUE);
-       index_atp[i] = create_indexed_atom_type (red[i], isize[i]);
-    }
-    sf_table = compute_scattering_factor_table (sf,&nsftable);
-    /* This is the main loop over frames */
-
-    do {
-       sf->nSteps++;
-       for (i = 0; i < ng; i++) {
-           rearrange_atoms (red[i], &fr, index[i], isize[i], &top,FALSE);
-
-           compute_structure_factor (sf, box, red[i], isize[i],
-                                     start_q, end_q, i, sf_table);
-       }
-    }
-    while (read_next_frame (oenv,status, &fr));
-
-    save_data (sf, fnXVG, ng, start_q, end_q,oenv);
-
-    return 0;
-}
 
 int gmx_rdf(int argc,char *argv[])
 {
@@ -1040,7 +632,7 @@ int gmx_rdf(int argc,char *argv[])
     "or to the closest particle in a set ([TT]-surf[tt]).",
     "With all methods rdf's can also be calculated around axes parallel",
     "to the z-axis with option [TT]-xy[tt].",
-    "With option [TT]-surf[tt] normalization can not be used.[PAR]"
+    "With option [TT]-surf[tt] normalization can not be used.[PAR]",
     "The option [TT]-rdf[tt] sets the type of rdf to be computed.",
     "Default is for atoms or particles, but one can also select center",
     "of mass or geometry of molecules or residues. In all cases only",
@@ -1064,7 +656,7 @@ int gmx_rdf(int argc,char *argv[])
     "Option [TT]-cn[tt] produces the cumulative number rdf,",
     "i.e. the average number of particles within a distance r.[PAR]",
     "To bridge the gap between theory and experiment structure factors can",
-    "be computed (option [TT]-sq[tt]). The algorithm uses FFT, the grid"
+    "be computed (option [TT]-sq[tt]). The algorithm uses FFT, the grid",
     "spacing of which is determined by option [TT]-grid[tt]."
   };
   static bool bCM=FALSE,bXY=FALSE,bPBC=TRUE,bNormalize=TRUE;
@@ -1115,7 +707,7 @@ int gmx_rdf(int argc,char *argv[])
      "Energy of the incoming X-ray (keV) "}
   };
 #define NPA asize(pa)
-  const char *fnTPS,*fnNDX;
+  const char *fnTPS,*fnNDX,*fnDAT=NULL;
   bool       bSQ,bRDF;
   output_env_t oenv;
   
@@ -1123,6 +715,7 @@ int gmx_rdf(int argc,char *argv[])
     { efTRX, "-f",  NULL,     ffREAD },
     { efTPS, NULL,  NULL,     ffOPTRD },
     { efNDX, NULL,  NULL,     ffOPTRD },
+    { efDAT, "-d",  "sfactor",     ffOPTRD },
     { efXVG, "-o",  "rdf",    ffOPTWR },
     { efXVG, "-sq", "sq",     ffOPTWR },
     { efXVG, "-cn", "rdf_cn", ffOPTWR },
@@ -1139,6 +732,7 @@ int gmx_rdf(int argc,char *argv[])
   bRDF  = opt2bSet("-o",NFILE,fnm) || !bSQ;
   if (bSQ || bCM || closet[0][0]!='n' || rdft[0][0]=='m' || rdft[0][6]=='m') {
     fnTPS = ftp2fn(efTPS,NFILE,fnm);
+    fnDAT = ftp2fn(efDAT,NFILE,fnm);
   } else {
     fnTPS = ftp2fn_null(efTPS,NFILE,fnm);
   }
@@ -1160,7 +754,7 @@ int gmx_rdf(int argc,char *argv[])
  
   if  (bSQ) 
    do_scattering_intensity(fnTPS,fnNDX,opt2fn("-sq",NFILE,fnm),
-                           ftp2fn(efTRX,NFILE,fnm),
+                           ftp2fn(efTRX,NFILE,fnm),fnDAT,
                           start_q, end_q, energy, ngroups,oenv);
 
   if (bRDF) 
index 6b410b556c51af0d8c53b54007199097e78be291..8baf414b1ab432c3366a15d74b621bf78b4a8fdc 100644 (file)
@@ -389,6 +389,7 @@ void spectrum(bool bVerbose,
   rvec   **corr;
   real   **Corr;
   t_sij  *spec;
+  gmx_rmpbc_t  gpbc=NULL;
 
   snew(spec,npair);
   
@@ -401,6 +402,8 @@ void spectrum(bool bVerbose,
   natoms  = read_first_x(&status,trj,&t0,&x,box);
   if (natoms > nat)
     gmx_fatal(FARGS,"Not enough atoms in trajectory");
+  gpbc = gmx_rmpbc_init(idef,ePBC,natoms,box);
+
   do {
     if (nframes >= maxframes) {
       fprintf(stderr,"\nThere are more than the %d frames you told me!",
@@ -410,7 +413,7 @@ void spectrum(bool bVerbose,
     t1 = t;
     if (bVerbose)
       fprintf(stderr,"\rframe: %d",nframes);
-    rm_pbc(idef,natoms,box,x,x);
+    gmx_rmpbc(gpbc,box,x,x);
     if (bFit)
       do_fit(natoms,w_rls,xp,x);  
     
@@ -437,6 +440,8 @@ void spectrum(bool bVerbose,
   if (bVerbose)
     fprintf(stderr,"\n");
  
+  gmx_rmpbc_done(gpbc);
+
   fp=ffopen("ylm.out","w");
   calc_aver(fp,nframes,npair,pair,spec,maxdist);
   ffclose(fp);
index f6524fd7260a2870f7dd92ed1082e168e68fa88b..034983c0da5182a45d741bb0080080dda8738ed5 100644 (file)
@@ -226,7 +226,7 @@ int gmx_rms(int argc, char *argv[])
     matrix box;
     rvec *x, *xp, *xm = NULL, **mat_x = NULL, **mat_x2, *mat_x2_j = NULL, vec1,
         vec2;
-    int status;
+    t_trxstatus *status;
     char buf[256], buf2[256];
     int ncons = 0;
     FILE *fp;
@@ -245,6 +245,8 @@ int gmx_rms(int argc, char *argv[])
     char *gn_fit, **gn_rms;
     t_rgb rlo, rhi;
     output_env_t oenv;
+    gmx_rmpbc_t  gpbc=NULL;
+
     t_filenm fnm[] =
         {
             { efTPS, NULL, NULL, ffREAD },
@@ -429,8 +431,10 @@ int gmx_rms(int argc, char *argv[])
         }
     }
     /* Prepare reference frame */
-    if (bPBC)
-        rm_pbc(&(top.idef),ePBC,top.atoms.nr,box,xp,xp);
+    if (bPBC) {
+      gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,box);
+      gmx_rmpbc(gpbc,box,xp,xp);
+    }
     if (bReset)
         reset_x(ifit,ind_fit,top.atoms.nr,NULL,xp,w_rls);
     if (bMirror) {
@@ -529,7 +533,7 @@ int gmx_rms(int argc, char *argv[])
     teller = 0;
     do {
         if (bPBC) 
-            rm_pbc(&(top.idef),ePBC,natoms,box,x,x);
+         gmx_rmpbc(gpbc,box,x,x);
 
         if (bReset)
             reset_x(ifit,ind_fit,natoms,NULL,x,w_rls);
@@ -611,7 +615,7 @@ int gmx_rms(int argc, char *argv[])
         teller2 = 0;
         do {
             if (bPBC) 
-                rm_pbc(&(top.idef),ePBC,natoms,box,x,x);
+             gmx_rmpbc(gpbc,box,x,x);
 
             if (bReset)
                 reset_x(ifit,ind_fit,natoms,NULL,x,w_rls);
@@ -649,6 +653,7 @@ int gmx_rms(int argc, char *argv[])
         tel_mat2=tel_mat;
         freq2=freq;
     }
+    gmx_rmpbc_done(gpbc);
 
     if (bMat || bBond) {
         /* calculate RMS matrix */
index 02a52640923c4ab462d711e153ccdd03b45eccf7..65f732fe718e4c586f04e4799e78a9fda701548f 100644 (file)
@@ -542,7 +542,8 @@ int gmx_rmsdist (int argc,char *argv[])
   rvec         *x;
   FILE         *fp;
 
-  int      status,isize,gnr=0;
+  t_trxstatus *status;
+  int      isize,gnr=0;
   atom_id  *index, *noe_index;
   char     *grpname;
   real     **d_r,**d,**dtot,**dtot2,**mean,**rms,**rmsc,*resnr;
@@ -558,7 +559,7 @@ int gmx_rmsdist (int argc,char *argv[])
   static int  nlevels=40;
   static real scalemax=-1.0;
   static bool bSumH=TRUE;
-
+  static bool bPBC=TRUE;
   output_env_t oenv;
 
   t_pargs pa[] = {
@@ -567,7 +568,9 @@ int gmx_rmsdist (int argc,char *argv[])
     { "-max",   FALSE, etREAL, {&scalemax},    
       "Maximum level in matrices" },
     { "-sumh",  FALSE, etBOOL, {&bSumH},       
-      "average distance over equivalent hydrogens" }
+      "average distance over equivalent hydrogens" },
+    { "-pbc",   FALSE, etBOOL, {&bPBC},
+      "Use periodic boundary conditions when computing distances" }
   };
   t_filenm fnm[] = {
     { efTRX, "-f",   NULL,       ffREAD },
@@ -608,6 +611,9 @@ int gmx_rmsdist (int argc,char *argv[])
     
   /* get topology and index */
   read_tps_conf(ftp2fn(efTPS,NFILE,fnm),buf,&top,&ePBC,&x,NULL,box,FALSE);
+  
+  if (!bPBC)
+    ePBC = epbcNONE;
   atoms=&(top.atoms);
   
   get_index(atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&isize,&index,&grpname);
@@ -664,7 +670,7 @@ int gmx_rmsdist (int argc,char *argv[])
   ffclose(fp);
   close_trj(status);
 
-  teller = nframes_read();
+  teller = nframes_read(status);
   calc_rms(isize,teller,dtot,dtot2,mean,&meanmax,rms,&rmsmax,rmsc,&rmscmax);
   fprintf(stderr,"rmsmax = %g, rmscmax = %g\n",rmsmax,rmscmax);
   
index d241e4225b8b132f828a5b8eb7f95162531466a6..385fd0c4cb3e5037c4043c51124f2e4fcf554ef3 100644 (file)
@@ -199,7 +199,8 @@ int gmx_rmsf(int argc,char *argv[])
     { "-fit", FALSE, etBOOL, {&bFit},
       "Do a least squares superposition before computing RMSF. Without this you must make sure that the reference structure and the trajectory match." }
   };
-  int          step,nre,natom,natoms,i,g,m,teller=0;
+  int          natom=0;
+  int          step,nre,natoms,i,g,m,teller=0;
   real         t,lambda,*w_rls,*w_rms;
   
   t_tpxheader  header;
@@ -211,7 +212,8 @@ int gmx_rmsf(int argc,char *argv[])
 
   matrix       box,pdbbox;
   rvec         *x,*pdbx,*xref;
-  int          status,npdbatoms,res0;
+  t_trxstatus   *status;
+  int          npdbatoms,res0;
   char         buf[256];
   const char   *label;
   char         title[STRLEN];
@@ -233,6 +235,7 @@ int gmx_rmsf(int argc,char *argv[])
   int          d;
   real         count=0;
   rvec         xcm;
+  gmx_rmpbc_t  gpbc=NULL;
 
   output_env_t oenv;
 
@@ -299,9 +302,11 @@ int gmx_rmsf(int argc,char *argv[])
     copy_mat(box,pdbbox);
   }
   
-  if (bFit)
+  if (bFit) {
     sub_xcm(xref,isize,index,top.atoms.atom,xcm,FALSE);
-  
+    gpbc = gmx_rmpbc_init(&top.idef,ePBC,natom,box);
+  }
+    
   natom = read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
     
   /* Now read the trj again to compute fluctuations */
@@ -309,8 +314,8 @@ int gmx_rmsf(int argc,char *argv[])
   do {
     if (bFit) {
       /* Remove periodic boundary */
-      rm_pbc(&(top.idef),ePBC,natom,box,x,x);
-      
+      gmx_rmpbc(gpbc,box,x,x);
+
       /* Set center of mass to zero */
       sub_xcm(x,isize,index,top.atoms.atom,xcm,FALSE);
       
@@ -342,6 +347,10 @@ int gmx_rmsf(int argc,char *argv[])
   } while(read_next_x(oenv,status,&t,natom,x,box));
   close_trj(status);
   
+  if (bFit)
+    gmx_rmpbc_done(gpbc);
+
+
   invcount = 1.0/count;
   snew(Uaver,DIM*DIM);
   totmass = 0;
index 677c4e7e287957c7d1359b4e4b976a96f94614c6..c8a53d08e77cb92b74878e40f7635661e8d3618b 100644 (file)
@@ -73,7 +73,7 @@ int gmx_rotacf(int argc,char *argv[])
     "This will calculate the rotational correlation function using a first",
     "order Legendre polynomial of the angle of a vector defined by the index",
     "file. The correlation function will be fitted from 2.5 ps till 20.0 ps",
-    "to a two parameter exponential",
+    "to a two parameter exponential.",
 
 
     ""
@@ -87,7 +87,8 @@ int gmx_rotacf(int argc,char *argv[])
       "Average over molecules" }
   };
 
-  int        status,isize;
+  t_trxstatus *status;
+  int        isize;
   atom_id    *index;
   char       *grpname;
   rvec       *x,*x_s;
@@ -97,6 +98,7 @@ int gmx_rotacf(int argc,char *argv[])
   int        i,m,teller,n_alloc,natoms,nvec,ai,aj,ak;
   unsigned long mode;
   real       t,t0,t1,dt;
+  gmx_rmpbc_t  gpbc=NULL;
   t_topology *top;
   int        ePBC;
   t_filenm   fnm[] = {
@@ -142,6 +144,8 @@ int gmx_rotacf(int argc,char *argv[])
   natoms=read_first_x(oenv,&status,ftp2fn(efTRX,NFILE,fnm),&t,&x,box);
   snew(x_s,natoms);
   
+  gpbc = gmx_rmpbc_init(&(top->idef),ePBC,natoms,box);
+
   /* Start the loop over frames */
   t1 = t0 = t;
   teller  = 0;
@@ -154,8 +158,8 @@ int gmx_rotacf(int argc,char *argv[])
     t1 = t;
     
     /* Remove periodicity */
-    rm_pbc(&(top->idef),ePBC,natoms,box,x,x_s);
-    
+    gmx_rmpbc(gpbc,box,x,x_s);
+  
     /* Compute crossproducts for all vectors, if triplets.
      * else, just get the vectors in case of doublets.
      */
@@ -186,6 +190,9 @@ int gmx_rotacf(int argc,char *argv[])
   close_trj(status); 
   fprintf(stderr,"\nDone with trajectory\n");
   
+  gmx_rmpbc_done(gpbc);
+
+
   /* Autocorrelation function */
   if (teller < 2)
     fprintf(stderr,"Not enough frames for correlation function\n");
index a0f6d9df20523620a1bd3e71a27388785f90d691..e9fed2f71822190f01a3424e81cf1b1f70a8ba85 100644 (file)
@@ -64,13 +64,15 @@ static void get_refx(output_env_t oenv,const char *trxfn,int nfitdim,int skip,
                      bool bMW,t_topology *top,int ePBC,rvec *x_ref)
 {
     int    natoms,nfr_all,nfr,i,j,a,r,c,min_fr;
-    int    status;
+    t_trxstatus *status;
     real   *ti,min_t;
     double tot_mass,msd,*srmsd,min_srmsd,srmsd_tot;
     rvec   *x,**xi;
     real   xf;
     matrix box,R;
     real   *w_rls;
+    gmx_rmpbc_t  gpbc=NULL;
+
 
     nfr_all = 0;
     nfr     = 0;
@@ -89,12 +91,13 @@ static void get_refx(output_env_t oenv,const char *trxfn,int nfitdim,int skip,
         w_rls[a] = (bMW ? top->atoms.atom[index[a]].m : 1.0);
         tot_mass += w_rls[a];
     }
+    gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
 
     do
     {
         if (nfr_all % skip == 0)
         {
-            rm_pbc(&top->idef,ePBC,natoms,box,x,x);
+            gmx_rmpbc(gpbc,box,x,x);
             snew(xi[nfr],gnx);
             for(i=0; i<gnx; i++)
             {
@@ -114,6 +117,8 @@ static void get_refx(output_env_t oenv,const char *trxfn,int nfitdim,int skip,
     close_trj(status);
     sfree(x);
 
+    gmx_rmpbc_done(gpbc);
+
     snew(srmsd,nfr);
     for(i=0; i<nfr; i++)
     {
@@ -216,7 +221,7 @@ int gmx_rotmat(int argc,char *argv[])
           "Use mass weighted fitting" }
     };
     FILE       *out;
-    int        status;
+    t_trxstatus *status;
     t_topology top;
     int        ePBC;
     rvec       *x_ref,*x;
@@ -225,6 +230,7 @@ int gmx_rotmat(int argc,char *argv[])
     int        natoms,i;
     char       *grpname,title[256];
     int        gnx;
+    gmx_rmpbc_t  gpbc=NULL;
     atom_id    *index;
     output_env_t oenv;
     real       *w_rls;
@@ -245,7 +251,10 @@ int gmx_rotmat(int argc,char *argv[])
     
     read_tps_conf(ftp2fn(efTPS,NFILE,fnm),title,&top,&ePBC,&x_ref,NULL,box,bMW);
 
-    rm_pbc(&top.idef,ePBC,top.atoms.nr,box,x_ref,x_ref);
+    gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,box);
+    
+    gmx_rmpbc(gpbc,box,x_ref,x_ref);
+    
     get_index(&top.atoms,ftp2fn_null(efNDX,NFILE,fnm),1,&gnx,&index,&grpname);
 
     if (reffit[0][0] != 'n')
@@ -277,7 +286,7 @@ int gmx_rotmat(int argc,char *argv[])
     
     do
     {
-        rm_pbc(&top.idef,ePBC,natoms,box,x,x);
+        gmx_rmpbc(gpbc,box,x,x);
 
         reset_x(gnx,index,natoms,NULL,x,w_rls);
 
@@ -297,6 +306,8 @@ int gmx_rotmat(int argc,char *argv[])
     }
     while(read_next_x(oenv,status,&t,natoms,x,box));
 
+    gmx_rmpbc_done(gpbc);
+
     close_trj(status);
     
     ffclose(out);
index 1bcad58508b547ce4fcb60faf0c39f13c5bd0761..fe9aae9b9d927b31323b41b5772beb467a635e46 100644 (file)
@@ -79,9 +79,10 @@ static t_charge *mk_charge(t_atoms *atoms,t_block *cgs,int *nncg)
       cg[ncg].cg=i;
       anr=cgs->index[i];
       resnr=atoms->atom[anr].resind;
-      sprintf(buf,"%s%d",
+      sprintf(buf,"%s%d-%d",
              *(atoms->resinfo[resnr].name),
-             atoms->resinfo[resnr].nr);
+             atoms->resinfo[resnr].nr,
+             anr+1);
       cg[ncg].label=strdup(buf);
       ncg++;
     }
@@ -120,11 +121,13 @@ int gmx_saltbr(int argc,char *argv[])
 {
   const char *desc[] = {
     "g_saltbr plots the distance between all combination of charged groups",
-    "as a function of time. The groups are combined in different ways."
+    "as a function of time. The groups are combined in different ways.",
     "A minimum distance can be given, (eg. the cut-off), then groups",
     "that are never closer than that distance will not be plotted.[BR]",
     "Output will be in a number of fixed filenames, min-min.xvg, plus-min.xvg",
-    "and plus-plus.xvg, or files for every individual ion-pair if selected"
+    "and plus-plus.xvg, or files for every individual ion-pair if the [TT]-sep[tt]",
+    "option is selected. In this case files are named as [TT]sb-ResnameResnr-Atomnr[tt].",
+    "There may be many such files."
   };
   static bool bSep=FALSE;
   static real truncate=1000.0;
@@ -156,7 +159,8 @@ int gmx_saltbr(int argc,char *argv[])
   t_topology *top;
   int        ePBC;
   char       *buf;
-  int        status,i,j,k,m,nnn,teller,ncg,n1,n2,n3,natoms;
+  t_trxstatus *status;
+  int        i,j,k,m,nnn,teller,ncg,n1,n2,n3,natoms;
   real       t,*time,qi,qj;
   t_charge   *cg;
   real       ***cgdist;
index 79a9847b81bdbc1ce356bc4b0d04be7c8c090a80..3d83d14622c46d76b2a06be26e3259987172ce76 100644 (file)
@@ -229,7 +229,9 @@ void sas_plot(int nfile,t_filenm fnm[],real solsize,int ndots,
   const char   *vfile;
   real         t;
   gmx_atomprop_t aps=NULL;
-  int          status,ndefault;
+  gmx_rmpbc_t  gpbc=NULL;
+  t_trxstatus  *status;
+  int          ndefault;
   int          i,j,ii,nfr,natoms,flag,nsurfacedots,res;
   rvec         *xtop,*x;
   matrix       topbox,box;
@@ -395,10 +397,13 @@ void sas_plot(int nfile,t_filenm fnm[],real solsize,int ndots,
     
   gmx_atomprop_destroy(aps);
 
+  if (bPBC)
+    gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
+  
   nfr=0;
   do {
     if (bPBC)
-      rm_pbc(&top.idef,ePBC,natoms,box,x,x);
+      gmx_rmpbc(gpbc,box,x,x);
     
     bConnelly = (nfr==0 && opt2bSet("-q",nfile,fnm));
     if (bConnelly) {
@@ -473,7 +478,10 @@ void sas_plot(int nfile,t_filenm fnm[],real solsize,int ndots,
     }
     nfr++;
   } while (read_next_x(oenv,status,&t,natoms,x,box));
-  
+
+  if (bPBC)  
+    gmx_rmpbc_done(gpbc);
+
   fprintf(stderr,"\n");
   close_trj(status);
   ffclose(fp);
index d9a9ac28ce243fe47c20579a0dd3dae4cf7cf280..d69ddba6ecc3fafdae2b23ccba6152400cff62e8 100644 (file)
@@ -71,7 +71,7 @@ static void do_sdf(const char *fnNDX,const char *fnTPS,const char *fnTRX,
                    rvec dtri, const output_env_t oenv)
 {
   FILE       *fp;
-  int        status;
+  t_trxstatus *status;
   int        ng,natoms,i,j,k,l,X,Y,Z,lc,dest;
   ivec       nbin;
   int        ***count;
@@ -96,6 +96,7 @@ static void do_sdf(const char *fnNDX,const char *fnTPS,const char *fnTRX,
   real       delta;
   atom_id    ix,jx;
   t_topology top;
+  gmx_rmpbc_t  gpbc=NULL;
   int        ePBC=-1;
   t_pbc      pbc;
   bool       bTop=FALSE,bRefDone=FALSE,bInGroup=FALSE;
@@ -337,14 +338,14 @@ structure if needed */
 
   normfac = 0;
 
-
+  gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
+  
   do {
     /* Must init pbc every step because of pressure coupling */
     set_pbc(&pbc,ePBC,box);
-    rm_pbc(&top.idef,ePBC,natoms,box,x,x);
-
-
-    /* Dynamically build the ref tripels */
+    gmx_rmpbc(gpbc,box,x,x);
+  
+    /* Dynamically build the ref triples */
     if ( mode == 2 )
       {
         isize[NDX_REF1]=0;
@@ -537,6 +538,9 @@ structure if needed */
   } while (read_next_x(oenv,status,&t,natoms,x,box));
   fprintf(stderr,"\n");
   
+  gmx_rmpbc_done(gpbc);
+
+
   close_trj(status);
   
   sfree(x);
@@ -564,7 +568,7 @@ structure if needed */
 
 
   /* Calculate the mean probability density */
-  fprintf(stderr,"\nNumber of configuations used for SDF: %d\n",(int)normfac);
+  fprintf(stderr,"\nNumber of configurations used for SDF: %d\n",(int)normfac);
 
 
   normfac = nbin[0]*nbin[1]*nbin[2] / normfac;
@@ -652,7 +656,7 @@ int gmx_sdf(int argc,char *argv[])
     "file to work. ",
     "You have to setup 4 groups in the index file before using g_sdf: [PAR]",
     "The first three groups are used to define the SDF coordinate system.",
-    "The programm will dynamically generate the atom tripels according to ",
+    "The program will dynamically generate the atom triples according to ",
     "the selected -mode: ", 
     "In -mode 1 the triples will be just the 1st, 2nd, 3rd, ... atoms from ",
     "groups 1, 2 and 3. Hence the nth entries in groups 1, 2 and 3 must be from the",
@@ -665,10 +669,10 @@ int gmx_sdf(int argc,char *argv[])
     "meeting the further conditions. The triple will only be used if all three atoms",
     "have different res-id's.[PAR]",
     "The local coordinate system is always defined using the following scheme:",
-    "Atom 1 will be used as the point of origin for the SDF. "
+    "Atom 1 will be used as the point of origin for the SDF. ",
     "Atom 1 and 2 will define the principle axis (Z) of the coordinate system.",
     "The other two axis will be defined inplane (Y) and normal (X) to the plane through",
-    "Atoms 1, 2 and 3. "
+    "Atoms 1, 2 and 3. ",
     "The fourth group",
     "contains the atoms for which the SDF will be evaluated.[PAR]",
     "For -mode 2 and 3 you have to define the distance conditions for the ",
@@ -676,11 +680,11 @@ int gmx_sdf(int argc,char *argv[])
     "The SDF will be sampled in cartesian coordinates.",
     "Use '-grid x y z' to define the size of the SDF grid around the ",
     "reference molecule. ",
-    "The Volume of the SDF grid will be V=x*y*z (nm^3). "
+    "The Volume of the SDF grid will be V=x*y*z (nm^3). ",
     "Use -bin to set the binwidth for grid.[PAR]",
     "The output will be a binary 3D-grid file (gom_plt.dat) in the .plt format that can be be",
     "read directly by gOpenMol. ",
-    "The option -r will generate a .gro file with the reference molecule(s) transfered to",
+    "The option -r will generate a .gro file with the reference molecule(s) transferred to",
     "the SDF coordinate system. Load this file into gOpenMol and display the",
     "SDF as a contour plot (see http://www.csc.fi/gopenmol/index.phtml for ",
     "further documentation). [PAR]",
@@ -740,7 +744,7 @@ int gmx_sdf(int argc,char *argv[])
                 "             Nothing to do!");
 
 
-  if ( bRef && fn2ftp(fnREF) != efGRO)
+  if ( bRef && (fn2ftp(fnREF) != efGRO))
     {
       fprintf(stderr,"\nOnly GROMACS format is supported for reference structures.\n");
       fprintf(stderr,"Option -r will be ignored!\n");
@@ -748,8 +752,8 @@ int gmx_sdf(int argc,char *argv[])
     }
 
 
-  if (mode < 1 || mode > 3)
-    gmx_fatal(FARGS,"Wrong -mode selection. Chose 1-, 2- oder 3-praticle mode.\n");
+  if ((mode < 1) || (mode > 3))
+    gmx_fatal(FARGS,"Wrong -mode selection. Chose 1-, 2- oder 3-particle mode.\n");
 
 
   do_sdf(fnNDX,fnTPS,ftp2fn(efTRX,NFILE,fnm),opt2fn("-o",NFILE,fnm),
index 449c33d7e1abb1d3dddf3740578f0d550d91fb2c..5c58941ab83c1f438af9dc1545c4e66fd95b25ec 100644 (file)
@@ -196,10 +196,13 @@ void sgangle_plot(const char *fn,const char *afile,const char *dfile,
     distance,            /* distance between two groups. */
     distance1,           /* distance between plane and one of two atoms */
     distance2;           /* same for second of two atoms */
-  int        status,natoms,teller=0;
+  t_trxstatus *status;
+  int        natoms,teller=0;
   rvec       *x0;   /* coordinates, and coordinates corrected for pb */
   matrix     box;        
   char       buf[256];   /* for xvgr title */
+  gmx_rmpbc_t  gpbc=NULL;
+  
 
   if ((natoms = read_first_x(oenv,&status,fn,&t,&x0,box)) == 0)
     gmx_fatal(FARGS,"Could not read coordinates from statusfile\n");
@@ -222,11 +225,13 @@ void sgangle_plot(const char *fn,const char *afile,const char *dfile,
     sg_distance2 = xvgropen(d2file,buf,"Time (ps","Distance (nm)",oenv);
   }
 
+  gpbc = gmx_rmpbc_init(&(top->idef),ePBC,natoms,box);
+  
   do 
     {
       teller++;
 
-      rm_pbc(&(top->idef),ePBC,natoms,box,x0,x0);
+      gmx_rmpbc(gpbc,box,x0,x0);
       
       calc_angle(ePBC,box,x0,index1,index2,gnx1,gnx2,&angle,
                 &distance,&distance1,&distance2);
@@ -240,7 +245,9 @@ void sgangle_plot(const char *fn,const char *afile,const char *dfile,
        fprintf(sg_distance2,"%12g  %12g\n",t,distance1);
 
     } while (read_next_x(oenv,status,&t,natoms,x0,box));
-  
+    
+  gmx_rmpbc_done(gpbc);
+
   fprintf(stderr,"\n");
   close_trj(status);
   ffclose(sg_angle);
@@ -355,13 +362,16 @@ void sgangle_plot_single(const char *fn,const char *afile,const char *dfile,
     distance,            /* distance between two groups. */
     distance1,           /* distance between plane and one of two atoms */
     distance2;           /* same for second of two atoms */
-  int        status,natoms,teller=0;
+  t_trxstatus *status;
+  int        natoms,teller=0;
   int        i;
   rvec       *x0;   /* coordinates, and coordinates corrected for pb */
   rvec       *xzero;
   matrix     box;        
   char       buf[256];   /* for xvgr title */
+  gmx_rmpbc_t  gpbc=NULL;
   
+
   if ((natoms = read_first_x(oenv,&status,fn,&t,&x0,box)) == 0)
     gmx_fatal(FARGS,"Could not read coordinates from statusfile\n");
   
@@ -384,11 +394,12 @@ void sgangle_plot_single(const char *fn,const char *afile,const char *dfile,
   }
   
   snew(xzero,natoms);
+  gpbc = gmx_rmpbc_init(&top->idef,ePBC,natoms,box);
 
   do {
     teller++;
     
-    rm_pbc(&(top->idef),ePBC,natoms,box,x0,x0);
+    gmx_rmpbc(gpbc,box,x0,x0);
     if (teller==1) {
       for(i=0;i<natoms;i++)
        copy_rvec(x0[i],xzero[i]);
@@ -408,6 +419,7 @@ void sgangle_plot_single(const char *fn,const char *afile,const char *dfile,
       fprintf(sg_distance2,"%12g  %12g\n",t,distance1);
     
   } while (read_next_x(oenv,status,&t,natoms,x0,box));
+  gmx_rmpbc_done(gpbc);
   
   fprintf(stderr,"\n");
   close_trj(status);
@@ -442,7 +454,7 @@ int gmx_sgangle(int argc,char *argv[])
     "Here is what some of the file options do:[BR]",
     "-oa: Angle between the two groups specified in the index file. If a group contains three atoms the normal to the plane defined by those three atoms will be used. If a group contains two atoms, the vector defined by those two atoms will be used.[BR]",
     "-od: Distance between two groups. Distance is taken from the center of one group to the center of the other group.[BR]",
-    "-od1: If one plane and one vector is given, the distances for each of the atoms from the center of the plane is given seperately.[BR]",
+    "-od1: If one plane and one vector is given, the distances for each of the atoms from the center of the plane is given separately.[BR]",
     "-od2: For two planes this option has no meaning."
   };
 
index 4f36bef2a08876095e8e6cc5f4729584eebdca46..d623b9249e09819ad15acc19dd4d7926c419a431 100644 (file)
@@ -688,7 +688,7 @@ int gmx_sham(int argc,char *argv[])
     "A line in the input file may start with a time",
     "(see option [TT]-time[tt]) and any number of y values may follow.",
     "Multiple sets can also be",
-    "read when they are seperated by & (option [TT]-n[tt]),",
+    "read when they are separated by & (option [TT]-n[tt]),",
     "in this case only one y value is read from each line.",
     "All lines starting with # and @ are skipped.",
     "[PAR]",
@@ -737,7 +737,7 @@ int gmx_sham(int argc,char *argv[])
     { "-ttol",     FALSE, etREAL, {&ttol},
       "Tolerance on time in appropriate units (usually ps)" },
     { "-n",       FALSE, etINT, {&nsets_in},
-      "Read # sets seperated by &" },
+      "Read # sets separated by &" },
     { "-d",       FALSE, etBOOL, {&bDer},
        "Use the derivative" },
     { "-bw",      FALSE, etREAL, {&binwidth},
index 3719d19d399bacbb3c336449268ecc07e69a9cac..b6d860a8d4e613c91b9c15c1d6c520f828525a4f 100644 (file)
@@ -99,7 +99,7 @@ int gmx_sorient(int argc,char *argv[])
   t_topology top;
   int      ePBC;
   char     title[STRLEN];
-  int      status;
+  t_trxstatus *status;
   int      natoms;
   real     t;
   rvec     *xtop,*x;
@@ -117,6 +117,7 @@ int gmx_sorient(int argc,char *argv[])
   char    str[STRLEN];
   bool    bTPS;
   rvec    xref,dx,dxh1,dxh2,outer;
+  gmx_rmpbc_t gpbc=NULL;
   t_pbc   pbc;
   char *legr[] = { "<cos(\\8q\\4\\s1\\N)>", 
                         "<3cos\\S2\\N(\\8q\\4\\s2\\N)-1>" };
@@ -126,7 +127,7 @@ int gmx_sorient(int argc,char *argv[])
   const char *desc[] = {
     "g_sorient analyzes solvent orientation around solutes.", 
     "It calculates two angles between the vector from one or more",
-    "reference positions to the first atom of each solvent molecule:[BR]"
+    "reference positions to the first atom of each solvent molecule:[BR]",
     "theta1: the angle with the vector from the first atom of the solvent",
     "molecule to the midpoint between atoms 2 and 3.[BR]",
     "theta2: the angle with the normal of the solvent plane, defined by the",
@@ -219,14 +220,14 @@ int gmx_sorient(int argc,char *argv[])
   rcut2 = sqr(rcut);
 
   invbw = 1/binwidth;
-  nbin1 = (int)(2*invbw + 0.5);
-  nbin2 = (int)(invbw + 0.5);
+  nbin1 = 1+(int)(2*invbw + 0.5);
+  nbin2 = 1+(int)(invbw + 0.5);
 
   invrbw = 1/rbinw;
   
-  snew(hist1,nbin1+1);
-  snew(hist2,nbin2+1);
-  nrbin = rcut/rbinw;
+  snew(hist1,nbin1);
+  snew(hist2,nbin2);
+  nrbin = 1+(int)(rcut/rbinw);
   if (nrbin == 0)
     nrbin = 1;
   snew(histi1,nrbin);
@@ -238,11 +239,15 @@ int gmx_sorient(int argc,char *argv[])
   sum1 = 0;
   sum2 = 0;
 
+  if (bTPS) {
+    /* make molecules whole again */
+    gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
+  }
   /* start analysis of trajectory */
   do {
     if (bTPS) {
       /* make molecules whole again */
-      rm_pbc(&top.idef,ePBC,natoms,box,x,x);
+      gmx_rmpbc(gpbc,box,x,x);
     }
     
     set_pbc(&pbc,ePBC,box);
@@ -259,6 +264,9 @@ int gmx_sorient(int argc,char *argv[])
        sa0 = index[1][m];
        sa1 = index[1][m+1];
        sa2 = index[1][m+2];
+       range_check(sa0,0,natoms);
+       range_check(sa1,0,natoms);
+       range_check(sa2,0,natoms);
        pbc_dx(&pbc,x[sa0],xref,dx);
        r2  = norm2(dx);
        if (r2 < rcut2) {
@@ -280,15 +288,24 @@ int gmx_sorient(int argc,char *argv[])
            unitv(dxh2,dxh2);
            outp = iprod(dx,dxh2)/r;
          }
-         (histi1[(int)(invrbw*r)]) += inp;
-         (histi2[(int)(invrbw*r)]) += 3*sqr(outp) - 1;
-         (histn[(int)(invrbw*r)])++;
-         if (r2>=rmin2 && r2<rmax2) {
-           (hist1[(int)(invbw*(inp + 1))])++;
-           (hist2[(int)(invbw*fabs(outp))])++;
+         {
+           int ii = (int)(invrbw*r);
+           range_check(ii,0,nrbin);
+           histi1[ii] += inp;
+           histi2[ii] += 3*sqr(outp) - 1;
+           histn[ii]++;
+         }
+         if ((r2>=rmin2) && (r2<rmax2)) {
+           int ii1 = (int)(invbw*(inp + 1));
+           int ii2 = (int)(invbw*fabs(outp));
+           
+           range_check(ii1,0,nbin1);
+           range_check(ii2,0,nbin2);
+           hist1[ii1]++;
+           hist2[ii2]++;
            sum1 += inp;
            sum2 += outp;
-            n++;
+           n++;
          }
        }
       }
@@ -301,7 +318,8 @@ int gmx_sorient(int argc,char *argv[])
   /* clean up */
   sfree(x);
   close_trj(status);
-
+  gmx_rmpbc_done(gpbc);
+  
   /* Add the bin for the exact maximum to the previous bin */
   hist1[nbin1-1] += hist1[nbin1];
   hist2[nbin2-1] += hist2[nbin2];
index 1ec61418939ab3c7998ee2b1b94653669e1f3e97..ef55e276dfa2c2ff1c7ec9a3df7c4eec4f07a274 100644 (file)
@@ -129,7 +129,7 @@ int gmx_spatial(int argc,char *argv[])
   t_trxframe fr;
   rvec       *xtop,*shx[26];
   matrix     box,box_pbc;
-  int        status;
+  t_trxstatus *status;
   int        flags = TRX_READ_X;
   t_pbc      pbc;
   t_atoms    *atoms;
@@ -147,6 +147,7 @@ int gmx_spatial(int argc,char *argv[])
   long tot,max,min;
   double norm;
   output_env_t oenv;
+  gmx_rmpbc_t  gpbc=NULL;
 
   t_filenm fnm[] = {
     { efTPS,  NULL,  NULL, ffREAD },   /* this is for the topology */
@@ -206,13 +207,16 @@ int gmx_spatial(int argc,char *argv[])
   numfr=0;
   minx=miny=minz=999;
   maxx=maxy=maxz=0;
+
+  if (bPBC)
+    gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
   /* This is the main loop over frames */
   do {
     /* Must init pbc every step because of pressure coupling */
 
     copy_mat(box,box_pbc);
     if (bPBC) {
-      rm_pbc(&top.idef,ePBC,natoms,box,fr.x,fr.x);
+      gmx_rmpbc(gpbc,box,fr.x,fr.x);
       set_pbc(&pbc,ePBC,box_pbc);
     }
 
@@ -242,6 +246,9 @@ int gmx_spatial(int argc,char *argv[])
 
   } while(read_next_frame(oenv,status,&fr));
 
+  if (bPBC)
+    gmx_rmpbc_done(gpbc);
+
   if(!bCUTDOWN){
     minx=miny=minz=0;
     maxx=nbin[XX];
index ed2d9aa864ad991d6ca0e7a6acc92ce42407f84d..7609b1e205d4ec4c878497cba789aa990e6ebad2 100644 (file)
@@ -126,7 +126,7 @@ int gmx_spol(int argc,char *argv[])
   t_inputrec *ir;
   t_atom     *atom;
   char     title[STRLEN];
-  int      status;
+  t_trxstatus *status;
   int      nrefat,natoms,nf,ntot;
   real     t;
   rvec     *xtop,*x,xref,trial,dx={0},dip,dir;
@@ -141,6 +141,8 @@ int gmx_spol(int argc,char *argv[])
   double  sdip,sdip2,sinp,sdinp,nmol;
   int     *hist;
   t_pbc   pbc;
+  gmx_rmpbc_t  gpbc=NULL;
+
   
   const char *desc[] = {
     "g_spol analyzes dipoles around a solute; it is especially useful",
@@ -236,12 +238,14 @@ int gmx_spol(int argc,char *argv[])
 
   molindex = top->mols.index;
   atom     = top->atoms.atom;
+  
+  gpbc = gmx_rmpbc_init(&top->idef,ir->ePBC,natoms,box);
 
   /* start analysis of trajectory */
   do {
     /* make molecules whole again */
-    rm_pbc(&top->idef,ir->ePBC,natoms,box,x,x);
-    
+    gmx_rmpbc(gpbc,box,x,x);
+
     set_pbc(&pbc,ir->ePBC,box);
     if (bCom)
       calc_com_pbc(nrefat,top,x,&pbc,index[0],xref,ir->ePBC,box);
@@ -296,6 +300,8 @@ int gmx_spol(int argc,char *argv[])
     nf++;
 
   }  while (read_next_x(oenv,status,&t,natoms,x,box));
+  
+  gmx_rmpbc_done(gpbc);
 
   /* clean up */
   sfree(x);
index 6c3e19b2caaba8287c6a94dfdf87f4dcd28244c3..cbe10ee6ae968d53df0fd1772a0dec004eddd63b 100644 (file)
@@ -271,7 +271,8 @@ int gmx_tcaf(int argc,char *argv[])
   char       *grpname;
   char       title[256];
   real       t0,t1,dt,m,mtot,sysmass,rho,sx,cx;
-  int        status,nframes,n_alloc,i,j,k,d;
+  t_trxstatus *status;
+  int        nframes,n_alloc,i,j,k,d;
   rvec       mv_mol,cm_mol,kfac[NK];
   int        nkc,nk,ntc;
   real       **c1,**tc;
index 1e2e321eee373a9a2db33d0605c2399adf29c109..2598d2cd24857798a7873de9774f9c6f5ff660fc 100644 (file)
@@ -133,7 +133,7 @@ static void print_data(FILE *fp,real time,rvec x[],real *mass,bool bCom,
     low_print_data(fp,time,x,isize[0],index[0],bDim);
 }
 
-static void write_trx_x(int status,t_trxframe *fr,real *mass,bool bCom,
+static void write_trx_x(t_trxstatus *status,t_trxframe *fr,real *mass,bool bCom,
                        int ngrps,int isize[],atom_id **index)
 {
   static rvec *xav=NULL;
@@ -528,7 +528,9 @@ int gmx_traj(int argc,char *argv[])
   rvec       *xtop,*xp=NULL;
   rvec       *sumxv=NULL,*sumv=NULL,*sumxf=NULL,*sumf=NULL;
   matrix     topbox;
-  int        status,status_out=-1;
+  t_trxstatus *status;
+  t_trxstatus *status_out=NULL;
+  gmx_rmpbc_t  gpbc=NULL;
   int        i,j,n;
   int        nr_xfr,nr_vfr,nr_ffr;
   char       **grpname;
@@ -720,6 +722,8 @@ int gmx_traj(int argc,char *argv[])
   nr_xfr = 0;
   nr_vfr = 0;
   nr_ffr = 0;
+
+  gpbc = gmx_rmpbc_init(&top.idef,ePBC,fr.natoms,fr.box);
   
   do {
     time = output_env_conv_time(oenv,fr.time);
@@ -734,7 +738,7 @@ int gmx_traj(int argc,char *argv[])
     }
     
     if (fr.bX && bCom)
-      rm_pbc(&(top.idef),ePBC,fr.natoms,fr.box,fr.x,fr.x);
+      gmx_rmpbc(gpbc,fr.box,fr.x,fr.x);
 
     if (bVD && fr.bV) 
       update_histo(isize[0],index[0],fr.v,&nvhisto,&vhisto,binwidth);
@@ -802,6 +806,7 @@ int gmx_traj(int argc,char *argv[])
     
   } while(read_next_frame(oenv,status,&fr));
   
+  gmx_rmpbc_done(gpbc);
 
   /* clean up a bit */
   close_trj(status);
index 01517bb64ba22800127bac81b1186654417a2e43..4bafafd738afaa2e515c42ebb5330bcd77123a2c 100644 (file)
@@ -76,7 +76,8 @@ static void scan_trj_files(char **fnms, int nfiles, real *readtime,
                            const output_env_t oenv)
 {
     /* Check start time of all files */
-    int i, status, natoms = 0;
+    int i, natoms = 0;
+    t_trxstatus *status;
     real t;
     t_trxframe fr;
     bool ok;
@@ -291,7 +292,7 @@ static void do_demux(int nset, char *fnms[], char *fnms_out[], int nval,
                      atom_id index[], real dt, const output_env_t oenv)
 {
     int i, j, k, natoms, nnn;
-    int *fp_in, *fp_out;
+    t_trxstatus **fp_in, **fp_out;
     bool bCont, *bSet;
     real t, first_time = 0;
     t_trxframe *trx;
@@ -404,7 +405,7 @@ int gmx_trjcat(int argc, char *argv[])
             "Obviously the file to append to has to be the one with lowest starting",
             "time since one can only append at the end of a file.[PAR]",
             "If the [TT]-demux[tt] option is given, the N trajectories that are",
-            "read, are written in another order as specified in the xvg file."
+            "read, are written in another order as specified in the xvg file.",
             "The xvg file should contain something like:[PAR]",
             "0  0  1  2  3  4  5[BR]",
             "2  1  0  2  3  5  4[BR]",
@@ -451,13 +452,14 @@ int gmx_trjcat(int argc, char *argv[])
             { "-cat", FALSE, etBOOL,
                 { &bCat }, "do not discard double time frames" } };
 #define npargs asize(pa)
-    int status, ftpin, i, frame, frame_out, step = 0, trjout = 0;
+    int ftpin, i, frame, frame_out, step = 0, trjout = 0;
+    t_trxstatus *status;
     rvec *x, *v;
     real xtcpr, t_corr;
     t_trxframe fr, frout;
     char **fnms, **fnms_out, *in_file, *out_file;
     int n_append;
-    int trxout = -1;
+    t_trxstatus *trxout = NULL;
     bool bNewFile, bIndex, bWrite;
     int earliersteps, nfile_in, nfile_out, *cont_type, last_ok_step;
     real *readtime, *timest, *settime;
@@ -619,8 +621,12 @@ int gmx_trjcat(int argc, char *argv[])
         }
         else 
         {
+            t_fileio *stfio;
+
             if (!read_first_frame(oenv,&status,out_file,&fr,FLAGS))
                 gmx_fatal(FARGS,"Reading first frame from %s",out_file);
+
+            stfio=trx_get_fileio(status);
             if (!bKeepLast && !bOverwrite)
             {
                 fprintf(stderr, "\n\nWARNING: Appending without -overwrite implies -keeplast "
@@ -631,9 +637,12 @@ int gmx_trjcat(int argc, char *argv[])
                 /* Fails if last frame is incomplete
                  * We can't do anything about it without overwriting
                  * */
-                if (gmx_fio_getftp(status) == efXTC) 
+                if (gmx_fio_getftp(stfio) == efXTC) 
                 {
-                    lasttime = xdr_xtc_get_last_frame_time(gmx_fio_getfp(status),gmx_fio_getxdr(status),fr.natoms,&bOK);
+                    lasttime = 
+                         xdr_xtc_get_last_frame_time(gmx_fio_getfp(stfio),
+                                                     gmx_fio_getxdr(stfio),
+                                                     fr.natoms,&bOK);
                     fr.time = lasttime;
                     if (!bOK)
                     {
@@ -652,10 +661,13 @@ int gmx_trjcat(int argc, char *argv[])
             }
             else if (bOverwrite)
             {
-                if (gmx_fio_getftp(status) != efXTC) {
+                if (gmx_fio_getftp(stfio) != efXTC) {
                     gmx_fatal(FARGS,"Overwrite only supported for XTC." );
                 }
-                last_frame_time = xdr_xtc_get_last_frame_time(gmx_fio_getfp(status),gmx_fio_getxdr(status),fr.natoms,&bOK);
+                last_frame_time = 
+                          xdr_xtc_get_last_frame_time(gmx_fio_getfp(stfio),
+                                                      gmx_fio_getxdr(stfio),
+                                                      fr.natoms,&bOK);
                 if (!bOK)
                 {
                    gmx_fatal(FARGS,"Error reading last frame. Maybe seek not supported." );
@@ -672,7 +684,7 @@ int gmx_trjcat(int argc, char *argv[])
                 {
                     searchtime = last_frame_time;
                 }
-                if (xtc_seek_time(searchtime,status,fr.natoms))
+                if (xtc_seek_time(stfio,searchtime,fr.natoms))
                 {
                     gmx_fatal(FARGS,"Error seeking to append position.");
                 }
@@ -683,10 +695,10 @@ int gmx_trjcat(int argc, char *argv[])
                               searchtime,fr.time);
                 }
                 lasttime = fr.time;             
-                fpos = gmx_fio_ftell(status);
+                fpos = gmx_fio_ftell(stfio);
                 close_trj(status);
                 trxout = open_trx(out_file,"r+");
-                if (gmx_fio_seek(trxout,fpos)) {
+                if (gmx_fio_seek(trx_get_fileio(trxout),fpos)) {
                     gmx_fatal(FARGS,"Error seeking to append position.");
                 }
             }
@@ -822,7 +834,8 @@ int gmx_trjcat(int argc, char *argv[])
 
                         if (bIndex)
                         {
-                            write_trxframe_indexed(trxout,&frout,isize,index,NULL);
+                            write_trxframe_indexed(trxout,&frout,isize,index,
+                                                   NULL);
                         }
                         else
                         {
@@ -841,7 +854,7 @@ int gmx_trjcat(int argc, char *argv[])
 
             earliersteps+=step;          
         }  
-        if (trxout >= 0)
+        if (trxout)
         {
             close_trx(trxout);
         }
index c36c443b276cf6954fab2c5a121c9f14dbb4c6fd..c962361484fd4a1378667988629b5cf26ddf5604 100644 (file)
@@ -413,7 +413,7 @@ void check_trn(const char *fn)
 #if (!defined WIN32 && !defined _WIN32 && !defined WIN64 && !defined _WIN64)
 void do_trunc(const char *fn, real t0)
 {
-    int          in;
+    t_fileio     *in;
     FILE         *fp;
     bool         bStop,bOK;
     t_trnheader  sh;
@@ -483,7 +483,7 @@ int gmx_trjconv(int argc,char *argv[])
     const char *desc[] = {
         "trjconv can convert trajectory files in many ways:[BR]",
         "[BB]1.[bb] from one format to another[BR]",
-        "[BB]2.[bb] select a subset of atoms[BR]"
+        "[BB]2.[bb] select a subset of atoms[BR]",
         "[BB]3.[bb] change the periodicity representation[BR]",
         "[BB]4.[bb] keep multimeric molecules together[BR]",
         "[BB]5.[bb] center atoms in the box[BR]",
@@ -518,7 +518,7 @@ int gmx_trjconv(int argc,char *argv[])
         "append output to an existing trajectory file.",
         "No checks are performed to ensure integrity",
         "of the resulting combined trajectory file.[PAR]",
-        "Option [TT]-sep[tt] can be used to write every frame to a seperate",
+        "Option [TT]-sep[tt] can be used to write every frame to a separate",
         ".gro, .g96 or .pdb file, default all frames all written to one file.",
         "[TT].pdb[tt] files with all frames concatenated can be viewed with",
         "[TT]rasmol -nmrpdb[tt].[PAR]",
@@ -559,7 +559,7 @@ int gmx_trjconv(int argc,char *argv[])
         "* [TT]whole[tt] only makes broken molecules whole.[PAR]",
         "Option [TT]-ur[tt] sets the unit cell representation for options",
         "[TT]mol[tt], [TT]res[tt] and [TT]atom[tt] of [TT]-pbc[tt].",
-        "All three options give different results for triclinc boxes and",
+        "All three options give different results for triclinic boxes and",
         "identical results for rectangular boxes.",
         "[TT]rect[tt] is the ordinary brick shape.",
         "[TT]tric[tt] is the triclinic unit cell.", 
@@ -731,8 +731,9 @@ int gmx_trjconv(int argc,char *argv[])
 #define NPA asize(pa)
 
     FILE         *out=NULL;
-    int          trxout=NOTSET;
-    int          status,ftp,ftpin=0,file_nr;
+    t_trxstatus *trxout=NULL;
+    t_trxstatus *status;
+    int          ftp,ftpin=0,file_nr;
     t_trxframe   fr,frout;
     int          flags;
     rvec         *xmem=NULL,*vmem=NULL,*fmem=NULL;
@@ -753,7 +754,8 @@ int gmx_trjconv(int argc,char *argv[])
     atom_id      *ind_fit,*ind_rms;
     char         *gn_fit,*gn_rms;
     t_cluster_ndx *clust=NULL;
-    int          *clust_status=NULL;
+    t_trxstatus  **clust_status=NULL;
+    int          *clust_status_id=NULL;
     int          ntrxopen=0;
     int          *nfwritten=NULL;
     int          ndrop=0,ncol,drop0=0,drop1=0,dropuse=0;
@@ -761,6 +763,7 @@ int gmx_trjconv(int argc,char *argv[])
     real         tshift=0,t0=-1,dt=0.001,prec;
     bool         bFit,bFitXY,bPFit,bReset;
     int          nfitdim;
+    gmx_rmpbc_t  gpbc=NULL;
     bool         bRmPBC,bPBCWhole,bPBCcomRes,bPBCcomMol,bPBCcomAtom,bPBC,bNoJump,bCluster;
     bool         bCopy,bDoIt,bIndex,bTDump,bSetTime,bTPS=FALSE,bDTset=FALSE;
     bool         bExec,bTimeStep=FALSE,bDumpFrame=FALSE,bSetPrec,bNeedPrec;
@@ -844,6 +847,7 @@ int gmx_trjconv(int argc,char *argv[])
         if (bFit || bReset)
             nfitdim = (fit_enum==efFitXY || fit_enum==efResetXY) ? 2 : 3;
         bRmPBC = bFit || bPBCWhole || bPBCcomRes || bPBCcomMol;
+         
         if (bSetUR) {
             if (!(bPBCcomRes || bPBCcomMol ||  bPBCcomAtom)) {
                 fprintf(stderr,
@@ -909,9 +913,13 @@ int gmx_trjconv(int argc,char *argv[])
                           clust->clust->nr,1+clust->clust->nr/FOPEN_MAX,FOPEN_MAX);
 
             snew(clust_status,clust->clust->nr);
+            snew(clust_status_id,clust->clust->nr);
             snew(nfwritten,clust->clust->nr);
             for(i=0; (i<clust->clust->nr); i++)
-                clust_status[i] = -1;
+            {
+                clust_status[i] = NULL;
+                clust_status_id[i] = -1;
+            }
             bSeparate = bSplit = FALSE;
         }
         /* skipping */  
@@ -939,6 +947,8 @@ int gmx_trjconv(int argc,char *argv[])
 
             if (bCONECT)
                 gc = gmx_conect_generate(&top);
+           if (bRmPBC)
+             gpbc = gmx_rmpbc_init(&top.idef,ePBC,top.atoms.nr,top_box);
         }
 
         /* get frame number index */
@@ -1005,7 +1015,7 @@ int gmx_trjconv(int argc,char *argv[])
             /* Restore reference structure and set to origin, 
          store original location (to put structure back) */
             if (bRmPBC)
-                rm_pbc(&(top.idef),ePBC,atoms->nr,top_box,xp,xp);
+             gmx_rmpbc(gpbc,top_box,xp,xp);
             copy_rvec(xp[index[0]],x_shift);
             reset_x_ndim(nfitdim,ifit,ind_fit,atoms->nr,NULL,xp,w_rls);
             rvec_dec(x_shift,xp[index[0]]);
@@ -1110,7 +1120,8 @@ int gmx_trjconv(int argc,char *argv[])
             }
 
             if (ftp == efG87)
-                fprintf(gmx_fio_getfp(trxout),"Generated by %s. #atoms=%d, a BOX is"
+                fprintf(gmx_fio_getfp(trx_get_fileio(trxout)),
+                        "Generated by %s. #atoms=%d, a BOX is"
                         " stored in this file.\n",Program(),nout);
 
             /* Start the big loop over frames */
@@ -1195,7 +1206,7 @@ int gmx_trjconv(int argc,char *argv[])
                     /* Now modify the coords according to the flags,
             for normal fit, this is only done for output frames */
                     if (bRmPBC)
-                        rm_pbc(&(top.idef),ePBC,natoms,fr.box,fr.x,fr.x);
+                     gmx_rmpbc(gpbc,fr.box,fr.x,fr.x);
 
                     reset_x_ndim(nfitdim,ifit,ind_fit,natoms,NULL,fr.x,w_rls);
                     do_fit(natoms,w_rls,xp,fr.x);
@@ -1273,7 +1284,7 @@ int gmx_trjconv(int argc,char *argv[])
                                for PFit we did this already! */
 
                             if (bRmPBC)
-                                rm_pbc(&(top.idef),ePBC,natoms,fr.box,fr.x,fr.x);
+                             gmx_rmpbc(gpbc,fr.box,fr.x,fr.x);
 
                             if (bReset) {
                                 reset_x_ndim(nfitdim,ifit,ind_fit,natoms,NULL,fr.x,w_rls);
@@ -1364,19 +1375,20 @@ int gmx_trjconv(int argc,char *argv[])
                         case efG87:
                         case efXTC:
                             if ( bSplitHere ) {
-                                if ( trxout >= 0 )
+                                if ( trxout )
                                     close_trx(trxout);
                                 trxout = open_trx(out_file2,filemode);
                             }
                             if (bSubTraj) {
                                 if (my_clust != -1) {
                                     char buf[STRLEN];
-                                    if (clust_status[my_clust] == -1) {
+                                    if (clust_status_id[my_clust] == -1) {
                                         sprintf(buf,"%s.%s",clust->grpname[my_clust],ftp2ext(ftp));
                                         clust_status[my_clust] = open_trx(buf,"w");
+                                        clust_status_id[my_clust] = 1;
                                         ntrxopen++;
                                     }
-                                    else if (clust_status[my_clust] == -2)
+                                    else if (clust_status_id[my_clust] == -2)
                                         gmx_fatal(FARGS,"File %s.xtc should still be open (%d open xtc files)\n""in order to write frame %d. my_clust = %d",
                                                   clust->grpname[my_clust],ntrxopen,frame,
                                                   my_clust);
@@ -1386,7 +1398,7 @@ int gmx_trjconv(int argc,char *argv[])
                                         (clust->clust->index[my_clust+1]-
                                             clust->clust->index[my_clust])) {
                                         close_trx(clust_status[my_clust]);
-                                        clust_status[my_clust] = -2;
+                                        clust_status_id[my_clust] = -2;
                                         ntrxopen--;
                                         if (ntrxopen < 0)
                                             gmx_fatal(FARGS,"Less than zero open xtc files!");
@@ -1474,18 +1486,20 @@ int gmx_trjconv(int argc,char *argv[])
 
         if (!bHaveFirstFrame || (bTDump && !bDumpFrame))
             fprintf(stderr,"\nWARNING no output, "
-                    "trajectory ended at %g\n",fr.time);
+                    "last frame read at t=%g\n",fr.time);
         fprintf(stderr,"\n");
 
         close_trj(status);
-
-        if (trxout >= 0)
+       if (bRmPBC)
+         gmx_rmpbc_done(gpbc);
+       
+        if (trxout)
             close_trx(trxout);
         else if (out != NULL)
             ffclose(out);
         if (bSubTraj) {
             for(i=0; (i<clust->clust->nr); i++)
-                if (clust_status[i] >= 0)
+                if (clust_status[i] )
                     close_trx(clust_status[i]);
         }
     }
index 2019eaf7e4363f00783399dc79a6c7e74d57a8a1..dbbd57d33239c7fda67b8fbbcc3d5068c9dffb62 100644 (file)
@@ -102,7 +102,7 @@ int gmx_trjorder(int argc,char *argv[])
     "will be stored in the B-factor field in order to color with e.g. rasmol.",
     "[PAR]",
     "With option [TT]-nshell[tt] the number of molecules within a shell",
-    "of radius [TT]-r[tt] around the refernce group are printed."
+    "of radius [TT]-r[tt] around the reference group are printed."
   };
   static int na=3,ref_a=1;
   static real rcut=0;
@@ -120,13 +120,15 @@ int gmx_trjorder(int argc,char *argv[])
       "Order molecules on z-coordinate" }
   };
   FILE       *fp;
-  int        status,out;
+  t_trxstatus *out;
+  t_trxstatus *status;
   bool       bNShell,bPDBout;
   t_topology top;
   int        ePBC;
   rvec       *x,*xsol,xcom,dx;
   matrix     box;
   t_pbc      pbc;
+  gmx_rmpbc_t gpbc;
   real       t,totmass,mass,rcut2=0,n2;
   int        natoms,nwat,ncut;
   char       **grpname,title[256];
@@ -190,7 +192,7 @@ int gmx_trjorder(int argc,char *argv[])
   for(i=0; (i<natoms); i++)
     swi[i] = i;
 
-  out     = -1;
+  out     = NULL;
   fp      = NULL;
   bNShell = ((opt2bSet("-nshell",NFILE,fnm)) ||
             (opt2parg_bSet("-r",asize(pa),pa)));
@@ -210,8 +212,9 @@ int gmx_trjorder(int argc,char *argv[])
     }
     out = open_trx(opt2fn("-o",NFILE,fnm),"w");
   }
+  gpbc = gmx_rmpbc_init(&top.idef,ePBC,natoms,box);
   do {
-    rm_pbc(&top.idef,ePBC,natoms,box,x,x);
+    gmx_rmpbc(gpbc,box,x,x);
     set_pbc(&pbc,ePBC,box);
 
     if (ref_a == -1) {
@@ -285,7 +288,7 @@ int gmx_trjorder(int argc,char *argv[])
          ncut++;
       fprintf(fp,"%10.3f  %8d\n",t,ncut);
     }
-    if (out != -1) {
+    if (out) {
       qsort(order,nwat,sizeof(*order),ocomp);
       for(i=0; (i<nwat); i++)
        for(j=0; (j<na); j++) 
@@ -303,11 +306,12 @@ int gmx_trjorder(int argc,char *argv[])
     }
   } while(read_next_x(oenv,status,&t,natoms,x,box));
   close_trj(status);
-  if (out != -1)
+  if (out)
     close_trx(out);
   if (fp)
     ffclose(fp);
-
+  gmx_rmpbc_done(gpbc);
+  
   thanx(stderr);
   
   return 0;
index 4c5d4d84ce927674d817df3e2e03242d282f9410..642974845ba644a245c9a62be212907b067cf871 100644 (file)
@@ -43,6 +43,7 @@
 #include "calcgrid.h"
 #include "checkpoint.h"
 #include "gmx_ana.h"
+#include "names.h"
 
 
 
@@ -50,13 +51,19 @@ enum {
   ddnoSEL, ddnoINTERLEAVE, ddnoPP_PME, ddnoCARTESIAN, ddnoNR
 };
 
-/* Enum for situations that can occur during log file parsing */
+/* Enum for situations that can occur during log file parsing, the
+ * corresponding string entries can be found in do_the_tests() in
+ * const char* ParseLog[] */
 enum {
     eParselogOK,
     eParselogNotFound,
     eParselogNoPerfData,
     eParselogTerm,
     eParselogResetProblem,
+    eParselogNoDDGrid,
+    eParselogTPXVersion,
+    eParselogNotParallel,
+    eParselogFatal,
     eParselogNr
 };
 
@@ -81,9 +88,18 @@ typedef struct
     int  nr_inputfiles;         /* The number of tpr and mdp input files */
     gmx_large_int_t orig_sim_steps;  /* Number of steps to be done in the real simulation */
     real *r_coulomb;            /* The coulomb radii [0...nr_inputfiles] */
-    real *r_vdW;                /* The vdW radii */
+    real *r_vdw;                /* The vdW radii */
+    real *rlist;                /* Neighbourlist cutoff radius */
+    real *rlistlong;
     int  *fourier_nx, *fourier_ny, *fourier_nz;
     real *fourier_sp;           /* Fourierspacing */
+
+    /* Original values as in inputfile: */
+    real orig_rcoulomb;
+    real orig_rvdw;
+    real orig_rlist, orig_rlistlong;
+    int  orig_nk[DIM];
+    real orig_fs[DIM];
 } t_inputinfo;
 
 
@@ -121,10 +137,46 @@ static void cleandata(t_perf *perfdata, int test_nr)
 }
 
 
+static bool is_equal(real a, real b)
+{
+    real diff, eps=1.0e-6;
+
+
+    diff = a - b;
+
+    if (diff < 0.0) diff = -diff;
+
+    if (diff < eps)
+        return TRUE;
+    else
+        return FALSE;
+}
+
+
+static void finalize(const char *fn_out)
+{
+    char buf[STRLEN];
+    FILE *fp;
+
+
+    fp = fopen(fn_out,"r");
+    fprintf(stdout,"\n\n");
+
+    while( fgets(buf,STRLEN-1,fp) != NULL )
+    {
+        fprintf(stdout,"%s",buf);
+    }
+    fclose(fp);
+    fprintf(stdout,"\n\n");
+    thanx(stderr);
+}
+
+
 enum {eFoundNothing, eFoundDDStr, eFoundAccountingStr, eFoundCycleStr};
 
-static int parse_logfile(const char *logfile, t_perf *perfdata, int test_nr, 
-                         int presteps, gmx_large_int_t cpt_steps, int nnodes)
+static int parse_logfile(const char *logfile, const char *errfile,
+        t_perf *perfdata, int test_nr, int presteps, gmx_large_int_t cpt_steps,
+        int nnodes)
 {
     FILE  *fp;
     char  line[STRLEN], dumstring[STRLEN], dumstring2[STRLEN];
@@ -208,6 +260,19 @@ static int parse_logfile(const char *logfile, t_perf *perfdata, int test_nr,
                         gmx_fatal(FARGS, "PME nodes from command line and output file are not identical");
                     iFound = eFoundDDStr;
                 }
+                /* Catch a few errors that might have occured: */
+                else if (str_starts(line, "There is no domain decomposition for"))
+                {
+                    return eParselogNoDDGrid;
+                }
+                else if (str_starts(line, "reading tpx file"))
+                {
+                    return eParselogTPXVersion;
+                }
+                else if (str_starts(line, "The -dd or -npme option request a parallel simulation"))
+                {
+                    return eParselogNotParallel;
+                }
                 break;
             case eFoundDDStr:
                 /* Look for PME mesh/force balance (not necessarily present, though) */
@@ -239,6 +304,33 @@ static int parse_logfile(const char *logfile, t_perf *perfdata, int test_nr,
                 break;
         }
     } /* while */
+    
+    /* Check why there is no performance data in the log file.
+     * Did a fatal errors occur? */
+    if (gmx_fexist(errfile))
+    {
+        fp = fopen(errfile, "r");
+        while (fgets(line, STRLEN, fp) != NULL)
+        {
+            if ( str_starts(line, "Fatal error:") )
+            {
+                if (fgets(line, STRLEN, fp) != NULL)
+                    fprintf(stderr, "\nWARNING: A fatal error has occured during this benchmark:\n"
+                                    "%s\n", line);
+                fclose(fp);
+                cleandata(perfdata, test_nr);
+                return eParselogFatal;
+            }
+        }
+        fclose(fp);
+    }
+    else
+    {
+        fprintf(stderr, "WARNING: Could not find stderr file %s.\n", errfile);
+    }
+
+    /* Giving up ... we could not find out why there is no performance data in
+     * the log file. */
     fprintf(stdout, "No performance data in log file.\n");
     fclose(fp);
     cleandata(perfdata, test_nr);
@@ -247,8 +339,9 @@ static int parse_logfile(const char *logfile, t_perf *perfdata, int test_nr,
 }
 
 
-static int analyze_data(
+static bool analyze_data(
         FILE        *fp,
+        const char  *fn,
         t_perf      **perfdata,
         int         nnodes,
         int         ntprs,
@@ -265,6 +358,7 @@ static int analyze_data(
     t_perf *pd;
     char strbuf[STRLEN];
     char str_PME_f_load[13];
+    bool bCanUseOrigTPR;
 
 
     if (nrepeats > 1)
@@ -357,7 +451,7 @@ static int analyze_data(
     }
 
     if (k_win == -1)
-        gmx_fatal(FARGS, "None of the runs was successful! Exiting.");
+        gmx_fatal(FARGS, "None of the runs was successful! Check %s for problems.", fn);
 
     sep_line(fp);
 
@@ -368,19 +462,38 @@ static int analyze_data(
         sprintf(strbuf, "%d", winPME);
     fprintf(fp, "Best performance was achieved with %s PME nodes", strbuf);
     if (nrepeats > 1)
-        fprintf(fp, " (see line %d) ", line_win);
-    if (ntprs > 1)
-        fprintf(fp, "\nand %s PME settings. ", (k_win ? "optimized" : "original"));
+        fprintf(fp, " (see line %d)", line_win);
     fprintf(fp, "\n");
 
-    /* Only mention settings if rcoulomb, rvdv, nkx, nky, or nkz was modified: */
-    if (k_win)
+    /* Only mention settings if they were modified: */
+    bCanUseOrigTPR = TRUE;
+    if ( !is_equal(info->r_coulomb[k_win], info->orig_rcoulomb) )
+    {
+        fprintf(fp, "Optimized PME settings:\n"
+                    "   New Coulomb radius: %f nm (was %f nm)\n",
+                    info->r_coulomb[k_win], info->orig_rcoulomb);
+        bCanUseOrigTPR = FALSE;
+    }
+
+    if ( !is_equal(info->r_vdw[k_win], info->orig_rvdw) )
     {
-        fprintf(fp, "Optimized PME settings:\n");
-        fprintf(fp, "r_coulomb = %f, r_vdW = %f, nx,ny,nz = %d %d %d\n",
-                info->r_coulomb[k_win], info->r_vdW[k_win],
-                info->fourier_nx[k_win], info->fourier_ny[k_win], info->fourier_nz[k_win]);
+        fprintf(fp, "   New Van der Waals radius: %f nm (was %f nm)\n",
+                info->r_vdw[k_win], info->orig_rvdw);
+        bCanUseOrigTPR = FALSE;
     }
+
+    if ( ! (info->fourier_nx[k_win]==info->orig_nk[XX] &&
+            info->fourier_ny[k_win]==info->orig_nk[YY] &&
+            info->fourier_nz[k_win]==info->orig_nk[ZZ] ) )
+    {
+        fprintf(fp, "   New Fourier grid xyz: %d %d %d (was %d %d %d)\n",
+                info->fourier_nx[k_win], info->fourier_ny[k_win], info->fourier_nz[k_win],
+                info->orig_nk[XX], info->orig_nk[YY], info->orig_nk[ZZ]);
+        bCanUseOrigTPR = FALSE;
+    }
+    if (bCanUseOrigTPR && ntprs > 1)
+        fprintf(fp, "and original PME settings.\n");
+    
     fflush(fp);
     
     /* Return the index of the mdp file that showed the highest performance
@@ -388,12 +501,13 @@ static int analyze_data(
     *index_tpr    = k_win; 
     *npme_optimal = winPME;
     
-    return 0;
+    return bCanUseOrigTPR;
 }
 
 
 /* Get the commands we need to set up the runs from environment variables */
-static void get_program_paths(char *cmd_mpirun[], char *cmd_mdrun[], int repeats)
+static void get_program_paths(bool bThreads, char *cmd_mpirun[], char cmd_np[],
+                              char *cmd_mdrun[], int repeats)
 {
     char *command=NULL;
     char *cp;
@@ -402,60 +516,114 @@ static void get_program_paths(char *cmd_mpirun[], char *cmd_mdrun[], int repeats
     FILE *fp;
     const char def_mpirun[] = "mpirun";
     const char def_mdrun[]  = "mdrun";
-    const char filename[]   = "testrun.log";
-    const char match_mdrun[]= "NNODES=";
-    bool  bFound = FALSE;
+    const char filename[]   = "benchtest.log";
+    const char match_mpi[]  = "NNODES=";
+    const char match_mdrun[]= "Program: ";
+    const char empty_mpirun[] = "";
+    bool  bMdrun = FALSE;
+    bool  bMPI   = FALSE;
     
 
     /* Get the commands we need to set up the runs from environment variables */
-     if ( (cp = getenv("MPIRUN")) != NULL)
-         *cmd_mpirun = strdup(cp);
-     else
-         *cmd_mpirun = strdup(def_mpirun);
-     
-     if ( (cp = getenv("MDRUN" )) != NULL )
-         *cmd_mdrun  = strdup(cp);
-     else
-         *cmd_mdrun  = strdup(def_mdrun);
-     
-               
-     /* If no simulations have to be performed, we are done here */
-     if (repeats <= 0)
-         return;
-     
-     /* Run a small test to see if mpirun and mdrun work if we intend to execute mdrun! */
-     fprintf(stdout, "Making shure that mdrun can be executed. ");
-     
-     snew(command, strlen(*cmd_mpirun) + strlen(*cmd_mdrun) + strlen(filename) + 30);
-     sprintf(command, "%s -np 1 %s -h -quiet >& %s", *cmd_mpirun, *cmd_mdrun, filename);
-     fprintf(stdout, "Trying '%s' ... ", command);
-     
-     gmx_system_call(command);
+    if (!bThreads)
+    {
+        if ( (cp = getenv("MPIRUN")) != NULL)
+            *cmd_mpirun = strdup(cp);
+        else
+            *cmd_mpirun = strdup(def_mpirun);
+    }
+    else
+    {
+        *cmd_mpirun = strdup(empty_mpirun);
+    }
      
-     /* Check if we find the gromacs header in the log file: */
-     fp = fopen(filename, "r");
-     while ( (!feof(fp)) && (bFound==FALSE) )
-     {
-         cp2=fgets(line, STRLEN, fp);
-         if (cp2!=NULL && str_starts(line, match_mdrun))
-             bFound = TRUE;
-     }
-
-     if (!bFound)
-         gmx_fatal(FARGS, "Cannot execute mdrun. Please check %s for problems!", filename);
-
-     fclose(fp);
-     fprintf(stdout, "passed.\n");
-
-     /* Clean up ... */
-        remove(filename);
+    if ( (cp = getenv("MDRUN" )) != NULL )
+        *cmd_mdrun  = strdup(cp);
+    else
+        *cmd_mdrun  = strdup(def_mdrun);
+
+
+    /* If no simulations have to be performed, we are done here */
+    if (repeats <= 0)
+        return;
+
+    /* Run a small test to see whether mpirun + mdrun work  */
+    fprintf(stdout, "Making sure that mdrun can be executed. ");
+    if (bThreads)
+    {
+        snew(command, strlen(*cmd_mdrun) + strlen(cmd_np) + strlen(filename) + 50);
+        sprintf(command, "%s%s-version -maxh 0.001 1> %s 2>&1", *cmd_mdrun, cmd_np, filename);
+    }  
+    else
+    {
+        snew(command, strlen(*cmd_mpirun) + strlen(cmd_np) + strlen(*cmd_mdrun) + strlen(filename) + 50);
+        sprintf(command, "%s%s%s -version -maxh 0.001 1> %s 2>&1", *cmd_mpirun, cmd_np, *cmd_mdrun, filename);
+    }
+    fprintf(stdout, "Trying '%s' ... ", command);
+    make_backup(filename);
+    gmx_system_call(command);
+
+    /* Check if we find the characteristic string in the output: */
+    if (!gmx_fexist(filename))
+        gmx_fatal(FARGS, "Output from test run could not be found.");
+
+    fp = fopen(filename, "r");
+    /* We need to scan the whole output file, since sometimes the queuing system
+     * also writes stuff to stdout/err */
+    while ( !feof(fp) )
+    {
+        cp2=fgets(line, STRLEN, fp);
+        if (cp2!=NULL)
+        {
+            if ( str_starts(line, match_mdrun) )
+                bMdrun = TRUE;
+            if ( str_starts(line, match_mpi) )
+                bMPI = TRUE;
+        }
+    }
+    fclose(fp);
+
+    if (bThreads)
+    {
+        if (bMPI)
+        {
+            gmx_fatal(FARGS, "Need a threaded version of mdrun. This one\n"
+                    "(%s)\n"
+                    "seems to have been compiled with MPI instead.",
+                    *cmd_mdrun);
+        }
+    }
+    else
+    {
+        if (bMdrun && !bMPI)
+        {
+            gmx_fatal(FARGS, "Need an MPI-enabled version of mdrun. This one\n"
+                    "(%s)\n"
+                    "seems to have been compiled without MPI support.",
+                    *cmd_mdrun);
+        }
+    }
+
+    if (!bMdrun)
+    {
+        gmx_fatal(FARGS, "Cannot execute mdrun. Please check %s for problems!",
+                filename);
+    }
+
+    fprintf(stdout, "passed.\n");
+
+    /* Clean up ... */
+    remove(filename);
+    sfree(command);
 }
 
 
 static void launch_simulation(
         bool bLaunch,           /* Should the simulation be launched? */
         FILE *fp,               /* General log file */
+        bool bThreads,          /* whether to use threads */
         char *cmd_mpirun,       /* Command for mpirun */
+        char *cmd_np,           /* Switch for -np or -nt or empty */
         char *cmd_mdrun,        /* Command for mdrun */
         char *args_for_mdrun,   /* Arguments for mdrun */
         const char *simulation_tpr,   /* This tpr will be simulated */
@@ -466,11 +634,21 @@ static void launch_simulation(
     
     
     /* Make enough space for the system call command, 
-     * (100 extra chars for -np ... etc. options should suffice): */
-    snew(command, strlen(cmd_mpirun)+strlen(cmd_mdrun)+strlen(args_for_mdrun)+strlen(simulation_tpr)+100);
-    
-    sprintf(command, "%s -np %d %s %s-npme %d -s %s",
-            cmd_mpirun, nnodes, cmd_mdrun, args_for_mdrun, nPMEnodes, simulation_tpr);
+     * (100 extra chars for -npme ... etc. options should suffice): */
+    snew(command, strlen(cmd_mpirun)+strlen(cmd_mdrun)+strlen(cmd_np)+strlen(args_for_mdrun)+strlen(simulation_tpr)+100);
+   
+    /* Note that the -passall options requires args_for_mdrun to be at the end
+     * of the command line string */
+    if (bThreads)
+    {
+        sprintf(command, "%s%s-npme %d -s %s %s",
+                cmd_mdrun, cmd_np, nPMEnodes, simulation_tpr, args_for_mdrun);
+    }
+    else 
+    {
+        sprintf(command, "%s%s%s -npme %d -s %s %s",
+                cmd_mpirun, cmd_np, cmd_mdrun, nPMEnodes, simulation_tpr, args_for_mdrun);
+    }
         
     fprintf(fp, "%s this command line to launch the simulation:\n\n%s", bLaunch? "Using":"Please use", command);
     sep_line(fp);
@@ -489,7 +667,7 @@ static void launch_simulation(
 
 
 static void modify_PMEsettings(
-        gmx_large_int_t simsteps, /* Set this value as number of time steps */
+        gmx_large_int_t simsteps,  /* Set this value as number of time steps */
         const char *fn_best_tpr,   /* tpr file with the best performance */
         const char *fn_sim_tpr)    /* name of tpr file to be launched */
 {
@@ -514,6 +692,8 @@ static void modify_PMEsettings(
 }
 
 
+#define EPME_SWITCHED(e) ((e) == eelPMESWITCH || (e) == eelPMEUSERSWITCH)
+
 /* Make additional TPR files with more computational load for the
  * direct space processors: */
 static void make_benchmark_tprs(
@@ -521,7 +701,8 @@ static void make_benchmark_tprs(
         char *fn_bench_tprs[],  /* WRITE: Names of benchmark tpr files */
         gmx_large_int_t benchsteps,  /* Number of time steps for benchmark runs */
         gmx_large_int_t statesteps,  /* Step counter in checkpoint file */
-        real maxfac,            /* Max scaling factor for rcoulomb and fourierspacing */
+        real upfac,             /* Scale rcoulomb inbetween downfac and upfac */
+        real downfac,
         int ntprs,              /* No. of TPRs to write, each with a different rcoulomb and fourierspacing */
         real fourierspacing,    /* Basic fourierspacing from tpr input file */
         t_inputinfo *info,      /* Contains information about mdp file options */
@@ -532,11 +713,10 @@ static void make_benchmark_tprs(
     t_state      state;
     gmx_mtop_t   mtop;
     real         fac;
-    real         orig_rcoulomb, orig_rvdw, orig_rlist;
-    rvec         orig_fs;      /* original fourierspacing per dimension */
-    ivec         orig_nk;      /* original number of grid points per dimension */
+    real         nlist_buffer; /* Thickness of the buffer regions for PME-switch potentials: */
     char         buf[200];
     rvec         box_size;
+    bool         bNote = FALSE;
     
 
     sprintf(buf, "Making benchmark tpr file%s with %s time steps", ntprs>1? "s":"", gmx_large_int_pfmt);
@@ -553,19 +733,29 @@ static void make_benchmark_tprs(
     snew(ir,1);
     read_tpx_state(fn_sim_tpr,ir,&state,NULL,&mtop);
 
-    /* Check if PME was chosen */
+    /* Check if some kind of PME was chosen */
     if (EEL_PME(ir->coulombtype) == FALSE)
-        gmx_fatal(FARGS, "Can only do optimizations for simulations with PME");
+        gmx_fatal(FARGS, "Can only do optimizations for simulations with %s electrostatics.",
+                EELTYPE(eelPME));
     
-    /* Check if rcoulomb == rlist, which is necessary for PME */
-    if (!(ir->rcoulomb == ir->rlist))
-        gmx_fatal(FARGS, "PME requires rcoulomb (%f) to be equal to rlist (%f).", ir->rcoulomb, ir->rlist);
+    /* Check if rcoulomb == rlist, which is necessary for plain PME. */
+    if (  (eelPME == ir->coulombtype) && !(ir->rcoulomb == ir->rlist) )
+    {
+        gmx_fatal(FARGS, "%s requires rcoulomb (%f) to be equal to rlist (%f).",
+                EELTYPE(eelPME), ir->rcoulomb, ir->rlist);
+    }
+    /* For other PME types, rcoulomb is allowed to be smaller than rlist */
+    else if (ir->rcoulomb > ir->rlist)
+    {
+        gmx_fatal(FARGS, "%s requires rcoulomb (%f) to be equal to or smaller than rlist (%f)",
+                EELTYPE(ir->coulombtype), ir->rcoulomb, ir->rlist);
+    }
 
     /* Reduce the number of steps for the benchmarks */
     info->orig_sim_steps = ir->nsteps;
     ir->nsteps           = benchsteps;
     
-    /* Determine lenght of triclinic box vectors */
+    /* Determine length of triclinic box vectors */
     for(d=0; d<DIM; d++)
     {
         box_size[d] = 0;
@@ -575,19 +765,47 @@ static void make_benchmark_tprs(
     }
     
     /* Remember the original values: */
-    orig_rvdw     = ir->rvdw;
-    orig_rcoulomb = ir->rcoulomb;
-    orig_rlist    = ir->rlist;
-    orig_nk[XX]   = ir->nkx;
-    orig_nk[YY]   = ir->nky;
-    orig_nk[ZZ]   = ir->nkz;
-    orig_fs[XX]   = box_size[XX]/ir->nkx;  /* fourierspacing in x direction */
-    orig_fs[YY]   = box_size[YY]/ir->nky;
-    orig_fs[ZZ]   = box_size[ZZ]/ir->nkz;
-     
-    fprintf(fp, "Input file fourier grid : %dx%dx%d\n", orig_nk[XX], orig_nk[YY], orig_nk[ZZ]);
+    info->orig_rvdw            = ir->rvdw;
+    info->orig_rcoulomb        = ir->rcoulomb;
+    info->orig_rlist           = ir->rlist;
+    info->orig_rlistlong       = ir->rlistlong;
+    info->orig_nk[XX]          = ir->nkx;
+    info->orig_nk[YY]          = ir->nky;
+    info->orig_nk[ZZ]          = ir->nkz;
+    info->orig_fs[XX]          = box_size[XX]/ir->nkx;  /* fourierspacing in x direction */
+    info->orig_fs[YY]          = box_size[YY]/ir->nky;
+    info->orig_fs[ZZ]          = box_size[ZZ]/ir->nkz;
+
+    /* For PME-switch potentials, keep the radial distance of the buffer region */
+    nlist_buffer   = info->orig_rlist    - info->orig_rcoulomb;
+
+    /* Print information about settings of which some are potentially modified: */
+    fprintf(fp, "   Coulomb type         : %s\n", EELTYPE(ir->coulombtype));
+    fprintf(fp, "   Fourier nkx nky nkz  : %d %d %d\n",
+            info->orig_nk[XX], info->orig_nk[YY], info->orig_nk[ZZ]);
+    fprintf(fp, "   rcoulomb             : %f nm\n", info->orig_rcoulomb);
+    fprintf(fp, "   Van der Waals type   : %s\n", EVDWTYPE(ir->vdwtype));
+    fprintf(fp, "   rvdw                 : %f nm\n", info->orig_rvdw);
+    if (EVDW_SWITCHED(ir->vdwtype))
+        fprintf(fp, "   rvdw_switch          : %f nm\n", ir->rvdw_switch);
+    if (EPME_SWITCHED(ir->coulombtype))
+        fprintf(fp, "   rlist                : %f nm\n", info->orig_rlist);
+    if (info->orig_rlistlong != max_cutoff(ir->rvdw,ir->rcoulomb))
+        fprintf(fp, "   rlistlong            : %f nm\n", info->orig_rlistlong);
+
+    /* Print a descriptive line about the tpr settings tested */
     fprintf(fp, "\nWill try these real/reciprocal workload settings:\n");
-    fprintf(fp, " No. scaling   r_coul   (r_vdW)     nkx  nky  nkz   (spacing)   tpr file\n");
+    fprintf(fp, " No.   scaling  rcoulomb");
+    fprintf(fp, "  nkx  nky  nkz");
+    if (fourierspacing > 0)
+        fprintf(fp, "   spacing");
+    if (evdwCUT == ir->vdwtype)
+        fprintf(fp, "      rvdw");
+    if (EPME_SWITCHED(ir->coulombtype))
+        fprintf(fp, "     rlist");
+    if ( info->orig_rlistlong != max_cutoff(info->orig_rlist,max_cutoff(info->orig_rvdw,info->orig_rcoulomb)) )
+        fprintf(fp, " rlistlong");
+    fprintf(fp, "  tpr file\n");
     
     if (ntprs > 1)
     {
@@ -603,15 +821,34 @@ static void make_benchmark_tprs(
     {
         /* Rcoulomb scaling factor for this file: */
         if (ntprs == 1)
-            fac = 1.0;
+            fac = downfac;
          else
-            fac = (maxfac-1.0f)/(ntprs-1) * j +1;
+            fac = (upfac-downfac)/(ntprs-1) * j + downfac;
         fprintf(stdout, "--- Scaling factor %f ---\n", fac);
         
-        ir->rcoulomb = orig_rcoulomb*fac;
-        ir->rlist    = orig_rlist   *fac;
-        ir->rvdw     = orig_rvdw    *fac;
-        
+        /* Scale the Coulomb radius */
+        ir->rcoulomb = info->orig_rcoulomb*fac;
+
+        /* Adjust other radii since various conditions neet to be fulfilled */
+        if (eelPME == ir->coulombtype)
+        {
+            /* plain PME, rcoulomb must be equal to rlist */
+            ir->rlist = ir->rcoulomb;
+        }
+        else
+        {
+            /* rlist must be >= rcoulomb, we keep the size of the buffer region */
+            ir->rlist = ir->rcoulomb + nlist_buffer;
+        }
+
+        if (evdwCUT == ir->vdwtype)
+        {
+            /* For vdw cutoff, rvdw >= rlist */
+            ir->rvdw = max(info->orig_rvdw, ir->rlist);
+        }
+
+        ir->rlistlong = max_cutoff(ir->rlist,max_cutoff(ir->rvdw,ir->rcoulomb));
+
         /* Try to reduce the number of reciprocal grid points in a smart way */
         /* Did the user supply a value for fourierspacing on the command line? */
         if (fourierspacing > 0)
@@ -621,14 +858,16 @@ static void make_benchmark_tprs(
             ir->nkx = 0;
             ir->nky = 0;
             ir->nkz = 0;
-            calc_grid(stdout,state.box,info->fourier_sp[j],&(ir->nkx),&(ir->nky),&(ir->nkz),1);
+            calc_grid(stdout,state.box,info->fourier_sp[j],
+                     &(ir->nkx),&(ir->nky),&(ir->nkz));
             /* Check consistency */
             if (0 == j)
-                if ((ir->nkx != orig_nk[XX]) || (ir->nky != orig_nk[YY]) || (ir->nkz != orig_nk[ZZ]))
+                if ((ir->nkx != info->orig_nk[XX]) || (ir->nky != info->orig_nk[YY]) || (ir->nkz != info->orig_nk[ZZ]))
                 {
                     fprintf(stderr, "WARNING: Original grid was %dx%dx%d. The fourierspacing of %f nm does not reproduce the grid\n"
                                     "         found in the tpr input file! Will use the new settings.\n", 
-                                    orig_nk[XX],orig_nk[YY],orig_nk[ZZ],fourierspacing);
+                                    info->orig_nk[XX],info->orig_nk[YY],info->orig_nk[ZZ],fourierspacing);
+                    bNote = TRUE;
                 }
         }
         else
@@ -636,31 +875,29 @@ static void make_benchmark_tprs(
             if (0 == j)
             {
                 /* Print out fourierspacing from input tpr */
-                fprintf(stdout, "Input file fourier grid is %dx%dx%d\n", orig_nk[XX], orig_nk[YY], orig_nk[ZZ]);
+                fprintf(stdout, "Input file fourier grid is %dx%dx%d\n",
+                        info->orig_nk[XX], info->orig_nk[YY], info->orig_nk[ZZ]);
             }
-            else
-            {
-                /* Reconstruct fourierspacing for each dimension from the input file */
-                ir->nkx=0;
-                calc_grid(stdout,state.box,orig_fs[XX]*fac,&(ir->nkx),&(ir->nky),&(ir->nkz),1);
-                ir->nky=0;
-                calc_grid(stdout,state.box,orig_fs[YY]*fac,&(ir->nkx),&(ir->nky),&(ir->nkz),1);
-                ir->nkz=0;
-                calc_grid(stdout,state.box,orig_fs[ZZ]*fac,&(ir->nkx),&(ir->nky),&(ir->nkz),1);
-            }
-        }
-        /* r_vdw should only grow if necessary! */
-        if (j > 0)
-        {
-            ir->rvdw = min(ir->rvdw, orig_rcoulomb*fac);
-            ir->rvdw = max(ir->rvdw, orig_rvdw);
+            /* Reconstruct fourierspacing for each dimension from the input file */
+            ir->nkx=0;
+            calc_grid(stdout,state.box,info->orig_fs[XX]*fac,
+                     &(ir->nkx),&(ir->nky),&(ir->nkz));
+            ir->nky=0;
+            calc_grid(stdout,state.box,info->orig_fs[YY]*fac,
+                     &(ir->nkx),&(ir->nky),&(ir->nkz));
+            ir->nkz=0;
+            calc_grid(stdout,state.box,info->orig_fs[ZZ]*fac,
+                     &(ir->nkx),&(ir->nky),&(ir->nkz));
         }
+
         /* Save modified radii and fourier grid components for later output: */
-        info->r_coulomb[j] = ir->rcoulomb;
-        info->r_vdW[j]     = ir->rvdw;        
-        info->fourier_nx[j]= ir->nkx;
-        info->fourier_ny[j]= ir->nky;
-        info->fourier_nz[j]= ir->nkz;
+        info->r_coulomb[j]        = ir->rcoulomb;
+        info->r_vdw[j]            = ir->rvdw;
+        info->fourier_nx[j]       = ir->nkx;
+        info->fourier_ny[j]       = ir->nky;
+        info->fourier_nz[j]       = ir->nkz;
+        info->rlist[j]            = ir->rlist;
+        info->rlistlong[j]        = ir->rlistlong;
 
         /* Write the benchmark tpr file */
         strncpy(fn_bench_tprs[j],fn_sim_tpr,strlen(fn_sim_tpr)-strlen(".tpr"));
@@ -671,13 +908,32 @@ static void make_benchmark_tprs(
         fprintf(stdout,", scaling factor %f\n", fac);
         write_tpx_state(fn_bench_tprs[j],ir,&state,&mtop);
         
-        /* Write some info to log file */
-        fprintf(fp, "%3d %9f %9f (%7f) %4d %4d %4d   %9f   %-14s\n",
-                j, fac, ir->rcoulomb, ir->rvdw, ir->nkx, ir->nky, ir->nkz, info->fourier_sp[j],fn_bench_tprs[j]);
+        /* Write information about modified tpr settings to log file */
+        fprintf(fp, "%4d%10f%10f", j, fac, ir->rcoulomb);
+        fprintf(fp, "%5d%5d%5d", ir->nkx, ir->nky, ir->nkz);
+        if (fourierspacing > 0)
+            fprintf(fp, "%9f ", info->fourier_sp[j]);
+        if (evdwCUT == ir->vdwtype)
+            fprintf(fp, "%10f", ir->rvdw);
+        if (EPME_SWITCHED(ir->coulombtype))
+            fprintf(fp, "%10f", ir->rlist);
+        if ( info->orig_rlistlong != max_cutoff(info->orig_rlist,max_cutoff(info->orig_rvdw,info->orig_rcoulomb)) )
+            fprintf(fp, "%10f", ir->rlistlong);
+        fprintf(fp, "  %-14s\n",fn_bench_tprs[j]);
+
+        /* Make it clear to the user that some additional settings were modified */
+        if (   !is_equal(ir->rvdw           , info->orig_rvdw)
+            || !is_equal(ir->rlistlong      , info->orig_rlistlong) )
+        {
+            bNote = TRUE;
+        }
     }
+    if (bNote)
+        fprintf(fp, "\nNote that in addition to rcoulomb and the fourier grid\n"
+                    "also other input settings were changed (see table above).\n"
+                    "Please check if the modified settings are appropriate.\n");
     fflush(stdout);
     fflush(fp);
-    
     sfree(ir);
 }
 
@@ -701,7 +957,7 @@ static bool tpr_triggers_file(const char *opt)
 /* Rename the files we want to keep to some meaningful filename and
  * delete the rest */
 static void cleanup(const t_filenm *fnm, int nfile, int k, int nnodes, 
-                    int nPMEnodes, int nr)
+                    int nPMEnodes, int nr, bool bKeepStderr)
 {
     char numstring[STRLEN];
     char newfilename[STRLEN];
@@ -734,6 +990,30 @@ static void cleanup(const t_filenm *fnm, int nfile, int k, int nnodes,
                 rename(opt2fn("-bg",nfile,fnm), newfilename);
             }
         }
+        else if (strcmp(opt, "-err") == 0)
+        {
+            /* This file contains the output of stderr. We want to keep it in
+             * cases where there have been problems. */
+            fn = opt2fn(opt, nfile, fnm);
+            numstring[0] = '\0';
+            if (nr > 0)
+                sprintf(numstring, "_%d", nr);
+            sprintf(newfilename, "%s_no%d_np%d_npme%d%s", fn, k, nnodes, nPMEnodes, numstring);
+            if (gmx_fexist(fn))
+            {
+                if (bKeepStderr)
+                {
+                    fprintf(stdout, "Saving stderr output in %s\n", newfilename);
+                    make_backup(newfilename);
+                    rename(fn, newfilename);
+                }
+                else
+                {
+                    fprintf(stdout, "Deleting %s\n", fn);
+                    remove(fn);
+                }
+            }
+        }
         /* Delete the files which are created for each benchmark run: (options -b*) */
         else if ( ( (0 == strncmp(opt, "-b", 2)) && (opt2bSet(opt,nfile,fnm) || !is_optional(&fnm[i])) ) 
                   || tpr_triggers_file(opt) )
@@ -749,88 +1029,266 @@ static void cleanup(const t_filenm *fnm, int nfile, int k, int nnodes,
 }
 
 
-static void do_the_tests(FILE *fp, char **tpr_names, int maxPMEnodes, 
-        int minPMEnodes,
-        int datasets, t_perf **perfdata, int repeats, int nnodes, int nr_tprs,
-        char *cmd_mpirun, char *cmd_mdrun, 
-        char *args_for_mdrun,
-        const t_filenm *fnm, int nfile, int sim_part, int presteps, 
-        gmx_large_int_t cpt_steps)
+/* Returns the largest common factor of n1 and n2 */
+static int largest_common_factor(int n1, int n2)
 {
-    int     i,nr,k,ret;
-    int     nPMEnodes;
+    int factor, nmax;
+
+    nmax = min(n1, n2);
+    for (factor=nmax; factor > 0; factor--)
+    {
+        if ( 0==(n1 % factor) && 0==(n2 % factor) )
+        {
+            return(factor);
+        }
+    }
+    return 0; /* one for the compiler */
+}
+
+enum {eNpmeAuto, eNpmeAll, eNpmeReduced, eNpmeSubset, eNpmeNr};
+
+/* Create a list of numbers of PME nodes to test */
+static void make_npme_list(
+        const char *npmevalues_opt,  /* Make a complete list with all
+                           * possibilities or a short list that keeps only
+                           * reasonable numbers of PME nodes                  */
+        int *nentries,    /* Number of entries we put in the nPMEnodes list   */
+        int *nPMEnodes[], /* Each entry contains the value for -npme          */
+        int nnodes,       /* Total number of nodes to do the tests on         */
+        int minPMEnodes,  /* Minimum number of PME nodes                      */
+        int maxPMEnodes)  /* Maximum number of PME nodes                      */
+{
+    int i,npme,npp;
+    int min_factor=1;     /* We request that npp and npme have this minimal
+                           * largest common factor (depends on npp)           */
+    int nlistmax;         /* Max. list size                                   */
+    int nlist;            /* Actual number of entries in list                 */
+    int eNPME=0;
+
+
+    /* Do we need to check all possible values for -npme or is a reduced list enough? */
+    if ( 0 == strcmp(npmevalues_opt, "all") )
+    {
+        eNPME = eNpmeAll;
+    }
+    else if ( 0 == strcmp(npmevalues_opt, "subset") )
+    {
+        eNPME = eNpmeSubset;
+    }
+    else if ( 0 == strcmp(npmevalues_opt, "auto") )
+    {
+        if (nnodes <= 64)
+            eNPME = eNpmeAll;
+        else if (nnodes < 128)
+            eNPME = eNpmeReduced;
+        else
+            eNPME = eNpmeSubset;
+    }
+    else
+    {
+        gmx_fatal(FARGS, "Unknown option for -npme in make_npme_list");
+    }
+
+    /* Calculate how many entries we could possibly have (in case of -npme all) */
+    if (nnodes > 2)
+    {
+        nlistmax = maxPMEnodes - minPMEnodes + 3;
+        if (0 == minPMEnodes)
+            nlistmax--;
+    }
+    else
+        nlistmax = 1;
+
+    /* Now make the actual list which is at most of size nlist */
+    snew(*nPMEnodes, nlistmax);
+    nlist = 0; /* start counting again, now the real entries in the list */
+    for (i = 0; i < nlistmax - 2; i++)
+    {
+        npme = maxPMEnodes - i;
+        npp  = nnodes-npme;
+        switch (eNPME)
+        {
+            case eNpmeAll:
+                min_factor = 1;
+                break;
+            case eNpmeReduced:
+                min_factor = 2;
+                break;
+            case eNpmeSubset:
+                /* For 2d PME we want a common largest factor of at least the cube
+                 * root of the number of PP nodes */
+                min_factor = (int) pow(npp, 1.0/3.0);
+                break;
+            default:
+                gmx_fatal(FARGS, "Unknown option for eNPME in make_npme_list");
+                break;
+        }
+        if (largest_common_factor(npp, npme) >= min_factor)
+        {
+            (*nPMEnodes)[nlist] = npme;
+            nlist++;
+        }
+    }
+    /* We always test 0 PME nodes and the automatic number */
+    *nentries = nlist + 2;
+    (*nPMEnodes)[nlist  ] =  0;
+    (*nPMEnodes)[nlist+1] = -1;
+
+    fprintf(stderr, "Will try the following %d different values for -npme:\n", *nentries);
+    for (i=0; i<*nentries-1; i++)
+        fprintf(stderr, "%d, ", (*nPMEnodes)[i]);
+    fprintf(stderr, "and %d (auto).\n", (*nPMEnodes)[*nentries-1]);
+}
+
+
+/* Allocate memory to store the performance data */
+static void init_perfdata(t_perf *perfdata[], int ntprs, int datasets, int repeats)
+{
+    int i, j, k;
+
+
+    for (k=0; k<ntprs; k++)
+    {
+        snew(perfdata[k], datasets);
+        for (i=0; i<datasets; i++)
+        {
+            for (j=0; j<repeats; j++)
+            {
+                snew(perfdata[k][i].Gcycles   , repeats);
+                snew(perfdata[k][i].ns_per_day, repeats);
+                snew(perfdata[k][i].PME_f_load, repeats);
+            }
+        }
+    }
+}
+
+
+static void do_the_tests(
+        FILE *fp,                   /* General g_tune_pme output file         */
+        char **tpr_names,           /* Filenames of the input files to test   */
+        int maxPMEnodes,            /* Max fraction of nodes to use for PME   */
+        int minPMEnodes,            /* Min fraction of nodes to use for PME   */
+        const char *npmevalues_opt, /* Which -npme values should be tested    */
+        t_perf **perfdata,          /* Here the performace data is stored     */
+        int *pmeentries,            /* Entries in the nPMEnodes list          */
+        int repeats,                /* Repeat each test this often            */
+        int nnodes,                 /* Total number of nodes = nPP + nPME     */
+        int nr_tprs,                /* Total number of tpr files to test      */
+        bool bThreads,              /* Threads or MPI?                        */
+        char *cmd_mpirun,           /* mpirun command string                  */
+        char *cmd_np,               /* "-np", "-n", whatever mpirun needs     */
+        char *cmd_mdrun,            /* mdrun command string                   */
+        char *cmd_args_bench,       /* arguments for mdrun in a string        */
+        const t_filenm *fnm,        /* List of filenames from command line    */
+        int nfile,                  /* Number of files specified on the cmdl. */
+        int sim_part,               /* For checkpointing                      */
+        int presteps,               /* DLB equilibration steps, is checked    */
+        gmx_large_int_t cpt_steps)  /* Time step counter in the checkpoint    */
+{
+    int     i,nr,k,ret,count=0,totaltests;
+    int     *nPMEnodes=NULL;
     t_perf  *pd=NULL;
     int     cmdline_length;
-    char    *command;
+    char    *command, *cmd_stub;
     char    buf[STRLEN];
-    char    *opt_noaddpart;
     bool    bResetProblem=FALSE;
-    
 
-    /* This string array corresponds to the eParselog enum type from above */
-    const char* ParseLog[] = {"OK",
-                              "Logfile not found", 
-                              "No timings in log file",
-                              "Run was terminated",
-                              "Counters were not reset properly"};
+
+    /* This string array corresponds to the eParselog enum type at the start
+     * of this file */
+    const char* ParseLog[] = {"OK.",
+                              "Logfile not found!",
+                              "No timings, logfile truncated?",
+                              "Run was terminated.",
+                              "Counters were not reset properly.",
+                              "No DD grid found for these settings.",
+                              "TPX version conflict!",
+                              "mdrun was not started in parallel!",
+                              "A fatal error occured!" };
     char    str_PME_f_load[13];
 
-    /* The -noaddpart option is needed so that the md.log files do not
-     * get renamed if checkpoints are used!
-     */
-    if (sim_part > 1) 
-        opt_noaddpart=" -noaddpart"; 
-    else
-        opt_noaddpart="";
 
-    /* Allocate space for the mdrun command line. 100 extra characters should be more than enough
-     * for the -npme etcetera arguments */
+    /* Allocate space for the mdrun command line. 100 extra characters should 
+       be more than enough for the -npme etcetera arguments */
     cmdline_length =  strlen(cmd_mpirun) 
+                    + strlen(cmd_np)
                     + strlen(cmd_mdrun) 
-                    + strlen(args_for_mdrun
+                    + strlen(cmd_args_bench
                     + strlen(tpr_names[0]) + 100;
-    snew(command, cmdline_length);
+    snew(command , cmdline_length);
+    snew(cmd_stub, cmdline_length);
+
+    /* Construct the part of the command line that stays the same for all tests: */
+    if (bThreads)
+    {
+        sprintf(cmd_stub, "%s%s", cmd_mdrun, cmd_np);
+    }
+    else
+    {
+        sprintf(cmd_stub, "%s%s%s ", cmd_mpirun, cmd_np, cmd_mdrun);
+    }
+
+    /* Create a list of numbers of PME nodes to test */
+    make_npme_list(npmevalues_opt, pmeentries, &nPMEnodes,
+                   nnodes, minPMEnodes, maxPMEnodes);
+
+    if (0 == repeats)
+    {
+        fprintf(fp, "\nNo benchmarks done since number of repeats (-r) is 0.\n");
+        fclose(fp);
+        finalize(opt2fn("-p", nfile, fnm));
+        exit(0);
+    }
+
+    /* Allocate one dataset for each tpr input file: */
+    init_perfdata(perfdata, nr_tprs, *pmeentries, repeats);
 
-    /* Loop over all tpr files to test: */
+    /*****************************************/
+    /* Main loop over all tpr files to test: */
+    /*****************************************/
+    totaltests = nr_tprs*(*pmeentries)*repeats;
     for (k=0; k<nr_tprs;k++)
     {
         fprintf(fp, "\nIndividual timings for input file %d (%s):\n", k, tpr_names[k]);
         fprintf(fp, "PME nodes      Gcycles       ns/day        PME/f    Remark\n");
-        i=0;
-        /* Start with the maximum number of PME only nodes: */
-        nPMEnodes = maxPMEnodes;
-
         /* Loop over various numbers of PME nodes: */
-        for (i = 0; i<datasets; i++)
+        for (i = 0; i < *pmeentries; i++)
         {
             pd = &perfdata[k][i];
 
             /* Loop over the repeats for each scenario: */
             for (nr = 0; nr < repeats; nr++)
             {
-                pd->nPMEnodes = nPMEnodes;
+                pd->nPMEnodes = nPMEnodes[i];
                 
-                /* Construct the command line to call mdrun (and save it): */
+                /* Add -npme and -s to the command line and save it. Note that
+                 * the -passall (if set) options requires cmd_args_bench to be
+                 * at the end of the command line string */
                 snew(pd->mdrun_cmd_line, cmdline_length);
-                sprintf(pd->mdrun_cmd_line, "%s -np %d %s %s-npme %d -s %s%s",
-                        cmd_mpirun, nnodes, cmd_mdrun, args_for_mdrun, nPMEnodes, tpr_names[k], opt_noaddpart);
+                sprintf(pd->mdrun_cmd_line, "%s-npme %d -s %s %s",
+                        cmd_stub, pd->nPMEnodes, tpr_names[k], cmd_args_bench);
 
                 /* Do a benchmark simulation: */
                 if (repeats > 1)
                     sprintf(buf, ", pass %d/%d", nr+1, repeats);
                 else
                     buf[0]='\0';
-                fprintf(stdout, "\n=== tpr %d/%d, run %d/%d%s:\n", k+1, nr_tprs, i+1, datasets, buf);
-                sprintf(command, "%s -noaddpart >& /dev/null", pd->mdrun_cmd_line);
+                fprintf(stdout, "\n=== Progress %2.0f%%, tpr %d/%d, run %d/%d%s:\n",
+                        (100.0*count)/totaltests,
+                        k+1, nr_tprs, i+1, *pmeentries, buf);
+                make_backup(opt2fn("-err",nfile,fnm));
+                sprintf(command, "%s 1> /dev/null 2>%s", pd->mdrun_cmd_line, opt2fn("-err",nfile,fnm));
                 fprintf(stdout, "%s\n", pd->mdrun_cmd_line);
                 gmx_system_call(command);
 
-                /* Collect the performance data from the log file */
-                ret = parse_logfile(opt2fn("-bg",nfile,fnm), pd, nr, presteps, cpt_steps, nnodes);
+                /* Collect the performance data from the log file; also check stderr
+                 * for fatal errors */
+                ret = parse_logfile(opt2fn("-bg",nfile,fnm), opt2fn("-err",nfile,fnm),
+                        pd, nr, presteps, cpt_steps, nnodes);
                 if ((presteps > 0) && (ret == eParselogResetProblem))
                     bResetProblem = TRUE;
 
-                if (nPMEnodes == -1)
+                if (-1 == pd->nPMEnodes)
                     sprintf(buf, "(%3d)", pd->guessPME);
                 else
                     sprintf(buf, "     ");
@@ -842,30 +1300,27 @@ static void do_the_tests(FILE *fp, char **tpr_names, int maxPMEnodes,
                     sprintf(str_PME_f_load, "%s", "         -  ");
                 
                 /* Write the data we got to disk */
-                fprintf(fp, "%4d%s %12.3f %12.3f %s    %s\n", pd->nPMEnodes, buf, pd->Gcycles[nr], pd->ns_per_day[nr], str_PME_f_load, ParseLog[ret]);
+                fprintf(fp, "%4d%s %12.3f %12.3f %s    %s", pd->nPMEnodes,
+                        buf, pd->Gcycles[nr], pd->ns_per_day[nr], str_PME_f_load, ParseLog[ret]);
+                if (! (ret==eParselogOK || ret==eParselogNoDDGrid || ret==eParselogNotFound) )
+                    fprintf(fp, " Check %s file for problems.", ret==eParselogFatal? "err":"log");
+                fprintf(fp, "\n");
                 fflush(fp);
+                count++;
 
                 /* Do some cleaning up and delete the files we do not need any more */
-                cleanup(fnm, nfile, k, nnodes, nPMEnodes, nr);
+                cleanup(fnm, nfile, k, nnodes, pd->nPMEnodes, nr, ret==eParselogFatal);
 
                 /* If the first run with this number of processors already failed, do not try again: */
                 if (pd->Gcycles[0] <= 0.0 && repeats > 1)
                 {
                     fprintf(stdout, "Skipping remaining passes of unsuccessful setting, see log file for details.\n");
+                    count += repeats-(nr+1);
                     break;
                 }
-            }
-            /* Prepare for the next number of PME only nodes */
-            /* The last but one check is always without MPMD PME ... */
-            if ((nPMEnodes == minPMEnodes) && (0 != minPMEnodes)) 
-                nPMEnodes = 0;
-            /* ... and the last check with the guessed settings */
-            else if (nPMEnodes == 0)
-                nPMEnodes = -1;
-            else
-                nPMEnodes--;
-        }
-    }
+            } /* end of repeats loop */
+        } /* end of -npme loop */
+    } /* end of tpr file loop */
     if (bResetProblem)
     {
         sep_line(fp);
@@ -877,22 +1332,8 @@ static void do_the_tests(FILE *fp, char **tpr_names, int maxPMEnodes,
                     "value normally provided by -presteps.");
         sep_line(fp);
     }
-}
-
-
-static bool is_equal(real a, real b)
-{
-    real diff, eps=1.0e-6;
-    
-    
-    diff = a - b;
-    
-    if (diff < 0.0) diff = -diff;
-    
-    if (diff < eps)
-        return TRUE;
-    else
-        return FALSE;
+    sfree(command);
+    sfree(cmd_stub);
 }
 
 
@@ -900,7 +1341,8 @@ static void check_input(
         int nnodes, 
         int repeats, 
         int *ntprs, 
-        real maxfac,
+        real *upfac,
+        real *downfac,
         real maxPMEfraction,
         real minPMEfraction,
         real fourierspacing,
@@ -908,23 +1350,25 @@ static void check_input(
         const t_filenm *fnm,
         int nfile,
         int sim_part,
-        int presteps)
+        int presteps,
+        int npargs,
+        t_pargs *pa)
 {
-    /* Make shure the input file exists */
+    /* Make sure the input file exists */
     if (!gmx_fexist(opt2fn("-s",nfile,fnm)))
         gmx_fatal(FARGS, "File %s not found.", opt2fn("-s",nfile,fnm));
     
-    /* Make shure that the checkpoint file is not overwritten by the benchmark runs */
+    /* Make sure that the checkpoint file is not overwritten by the benchmark runs */
     if ( (0 == strcmp(opt2fn("-cpi",nfile,fnm), opt2fn("-cpo",nfile,fnm)) ) && (sim_part > 1) )
         gmx_fatal(FARGS, "Checkpoint input and output file must not be identical,\nbecause then the input file might change during the benchmarks.");
     
-    /* Make shure that repeats is >= 0 (if == 0, only write tpr files) */
+    /* Make sure that repeats is >= 0 (if == 0, only write tpr files) */
     if (repeats < 0)
         gmx_fatal(FARGS, "Number of repeats < 0!");
 
     /* Check number of nodes */
     if (nnodes < 1)
-        gmx_fatal(FARGS, "Number of nodes must be a positive integer.");
+        gmx_fatal(FARGS, "Number of nodes/threads must be a positive integer.");
 
     /* Automatically choose -ntpr if not set */
     if (*ntprs < 1)
@@ -937,13 +1381,14 @@ static void check_input(
     }
     else
     {
-        if ( (1 == *ntprs) && !is_equal(maxfac,1.0) )
-            fprintf(stderr, "Note: Choose ntpr>1 to shift PME load to real space.\n");
+        if (1 == *ntprs)
+            fprintf(stderr, "Note: Choose ntpr>1 to shift PME load between real and reciprocal space.\n");
     }
     
-    if ( is_equal(1.0,maxfac) && (*ntprs > 1) )
+    if ( is_equal(*downfac,*upfac) && (*ntprs > 1) )
     {
-        fprintf(stderr, "WARNING: Resetting -ntpr to 1 since upscaling factor equals unity.\n  Please select -fac>1 if you want to test various PME grid settings\n");
+        fprintf(stderr, "WARNING: Resetting -ntpr to 1 since both scaling factors are the same.\n"
+                        "Please choose upfac unequal to downfac to test various PME grid settings\n");
         *ntprs = 1;
     }
 
@@ -963,7 +1408,7 @@ static void check_input(
     {
         fprintf(stderr, "WARNING: steps=");
         fprintf(stderr, gmx_large_int_pfmt, bench_nsteps);
-        fprintf(stderr, ". Are you shure you want to perform so %s steps for each benchmark?\n", (bench_nsteps < 100)? "few" : "many");
+        fprintf(stderr, ". Are you sure you want to perform so %s steps for each benchmark?\n", (bench_nsteps < 100)? "few" : "many");
     }
     
     if (presteps < 0)
@@ -971,17 +1416,35 @@ static void check_input(
         gmx_fatal(FARGS, "Cannot have a negative number of presteps.\n");
     }
     
-    if (maxfac <= 0.0)
-        gmx_fatal(FARGS, "Scaling factor must be larger than zero.");
-    
-    if (maxfac < 1.0)
-        fprintf(stderr, "WARNING: A scaling factor smaller than one means that load will be shifted to reciprocal space. Are you shure you want that?\n");
+    if (*upfac <= 0.0 || *downfac <= 0.0 || *downfac > *upfac)
+        gmx_fatal(FARGS, "Both scaling factors must be larger than zero and upper\n"
+                         "scaling limit (%f) must be larger than lower limit (%f).",
+                         *upfac, *downfac);
 
-    if (maxfac < 0.75 || maxfac > 1.5)
+    if (*downfac < 0.75 || *upfac > 1.5)
         fprintf(stderr, "WARNING: Applying extreme scaling factor. I hope you know what you are doing.\n");
     
     if (fourierspacing < 0)
         gmx_fatal(FARGS, "Please choose a positive value for fourierspacing.");
+
+    /* Make shure that the scaling factor options are compatible with the number of tprs */
+    if ( (1 == *ntprs) && ( opt2parg_bSet("-upfac",npargs,pa) || opt2parg_bSet("-downfac",npargs,pa) ) )
+    {
+        if (opt2parg_bSet("-upfac",npargs,pa) && opt2parg_bSet("-downfac",npargs,pa) && !is_equal(*upfac,*downfac))
+        {
+            gmx_fatal(FARGS, "Please specify -ntpr > 1 for both scaling factors to take effect.\n"
+                             "(upfac=%f, downfac=%f)\n", *upfac, *downfac);
+        }
+        if (opt2parg_bSet("-upfac",npargs,pa))
+            *downfac = *upfac;
+        if (opt2parg_bSet("-downfac",npargs,pa))
+            *upfac = *downfac;
+        if (!is_equal(*upfac, 1.0))
+        {
+            fprintf(stderr, "WARNING: Using a scaling factor of %f with -ntpr 1, thus not testing the original tpr settings.\n",
+                    *upfac);
+        }
+    }
 }
 
 
@@ -995,12 +1458,16 @@ static bool is_main_switch(char *opt)
       || (0 == strcmp(opt,"-ntpr"     ))
       || (0 == strcmp(opt,"-max"      ))
       || (0 == strcmp(opt,"-min"      ))
-      || (0 == strcmp(opt,"-fac"      ))
+      || (0 == strcmp(opt,"-upfac"    ))
+      || (0 == strcmp(opt,"-downfac"  ))
       || (0 == strcmp(opt,"-four"     ))
       || (0 == strcmp(opt,"-steps"    ))
       || (0 == strcmp(opt,"-simsteps" ))
       || (0 == strcmp(opt,"-resetstep"))
-      || (0 == strcmp(opt,"-so"       )) )
+      || (0 == strcmp(opt,"-so"       ))
+      || (0 == strcmp(opt,"-npstring" ))
+      || (0 == strcmp(opt,"-npme"     ))
+      || (0 == strcmp(opt,"-passall"  )) )
     return TRUE;
     
     return FALSE;
@@ -1039,9 +1506,11 @@ static bool is_bench_option(char *opt, bool bSet)
      * This includes -cpi */
     if (bSet)
     {
-        if ( (0 == strcmp(opt, "-append" ))
-          || (0 == strcmp(opt, "-addpart"))
-          || (0 == strcmp(opt, "-maxh"   )) )
+        if ( (0 == strcmp(opt, "-append"   ))
+          || (0 == strcmp(opt, "-maxh"     ))
+          || (0 == strcmp(opt, "-deffnm"   ))
+          || (0 == strcmp(opt, "-resethway"))
+          || (0 == strcmp(opt, "-cpnum"    )) )
             return FALSE;
         else
             return TRUE;
@@ -1075,37 +1544,46 @@ static bool is_bench_file(char *opt, bool bSet, bool bOptional, bool bIsOutput)
 }
 
 
-/* Adds 'buf' to 'cmd_args' */
-static void add_to_command_line(char **cmd_args, char *buf)
+/* Adds 'buf' to 'str' */
+static void add_to_string(char **str, char *buf)
 {
     int len;
     
     
-    len = strlen(*cmd_args) + strlen(buf) + 1;
-    srenew(*cmd_args, len);
-    strcat(*cmd_args, buf);
+    len = strlen(*str) + strlen(buf) + 1;
+    srenew(*str, len);
+    strcat(*str, buf);
 }
 
 
 /* Create the command line for the benchmark as well as for the real run */
 static void create_command_line_snippets(
+        bool     bThreads,
         int      presteps,
         int      nfile,
         t_filenm fnm[],
         int      npargs,
         t_pargs  *pa,
-        char     *cmd_np[],          /* -np string */
+        const char *procstring,      /* How to pass the number of processors to $MPIRUN */
+        char     *cmd_np[],          /* Actual command line snippet, e.g. '-np <N>' */
         char     *cmd_args_bench[],  /* command line arguments for benchmark runs */
-        char     *cmd_args_launch[]) /* command line arguments for simulation run */
+        char     *cmd_args_launch[], /* command line arguments for simulation run */
+        char     extra_args[])       /* Add this to the end of the command line */
 {
     int        i;
     char       *opt;
     const char *name;
+    char       *np_or_nt;
 #define BUFLENGTH 255
     char       buf[BUFLENGTH];
     char       strbuf[BUFLENGTH];
     char       strbuf2[BUFLENGTH];
     
+
+    if (bThreads)
+        np_or_nt=strdup("-nt");
+    else
+        np_or_nt=strdup("-np");
     
     /* strlen needs at least '\0' as a string: */
     snew(*cmd_args_bench ,1);
@@ -1121,7 +1599,6 @@ static void create_command_line_snippets(
     {
         /* What command line switch are we currently processing: */
         opt = (char *)pa[i].option;
-        
         /* Skip options not meant for mdrun */        
         if (!is_main_switch(opt))
         {
@@ -1129,19 +1606,29 @@ static void create_command_line_snippets(
             sprintf(strbuf2, "%s", pa_val(&pa[i],buf,BUFLENGTH));
             rtrim(strbuf2);
             sprintf(strbuf, "%s %s ", opt, strbuf2);
-            /* We need the -np switch in an extra buffer - whether or not it was set! */
-            if (0 == strcmp(opt,"-np"))
+            /* We need the -np (or -nt) switch in a separate buffer - whether or not it was set! */
+            if (0 == strcmp(opt,np_or_nt))
             {
-                snew(*cmd_np, strlen(strbuf)+1);
-                sprintf(*cmd_np, " %s", strbuf);
+                if (strcmp(procstring, "none")==0 && !bThreads)
+                {
+                    /* Omit -np <N> entirely */
+                    snew(*cmd_np, 2);
+                    sprintf(*cmd_np, " ");
+                }
+                else
+                {
+                    /* This is the normal case with -np <N> */
+                    snew(*cmd_np, strlen(procstring)+strlen(strbuf2)+4);
+                    sprintf(*cmd_np, " %s %s ", bThreads? "-nt" : procstring, strbuf2);
+                }
             }
             else 
             {
                 if (is_bench_option(opt,pa[i].bSet))
-                    add_to_command_line(cmd_args_bench, strbuf);
+                    add_to_string(cmd_args_bench, strbuf);
 
                 if (is_launch_option(opt,pa[i].bSet))
-                    add_to_command_line(cmd_args_launch, strbuf);
+                    add_to_string(cmd_args_launch, strbuf);
             }
         }
     }
@@ -1149,7 +1636,7 @@ static void create_command_line_snippets(
     {
         /* Add equilibration steps to benchmark options */
         sprintf(strbuf, "-resetstep %d ", presteps);
-        add_to_command_line(cmd_args_bench, strbuf);
+        add_to_string(cmd_args_bench, strbuf);
     }
     
     /********************/
@@ -1169,19 +1656,22 @@ static void create_command_line_snippets(
             
             if ( is_bench_file(opt, opt2bSet(opt,nfile,fnm), is_optional(&fnm[i]), is_output(&fnm[i])) )
             {
-                /* All options starting with -b* need th 'b' removed,
+                /* All options starting with -b* need the 'b' removed,
                  * therefore overwrite strbuf */
                 if (0 == strncmp(opt, "-b", 2))     
                     sprintf(strbuf, "-%s %s ", &opt[2], name);
                 
-                add_to_command_line(cmd_args_bench, strbuf);
+                add_to_string(cmd_args_bench, strbuf);
             }
             
             if ( is_launch_file(opt,opt2bSet(opt,nfile,fnm)) )
-                add_to_command_line(cmd_args_launch, strbuf);
+                add_to_string(cmd_args_launch, strbuf);
         }
     }
-#undef BUFLENGTH   
+
+    add_to_string(cmd_args_bench , extra_args);
+    add_to_string(cmd_args_launch, extra_args);
+#undef BUFLENGTH
 }
 
 
@@ -1254,11 +1744,11 @@ static double gettime()
 int gmx_tune_pme(int argc,char *argv[])
 {
     const char *desc[] = {
-            "For a given number [TT]-np[tt] of processors this program systematically",
+            "For a given number [TT]-np[tt] or [TT]-nt[tt] of processors/threads, this program systematically",
             "times mdrun with various numbers of PME-only nodes and determines",
             "which setting is fastest. It will also test whether performance can",
             "be enhanced by shifting load from the reciprocal to the real space",
-            "part of the Ewald sum. "
+            "part of the Ewald sum. ",
             "Simply pass your [TT].tpr[tt] file to g_tune_pme together with other options",
             "for mdrun as needed.[PAR]",
             "Which executables are used can be set in the environment variables",
@@ -1269,45 +1759,51 @@ int gmx_tune_pme(int argc,char *argv[])
             "'export MPIRUN=\"/usr/local/mpirun -machinefile hosts\"'[PAR]",
             "Please call g_tune_pme with the normal options you would pass to",
             "mdrun and add [TT]-np[tt] for the number of processors to perform the",
-            "tests on. You can also add [TT]-r[tt] to repeat each test several times",
-            "to get better statistics. [PAR]",
+            "tests on, or [TT]-nt[tt] for the number of threads. You can also add [TT]-r[tt]",
+            "to repeat each test several times to get better statistics. [PAR]",
             "g_tune_pme can test various real space / reciprocal space workloads",
             "for you. With [TT]-ntpr[tt] you control how many extra [TT].tpr[tt] files will be",
             "written with enlarged cutoffs and smaller fourier grids respectively.",
-            "The first test (no. 0) will be with the settings from the input",
+            "Typically, the first test (no. 0) will be with the settings from the input",
             "[TT].tpr[tt] file; the last test (no. [TT]ntpr[tt]) will have cutoffs multiplied",
             "by (and at the same time fourier grid dimensions divided by) the scaling",
             "factor [TT]-fac[tt] (default 1.2). The remaining [TT].tpr[tt] files will have equally",
             "spaced values inbetween these extremes. Note that you can set [TT]-ntpr[tt] to 1",
             "if you just want to find the optimal number of PME-only nodes; in that case",
-            "your input [TT].tpr[tt] file will remain unchanged[PAR]",
-            "For the benchmark runs, 2500 time steps should suffice for most MD",
-            "systems. Note that dynamic load balancing needs about 100 time steps",
-            "to adapt to local load imbalances. To get clean benchmark numbers,",
-            "[TT]-steps[tt] should therefore always be much larger than 100![PAR]",
+            "your input [TT].tpr[tt] file will remain unchanged.[PAR]",
+            "For the benchmark runs, the default of 1000 time steps should suffice for most",
+            "MD systems. The dynamic load balancing needs about 100 time steps",
+            "to adapt to local load imbalances, therefore the time step counters",
+            "are by default reset after 100 steps. For large systems",
+            "(>1M atoms) you may have to set [TT]-resetstep[tt] to a higher value.",
+            "From the 'DD' load imbalance entries in the md.log output file you",
+            "can tell after how many steps the load is sufficiently balanced.[PAR]"
             "Example call: [TT]g_tune_pme -np 64 -s protein.tpr -launch[tt][PAR]",
             "After calling mdrun several times, detailed performance information",
-            "is available in the output file perf.out. "
+            "is available in the output file perf.out. ",
             "Note that during the benchmarks a couple of temporary files are written",
-            "(options -b*), these will be automatically deleted after each test.[PAR]"
+            "(options -b*), these will be automatically deleted after each test.[PAR]",
             "If you want the simulation to be started automatically with the",
             "optimized parameters, use the command line option [TT]-launch[tt].[PAR]",
     };
 
-    int        nnodes =3;
+    int        nnodes =1;
     int        repeats=2;
+    int        pmeentries=0; /* How many values for -npme do we actually test for each tpr file */
     real       maxPMEfraction=0.50;
     real       minPMEfraction=0.25;
     int        maxPMEnodes, minPMEnodes;
-    real       maxfac=1.2;
+    real       downfac=1.0,upfac=1.2;
     int        ntprs=0;
-    real       fs=0.0;             /* 0 indicates: not set by the user */
+    real       fs=0.0;                    /* 0 indicates: not set by the user */
     gmx_large_int_t bench_nsteps=BENCHSTEPS;
-    gmx_large_int_t new_sim_nsteps=-1;  /* -1 indicates: not set by the user */
-    gmx_large_int_t cpt_steps=0;        /* Step counter in .cpt input file */
-    int        presteps=100;       /* Do a full cycle reset after presteps steps */
-    bool       bOverwrite=FALSE;
+    gmx_large_int_t new_sim_nsteps=-1;   /* -1 indicates: not set by the user */
+    gmx_large_int_t cpt_steps=0;         /* Step counter in .cpt input file   */
+    int        presteps=100;    /* Do a full cycle reset after presteps steps */
+    bool       bOverwrite=FALSE, bKeepTPR;
     bool       bLaunch=FALSE;
+    bool       bPassAll=FALSE;
+    char       *ExtraArgs=NULL;
     char       **tpr_names=NULL;
     const char *simulation_tpr=NULL;
     int        best_npme, best_tpr;
@@ -1315,12 +1811,12 @@ int gmx_tune_pme(int argc,char *argv[])
     
     /* Default program names if nothing else is found */
     char        *cmd_mpirun=NULL, *cmd_mdrun=NULL;
-    char        *cmd_args_bench, *cmd_args_launch, *cmd_np;
+    char        *cmd_args_bench, *cmd_args_launch;
+    char        *cmd_np=NULL;
 
-    t_perf      **perfdata;
+    t_perf      **perfdata=NULL;
     t_inputinfo *info;
-    int         datasets;
-    int         i,j,k;
+    int         i;
     FILE        *fp;
     t_commrec   *cr;
 
@@ -1330,6 +1826,7 @@ int gmx_tune_pme(int argc,char *argv[])
     static t_filenm fnm[] = {
       /* g_tune_pme */
       { efOUT, "-p",      "perf",     ffWRITE },
+      { efLOG, "-err",    "errors",   ffWRITE },
       { efTPX, "-so",     "tuned",    ffWRITE },
       /* mdrun: */
       { efTPX, NULL,      NULL,       ffREAD },
@@ -1399,6 +1896,7 @@ int gmx_tune_pme(int argc,char *argv[])
     bool bIonize      = FALSE;
     bool bConfout     = TRUE;
     bool bReproducible = FALSE;
+    bool bThreads     = FALSE;
 
     int  nmultisim=0;
     int  nstglobalcomm=-1;
@@ -1411,12 +1909,19 @@ int gmx_tune_pme(int argc,char *argv[])
       { NULL, "interleave", "pp_pme", "cartesian", NULL };
     const char *dddlb_opt[] =
       { NULL, "auto", "no", "yes", NULL };
+    const char *procstring[] =
+      { NULL, "-np", "-n", "none", NULL };
+    const char *npmevalues_opt[] =
+      { NULL, "auto", "all", "subset", NULL };
     real rdd=0.0,rconstr=0.0,dlb_scale=0.8,pforce=-1;
     char *ddcsx=NULL,*ddcsy=NULL,*ddcsz=NULL;
+    char *deffnm=NULL;
 #define STD_CPT_PERIOD (15.0)
     real cpt_period=STD_CPT_PERIOD,max_hours=-1;
-    bool bAppendFiles=FALSE,bAddPart=TRUE;
-    output_env_t oenv;
+    bool bAppendFiles=TRUE;
+    bool bKeepAndNumCPT=FALSE;
+    bool bResetCountersHalfWay=FALSE;
+    output_env_t oenv=NULL;
 
     t_pargs pa[] = {
       /***********************/
@@ -1424,22 +1929,32 @@ int gmx_tune_pme(int argc,char *argv[])
       /***********************/
       { "-np",       FALSE, etINT,  {&nnodes},
         "Number of nodes to run the tests on (must be > 2 for separate PME nodes)" },
+      { "-npstring", FALSE, etENUM, {procstring},
+        "Specify the number of processors to $MPIRUN using this string"},
+      { "-passall",  FALSE, etBOOL, {&bPassAll},
+        "HIDDENPut arguments unknown to mdrun at the end of the command line. Can e.g. be used for debugging purposes. "},
+      { "-nt",       FALSE, etINT,  {&nthreads},
+        "Number of threads to run the tests on (turns MPI & mpirun off)"},
       { "-r",        FALSE, etINT,  {&repeats},
         "Repeat each test this often" },
       { "-max",      FALSE, etREAL, {&maxPMEfraction},
         "Max fraction of PME nodes to test with" },
       { "-min",      FALSE, etREAL, {&minPMEfraction},
         "Min fraction of PME nodes to test with" },
-      { "-fac",      FALSE, etREAL, {&maxfac},
-        "Max upscaling factor for rcoulomb (= downscaling factor for the fourier grid)" },
+      { "-npme",     FALSE, etENUM, {npmevalues_opt},
+        "Benchmark all possible values for -npme or just the subset that is expected to perform well"},
+      { "-upfac",    FALSE, etREAL, {&upfac},
+        "Upper limit for rcoulomb scaling factor (Note that rcoulomb upscaling results in fourier grid downscaling)" },
+      { "-downfac",  FALSE, etREAL, {&downfac},
+        "Lower limit for rcoulomb scaling factor" },
       { "-ntpr",     FALSE, etINT,  {&ntprs},
         "Number of tpr files to benchmark. Create these many files with scaling factors ranging from 1.0 to fac. If < 1, automatically choose the number of tpr files to test" },
       { "-four",     FALSE, etREAL, {&fs},
-        "Use this fourierspacing value instead of the grid found in the tpr input file" },        
+        "Use this fourierspacing value instead of the grid found in the tpr input file. (Spacing applies to a scaling factor of 1.0 if multiple tpr files are written)" },
       { "-steps",    FALSE, etGMX_LARGE_INT, {&bench_nsteps},
         "Take timings for these many steps in the benchmark runs" }, 
       { "-resetstep",FALSE, etINT,  {&presteps},
-        "Let dlb equilibrate these many steps before timings are taken" },         
+        "Let dlb equilibrate these many steps before timings are taken (reset cycle counters after these many steps)" },
       { "-simsteps", FALSE, etGMX_LARGE_INT, {&new_sim_nsteps},
         "If non-negative, perform these many steps in the real run (overwrite nsteps from tpr, add cpt steps)" }, 
       { "-launch",   FALSE, etBOOL, {&bLaunch},
@@ -1447,8 +1962,8 @@ int gmx_tune_pme(int argc,char *argv[])
       /******************/
       /* mdrun options: */
       /******************/
-      { "-nt",        FALSE, etINT,  {&nthreads},
-        "HIDDENNumber of threads to start on each node" },
+      { "-deffnm",    FALSE, etSTR, {&deffnm},
+          "Set the default filename for all file options at launch time" },
       { "-ddorder",   FALSE, etENUM, {ddno_opt},
         "DD node order" },
       { "-ddcheck",   FALSE, etBOOL, {&bDDBondCheck},
@@ -1483,10 +1998,10 @@ int gmx_tune_pme(int argc,char *argv[])
         "Try to avoid optimizations that affect binary reproducibility" },
       { "-cpt",       FALSE, etREAL, {&cpt_period},
         "Checkpoint interval (minutes)" },
+      { "-cpnum",   FALSE, etBOOL, {&bKeepAndNumCPT},
+        "Keep and number checkpoint files" },
       { "-append",    FALSE, etBOOL, {&bAppendFiles},
-        "Append to previous output files when continuing from checkpoint" },
-      { "-addpart",  FALSE, etBOOL,  {&bAddPart},
-        "Add the simulation part number to all output files when continuing from checkpoint" },
+        "Append to previous output files when continuing from checkpoint instead of adding the simulation part number to all file names (for launch only)" },
       { "-maxh",      FALSE, etREAL, {&max_hours},
         "Terminate after 0.99 times this time (hours)" },
       { "-multi",     FALSE, etINT,  {&nmultisim},
@@ -1502,7 +2017,9 @@ int gmx_tune_pme(int argc,char *argv[])
       { "-confout",   FALSE, etBOOL, {&bConfout},
         "HIDDENWrite the last configuration with -c and force checkpointing at the last step" },
       { "-stepout",   FALSE, etINT,  {&nstepout},
-        "HIDDENFrequency of writing the remaining runtime" }
+        "HIDDENFrequency of writing the remaining runtime" },
+      { "-resethway", FALSE, etBOOL, {&bResetCountersHalfWay},
+        "HIDDENReset the cycle counters after half the number of steps or halfway -maxh (launch only)" }
     };
 
     
@@ -1516,14 +2033,43 @@ int gmx_tune_pme(int argc,char *argv[])
                       NFILE,fnm,asize(pa),pa,asize(desc),desc,
                       0,NULL,&oenv);        
 
+    /* Store the remaining unparsed command line entries in a string */
+    snew(ExtraArgs, 1);
+    ExtraArgs[0] = '\0';
+    for (i=1; i<argc; i++) /* argc will now be 1 if everything was understood */
+    {
+        add_to_string(&ExtraArgs, argv[i]);
+        add_to_string(&ExtraArgs, " ");
+    }
+    if ( !bPassAll && (ExtraArgs[0] != '\0') )
+    {
+        fprintf(stderr, "\nWARNING: The following arguments you provided have no effect:\n"
+                        "%s\n"
+                        "Use the -passall option to force them to appear on the command lines\n"
+                        "for the benchmark simulations%s.\n\n",
+                        ExtraArgs, bLaunch? " and at launch time" : "");
+    }
+
+    if (opt2parg_bSet("-nt",asize(pa),pa))
+    {
+        bThreads=TRUE;
+        if (opt2parg_bSet("-npstring",asize(pa),pa))
+            fprintf(stderr, "WARNING: -npstring has no effect when using threads.\n");
+
+        if (nnodes > 1)
+            gmx_fatal(FARGS, "Can't run multi-threaded MPI simulation yet!");
+        /* and now we just set this; a bit of an ugly hack*/
+        nnodes=nthreads;
+    }
     /* Automatically set -beo options if -eo is set etc. */
     couple_files_options(NFILE,fnm);
     
     /* Construct the command line arguments for benchmark runs 
      * as well as for the simulation run 
      */
-    create_command_line_snippets(presteps,NFILE,fnm,asize(pa),pa, 
-            &cmd_np, &cmd_args_bench, &cmd_args_launch);
+    create_command_line_snippets(bThreads,presteps,NFILE,fnm,asize(pa),pa,procstring[0],
+                                 &cmd_np, &cmd_args_bench, &cmd_args_launch,
+                                 bPassAll? ExtraArgs : (char *)"");
 
     /* Read in checkpoint file if requested */
     sim_part = 1;
@@ -1538,15 +2084,18 @@ int gmx_tune_pme(int argc,char *argv[])
         sim_part++;
         /* sim_part will now be 1 if no checkpoint file was found */
         if (sim_part<=1)
-            gmx_fatal(FARGS, "Checkpoint file %s not found!", opt2fn("-cpi",NFILE,fnm));
+            gmx_fatal(FARGS, "Checkpoint file %s not found!", opt2fn("-cpi",
+                                                                     NFILE,
+                                                                     fnm));
     }
     
     /* Open performance output file and write header info */
     fp = ffopen(opt2fn("-p",NFILE,fnm),"w");
     
     /* Make a quick consistency check of command line parameters */
-    check_input(nnodes, repeats, &ntprs, maxfac, maxPMEfraction, minPMEfraction, 
-                fs, bench_nsteps, fnm, NFILE, sim_part, presteps);
+    check_input(nnodes, repeats, &ntprs, &upfac, &downfac, maxPMEfraction,
+                minPMEfraction, fs, bench_nsteps, fnm, NFILE, sim_part, presteps,
+                asize(pa),pa);
     
     /* Determine max and min number of PME nodes to test: */
     if (nnodes > 2)
@@ -1565,17 +2114,26 @@ int gmx_tune_pme(int argc,char *argv[])
     }   
     
     /* Get the commands we need to set up the runs from environment variables */
-    get_program_paths(&cmd_mpirun, &cmd_mdrun, repeats);
+    get_program_paths(bThreads, &cmd_mpirun, cmd_np, &cmd_mdrun, repeats);
     
     /* Print some header info to file */
     sep_line(fp);
     fprintf(fp, "\n      P E R F O R M A N C E   R E S U L T S\n");
     sep_line(fp);
     fprintf(fp, "%s for Gromacs %s\n", ShortProgram(),GromacsVersion());
-    fprintf(fp, "Number of nodes         : %d\n", nnodes);
-    fprintf(fp, "The mpirun command is   : %s\n", cmd_mpirun);
+    if (!bThreads)
+    {
+        fprintf(fp, "Number of nodes         : %d\n", nnodes);
+        fprintf(fp, "The mpirun command is   : %s\n", cmd_mpirun);
+        if ( strcmp(procstring[0], "none") != 0)
+            fprintf(fp, "Passing # of nodes via  : %s\n", procstring[0]);
+        else
+            fprintf(fp, "Not setting number of nodes in system call\n");
+    }
+    else
+        fprintf(fp, "Number of threads       : %d\n", nnodes);
+
     fprintf(fp, "The mdrun  command is   : %s\n", cmd_mdrun);
-    fprintf(fp, "Input file is           : %s\n", opt2fn("-s",NFILE,fnm));
     fprintf(fp, "mdrun args benchmarks   : %s\n", cmd_args_bench);
     fprintf(fp, "Benchmark steps         : ");
     fprintf(fp, gmx_large_int_pfmt, bench_nsteps);
@@ -1589,6 +2147,8 @@ int gmx_tune_pme(int argc,char *argv[])
     }
     if (bLaunch)
         fprintf(fp, "mdrun args at launchtime: %s\n", cmd_args_launch);
+    if (!bPassAll && ExtraArgs[0] != '\0')
+        fprintf(fp, "Unused arguments        : %s\n", ExtraArgs);
     if (new_sim_nsteps >= 0)
     {
         bOverwrite = TRUE;
@@ -1603,15 +2163,22 @@ int gmx_tune_pme(int argc,char *argv[])
         fprintf(fp, "Repeats for each test   : %d\n", repeats);
     
     if (fs > 0.0)
+    {
         fprintf(fp, "Requested grid spacing  : %f (tpr file will be changed accordingly)\n", fs);
+        fprintf(fp, "                          This will be the grid spacing at a scaling factor of 1.0\n");
+    }
     
+    fprintf(fp, "Input file              : %s\n", opt2fn("-s",NFILE,fnm));
+
     /* Allocate memory for the inputinfo struct: */
     snew(info, 1);
     info->nr_inputfiles = ntprs;
     for (i=0; i<ntprs; i++)
     {
         snew(info->r_coulomb , ntprs);
-        snew(info->r_vdW     , ntprs);
+        snew(info->r_vdw     , ntprs);
+        snew(info->rlist     , ntprs);
+        snew(info->rlistlong , ntprs);
         snew(info->fourier_nx, ntprs);
         snew(info->fourier_ny, ntprs);
         snew(info->fourier_nz, ntprs);
@@ -1622,85 +2189,45 @@ int gmx_tune_pme(int argc,char *argv[])
     for (i=0; i<ntprs; i++)
         snew(tpr_names[i], STRLEN);
 
-    make_benchmark_tprs(opt2fn("-s",NFILE,fnm), tpr_names, bench_nsteps+presteps, cpt_steps, maxfac, ntprs, fs, info, fp);
+    make_benchmark_tprs(opt2fn("-s",NFILE,fnm), tpr_names, bench_nsteps+presteps,
+            cpt_steps, upfac, downfac, ntprs, fs, info, fp);
 
-    if (repeats == 0)
-    {
-        fprintf(stderr, "Nothing more to do.\n");
-        fprintf(fp, "\nNo benchmarks done since number of repeats (-r) is 0.\n");
-        thanx(stderr);
-        return 0;
-    }
-    
-    /* Memory allocation for performance data */
-    if (nnodes > 2)
-    {
-        datasets = maxPMEnodes - minPMEnodes + 3;
-        if (0 == minPMEnodes)
-            datasets--;
-    }
-    else
-        datasets = 1;
-
-    /* Allocate one dataset for each tpr input file: */
-    snew(perfdata, ntprs);
-
-    /* Allocate a subset for each test with a given number of PME nodes */
-    for (k=0; k<ntprs; k++)
-    {
-        snew(perfdata[k], datasets);
-        for (i=0; i<datasets; i++)
-        {
-            for (j=0; j<repeats; j++)
-            {
-                snew(perfdata[k][i].Gcycles   , repeats);
-                snew(perfdata[k][i].ns_per_day, repeats);
-                snew(perfdata[k][i].PME_f_load, repeats);
-            }
-        }
-    }
 
     /********************************************************************************/
     /* Main loop over all scenarios we need to test: tpr files, PME nodes, repeats  */
     /********************************************************************************/
-    do_the_tests(fp, tpr_names, maxPMEnodes, minPMEnodes, datasets, perfdata, repeats, nnodes, ntprs,
-            cmd_mpirun, cmd_mdrun, cmd_args_bench, fnm, NFILE, sim_part, presteps, cpt_steps);
+    snew(perfdata, ntprs);
+    do_the_tests(fp, tpr_names, maxPMEnodes, minPMEnodes, npmevalues_opt[0], perfdata, &pmeentries,
+                 repeats, nnodes, ntprs, bThreads, cmd_mpirun, cmd_np, cmd_mdrun,
+                 cmd_args_bench, fnm, NFILE, sim_part, presteps, cpt_steps);
     
     fprintf(fp, "\nTuning took%8.1f minutes.\n", (gettime()-seconds)/60.0);
 
     /* Analyse the results and give a suggestion for optimal settings: */
-    analyze_data(fp, perfdata, nnodes, ntprs, datasets, repeats, info, &best_tpr, &best_npme);
+    bKeepTPR = analyze_data(fp, opt2fn("-p", NFILE, fnm), perfdata, nnodes, ntprs, pmeentries,
+                            repeats, info, &best_tpr, &best_npme);
     
     /* Take the best-performing tpr file and enlarge nsteps to original value */
-    if ((best_tpr > 0) || bOverwrite || (fs > 0.0))
+    if ( bKeepTPR && !bOverwrite && !(fs > 0.0) )
     {
-        simulation_tpr = opt2fn("-so",NFILE,fnm);
-        modify_PMEsettings(bOverwrite? (new_sim_nsteps+cpt_steps):info->orig_sim_steps, tpr_names[best_tpr], simulation_tpr);            
+        simulation_tpr = opt2fn("-s",NFILE,fnm);
     }
     else
-        simulation_tpr = opt2fn("-s",NFILE,fnm);
+    {
+        simulation_tpr = opt2fn("-so",NFILE,fnm);
+        modify_PMEsettings(bOverwrite? (new_sim_nsteps+cpt_steps) : 
+                           info->orig_sim_steps, tpr_names[best_tpr], 
+                           simulation_tpr);            
+    }
 
     /* Now start the real simulation if the user requested it ... */
-    launch_simulation(bLaunch, fp, cmd_mpirun, cmd_mdrun, cmd_args_launch, 
-                      simulation_tpr, nnodes, best_npme);
+    launch_simulation(bLaunch, fp, bThreads, cmd_mpirun, cmd_np, cmd_mdrun,
+                      cmd_args_launch, simulation_tpr, nnodes, best_npme);
     ffclose(fp);
         
     /* ... or simply print the performance results to screen: */
     if (!bLaunch)
-    {
-               char buf[STRLEN];
-
-               fp = fopen(opt2fn("-p", NFILE, fnm),"r");
-        fprintf(stdout,"\n\n");
-               
-               while( fgets(buf,STRLEN-1,fp) != NULL )
-               {
-                       fprintf(stdout,"%s",buf);
-               }
-               fclose(fp);
-        fprintf(stdout,"\n\n");
-        thanx(stderr);
-    }
+        finalize(opt2fn("-p", NFILE, fnm));
     
     return 0;
 }
index 8e4c123edddd05cb4ed2b175afaddc574bab8464..bd81d928d03fb8ceeb110dfe7b99d1204da0ae00 100644 (file)
@@ -133,7 +133,8 @@ int gmx_vanhove(int argc,char *argv[])
   int      ePBC;
   matrix   boxtop,box,*sbox,avbox,corr;
   rvec     *xtop,*x,**sx;
-  int      status,isize,nalloc,nallocn,natom;
+  int      isize,nalloc,nallocn,natom;
+  t_trxstatus *status;
   atom_id  *index;
   char     *grpname;
   int      nfr,f,ff,i,m,mat_nx=0,nbin=0,bin,mbin,fbin;
index 9bab05fa761f50df670480eefa19b8c35b930cd7..5b041bc618d6d46dedf27adc850731dfeed313be 100644 (file)
@@ -137,7 +137,8 @@ int gmx_velacc(int argc,char *argv[])
   char       *grpname;
   char       title[256];
   real       t0,t1,m;
-  int        status,teller,n_alloc,i,j,tel3,k,l;
+  t_trxstatus *status;
+  int        teller,n_alloc,i,j,tel3,k,l;
   rvec       mv_mol;
   real       **c1;
   real      *normm=NULL;
index e7912b822866b82db5ad574aee6a1d583fd4cd7b..95d7f767f1585d8b14bb909ad124216f27dc8c23 100644 (file)
@@ -1324,7 +1324,7 @@ void read_tpr_header(const char *fn,t_UmbrellaHeader* header,
 
     if (ir.ePull != epullUMBRELLA)
         gmx_fatal(FARGS,"This is not a tpr of an umbrella simulation. Found ir.ePull = %s\n",
-                epullg_names[ir.ePull]);
+                epull_names[ir.ePull]);
 
     /* nr of pull groups */
     ngrp=ir.pull->ngrp;
@@ -1643,9 +1643,9 @@ int gmx_wham(int argc,char *argv[])
             "[TT]*[tt] Same as the previous input mode, except that the the user",
             "  provides the pull force ouput file names (pullf.xvg) with option -if.",
             "  From the pull force the position in the ubrella potential is",
-            "  computed. This does not work with tabulated umbrella potentials."
+            "  computed. This does not work with tabulated umbrella potentials.",
             "[TT]*[tt] With option [TT]-ip[tt], the user provides filenames of (gzipped) pdo files, i.e.",
-            "  the gromacs 3.3 umbrella output files. If you have some unusual"
+            "  the gromacs 3.3 umbrella output files. If you have some unusual",
             "  reaction coordinate you may also generate your own pdo files and",
             "  feed them with the -ip option into to g_wham. The pdo file header",
             "  must be similar to the folowing:[BR]",
@@ -1684,7 +1684,7 @@ int gmx_wham(int argc,char *argv[])
             "position to be zero, choose with -zprof0 (useful with bootstrapping, see below).[PAR]",
             "For cyclic (or periodic) reaction coordinates (dihedral angle, channel PMF",
             "without osmotic gradient), -cycl is useful.[BR]",
-            "[TT]-cycl yes[tt]        min and max are assumed to "
+            "[TT]-cycl yes[tt]        min and max are assumed to",
             "be neighboring points and histogram points outside min and max are mapped into ",
             "the interval [min,max] (compare histogram output). [BR]",
             "[TT]-cycl weighted[tt]   First, a non-cyclic profile is computed. Subsequently, ",
@@ -1770,7 +1770,7 @@ int gmx_wham(int argc,char *argv[])
             { "-bs-seed", FALSE, etINT, {&opt.bsSeed},
               "seed for bootstrapping. (-1 = use time)"},
             { "-histbs", FALSE, etBOOL, {&opt.bHistBootStrap},
-              "In bootstrapping, consider complete histograms as one data point."
+              "In bootstrapping, consider complete histograms as one data point. "
               "Accounts better for long autocorrelations."},
             { "-histbs-block", FALSE, etINT, {&opt.histBootStrapBlockLength},
               "when mixin histograms only mix within blocks of -histBS_block."},
index 6fedc683f3a3fc2231b155daacbc9003f7841459..aa60df9a1b1c51e0e657b891103b5e90550f1953 100644 (file)
@@ -203,7 +203,7 @@ void wheel2(const char *fn,int nres,char *resnm[],int r0,real rot0,char *title)
 int gmx_wheel(int argc,char *argv[])
 {
   const char *desc[] = {
-    "wheel plots a helical wheel representation of your sequence."
+    "wheel plots a helical wheel representation of your sequence.",
     "The input sequence is in the .dat file where the first line contains",
     "the number of residues and each consecutive line contains a residue"
     "name."
index f430a38baf659cdac7cff02b0f617da57dfb2940..f16fdf4d64086505b7e86425f4188caf492c1a28 100644 (file)
@@ -509,7 +509,7 @@ void do_start_end(int nres,t_bb bb[],rvec x[],int *nbb,atom_id bbindex[],
     /* Find start and end of longest helix fragment */
     check_ahx(nres,bb,x,&hstart,&hend);
   }
-  fprintf(stderr,"helix from: %d thru %d\n",
+  fprintf(stderr,"helix from: %d through %d\n",
          bb[hstart].resno,bb[hend].resno);
   
   for(j=0,i=hstart; (i<=hend); i++) {
index 01142f8264c21bf00950f7bf5fd37cfc912978ca..a360e2c011abc59e05b8852b9553cfb62953865c 100644 (file)
@@ -366,13 +366,13 @@ void read_eigenvalues(int vecs[],const char *eigfile, real values[],
   if (bHesse)
     for (i=0; vecs[i]; i++) {
       if (vecs[i]<7)
-       gmx_fatal(FARGS,"ERROR: You have choosen one of the first 6 eigenvectors of the HESSE Matrix. That does not make sense, since they correspond to the 6 rotational and translational degrees of freedom.\n\n");
+       gmx_fatal(FARGS,"ERROR: You have chosen one of the first 6 eigenvectors of the HESSE Matrix. That does not make sense, since they correspond to the 6 rotational and translational degrees of freedom.\n\n");
       values[i]=eigval[1][vecs[i]-1]/kT;
     }
   else
     for (i=0; vecs[i]; i++) {
       if (vecs[i]>(neig-6))
-       gmx_fatal(FARGS,"ERROR: You have choosen one of the last 6 eigenvectors of the COVARIANCE Matrix. That does not make sense, since they correspond to the 6 rotational and translational degrees of freedom.\n\n");
+       gmx_fatal(FARGS,"ERROR: You have chosen one of the last 6 eigenvectors of the COVARIANCE Matrix. That does not make sense, since they correspond to the 6 rotational and translational degrees of freedom.\n\n");
       values[i]=1/eigval[1][vecs[i]-1];
     }
   /* free memory */
@@ -471,14 +471,14 @@ int main(int argc,char *argv[])
       "([TT]-linfix[tt], [TT]-linacc[tt], [TT]-radfix[tt], [TT]-radacc[tt], [TT]-radcon[tt]),",
       "to keep the position along a certain (set of) coordinate(s) fixed ([TT]-linfix[tt]),",
       "or to only monitor the projections of the positions onto",
-      "these coordinates ([TT]-mon[tt]).[PAR]"
+      "these coordinates ([TT]-mon[tt]).[PAR]",
       "References:[BR]",
       "A. Amadei, A.B.M. Linssen, B.L. de Groot, D.M.F. van Aalten and ",
       "H.J.C. Berendsen; An efficient method for sampling the essential subspace ",
       "of proteins., J. Biomol. Struct. Dyn. 13:615-626 (1996)[BR]",
       "B.L. de Groot, A. Amadei, D.M.F. van Aalten and H.J.C. Berendsen; ",
       "Towards an exhaustive sampling of the configurational spaces of the ",
-      "two forms of the peptide hormone guanylin,"
+      "two forms of the peptide hormone guanylin,",
       "J. Biomol. Struct. Dyn. 13 : 741-751 (1996)[BR]",
       "B.L. de Groot, A.Amadei, R.M. Scheek, N.A.J. van Nuland and H.J.C. Berendsen; ",
       "An extended sampling of the configurational space of HPr from E. coli",
@@ -495,16 +495,16 @@ int main(int argc,char *argv[])
       "(steps in the desired direction will be accepted, others will be rejected).",
       "Note: by default the starting MD structure will be taken as origin of the first",
       "expansion cycle for radius expansion. If [TT]-ori[tt] is specified, you will be able",
-      "to read in a structure file that defines an external origin.[PAR]"
+      "to read in a structure file that defines an external origin.[PAR]",
       "[TT]-radcon[tt]: perform acceptance radius contraction along selected eigenvectors",
-      "towards a target structure specified with [TT]-tar[tt].[PAR]"
-      "NOTE: each eigenvector can be selected only once. [PAR]"
+      "towards a target structure specified with [TT]-tar[tt].[PAR]",
+      "NOTE: each eigenvector can be selected only once. [PAR]",
       "[TT]-outfrq[tt]: frequency (in steps) of writing out projections etc. to .edo file[PAR]",
       "[TT]-slope[tt]: minimal slope in acceptance radius expansion. A new expansion",
       "cycle will be started if the spontaneous increase of the radius (in nm/step)",
-      "is less than the value specified.[PAR]" 
+      "is less than the value specified.[PAR]",
       "[TT]-maxedsteps[tt]: maximum number of steps per cycle in radius expansion",
-      "before a new cycle is started.[PAR]"
+      "before a new cycle is started.[PAR]",
       "Note on the parallel implementation: since ED sampling is a 'global' thing",
       "(collective coordinates etc.), at least on the 'protein' side, ED sampling",
       "is not very parallel-friendly from an implentation point of view. Because",
index 1d9b7c5ff8e935422fe45af6715e0f36bb6e8160..8cdd013caab79eaa4f5361e3ab5be0fdd831aeab 100644 (file)
@@ -1182,7 +1182,7 @@ int main(int argc,char *argv[])
     "have to use make_ndx when you need SPECIAL index groups.",
     "There is a default index group for the whole system, 9 default", 
     "index groups are generated for proteins, a default index group",
-    "is generated for every other residue name.[PAR]"
+    "is generated for every other residue name.[PAR]",
     "When no index file is supplied, also make_ndx will generate the",
     "default groups.",
     "With the index editor you can select on atom, residue and chain names",
index faf13f8f11b393f8e0dda33be0899f59d5ef5c06..5541dc1000f921a505bf19ac975a4065d4112430 100644 (file)
@@ -151,11 +151,11 @@ void proptrj(char *fngro,char *fndat,t_topology *top,t_pinp *p)
   snew(xav,natoms);
   snew(vav,natoms);
   read_conf(fngro,buf,&natoms,xav,vav,box);
-  fprintf(stderr,"Succesfully read average positions (%s)\n",buf);
+  fprintf(stderr,"Successfully read average positions (%s)\n",buf);
   
   EV=read_ev(fndat,natoms);
   
-  fprintf(stderr,"Succesfully read eigenvectors\n");
+  fprintf(stderr,"Successfully read eigenvectors\n");
 
   snew(index,nev);
   for(i=0; (i<nev); i++)
index 4c5a4f653dc2944f6b47371e65bef7a87be6bad1..e7f71ea2c27bd2dacae0583aed3d9746ef224ec7 100644 (file)
@@ -84,7 +84,7 @@ real **read_proj(int nev,int nframes,char *base)
     }
     ffclose(in);
   }
-  fprintf(stderr,"\rSuccesfully read eigenvector projections\n");
+  fprintf(stderr,"\rSuccessfully read eigenvector projections\n");
   
   return evprj;
 }
index e942f3637457dd3bda3e49462de9d734bb8c091a..a34260e398f4a57235a0b51e48a0babbd34f6ec9 100644 (file)
@@ -55,7 +55,7 @@ real *read_gammaf(char *fn,int nframes)
     gf[i]=y;
   }
   ffclose(in);
-  fprintf(stderr,"Succesfully read gamma\n");
+  fprintf(stderr,"Successfully read gamma\n");
   return gf;
 }
 
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e7a39ae
--- /dev/null
@@ -0,0 +1,2 @@
+enable_testing()
+add_test(TestExec_mdrun-h ../src/kernel/mdrun -h)