lammps/examples/COUPLE/fortran2
sjplimp b4a109bfe8 git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@9908 f3b2605a-c512-4ea7-a41b-209d697bcdaa 2013-05-24 14:11:43 +00:00
..
LAMMPS-wrapper.cpp git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@8669 f3b2605a-c512-4ea7-a41b-209d697bcdaa 2012-08-15 14:18:34 +00:00
LAMMPS-wrapper.h git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@8669 f3b2605a-c512-4ea7-a41b-209d697bcdaa 2012-08-15 14:18:34 +00:00
LAMMPS.F90 git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@9908 f3b2605a-c512-4ea7-a41b-209d697bcdaa 2013-05-24 14:11:43 +00:00
README git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@9003 f3b2605a-c512-4ea7-a41b-209d697bcdaa 2012-10-25 15:42:25 +00:00
in.simple git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@9003 f3b2605a-c512-4ea7-a41b-209d697bcdaa 2012-10-25 15:42:25 +00:00
makefile git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@8768 f3b2605a-c512-4ea7-a41b-209d697bcdaa 2012-09-11 14:27:02 +00:00
simple.f90 git-svn-id: svn://svn.icms.temple.edu/lammps-ro/trunk@9003 f3b2605a-c512-4ea7-a41b-209d697bcdaa 2012-10-25 15:42:25 +00:00

README

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.