forked from lijiext/lammps
266 lines
13 KiB
Plaintext
266 lines
13 KiB
Plaintext
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. See --USE-- for notes on how this interface differs from the
|
|
C interface (and the Python interface).
|
|
|
|
This interface was created by Karl Hammond who you can contact with
|
|
questions:
|
|
|
|
Karl D. Hammond
|
|
University of Tennessee, Knoxville
|
|
karlh at ugcs.caltech.edu
|
|
karlh at utk.edu
|
|
|
|
-------------------------------------
|
|
|
|
--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).
|
|
|
|
Steps 3-5 are accomplished, possibly after some modifications to
|
|
the makefile, by make using the attached makefile. Said makefile also builds
|
|
the dynamically-linkable library (liblammps_fortran.so).
|
|
|
|
** STATIC LIBRARY INSTRUCTIONS **
|
|
(1) Compile LAMMPS as a static library.
|
|
Call the resulting file ${LAMMPS_LIB}, which will have an actual name
|
|
like liblmp_openmpi.a. If compiling using the MPI stubs in
|
|
${LAMMPS_SRC}/STUBS, you will need to know where libmpi_stubs.a
|
|
is as well (I'll call it ${MPI_STUBS} hereafter)
|
|
(2) Copy said library to your Fortran program's source directory or replace
|
|
${LAMMPS_LIB} with its full path in the instructions below.
|
|
(3) Compile (but don't link!) LAMMPS.F90. Example:
|
|
mpif90 -c LAMMPS.f90
|
|
OR
|
|
gfortran -c LAMMPS.F90
|
|
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
|
|
(5) OPTIONAL: Make a library from the object files 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" later. 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).
|
|
(6) Compile (but don't link) 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, like so:
|
|
mpif90 -I${LAMMPS_SRC}/examples/COUPLE/fortran2 -c myfreeformatfile.f90
|
|
|
|
(7) 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} -lmpi_cxx -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 -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.
|
|
|
|
** DYNAMIC LIBRARY INSTRUCTIONS **
|
|
(1) Compile LAMMPS as a dynamic library
|
|
(make makeshlib && make -f Makefile.shlib [targetname]).
|
|
(2) Compile, but don't link, LAMMPS.F90 using the -fPIC flag, such as
|
|
mpif90 -fPIC -c LAMMPS.f90
|
|
(3) Compile, but don't link, LAMMPS-wrapper.cpp in the same manner, e.g.
|
|
mpicxx -fPIC -c LAMMPS-wrapper.cpp
|
|
(4) Make the dynamic library, like so:
|
|
mpif90 -fPIC -shared -o liblammps_fortran.so LAMMPS.o LAMMPS-wrapper.o
|
|
(5) Compile your program, such as,
|
|
mpif90 -I${LAMMPS_SRC}/examples/COUPLE/fortran2 -c myfreeformatfile.f90
|
|
where ${LAMMPS_SRC}/examples/COUPLE/fortran2 contains the .mod file from
|
|
step (3)
|
|
(6) Link everything together, such as
|
|
mpif90 ${my_object_files} -L${LAMMPS_SRC} \
|
|
-L${LAMMPS_SRC}/examples/COUPLE/fortran2 -llammps_fortran \
|
|
-llammps_openmpi -lmpi_cxx -lstdc++ -lm
|
|
|
|
If you wish to avoid the -L flags, add the directories containing your
|
|
shared libraries to the LIBRARY_PATH environment variable. At run time, you
|
|
will have to add these directories to LD_LIBRARY_PATH as well; otherwise,
|
|
your executable will not find the libraries it needs.
|
|
|
|
-------------------------------------
|
|
|
|
--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
|
|
real (C_double) :: fix
|
|
real (C_double), dimension(:), pointer :: 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:
|
|
* Though I dislike the use of pointers, they are necessary when communicating
|
|
with C and C++, which do not support Fortran's ALLOCATABLE attribute.
|
|
* There is no need to deallocate C-allocated memory; this is done for you in
|
|
the cases when it is done (which are all cases when pointers are not
|
|
accepted, such as global fix data)
|
|
* 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 a pointer to type INTEGER, but it
|
|
will give the wrong answer if nlocal is a pointer to type REAL. This is a
|
|
feature of the (void*) type cast in library.cpp. There is no way I can
|
|
check this for you! It WILL catch you if you pass it an allocatable or
|
|
fixed-size array when it expects a pointer.
|
|
* Arrays constructed from temporary data from LAMMPS are ALLOCATABLE, and
|
|
represent COPIES of data, not the originals. Functions like
|
|
lammps_extract_atom, which return actual LAMMPS data, are pointers.
|
|
* IMPORTANT: Due to the differences between C and Fortran arrays (C uses
|
|
row-major vectors, Fortran uses column-major vectors), all arrays returned
|
|
from LAMMPS have their indices swapped.
|
|
* An example of a complete program, simple.f90, is included with this
|
|
package.
|
|
|
|
-------------------------------------
|
|
|
|
--TROUBLESHOOTING--
|
|
|
|
Compile-time errors (when compiling LAMMPS.F90, that is) 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-wrapper.cpp using the same MPI headers. Using
|
|
the stubs for one and the actual MPI library for the other will cause Bad
|
|
Things to happen.
|
|
|
|
If you find run-time errors, please pass them along via the LAMMPS Users
|
|
mailing list (please CC me as well; address above). 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. If you want the command line to be
|
|
passed to lammps_open (as it often would be from C/C++), use the
|
|
GET_COMMAND intrinsic to obtain it.
|
|
* 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/pointer to be returned (pretend it's on the left-hand side); 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.
|
|
* 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 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).
|
|
* lammps_extract_global returns COPIES of the (scalar) data, as does the
|
|
C version.
|
|
* lammps_extract_atom, lammps_extract_compute, and lammps_extract_fix
|
|
have a first argument that will be associated with ACTUAL LAMMPS DATA.
|
|
This means the first argument must be:
|
|
* The right rank (via the DIMENSION modifier)
|
|
* A C-interoperable POINTER type (i.e., INTEGER (C_int) or
|
|
REAL (C_double)).
|
|
* lammps_extract_variable returns COPIES of the data, as the C library
|
|
interface does. There is no need to deallocate using lammps_free.
|
|
* The 'data' argument to lammps_gather_atoms and lammps_scatter atoms must
|
|
be ALLOCATABLE. It should be of type INTEGER or DOUBLE PRECISION. It
|
|
does NOT need to be C inter-operable (and indeed should not be).
|
|
* The 'count' argument of lammps_scatter_atoms is unnecessary; the shape of
|
|
the array determines the number of elements LAMMPS will read.
|