git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@8636 f3b2605a-c512-4ea7-a41b-209d697bcdaa

This commit is contained in:
sjplimp
2012-08-13 23:49:26 +00:00
parent e69d5dacc9
commit a2f01ca576
11 changed files with 1697 additions and 7 deletions

View File

@ -34,5 +34,7 @@ library collection of useful inter-code communication routines
simple simple example of driver code calling LAMMPS as library simple simple example of driver code calling LAMMPS as library
fortran a wrapper on the LAMMPS library API that fortran a wrapper on the LAMMPS library API that
can be called from Fortran can be called from Fortran
fortran2 a more sophisticated wrapper on the LAMMPS library API that
can be called from Fortran
Each sub-directory has its own README. Each sub-directory has its own README.

View File

@ -1,9 +1,8 @@
libfwrapper.c is a C file that wraps the LAMMPS library API libfwrapper.c is a C file that wraps the LAMMPS library API
in src/library.h so that it can be called from Fortran. in src/library.h so that it can be called from Fortran.
See the couple/simple/simple.f90 program for an example See the couple/simple/simple.f90 program for an example of a Fortran
of a Fortran code that does this. code that does this.
See the README file in that dir for instructions See the README file in that dir for instructions on how to build a
on how to build a Fortran code that uses this Fortran code that uses this wrapper and links to the LAMMPS library.
wrapper and links to the LAMMPS library.

View File

@ -22,7 +22,7 @@
#include "library.h" /* this is a LAMMPS include file */ #include "library.h" /* this is a LAMMPS include file */
/* wrapper for creating a lammps instance from fortran. /* wrapper for creating a lammps instance from fortran.
since fortran has no simple way to emit a c-compatible since fortran has no simple way to emit a C-compatible
argument array, we don't support it. for simplicity, argument array, we don't support it. for simplicity,
the address of the pointer to the lammps object is the address of the pointer to the lammps object is
stored in a 64-bit integer on all platforms. */ stored in a 64-bit integer on all platforms. */
@ -109,6 +109,8 @@ void lammps_get_natoms_(int64_t *ptr, MPI_Fint *natoms)
/* wrapper to copy coordinates from lammps to fortran */ /* wrapper to copy coordinates from lammps to fortran */
/* NOTE: this is now out-of-date, needs to be updated to lammps_gather_atoms()
void lammps_get_coords_(int64_t *ptr, double *coords) void lammps_get_coords_(int64_t *ptr, double *coords)
{ {
void *obj; void *obj;
@ -117,8 +119,12 @@ void lammps_get_coords_(int64_t *ptr, double *coords)
lammps_get_coords(obj,coords); lammps_get_coords(obj,coords);
} }
*/
/* wrapper to copy coordinates from fortran to lammps */ /* wrapper to copy coordinates from fortran to lammps */
/* NOTE: this is now out-of-date, needs to be updated to lammps_scatter_atoms()
void lammps_put_coords_(int64_t *ptr, double *coords) void lammps_put_coords_(int64_t *ptr, double *coords)
{ {
void *obj; void *obj;
@ -127,3 +133,4 @@ void lammps_put_coords_(int64_t *ptr, double *coords)
lammps_put_coords(obj,coords); lammps_put_coords(obj,coords);
} }
*/

View File

