forked from lijiext/lammps
176 lines
4.8 KiB
C++
176 lines
4.8 KiB
C++
/* ----------------------------------------------------------------------
|
|
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: simpleCC 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 <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <mpi.h>
|
|
|
|
// these are LAMMPS include files
|
|
#include <lammps/lammps.h>
|
|
#include <lammps/input.h>
|
|
#include <lammps/atom.h>
|
|
#include <lammps/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: simpleCC 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 = NULL;
|
|
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) lammps_command(lmp,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
|
|
|
|
double *x = NULL;
|
|
double *v = NULL;
|
|
|
|
if (lammps == 1) {
|
|
lmp->input->one("run 10");
|
|
|
|
int natoms = static_cast<int> (lmp->atom->natoms);
|
|
x = new double[3*natoms];
|
|
v = new double[3*natoms];
|
|
lammps_gather_atoms(lmp,(char *) "x",1,3,x);
|
|
lammps_gather_atoms(lmp,(char *) "v",1,3,v);
|
|
double epsilon = 0.1;
|
|
x[0] += epsilon;
|
|
lammps_scatter_atoms(lmp,(char *) "x",1,3,x);
|
|
|
|
// these 2 lines are the same
|
|
|
|
// lammps_command(lmp,"run 1");
|
|
lmp->input->one("run 1");
|
|
}
|
|
|
|
// extract force on single atom two different ways
|
|
|
|
if (lammps == 1) {
|
|
double **f = (double **) lammps_extract_atom(lmp,(char *) "f");
|
|
printf("Force on 1 atom via extract_atom: %g\n",f[0][0]);
|
|
|
|
double *fx = (double *)
|
|
lammps_extract_variable(lmp,(char *) "fx",(char *) "all");
|
|
printf("Force on 1 atom via extract_variable: %g\n",fx[0]);
|
|
}
|
|
|
|
// use commands_string() and commands_list() to invoke more commands
|
|
|
|
char *strtwo = (char *) "run 10\nrun 20";
|
|
if (lammps == 1) lammps_commands_string(lmp,strtwo);
|
|
|
|
char *cmds[2];
|
|
cmds[0] = (char *) "run 10";
|
|
cmds[1] = (char *) "run 20";
|
|
if (lammps == 1) lammps_commands_list(lmp,2,cmds);
|
|
|
|
// delete all atoms
|
|
// create_atoms() to create new ones with old coords, vels
|
|
// initial thermo should be same as step 20
|
|
|
|
int *type = NULL;
|
|
|
|
if (lammps == 1) {
|
|
int natoms = static_cast<int> (lmp->atom->natoms);
|
|
type = new int[natoms];
|
|
for (int i = 0; i < natoms; i++) type[i] = 1;
|
|
|
|
lmp->input->one("delete_atoms group all");
|
|
lammps_create_atoms(lmp,natoms,NULL,type,x,v,NULL,0);
|
|
lmp->input->one("run 10");
|
|
}
|
|
|
|
delete [] x;
|
|
delete [] v;
|
|
delete [] type;
|
|
|
|
// close down LAMMPS
|
|
|
|
delete lmp;
|
|
|
|
// close down MPI
|
|
|
|
if (lammps == 1) MPI_Comm_free(&comm_lammps);
|
|
MPI_Barrier(MPI_COMM_WORLD);
|
|
MPI_Finalize();
|
|
}
|