lammps/examples/COUPLE/fortran2a2f01ca5763emaster
README
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.