@ -0,0 +1,235 @@
/* -----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------
Contributing author: Karl D. Hammond <karlh@ugcs.caltech.edu>
University of Tennessee, Knoxville (USA), 2012
------------------------------------------------------------------------- */
/* This is set of "wrapper" functions to assist LAMMPS.F90, which itself
provides a (I hope) robust Fortran interface to library.cpp and
library.h. All functions herein COULD be added to library.cpp instead of
including this as a separate file. See the README for instructions. */
#include <mpi.h>
#include "LAMMPS-wrapper.h"
#include <library.h>
#include <lammps.h>
#include <atom.h>
#include <fix.h>
#include <compute.h>
#include <modify.h>
#include <error.h>
using namespace LAMMPS_NS;
void lammps_open_fortran_wrapper (int argc, char **argv,
MPI_Fint communicator, void **ptr)
{
MPI_Comm C_communicator = MPI_Comm_f2c (communicator);
lammps_open (argc, argv, C_communicator, ptr);
}
int lammps_get_ntypes (void *ptr)
{
class LAMMPS *lmp = (class LAMMPS *) ptr;
int ntypes = lmp->atom->ntypes;
return ntypes;
}
void lammps_error_all (void *ptr, const char *file, int line, const char *str)
{
class LAMMPS *lmp = (class LAMMPS *) ptr;
lmp->error->all (file, line, str);
}
int lammps_extract_compute_vectorsize (void *ptr, char *id, int style)
{
class LAMMPS *lmp = (class LAMMPS *) ptr;
int icompute = lmp->modify->find_compute(id);
if ( icompute < 0 ) return 0;
class Compute *compute = lmp->modify->compute[icompute];
if ( style == 0 )
{
if ( !compute->vector_flag )
return 0;
else
return compute->size_vector;
}
else if ( style == 1 )
{
return lammps_get_natoms (ptr);
}
else if ( style == 2 )
{
if ( !compute->local_flag )
return 0;
else
return compute->size_local_rows;
}
else
return 0;
}
void lammps_extract_compute_arraysize (void *ptr, char *id, int style,
int *nrows, int *ncols)
{
class LAMMPS *lmp = (class LAMMPS *) ptr;
int icompute = lmp->modify->find_compute(id);
if ( icompute < 0 )
{
*nrows = 0;
*ncols = 0;
}
class Compute *compute = lmp->modify->compute[icompute];
if ( style == 0 )
{
if ( !compute->array_flag )
{
*nrows = 0;
*ncols = 0;
}
else
{
*nrows = compute->size_array_rows;
*ncols = compute->size_array_cols;
}
}
else if ( style == 1 )
{
if ( !compute->peratom_flag )
{
*nrows = 0;
*ncols = 0;
}
else
{
*nrows = lammps_get_natoms (ptr);
*ncols = compute->size_peratom_cols;
}
}
else if ( style == 2 )
{
if ( !compute->local_flag )
{
*nrows = 0;
*ncols = 0;
}
else
{
*nrows = compute->size_local_rows;
*ncols = compute->size_local_cols;
}
}
else
{
*nrows = 0;
*ncols = 0;
}
return;
}
int lammps_extract_fix_vectorsize (void *ptr, char *id, int style)
{
class LAMMPS *lmp = (class LAMMPS *) ptr;
int ifix = lmp->modify->find_fix(id);
if ( ifix < 0 ) return 0;
class Fix *fix = lmp->modify->fix[ifix];
if ( style == 0 )
{
if ( !fix->vector_flag )
return 0;
else
return fix->size_vector;
}
else if ( style == 1 )
{
return lammps_get_natoms (ptr);
}
else if ( style == 2 )
{
if ( !fix->local_flag )
return 0;
else
return fix->size_local_rows;
}
else
return 0;
}
void lammps_extract_fix_arraysize (void *ptr, char *id, int style,
int *nrows, int *ncols)
{
class LAMMPS *lmp = (class LAMMPS *) ptr;
int ifix = lmp->modify->find_fix(id);
if ( ifix < 0 )
{
*nrows = 0;
*ncols = 0;
}
class Fix *fix = lmp->modify->fix[ifix];
if ( style == 0 )
{
if ( !fix->array_flag )
{
*nrows = 0;
*ncols = 0;
}
else
{
*nrows = fix->size_array_rows;
*ncols = fix->size_array_cols;
}
}
else if ( style == 1 )
{
if ( !fix->peratom_flag )
{
*nrows = 0;
*ncols = 0;
}
else
{
*nrows = lammps_get_natoms (ptr);
*ncols = fix->size_peratom_cols;
}
}
else if ( style == 2 )
{
if ( !fix->local_flag )
{
*nrows = 0;
*ncols = 0;
}
else
{
*nrows = fix->size_local_rows;
*ncols = fix->size_local_cols;
}
}
else
{
*nrows = 0;
*ncols = 0;
}
return;
}
/* vim: set ts=3 sts=3 expandtab: */

