Work in progress for extract_global; committing but will probably undo later
This commit is contained in:
@ -80,7 +80,7 @@ the optional logical argument set to ``.true.``. Here is a simple example:
|
||||
END PROGRAM testlib
|
||||
|
||||
It is also possible to pass command line flags from Fortran to C/C++ and
|
||||
thus make the resulting executable behave similar to the standalone
|
||||
thus make the resulting executable behave similarly to the standalone
|
||||
executable (it will ignore the `-in/-i` flag, though). This allows to
|
||||
use the command line to configure accelerator and suffix settings,
|
||||
configure screen and logfile output, or to set index style variables
|
||||
@ -190,6 +190,7 @@ of the contents of the ``LIBLAMMPS`` Fortran interface to LAMMPS.
|
||||
:f reset_box: :f:func:`reset_box`
|
||||
:f memory_usage: :f:func:`memory_usage`
|
||||
:f extract_setting: :f:func:`extract_setting`
|
||||
:f extract_global: :f:func:`extract_global`
|
||||
|
||||
--------
|
||||
|
||||
@ -210,7 +211,57 @@ of the contents of the ``LIBLAMMPS`` Fortran interface to LAMMPS.
|
||||
:o integer comm [optional]: MPI communicator
|
||||
:r lammps: an instance of the :f:type:`lammps` derived type
|
||||
|
||||
--------
|
||||
.. note::
|
||||
|
||||
The ``MPI_F08`` module, which defines Fortran 2008 bindings for MPI,
|
||||
is not directly supported by this interface due to the complexities of
|
||||
supporting both the ``MPI_F08`` and ``MPI`` modules at the same time.
|
||||
However, you should be able to use the ``MPI_VAL`` member of the
|
||||
``MPI_comm`` derived type to access the integer value of the
|
||||
communicator, such as in
|
||||
|
||||
.. code-block:: Fortran
|
||||
|
||||
PROGRAM testmpi
|
||||
USE LIBLAMMPS
|
||||
USE MPI_F08
|
||||
TYPE(lammps) :: lmp
|
||||
lmp = lammps(MPI_COMM_SELF%MPI_VAL)
|
||||
END PROGRAM testmpi
|
||||
|
||||
Constants Defined by the API
|
||||
============================
|
||||
|
||||
The following constants are declared by the Fortran API to resolve the
|
||||
type/kind/rank signature for return values. These serve the same role as
|
||||
``LAMMPS_INT``, ``LAMMPS_DOUBLE``, and similar constants in ``src/library.h``
|
||||
and those in ``python/lammps/constants.py`` for the C and Python APIs,
|
||||
respectively. Unlike their C and Python bretheren, however, it is the type
|
||||
(e.g., ``INTEGER``), kind (e.g., ``C_int``), and rank (e.g., ``DIMENSION(:)``)
|
||||
of these constants that is used by the calling routine, rather than their
|
||||
numerical values.
|
||||
|
||||
:f:LMP_INT: 32-bit integer scalars
|
||||
:f:LMP_INT_1D: 32-bit integer vectors
|
||||
:f:LMP_INT_2D: 32-bit integer matrices
|
||||
:f:LMP_DOUBLE: 64-bit real scalars
|
||||
:f:LMP_DOUBLE_1D: 64-bit real vectors
|
||||
:f:LMP_DOUBLE_2D: 64-bit real matrices
|
||||
:f:LMP_INT64: 64-bit integer scalars
|
||||
:f:LMP_INT64_1D: 64-bit integer vectors
|
||||
:f:LMP_INT64_2D: 64-bit integer matrices
|
||||
|
||||
.. admonition:: Interaction with LAMMPS_BIGBIG and such
|
||||
|
||||
LAMMPS uses different-sized integers to store various entities, such as
|
||||
the number of timesteps or the total number of atoms, depending on certain
|
||||
compiler flags (see the :doc:`size limits <Build_settings_size>`
|
||||
documentation). This API is currently agnostic to these settings, and it
|
||||
is up to the user to know the size of LAMMPS_BIGINT and such and pass
|
||||
LMP_INT or LMP_INT64, as appropriate, for such entities.
|
||||
|
||||
Procedures Bound to the lammps Derived Type
|
||||
===========================================
|
||||
|
||||
.. f:subroutine:: close([finalize])
|
||||
|
||||
@ -278,6 +329,9 @@ of the contents of the ``LIBLAMMPS`` Fortran interface to LAMMPS.
|
||||
|
||||
.. f:function:: get_thermo(name)
|
||||
|
||||
This function will call :cpp:func:`lammps_get_thermo` and return the value
|
||||
of the corresponding thermodynamic keyword.
|
||||
|
||||
:p character(len=*) name: string with the name of the thermo keyword
|
||||
:r real(C_double): value of the requested thermo property or 0.0_C_double
|
||||
|
||||
@ -285,6 +339,11 @@ of the contents of the ``LIBLAMMPS`` Fortran interface to LAMMPS.
|
||||
|
||||
.. f:subroutine:: extract_box(boxlo, boxhi, xy, yz, xz, pflags, boxflag)
|
||||
|
||||
This subroutine will call :cpp:func:`lammps_extract_box`. All parameters
|
||||
are optional, though obviously at least one should be present. The
|
||||
parameters *pflags* and *boxflag* are stored in LAMMPS as integers, but
|
||||
should be declared as ``LOGICAL`` variables when calling from Fortran.
|
||||
|
||||
:p real(c_double) boxlo [dimension(3),optional]: vector in which to store
|
||||
lower-bounds of simulation box
|
||||
:p real(c_double) boxhi [dimension(3),optional]: vector in which to store
|
||||
@ -302,6 +361,9 @@ of the contents of the ``LIBLAMMPS`` Fortran interface to LAMMPS.
|
||||
|
||||
.. f:subroutine:: reset_box(boxlo, boxhi, xy, yz, xz)
|
||||
|
||||
This subroutine will call :cpp:func:`lammps_reset_box`. All parameters
|
||||
are required.
|
||||
|
||||
:p real(c_double) boxlo [dimension(3)]: vector of three doubles containing
|
||||
the lower box boundary
|
||||
:p real(c_double) boxhi [dimension(3)]: vector of three doubles containing
|
||||
@ -314,6 +376,9 @@ of the contents of the ``LIBLAMMPS`` Fortran interface to LAMMPS.
|
||||
|
||||
.. f:subroutine:: memory_usage(meminfo)
|
||||
|
||||
This subroutine will call :cpp:func:`lammps_memory_usage` and store the
|
||||
result in the three-element array *meminfo*.
|
||||
|
||||
:p real(c_double) meminfo [dimension(3)]: vector of three doubles in which
|
||||
to store memory usage data
|
||||
|
||||
@ -321,15 +386,25 @@ of the contents of the ``LIBLAMMPS`` Fortran interface to LAMMPS.
|
||||
|
||||
.. f:function:: get_mpi_comm()
|
||||
|
||||
This function returns a Fortran representation of the LAMMPS "world"
|
||||
communicator.
|
||||
|
||||
:r integer: Fortran integer equivalent to the MPI communicator LAMMPS is
|
||||
using
|
||||
|
||||
.. note::
|
||||
.. note::
|
||||
|
||||
The MPI_F08 module, which is in compliance with the Fortran 2008 standard,
|
||||
is not directly supported by this function. However, you should be able to
|
||||
convert between the two using the MPI_VAL member of the communicator. For
|
||||
example,
|
||||
The C library interface currently returns type "int" instead of type
|
||||
"MPI_Fint", which is the C type correspending to Fortran "INTEGER"
|
||||
types of the default kind. On most compilers, these are the same anyway,
|
||||
but this interface exchanges values this way to avoid warning messages.
|
||||
|
||||
.. note::
|
||||
|
||||
The MPI_F08 module, which defines Fortran 2008 bindings for MPI, is not
|
||||
directly supported by this function. However, you should be able to
|
||||
convert between the two using the MPI_VAL member of the communicator.
|
||||
For example,
|
||||
|
||||
.. code-block:: fortran
|
||||
|
||||
@ -346,5 +421,57 @@ of the contents of the ``LIBLAMMPS`` Fortran interface to LAMMPS.
|
||||
|
||||
.. f:function:: extract_setting(keyword)
|
||||
|
||||
Query LAMMPS about global settings. See the documentation for the
|
||||
:c:func:`lammps_extract_setting` function from the C library.
|
||||
|
||||
:p character(len=*) keyword: string containing the name of the thermo keyword
|
||||
:r integer(c_int): value of the queried setting or :math:`-1` if unknown
|
||||
|
||||
--------
|
||||
|
||||
.. f:function:: extract_global(name, dtype)
|
||||
|
||||
Overloaded function to get internal global LAMMPS data. Note that all
|
||||
currently implemented global types only return scalars or strings; all
|
||||
array-returning entities currently supported use :f:func:`extract_box`.
|
||||
|
||||
Note that type/kind/rank of the *dtype* argument is used to determine
|
||||
whether to return a type correspending to a C int, a C int64_t, or a
|
||||
C double. The type/kind/rank signature of dtype is checked at runtime to
|
||||
match that of the return value; this type of check cannot be performed at
|
||||
compile time. For example,
|
||||
|
||||
.. code-block:: fortran
|
||||
|
||||
PROGRAM demo
|
||||
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_int64_t
|
||||
USE LIBLAMMPS
|
||||
TYPE(lammps) :: lmp
|
||||
INTEGER(C_int) :: nlocal
|
||||
INTEGER(C_int64_t) :: ntimestep
|
||||
CHARACTER(LEN=10) :: units
|
||||
REAL(C_double) :: dt
|
||||
lmp = lammps()
|
||||
! other commands
|
||||
nlocal = lmp%extract_global('nlocal', LMP_INT)
|
||||
ntimestep = lmp%extract_global('ntimestep', LMP_INT64)
|
||||
dt = lmp%extract_global('dt', LMP_DOUBLE)
|
||||
units = lmp%extract_global('units', LMP_STRING)
|
||||
! more commands
|
||||
lmp.close(.TRUE.)
|
||||
END PROGRAM demo
|
||||
|
||||
would extract the number of atoms on this processor, the current time step,
|
||||
the size of the current time step, and the units being used into the
|
||||
variables *nlocal*, *ntimestep*, *dt*, and *units*, respectively.
|
||||
|
||||
*Note*: if this function returns a string, the string must have
|
||||
length greater than or equal to the length of the string (not including the
|
||||
terminal NULL character) that LAMMPS returns. If the variable's length is
|
||||
too short, the string will be truncated. As usual in Fortran, strings
|
||||
are padded with spaces at the end.
|
||||
|
||||
:p character(len=*) name: string with the name of the extracted property
|
||||
:p polymorphic dtype: one of *LMP_INT*, *LMP_INT64*, *LMP_DOUBLE*, or
|
||||
*LMP_STRING* designating the type/kind/rank of the return value
|
||||
:r polymorphic: value of the extracted property
|
||||
|
||||
@ -38,10 +38,10 @@ MODULE LIBLAMMPS
|
||||
|
||||
! These are public-interface constants that have the same purpose as the
|
||||
! constants in library.h, except that their types match the type of the
|
||||
! constant in question. Their purpose is to determine the type of the
|
||||
! constant in question. Their purpose is to specify the type of the
|
||||
! return value without something akin to a C/C++ type cast
|
||||
INTEGER (c_int), PUBLIC, PARAMETER :: LMP_INT = 0_c_int
|
||||
INTEGER (c_int), PUBLIC, DIMENSION(3), PARAMETER :: LMP_INT_1D = 1_c_int
|
||||
INTEGER (c_int), PUBLIC, DIMENSION(3), PARAMETER :: LMP_INT_1D = 0_c_int
|
||||
INTEGER (c_int), PUBLIC, DIMENSION(3,3), PARAMETER :: LMP_INT_2D = 1_c_int
|
||||
REAL (c_double), PUBLIC, PARAMETER :: LMP_DOUBLE = 2.0_c_double
|
||||
REAL (c_double), PUBLIC, DIMENSION(3), PARAMETER :: &
|
||||
@ -59,6 +59,8 @@ MODULE LIBLAMMPS
|
||||
!
|
||||
! Must be kept in sync with the equivalent declarations in
|
||||
! src/library.h and python/lammps/constants.py
|
||||
!
|
||||
! NOT part of the API (the part the user sees)
|
||||
INTEGER (c_int), PARAMETER :: &
|
||||
LAMMPS_INT = 0_c_int, & ! 32-bit integer (array)
|
||||
LAMMPS_INT_2D = 1, & ! two-dimensional 32-bit integer array
|
||||
@ -84,8 +86,12 @@ MODULE LIBLAMMPS
|
||||
PROCEDURE :: get_mpi_comm => lmp_get_mpi_comm
|
||||
PROCEDURE :: extract_setting => lmp_extract_setting
|
||||
PROCEDURE, PRIVATE :: lmp_extract_global_int
|
||||
GENERIC :: extract_global => lmp_extract_global_int ! TODO
|
||||
|
||||
PROCEDURE, PRIVATE :: lmp_extract_global_int64_t
|
||||
PROCEDURE, PRIVATE :: lmp_extract_global_double
|
||||
PROCEDURE, PRIVATE :: lmp_extract_global_str
|
||||
GENERIC :: extract_global => lmp_extract_global_int, &
|
||||
lmp_extract_global_int64_t, lmp_extract_global_double, &
|
||||
lmp_extract_global_str
|
||||
PROCEDURE :: version => lmp_version
|
||||
END TYPE lammps
|
||||
|
||||
@ -207,6 +213,13 @@ MODULE LIBLAMMPS
|
||||
INTEGER (c_int) :: lammps_extract_global_datatype
|
||||
END FUNCTION lammps_extract_global_datatype
|
||||
|
||||
FUNCTION c_strlen (str) bind(C,name='strlen')
|
||||
IMPORT :: c_ptr, c_size_t
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr) :: str
|
||||
INTEGER(c_size_t) :: c_strlen
|
||||
END FUNCTION c_strlen
|
||||
|
||||
FUNCTION lammps_extract_global(handle, name) BIND(C)
|
||||
IMPORT :: c_ptr
|
||||
TYPE(c_ptr), VALUE :: handle, name
|
||||
@ -530,49 +543,94 @@ CONTAINS
|
||||
! END FUNCTION lmp_extract_global_datatype
|
||||
|
||||
! equivalent functions to lammps_extract_global (overloaded)
|
||||
! This implementation assumes there are no non-scalar data that can be
|
||||
! extracted through lammps_extract_global
|
||||
FUNCTION lmp_extract_global_int (self, name, dtype)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
CHARACTER(LEN=*), INTENT(IN) :: name
|
||||
INTEGER(c_int) :: dtype
|
||||
INTEGER(c_int), INTENT(IN) :: dtype
|
||||
INTEGER(c_int) :: lmp_extract_global_int
|
||||
TYPE(c_ptr) :: Cname, Cptr
|
||||
INTEGER(c_int) :: datatype
|
||||
INTEGER(c_int), POINTER :: ptr
|
||||
|
||||
Cname = f2c_string(name)
|
||||
datatype = lammps_extract_global_datatype(Cname)
|
||||
datatype = lammps_extract_global_datatype(c_null_ptr, Cname)
|
||||
IF ( datatype /= LAMMPS_INT ) THEN
|
||||
! throw an exception or something; data type doesn't match!
|
||||
WRITE(0,*) 'WARNING: global data type is inconsistent'
|
||||
WRITE(0,*) 'WARNING: global data type is inconsistent (not an int)'
|
||||
END IF
|
||||
Cptr = lammps_extract_global(self%handle, Cname)
|
||||
CALL c_f_pointer(Cptr, ptr)
|
||||
lmp_extract_global_int = ptr
|
||||
CALL lammps_free(Cname)
|
||||
END FUNCTION lmp_extract_global_int
|
||||
FUNCTION lmp_extract_global_int_1d (self, name, dtype)
|
||||
! This implementation assumes there are three elements to all arrays
|
||||
FUNCTION lmp_extract_global_int64_t (self, name, dtype)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
CHARACTER(LEN=*), INTENT(IN) :: name
|
||||
INTEGER(c_int), DIMENSION(3) :: dtype
|
||||
INTEGER(c_int) :: lmp_extract_global_int
|
||||
INTEGER(c_int64_t), INTENT(IN) :: dtype
|
||||
INTEGER(c_int64_t) :: lmp_extract_global_int64_t
|
||||
TYPE(c_ptr) :: Cname, Cptr
|
||||
INTEGER(c_int) :: datatype
|
||||
INTEGER(c_int), DIMENSION(3), POINTER :: ptr
|
||||
INTEGER(c_int64_t), POINTER :: ptr
|
||||
|
||||
Cname = f2c_string(name)
|
||||
datatype = lammps_extract_global_datatype(Cname)
|
||||
IF ( datatype /= LAMMPS_INT ) THEN
|
||||
datatype = lammps_extract_global_datatype(c_null_ptr, Cname)
|
||||
IF ( datatype /= LAMMPS_INT64 ) THEN
|
||||
! throw an exception or something; data type doesn't match!
|
||||
WRITE(0,*) 'WARNING: global data type is inconsistent (not an int64_t)'
|
||||
END IF
|
||||
Cptr = lammps_extract_global(self%handle, Cname)
|
||||
CALL c_f_pointer(Cptr, ptr, shape(dtype))
|
||||
lmp_extract_global_int = ptr
|
||||
CALL c_f_pointer(Cptr, ptr)
|
||||
lmp_extract_global_int64_t = ptr
|
||||
CALL lammps_free(Cname)
|
||||
END FUNCTION lmp_extract_global_int_1d
|
||||
! TODO need more generics here to match TKR of LMP_INT_1D, LMP_BIGINT,
|
||||
! LMP_DOUBLE, LMP_DOUBLE_1D, LMS_STRING [this assumes no one adds anything
|
||||
! requiring LMP_DOUBLE_2D and the like!]
|
||||
END FUNCTION lmp_extract_global_int64_t
|
||||
FUNCTION lmp_extract_global_double (self, name, dtype)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
CHARACTER(LEN=*), INTENT(IN) :: name
|
||||
REAL(c_double), INTENT(IN) :: dtype
|
||||
REAL(c_double) :: lmp_extract_global_double
|
||||
TYPE(c_ptr) :: Cname, Cptr
|
||||
INTEGER(c_int) :: datatype
|
||||
REAL(c_double), POINTER :: ptr
|
||||
|
||||
Cname = f2c_string(name)
|
||||
datatype = lammps_extract_global_datatype(c_null_ptr, Cname)
|
||||
IF ( datatype /= LAMMPS_DOUBLE ) THEN
|
||||
! throw an exception or something; data type doesn't match!
|
||||
WRITE(0,*) 'WARNING: global data type is inconsistent (not a double)'
|
||||
END IF
|
||||
Cptr = lammps_extract_global(self%handle, Cname)
|
||||
CALL c_f_pointer(Cptr, ptr)
|
||||
lmp_extract_global_double = ptr
|
||||
CALL lammps_free(Cname)
|
||||
END FUNCTION lmp_extract_global_double
|
||||
FUNCTION lmp_extract_global_str (self, name, dtype)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
CHARACTER(LEN=*), INTENT(IN) :: name, dtype
|
||||
CHARACTER(LEN=:), ALLOCATABLE :: lmp_extract_global_str
|
||||
TYPE(c_ptr) :: Cname, Cptr
|
||||
INTEGER(c_int) :: datatype
|
||||
CHARACTER(KIND=c_char,LEN=1), dimension(:), POINTER :: ptr
|
||||
INTEGER(c_size_t) :: length
|
||||
INTEGER :: i
|
||||
|
||||
Cname = f2c_string(name)
|
||||
datatype = lammps_extract_global_datatype(c_null_ptr, Cname)
|
||||
IF ( datatype /= LAMMPS_STRING ) THEN
|
||||
! throw an exception or something; data type doesn't match!
|
||||
WRITE(0,*) 'WARNING: global data type is inconsistent (not a string)'
|
||||
END IF
|
||||
Cptr = lammps_extract_global(self%handle, Cname)
|
||||
length = c_strlen(Cptr)
|
||||
CALL c_f_pointer(Cptr, ptr, [length])
|
||||
ALLOCATE ( CHARACTER(LEN=length) :: lmp_extract_global_str )
|
||||
FORALL ( I=1:length )
|
||||
lmp_extract_global_str(i:i) = ptr(i)
|
||||
END FORALL
|
||||
CALL lammps_free(Cname)
|
||||
! the allocatable scalar (return value) gets auto-deallocated on return
|
||||
END FUNCTION lmp_extract_global_str
|
||||
|
||||
! equivalent function to lammps_version()
|
||||
INTEGER FUNCTION lmp_version(self)
|
||||
|
||||
Reference in New Issue
Block a user