Sample LAMMPS MD wrapper on NWChem via client/server coupling

See the MESSAGE package (doc/Section_messages.html#MESSAGE) and
Section_howto.html#howto10 for more details on how client/server
coupling works in LAMMPS.

In this dir, the nwchem_wrap.py is a wrapper on the NWChem electronic
structure code so it can work as a "server" code which LAMMPS drives
as a "client" code to perform ab initio MD.  LAMMPS performs the MD
timestepping, sends NWChem a current set of coordinates each timestep,
NWChem computes forces and energy (and virial) and returns that info
to LAMMPS.

Messages are exchanged between NWChem and LAMMPS via a client/server
library (CSlib), which is included in the LAMMPS distribution in
lib/message.  As explained below you can choose to exchange data
between the two programs either via files or sockets (ZMQ).  If the
nwchem_wrap.py program became parallel, or the CSlib library calls were
integrated into NWChem directly, then data could also be exchanged via
MPI.

There are 2 examples provided in the planeware and ao_basis
sub-directories.  See details below.

----------------

Build LAMMPS with its MESSAGE package installed:

See the Build extras doc page and its MESSAGE package
section for details.

CMake:

-D PKG_MESSAGE=yes      # include the MESSAGE package
-D MESSAGE_ZMQ=value    # build with ZeroMQ support, value = no (default) or yes

Traditional make:

cd lammps/lib/message
python Install.py -m -z       # build CSlib with MPI and ZMQ support
cd lammps/src
make yes-message
make mpi

You can leave off the -z if you do not have ZMQ on your system.

----------------

Build the CSlib in a form usable by the nwchem_wrapper.py script:

% cd lammps/lib/message/cslib/src
% make shlib            # build serial and parallel shared lib with ZMQ support
% make shlib zmq=no     # build serial and parallel shared lib w/out ZMQ support

This will make a shared library versions of the CSlib, which Python
requires.  Python must be able to find both the cslib.py script and
the libcsnompi.so library in your lammps/lib/message/cslib/src
directory.  If it is not able to do this, you will get an error when
you run nwchem_wrapper.py.

You can do this by augmenting two environment variables, either from
the command line, or in your shell start-up script.  Here is the
sample syntax for the csh or tcsh shells:

setenv PYTHONPATH ${PYTHONPATH}:/home/sjplimp/lammps/lib/message/cslib/src
setenv LD_LIBRARY_PATH ${LD_LIBRARY_PATH}:/home/sjplimp/lammps/lib/message/cslib/src

----------------

Prepare to use NWChem and the nwchem_wrap.py script

You can run the nwchem_wrap.py script as-is to test that the coupling
between it and LAMMPS is functional.  This will use the included
nwchem_lammps.out files output by a previous NWChem run.

But note that the as-is version of nwchem_wrap.py will not attempt to
run NWChem.

To do this, you must edit the 1st nwchemcmd line at the top of
nwchem_wrapper.py to be the launch command needed to run NWChem on
your system.  It can be a command to run NWChem in serial or in
parallel, e.g. an mpirun command.  Then comment out the 2nd nwchemcmd
line immediately following it.

Ensure you have the necessary NWChem input file in this directory,
suitable for the NWChem calculation you want to perform.

Example input files are provided for both atom-centered AO basis sets
and plane-wave basis sets. Note that the NWChem template file should
be matched to the LAMMPS input script (# of atoms and atom types, box
size, etc).

Once you run NWChem yourself, the nwchem_lammps.out file will be
overwritten.

The syntax of the wrapper is:
nwchem_wrap.py file/zmq ao/pw input_template
* file/zmg = messaging mode, must match LAMMPS messaging mode
* ao/pw = basis set mode, selects between atom-centered and plane-wave
          the input_template file must correspond to the appropriate basis set mode:
          the "ao" mode supports the scf and dft modules in NWChem,
          the "pw" mode supports the nwpw module.
* input_template = NWChem input file used as template, must include a
                   "geometry" block with the atoms in the simulation, dummy
                   xyz coordinates should be included (but are not used).
                   Atom ordering must match LAMMPS input.

During a simulation, the molecular orbitals from the previous timestep
will be used as the initial guess for the next NWChem calculation. If
a file named "nwchem_lammps.movecs" is in the directory the wrapper is
called from, these orbitals will be used as the initial guess orbitals
in the first step of the simulation.

----------------

Example directories

(1) planewave

Demonstrates coupling of the nwpw module in NWChem with LAMMPS. Only fully
periodic boundary conditions and orthogonal simulation boxes are currently
supported by the wrapper. The included files provide an example run using a
2 atom unit cell of tungsten.

Files:
  * data.W               LAMMPS input with geometry information
  * in.client.W          LAMMPS simulation input
  * log.client.output    LAMMPS simulation output
  * w.nw                 NWChem template input file
  * nwchem_lammps.out    NWChem output

(2) ao_basis

Demonstrates coupling of the scf (or dft) modules in NWChem with
LAMMPS.  Only fully aperiodic boundary conditions are currently
supported by the wrapper. The included files provide an example run
using a single water molecule.

Files:
  * data.h2o               LAMMPS input with geometry information
  * in.client.h2o          LAMMPS simulation input
  * log.client.output      LAMMPS simulation output
  * h2o.nw                 NWChem template input file
  * nwchem_lammps.out      NWChem output

As noted above, you can run the nwchem_wrap.py script as-is to test that
the coupling between it and LAMMPS is functional.  This will use the included
nwchem_lammps.out files.

----------------

To run in client/server mode:

NOTE: The nwchem_wrap.py script must be run with Python version 2, not
3.  This is because it used the CSlib python wrapper, which only
supports version 2.  We plan to upgrade CSlib to support Python 3.

Both the client (LAMMPS) and server (nwchem_wrap.py) must use the same
messaging mode, namely file or zmq.  This is an argument to the
nwchem_wrap.py code; it can be selected by setting the "mode" variable
when you run LAMMPS.  The default mode = file.

Here we assume LAMMPS was built to run in parallel, and the MESSAGE
package was installed with socket (ZMQ) support.  This means either of
the messaging modes can be used and LAMMPS can be run in serial or
parallel.  The nwchem_wrap.py code is always run in serial, but it
launches NWChem from Python via an mpirun command which can run NWChem
itself in parallel.

When you run, the server should print out thermodynamic info every
timestep which corresponds to the forces and virial computed by NWChem.
NWChem will also generate output files each timestep.  Output files from
previous timesteps are archived in a "nwchem_logs" directory.

The examples below are commands you should use in two different
terminal windows.  The order of the two commands (client or server
launch) does not matter.  You can run them both in the same window if
you append a "&" character to the first one to run it in the
background.

--------------

File mode of messaging:

% mpirun -np 1 lmp_mpi -v mode file < in.client.W
% python nwchem_wrap.py file pw w.nw

% mpirun -np 2 lmp_mpi -v mode file < in.client.h2o
% python nwchem_wrap.py file ao h2o.nw

ZMQ mode of messaging:

% mpirun -np 1 lmp_mpi -v mode zmq < in.client.W
% python nwchem_wrap.py zmq pw w.nw

% mpirun -np 2 lmp_mpi -v mode zmq < in.client.h2o
% python nwchem_wrap.py zmq ao h2o.nw