View File

@ -0,0 +1,47 @@
/* -----------------------------------------------------------------------
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.
------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------
Contributing author: Karl D. Hammond <karlh@ugcs.caltech.edu>
University of Tennessee, Knoxville (USA), 2012
------------------------------------------------------------------------- */
/* This is set of "wrapper" functions to assist LAMMPS.F90, which itself
provides a (I hope) robust Fortran interface to library.cpp and
library.h. All prototypes herein COULD be added to library.h instead of
including this as a separate file. See the README for instructions. */
/* These prototypes probably belong in mpi.h in the src/STUBS directory. */
#ifndef OPEN_MPI
#define MPI_Comm_f2c(a) a
#define MPI_Fint int
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* Prototypes for auxiliary functions */
void lammps_open_fortran_wrapper (int, char**, MPI_Fint, void**);
int lammps_get_ntypes (void*);
int lammps_extract_compute_vectorsize (void*, char*, int);
void lammps_extract_compute_arraysize (void*, char*, int, int*, int*);
int lammps_extract_fix_vectorsize (void*, char*, int);
void lammps_extract_fix_arraysize (void*, char*, int, int*, int*);
void lammps_error_all (void *ptr, const char*, int, const char*);
#ifdef __cplusplus
}
#endif
/* vim: set ts=3 sts=3 expandtab: */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,213 @@
LAMMPS.F90 defines a Fortran 2003 module, LAMMPS, which wraps all functions in
src/library.h so they can be used directly from Fortran-encoded programs.
All functions in src/library.h that use and/or return C-style pointers have
Fortran wrapper functions that use Fortran-style arrays, pointers, and
strings; all C-style memory management is handled internally with no user
intervention.
-------------------------------------
--COMPILATION--
First, be advised that mixed-language programming is not trivial. It requires
you to link in the required libraries of all languages you use (in this case,
those for Fortran, C, and C++), as well as any other libraries required.
You are also advised to read the --USE-- section below before trying to
compile.
The following steps will work to compile this module (replace ${LAMMPS_SRC}
with the path to your LAMMPS source directory):
(1) Compile LAMMPS as a static library. Call the resulting file ${LAMMPS_LIB},
which will have an actual name lake liblmp_openmpi.a. If compiling
using the MPI stubs in ${LAMMPS_SRC}/STUBS, you will need to know where
libmpi.a is as well (I'll call it ${MPI_STUBS} hereafter)
(2) Copy said library to your Fortran program's source directory or include
its location in a -L${LAMMPS_SRC} flag to your compiler.
(3) Compile (but don't link!) LAMMPS.F90. Example:
mpif90 -c LAMMPS.f90
OR
gfortran -c LAMMPS.F90
Copy the LAMMPS.o and lammps.mod (or whatever your compiler calls module
files) to your Fortran program's source directory.
NOTE: you may get a warning such as,
subroutine lammps_open_wrapper (argc, argv, communicator, ptr) &
Variable 'communicator' at (1) is a parameter to the BIND(C)
procedure 'lammps_open_wrapper' but may not be C interoperable
This is normal (see --IMPLEMENTATION NOTES--).
(4) Compile (but don't link) LAMMPS-wrapper.cpp. You will need its header
file as well. You will have to provide the locations of LAMMPS's
header files. For example,
mpicxx -c -I${LAMMPS_SRC} LAMMPS-wrapper.cpp
OR
g++ -c -I${LAMMPS_SRC} -I${LAMMPS_SRC}/STUBS LAMMPS-wrapper.cpp
OR
icpc -c -I${LAMMPS_SRC} -I${LAMMPS_SRC}/STUBS LAMMPS-wrapper.cpp
Copy the resulting object file LAMMPS-wrapper.o to your Fortran program's
source directory.
(4b) OPTIONAL: Make a library so you can carry around two files instead of
three. Example:
ar rs liblammps_fortran.a LAMMPS.o LAMMPS-wrapper.o
This will create the file liblammps_fortran.a that you can use in place
of "LAMMPS.o LAMMPS-wrapper.o" in part (6). Note that you will still
need to have the .mod file from part (3).
It is also possible to add LAMMPS.o and LAMMPS-wrapper.o into the
LAMMPS library (e.g., liblmp_openmpi.a) instead of creating a separate
library, like so:
ar rs ${LAMMPS_LIB} LAMMPS.o LAMMPS-wrapper.o
In this case, you can now use the Fortran wrapper functions as if they
were part of the usual LAMMPS library interface (if you have the module
file visible to the compiler, that is).
(5) Compile your Fortran program. Example:
mpif90 -c myfreeformatfile.f90
mpif90 -c myfixedformatfile.f
OR
gfortran -c myfreeformatfile.f90
gfortran -c myfixedformatfile.f
The object files generated by these steps are collectively referred to
as ${my_object_files} in the next step(s).
IMPORTANT: If the Fortran module from part (3) is not in the current
directory or in one searched by the compiler for module files, you will
need to include that location via the -I flag to the compiler.
(6) Link everything together, including any libraries needed by LAMMPS (such
as the C++ standard library, the C math library, the JPEG library, fftw,
etc.) For example,
mpif90 LAMMPS.o LAMMPS-wrapper.o ${my_object_files} \
${LAMMPS_LIB} -lstdc++ -lm
OR
gfortran LAMMPS.o LAMMPS-wrapper.o ${my_object_files} \
${LAMMPS_LIB} ${MPI_STUBS} -lstdc++ -lm
OR
ifort LAMMPS.o LAMMPS-wrapper.o ${my_object_files} \
${LAMMPS_LIB} ${MPI_STUBS} -cxxlib -limf -lm
Any other required libraries (e.g. -ljpeg, -lfftw) should be added to
the end of this line.
You should now have a working executable.
Steps 3 and 4 above are accomplished, possibly after some modifications to
the makefile, by make using the attached makefile.
-------------------------------------
--USAGE--
To use this API, your program unit (PROGRAM/SUBROUTINE/FUNCTION/MODULE/etc.)
should look something like this:
program call_lammps
use LAMMPS
! Other modules, etc.
implicit none
type (lammps_instance) :: lmp ! This is a pointer to your LAMMPS instance
double precision :: fix
double precision, dimension(:), allocatable :: fix2
! Rest of declarations
call lammps_open_no_mpi ('lmp -in /dev/null -screen out.lammps',lmp)
! Set up rest of program here
call lammps_file (lmp, 'in.example')
call lammps_extract_fix (fix, lmp, '2', 0, 1, 1, 1)
call lammps_extract_fix (fix2, lmp, '4', 0, 2, 1, 1)
call lammps_close (lmp)
end program call_lammps
Important notes:
* All arguments which are char* variables in library.cpp are character (len=*)
variables here. For example,
call lammps_command (lmp, 'units metal')
will work as expected.
* The public functions (the only ones you can use) have interfaces as
described in the comments at the top of LAMMPS.F90. They are not always
the same as those in library.h, since C strings are replaced by Fortran
strings and the like.
* The module attempts to check whether you have done something stupid (such
as assign a 2D array to a scalar), but it's not perfect. For example, the
command
call lammps_extract_global (nlocal, ptr, 'nlocal')
will give nlocal correctly if nlocal is of type INTEGER, but it will give
the wrong answer if nlocal is of type REAL or DOUBLE PRECISION. This is a
feature of the (void*) type cast in library.cpp. There is no way I can
check this for you!
* You are allowed to use REAL or DOUBLE PRECISION floating-point numbers.
All LAMMPS data (which are of type REAL(C_double)) are rounded off if
placed in single precision variables. It is tacitly assumed that NO C++
variables are of type float; everything is int or double (since this is
all library.cpp currently handles).
* An example of a complete program is offered at the end of this file.
-------------------------------------
--TROUBLESHOOTING--
Compile-time errors probably indicate that your compiler is not new enough to
support Fortran 2003 features. For example, GCC 4.1.2 will not compile this
module, but GCC 4.4.0 will.
If your compiler balks at 'use, intrinsic :: ISO_C_binding,' try removing the
intrinsic part so it looks like an ordinary module. However, it is likely
that such a compiler will also have problems with everything else in the
file as well.
If you get a segfault as soon as the lammps_open call is made, check that you
compiled your program AND LAMMPS-header.cpp using the same MPI headers. Using
the stubs for one and the actual MPI library for the other will cause major
problems.
If you find run-time errors, please pass them along via the LAMMPS Users
mailing list. Please provide a minimal working example along with the names
and versions of the compilers you are using. Please make sure the error is
repeatable and is in MY code, not yours (generating a minimal working example
will usually ensure this anyway).
-------------------------------------
--IMPLEMENTATION NOTES--
The Fortran procedures have the same names as the C procedures, and
their purpose is the same, but they may take different arguments. Here are
some of the important differences:
* lammps_open and lammps_open_no_mpi take a string instead of argc and
argv. This is necessary because C and C++ have a very different way
of treating strings than Fortran.
* All C++ functions that accept char* pointers now accept Fortran-style
strings within this interface instead.
* All of the lammps_extract_[something] functions, which return void*
C-style pointers, have been replaced by generic subroutines that return
Fortran variables (which may be arrays). The first argument houses the
variable to be returned; all other arguments are identical except as
stipulated above. Note that it is not possible to declare generic
functions that are selected based solely on the type/kind/rank (TKR)
signature of the return value, only based on the TKR of the arguments.
* The SHAPE of the first argument to lammps_extract_[something] is checked
against the "shape" of the C array (e.g., double vs. double* vs. double**).
Calling a subroutine with arguments of inappropriate rank will result in an
error at run time.
* All arrays passed to subroutines must be ALLOCATABLE and are REALLOCATED
to fit the shape of the array LAMMPS will be returning.
* The indices i and j in lammps_extract_fix are used the same way they
are in f_ID[i][j] references in LAMMPS (i.e., starting from 1). This is
different than the way library.cpp uses these numbers, but is more
consistent with the way arrays are accessed in LAMMPS and in Fortran.
* The char* pointer normally returned by lammps_command is thrown away
in this version; note also that lammps_command is now a subroutine
instead of a function.
* The pointer to LAMMPS itself is of type(lammps_instance), which is itself
a synonym for type(C_ptr), part of ISO_C_BINDING. Type (C_ptr) is
C's void* data type. This should be the only C data type that needs to
be used by the end user.
* This module will almost certainly generate a compile-time warning,
such as,
subroutine lammps_open_wrapper (argc, argv, communicator, ptr) &
Variable 'communicator' at (1) is a parameter to the BIND(C)
procedure 'lammps_open_wrapper' but may not be C interoperable
This happens because lammps_open_wrapper actually takes a Fortran
INTEGER argument, whose type is defined by the MPI library itself. The
Fortran integer is converted to a C integer by the MPI library (if such
conversion is actually necessary).
* Unlike library.cpp, this module returns COPIES of the data LAMMPS actually
uses. This is done for safety reasons, as you should, in general, not be
overwriting LAMMPS data directly from Fortran. If you require this
functionality, it is possible to write another function that, for example,
returns a Fortran pointer that resolves to the C/C++ data instead of
copying the contents of that pointer to the original array as is done now.

View File

@ -0,0 +1,15 @@
units metal
lattice bcc 3.1656
region simbox block 0 10 0 10 0 10
create_box 2 simbox
create_atoms 1 region simbox
pair_style eam/fs
pair_coeff * * path/to/my_potential.eam.fs A1 A2
mass 1 58.2 # These are made-up numbers
mass 2 28.3
velocity all create 1200.0 7474848 dist gaussian
fix 1 all nve
fix 2 all dt/reset 1 1E-5 1E-3 0.01 units box
fix 4 all ave/histo 10 5 100 0.5 1.5 50 f_2 file temp.histo ave running
thermo_style custom step dt temp press etotal f_4[1][1]
thermo 100

View File

@ -0,0 +1,33 @@
SHELL = /bin/sh
# Path to LAMMPS extraction directory
LAMMPS_ROOT = ../svn-dist
LAMMPS_SRC = $(LAMMPS_ROOT)/src
# Remove the line below if using mpicxx/mpic++ as your C++ compiler
MPI_STUBS = $(LAMMPS_SRC)/STUBS
FC = gfortran # replace with your Fortran compiler
CXX = g++ # replace with your C++ compiler
# Flags for Fortran compiler, C++ compiler, and C preprocessor, respectively
FFLAGS = -O2
CXXFLAGS = -O2
CPPFLAGS =
all : liblammps_fortran.a
liblammps_fortran.a : LAMMPS.o LAMMPS-wrapper.o
$(AR) rs $@ $^
LAMMPS.o lammps.mod : LAMMPS.F90
$(FC) $(CPPFLAGS) $(FFLAGS) -c $<
LAMMPS-wrapper.o : LAMMPS-wrapper.cpp LAMMPS-wrapper.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -I$(LAMMPS_SRC) -I$(MPI_STUBS)
clean :
$(RM) *.o *.mod liblammps_fortran.a
dist :
tar -czf Fortran-interface.tar.gz LAMMPS-wrapper.h LAMMPS-wrapper.cpp LAMMPS.F90 makefile README

View File

@ -0,0 +1,44 @@
program simple
use LAMMPS
implicit none
type (lammps_instance) :: lmp
double precision :: compute, fix, fix2
double precision, dimension(:), allocatable :: compute_v, mass, r
double precision, dimension(:,:), allocatable :: x
real, dimension(:,:), allocatable :: x_r
call lammps_open_no_mpi ('',lmp)
call lammps_file (lmp, 'in.simple')
call lammps_command (lmp, 'run 500')
call lammps_extract_fix (fix, lmp, '2', 0, 1, 1, 1)
print *, 'Fix is ', fix
call lammps_extract_fix (fix2, lmp, '4', 0, 2, 1, 1)
print *, 'Fix 2 is ', fix2
call lammps_extract_compute (compute, lmp, 'thermo_temp', 0, 0)
print *, 'Compute is ', compute
call lammps_extract_compute (compute_v, lmp, 'thermo_temp', 0, 1)
print *, 'Vector is ', compute_v
call lammps_extract_atom (mass, lmp, 'mass')
print *, 'Mass is ', mass
call lammps_extract_atom (x, lmp, 'x')
if ( .not. allocated (x) ) print *, 'x is not allocated'
print *, 'x is ', x(1,:)
call lammps_extract_atom (x_r, lmp, 'x')
if ( .not. allocated (x_r) ) print *, 'x is not allocated'
print *, 'x_r is ', x_r(1,:)
call lammps_get_coords (lmp, r)
print *, 'r is ', r(1:3)
call lammps_close (lmp)
end program simple

View File

@ -35,7 +35,8 @@ gcc -L/home/sjplimp/lammps/src simple.o \
-llmp_g++ -lfftw -lmpich -lmpl -lpthread -lstdc++ -o simpleC -llmp_g++ -lfftw -lmpich -lmpl -lpthread -lstdc++ -o simpleC
This builds the Fortran wrapper and driver with the LAMMPS library This builds the Fortran wrapper and driver with the LAMMPS library
using a Fortran and C compiler: using a Fortran and C compiler, using the wrapper in the fortran
directory:
cp ../fortran/libfwrapper.c . cp ../fortran/libfwrapper.c .
gcc -I/home/sjplimp/lammps/src -c libfwrapper.c gcc -I/home/sjplimp/lammps/src -c libfwrapper.c