diff --git a/examples/COUPLE/README b/examples/COUPLE/README new file mode 100644 index 0000000000..d9d787bd7c --- /dev/null +++ b/examples/COUPLE/README @@ -0,0 +1,66 @@ +This directory has a C and C++ code that shows how LAMMPS can be +linked to a driver application as a library. The purpose is to +illustrate how another code could perform computations while using +LAMMPS to perform MD, or how an umbrella code or script could call +both LAMMPS and some other code to perform a coupled calculation. + +c_driver.c is the C driver +c++_driver.c is the C++ driver + +The 2 codes do the same thing, so you can compare them to see how to +drive LAMMPS in this manner. The C driver is similar in spirit to +what one could use from a Fortran program or scripting language. + +LAMMPS must first be built as a library. See the "Making LAMMPS" +section of Section_start.html in the documentation for info on how to +do this. Basically, you type something like + +make makelib +make -f Makefile.lib g++ + +in the LAMMPS src directory to create liblmp_g++.a + +You can then build either driver code with a compile line something +like this, which includes paths to the LAMMPS library interface, MPI, +and FFTW. + +This builds the C++ driver with the LAMMPS library using a C++ compiler: + +g++ -I/home/sjplimp/lammps/src -c c++_driver.cpp +g++ -L/home/sjplimp/lammps/src c++_driver.o \ + -llmp_g++ -lfftw -lmpich -lpthread -o c++_driver + +This builds the C driver with the LAMMPS library using a C compiler: + +gcc -I/home/sjplimp/lammps/src -c c_driver.cpp +gcc -L/home/sjplimp/lammps/src c_driver.o \ + -llmp_g++ -lfftw -lmpich -lpthread -lstdc++ -o c_driver + +You then run c++_driver or c_driver on a parallel machine on some +number of processors Q with 2 arguments: + +mpirun -np Q c_driver P in.lj + +P is the number of procs you want LAMMPS to run on (must be <= Q). +In.lj is a LAMMPS input script. + +The driver will launch LAMMPS on P procs, read the input script a line +at a time, and pass each command line to LAMMPS. The final line of +the script is a "run" command, so LAMMPS will run the problem. + +The driver then requests all the atom coordinates from LAMMPS, moves +one of the atoms a small amount "epsilon", passes the coordinates back +to LAMMPS, and runs LAMMPS again. If you look at the output, you +should see a small energy change between runs, due to the moved atom. + +The C driver is calling C-style routines in the src/library.cpp file +of LAMMPS. You could add any functions you wish to this file to +manipulate LAMMPS data however you wish. + +The C++ driver does the same thing, except that it instantiates LAMMPS +as an object first. Some of the functions in src/library.cpp can be +invoked directly as methods within appropriate LAMMPS classes, which +is what the driver does. Any public LAMMPS class method could be +called from the driver this way. However the get/put functions are +only implemented in src/library.cpp, so the C++ driver calls them as +C-style functions. diff --git a/examples/COUPLE/c++_driver.cpp b/examples/COUPLE/c++_driver.cpp new file mode 100644 index 0000000000..ff78e49657 --- /dev/null +++ b/examples/COUPLE/c++_driver.cpp @@ -0,0 +1,121 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + www.cs.sandia.gov/~sjplimp/lammps.html + Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +// c++_driver = simple example of how an umbrella program +// can invoke LAMMPS as a library on some subset of procs +// Syntax: c++_driver P in.lammps +// P = # of procs to run LAMMPS on +// must be <= # of procs the driver code itself runs on +// in.lammps = LAMMPS input script +// See README for compilation instructions + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "mpi.h" +#include "lammps.h" // these are LAMMPS include files +#include "input.h" +#include "atom.h" +#include "library.h" + +using namespace LAMMPS_NS; + +int main(int narg, char **arg) +{ + // setup MPI and various communicators + // driver runs on all procs in MPI_COMM_WORLD + // comm_lammps only has 1st P procs (could be all or any subset) + + MPI_Init(&narg,&arg); + + if (narg != 3) { + printf("Syntax: c++_driver P in.lammps\n"); + exit(1); + } + + int me,nprocs; + MPI_Comm_rank(MPI_COMM_WORLD,&me); + MPI_Comm_size(MPI_COMM_WORLD,&nprocs); + + int nprocs_lammps = atoi(arg[1]); + if (nprocs_lammps > nprocs) { + if (me == 0) + printf("ERROR: LAMMPS cannot use more procs than available\n"); + MPI_Abort(MPI_COMM_WORLD,1); + } + + int lammps; + if (me < nprocs_lammps) lammps = 1; + else lammps = MPI_UNDEFINED; + MPI_Comm comm_lammps; + MPI_Comm_split(MPI_COMM_WORLD,lammps,0,&comm_lammps); + + // open LAMMPS input script + + FILE *fp; + if (me == 0) { + fp = fopen(arg[2],"r"); + if (fp == NULL) { + printf("ERROR: Could not open LAMMPS input script\n"); + MPI_Abort(MPI_COMM_WORLD,1); + } + } + + // run the input script thru LAMMPS one line at a time until end-of-file + // driver proc 0 reads a line, Bcasts it to all procs + // (could just send it to proc 0 of comm_lammps and let it Bcast) + // all LAMMPS procs call input->one() on the line + + LAMMPS *lmp; + if (lammps == 1) lmp = new LAMMPS(0,NULL,comm_lammps); + + int n; + char line[1024]; + while (1) { + if (me == 0) { + if (fgets(line,1024,fp) == NULL) n = 0; + else n = strlen(line) + 1; + if (n == 0) fclose(fp); + } + MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD); + if (n == 0) break; + MPI_Bcast(line,n,MPI_CHAR,0,MPI_COMM_WORLD); + if (lammps == 1) lmp->input->one(line); + } + + // run 10 more steps + // get coords from LAMMPS + // change coords of 1st atom + // put coords back into LAMMPS + // run a single step with changed coords + + if (lammps == 1) { + lmp->input->one("run 10"); + + int natoms = static_cast (lmp->atom->natoms); + double *x = new double[3*natoms]; + lammps_get_coords(lmp,x); // no LAMMPS class function for this + double epsilon = 0.1; + x[0] += epsilon; + lammps_put_coords(lmp,x); // no LAMMPS class function for this + delete [] x; + + lmp->input->one("run 1"); + } + + if (lammps == 1) delete lmp; + + // close down MPI + + MPI_Finalize(); +} diff --git a/examples/COUPLE/c_driver.c b/examples/COUPLE/c_driver.c new file mode 100644 index 0000000000..5b80815160 --- /dev/null +++ b/examples/COUPLE/c_driver.c @@ -0,0 +1,116 @@ +/* ---------------------------------------------------------------------- + LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator + www.cs.sandia.gov/~sjplimp/lammps.html + Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories + + Copyright (2003) Sandia Corporation. Under the terms of Contract + DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains + certain rights in this software. This software is distributed under + the GNU General Public License. + + See the README file in the top-level LAMMPS directory. +------------------------------------------------------------------------- */ + +/* c_driver = simple example of how an umbrella program + can invoke LAMMPS as a library on some subset of procs + Syntax: c_driver P in.lammps + P = # of procs to run LAMMPS on + must be <= # of procs the driver code itself runs on + in.lammps = LAMMPS input script + See README for compilation instructions */ + +#include "stdio.h" +#include "stdlib.h" +#include "string.h" +#include "mpi.h" +#include "library.h" /* this is a LAMMPS include file */ + +int main(int narg, char **arg) +{ + /* setup MPI and various communicators + driver runs on all procs in MPI_COMM_WORLD + comm_lammps only has 1st P procs (could be all or any subset) */ + + MPI_Init(&narg,&arg); + + if (narg != 3) { + printf("Syntax: c_driver P in.lammps\n"); + exit(1); + } + + int me,nprocs; + MPI_Comm_rank(MPI_COMM_WORLD,&me); + MPI_Comm_size(MPI_COMM_WORLD,&nprocs); + + int nprocs_lammps = atoi(arg[1]); + if (nprocs_lammps > nprocs) { + if (me == 0) + printf("ERROR: LAMMPS cannot use more procs than available\n"); + MPI_Abort(MPI_COMM_WORLD,1); + } + + int lammps; + if (me < nprocs_lammps) lammps = 1; + else lammps = MPI_UNDEFINED; + MPI_Comm comm_lammps; + MPI_Comm_split(MPI_COMM_WORLD,lammps,0,&comm_lammps); + + /* open LAMMPS input script */ + + FILE *fp; + if (me == 0) { + fp = fopen(arg[2],"r"); + if (fp == NULL) { + printf("ERROR: Could not open LAMMPS input script\n"); + MPI_Abort(MPI_COMM_WORLD,1); + } + } + + /* run the input script thru LAMMPS one line at a time until end-of-file + driver proc 0 reads a line, Bcasts it to all procs + (could just send it to proc 0 of comm_lammps and let it Bcast) + all LAMMPS procs call lammps_command() on the line */ + + void *ptr; + if (lammps == 1) lammps_open(0,NULL,comm_lammps,&ptr); + + int n; + char line[1024]; + while (1) { + if (me == 0) { + if (fgets(line,1024,fp) == NULL) n = 0; + else n = strlen(line) + 1; + if (n == 0) fclose(fp); + } + MPI_Bcast(&n,1,MPI_INT,0,MPI_COMM_WORLD); + if (n == 0) break; + MPI_Bcast(line,n,MPI_CHAR,0,MPI_COMM_WORLD); + if (lammps == 1) lammps_command(ptr,line); + } + + /* run 10 more steps + get coords from LAMMPS + change coords of 1st atom + put coords back into LAMMPS + run a single step with changed coords */ + + if (lammps == 1) { + lammps_command(ptr,"run 10"); + + int natoms = lammps_get_natoms(ptr); + double *x = (double *) malloc(3*natoms*sizeof(double)); + lammps_get_coords(ptr,x); + double epsilon = 0.1; + x[0] += epsilon; + lammps_put_coords(ptr,x); + free(x); + + lammps_command(ptr,"run 1"); + } + + if (lammps == 1) lammps_close(ptr); + + /* close down MPI */ + + MPI_Finalize(); +} diff --git a/examples/COUPLE/in.lj b/examples/COUPLE/in.lj new file mode 100644 index 0000000000..98de6750b4 --- /dev/null +++ b/examples/COUPLE/in.lj @@ -0,0 +1,24 @@ +# 3d Lennard-Jones melt + +units lj +atom_style atomic +atom_modify map array + +lattice fcc 0.8442 +region box block 0 4 0 4 0 4 +create_box 1 box +create_atoms 1 box +mass 1 1.0 + +velocity all create 1.44 87287 loop geom + +pair_style lj/cut 2.5 +pair_coeff 1 1 1.0 1.0 2.5 + +neighbor 0.3 bin +neigh_modify delay 0 every 20 check no + +fix 1 all nve + +run 10 +