add new "official" fortran interface to LAMMPS in new folder "fortran"

This commit is contained in:
Axel Kohlmeyer 2020-08-28 20:56:15 -04:00
parent 2e1b4498bd
commit 3e92647abb
No known key found for this signature in database
GPG Key ID: D9B44E93BF0C375A
2 changed files with 292 additions and 0 deletions

11
fortran/README Normal file
View File

@ -0,0 +1,11 @@
This directory contains Fortran code which interface LAMMPS as a library
and allows the LAMMPS library interface to be invoked from Fortran codes.
It requires a Fortran compiler that supports the Fortran 2003 standard.
This interface is based on and supersedes the previous Fortran interfaces
in the examples/COUPLE/fortran* folders. But is fully supported by the
LAMMPS developers and included in the documentation and unit testing.
Details on this Fortran interface and how to build programs using it
are in the manual in the doc/html/pg_fortran.html file.

281
fortran/lammps.f90 Normal file
View File

@ -0,0 +1,281 @@
! -------------------------------------------------------------------------
! LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
! http://lammps.sandia.gov, Sandia National Laboratories
! Steve Plimpton, sjplimp@sandia.gov
!
! 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.
! -------------------------------------------------------------------------
!
! Fortran interface to the LAMMPS library implemented as a Fortran 2003
! style module that wraps the C-style library interface in library.cpp
! and library.h using the ISO_C_BINDING module of the Fortran compiler.
!
! Based on the LAMMPS Fortran 2003 module contributed by:
! Karl D. Hammond <karlh@ugcs.caltech.edu>
! University of Tennessee, Knoxville (USA), 2012
!
! The Fortran module tries to follow the API of the C-library interface
! closely, but like the Python wrapper it employs an object oriented
! approach. To accommodate the object oriented approach, all exported
! subroutine and functions have to be implemented in Fortran to then
! call the interfaced C style functions with adapted calling conventions
! as needed. The C-library interfaced functions retain their names
! starting with "lammps_" while the Fortran versions start with "lmp_".
!
MODULE LIBLAMMPS
USE, INTRINSIC :: ISO_C_BINDING, ONLY: c_ptr, c_null_ptr, c_loc, &
c_int, c_char, c_null_char, c_double
IMPLICIT NONE
PRIVATE
PUBLIC :: lammps
TYPE lammps
TYPE(c_ptr) :: handle
CONTAINS
PROCEDURE :: close => lmp_close
PROCEDURE :: file => lmp_file
PROCEDURE :: command => lmp_command
PROCEDURE :: commands_list => lmp_commands_list
PROCEDURE :: commands_string => lmp_commands_string
PROCEDURE :: version => lmp_version
PROCEDURE :: get_natoms => lmp_get_natoms
END TYPE lammps
INTERFACE lammps
MODULE PROCEDURE lmp_open
END INTERFACE lammps
! interface definitions for calling functions in library.cpp
INTERFACE
FUNCTION lammps_open(argc,argv,comm,handle) &
BIND(C, name='lammps_open_fortran')
IMPORT :: c_ptr, c_int
INTEGER(c_int), VALUE, INTENT(in) :: argc, comm
TYPE(c_ptr), DIMENSION(*), INTENT(in) :: argv
TYPE(c_ptr), INTENT(out) :: handle
TYPE(c_ptr) :: lammps_open
END FUNCTION lammps_open
FUNCTION lammps_open_no_mpi(argc,argv,handle) &
BIND(C, name='lammps_open_no_mpi')
IMPORT :: c_ptr, c_int
INTEGER(c_int), VALUE, INTENT(in) :: argc
TYPE(c_ptr), DIMENSION(*), INTENT(in) :: argv
TYPE(c_ptr), INTENT(out) :: handle
TYPE(c_ptr) :: lammps_open_no_mpi
END FUNCTION lammps_open_no_mpi
SUBROUTINE lammps_close(handle) BIND(C, name='lammps_close')
IMPORT :: c_ptr
TYPE(c_ptr), VALUE :: handle
END SUBROUTINE lammps_close
SUBROUTINE lammps_mpi_init(handle) BIND(C, name='lammps_mpi_init')
IMPORT :: c_ptr
TYPE(c_ptr), VALUE :: handle
END SUBROUTINE lammps_mpi_init
SUBROUTINE lammps_mpi_finalize(handle) &
BIND(C, name='lammps_mpi_finalize')
IMPORT :: c_ptr
TYPE(c_ptr), VALUE :: handle
END SUBROUTINE lammps_mpi_finalize
SUBROUTINE lammps_file(handle,filename) BIND(C, name='lammps_file')
IMPORT :: c_ptr
TYPE(c_ptr), VALUE :: handle
TYPE(c_ptr), VALUE :: filename
END SUBROUTINE lammps_file
SUBROUTINE lammps_command(handle,cmd) BIND(C, name='lammps_command')
IMPORT :: c_ptr
TYPE(c_ptr), VALUE :: handle
TYPE(c_ptr), VALUE :: cmd
END SUBROUTINE lammps_command
SUBROUTINE lammps_commands_list(handle,ncmd,cmds) &
BIND(C, name='lammps_commands_list')
IMPORT :: c_ptr, c_int
TYPE(c_ptr), VALUE :: handle
INTEGER(c_int), VALUE, INTENT(in) :: ncmd
TYPE(c_ptr), DIMENSION(*), INTENT(in) :: cmds
END SUBROUTINE lammps_commands_list
SUBROUTINE lammps_commands_string(handle,str) &
BIND(C, name='lammps_commands_string')
IMPORT :: c_ptr
TYPE(c_ptr), VALUE :: handle
TYPE(c_ptr), VALUE :: str
END SUBROUTINE lammps_commands_string
SUBROUTINE lammps_free(ptr) BIND(C, name='lammps_free')
IMPORT :: c_ptr
TYPE(c_ptr), VALUE :: ptr
END SUBROUTINE lammps_free
FUNCTION lammps_version(handle) BIND(C, name='lammps_version')
IMPORT :: c_ptr, c_int
TYPE(c_ptr), VALUE :: handle
INTEGER(c_int) :: lammps_version
END FUNCTION lammps_version
FUNCTION lammps_get_natoms(handle) BIND(C, name='lammps_get_natoms')
IMPORT :: c_ptr, c_double
TYPE(c_ptr), VALUE :: handle
REAL(c_double) :: lammps_get_natoms
END FUNCTION lammps_get_natoms
END INTERFACE
CONTAINS
! Fortran wrappers and helper functions.
! Constructor for the LAMMPS class.
! Combined wrapper around lammps_open_fortran() and lammps_open_no_mpi()
TYPE(lammps) FUNCTION lmp_open(args,comm)
IMPLICIT NONE
INTEGER,INTENT(in), OPTIONAL :: comm
CHARACTER(len=*), INTENT(in), OPTIONAL :: args(:)
TYPE(c_ptr), ALLOCATABLE :: argv(:)
TYPE(c_ptr) :: dummy=c_null_ptr
INTEGER :: i,argc
IF (PRESENT(args)) THEN
! convert argument list to c style
argc = SIZE(args)
ALLOCATE(argv(argc))
DO i=1,argc
argv(i) = f2c_string(args(i))
END DO
ELSE
argc = 1
ALLOCATE(argv(1))
argv(1) = f2c_string("liblammps")
ENDIF
IF (PRESENT(comm)) THEN
lmp_open%handle = lammps_open(argc,argv,comm,dummy)
ELSE
lmp_open%handle = lammps_open_no_mpi(argc,argv,dummy)
END IF
! Clean up allocated memory
DO i=1,argc
CALL lammps_free(argv(i))
END DO
DEALLOCATE(argv)
END FUNCTION lmp_open
! Combined Fortran wrapper around lammps_close() and lammps_mpi_finalize()
SUBROUTINE lmp_close(self,finalize)
IMPLICIT NONE
CLASS(lammps) :: self
LOGICAL,INTENT(in),OPTIONAL :: finalize
CALL lammps_close(self%handle)
IF (PRESENT(finalize)) THEN
IF (finalize) THEN
CALL lammps_mpi_finalize(self%handle)
END IF
END IF
END SUBROUTINE lmp_close
INTEGER FUNCTION lmp_version(self)
IMPLICIT NONE
CLASS(lammps) :: self
lmp_version = lammps_version(self%handle)
END FUNCTION lmp_version
DOUBLE PRECISION FUNCTION lmp_get_natoms(self)
IMPLICIT NONE
CLASS(lammps) :: self
lmp_get_natoms = lammps_get_natoms(self%handle)
END FUNCTION lmp_get_natoms
SUBROUTINE lmp_file(self,filename)
IMPLICIT NONE
CLASS(lammps) :: self
CHARACTER(len=*) :: filename
TYPE(c_ptr) :: str
str = f2c_string(filename)
CALL lammps_file(self%handle,str)
CALL lammps_free(str)
END SUBROUTINE lmp_file
! equivalent function to lammps_command()
SUBROUTINE lmp_command(self,cmd)
IMPLICIT NONE
CLASS(lammps) :: self
CHARACTER(len=*) :: cmd
TYPE(c_ptr) :: str
str = f2c_string(cmd)
CALL lammps_command(self%handle,str)
CALL lammps_free(str)
END SUBROUTINE lmp_command
! equivalent function to lammps_commands_list()
SUBROUTINE lmp_commands_list(self,cmds)
IMPLICIT NONE
CLASS(lammps) :: self
CHARACTER(len=*), INTENT(in), OPTIONAL :: cmds(:)
TYPE(c_ptr), ALLOCATABLE :: cmdv(:)
INTEGER :: i,ncmd
! convert command list to c style
ncmd = SIZE(cmds)
ALLOCATE(cmdv(ncmd))
DO i=1,ncmd
cmdv(i) = f2c_string(cmds(i))
END DO
CALL lammps_commands_list(self%handle,ncmd,cmdv)
! Clean up allocated memory
DO i=1,ncmd
CALL lammps_free(cmdv(i))
END DO
DEALLOCATE(cmdv)
END SUBROUTINE lmp_commands_list
! equivalent function to lammps_commands_string()
SUBROUTINE lmp_commands_string(self,str)
IMPLICIT NONE
CLASS(lammps) :: self
CHARACTER(len=*) :: str
TYPE(c_ptr) :: tmp
tmp = f2c_string(str)
CALL lammps_commands_string(self%handle,tmp)
CALL lammps_free(tmp)
END SUBROUTINE lmp_commands_string
! ----------------------------------------------------------------------
! local helper functions
! copy fortran string to zero terminated c string
FUNCTION f2c_string(f_string) RESULT(ptr)
CHARACTER (len=*), INTENT(in) :: f_string
CHARACTER (len=1, kind=c_char), POINTER :: c_string(:)
TYPE(c_ptr) :: ptr
INTEGER :: i, n
n = LEN_TRIM(f_string)
ALLOCATE(c_string(n+1))
DO i=1,n
c_string(i) = f_string(i:i)
END DO
c_string(n+1) = c_null_char
ptr = c_loc(c_string(1))
END FUNCTION f2c_string
END MODULE LIBLAMMPS