Wrote docs for extract_fix,extract_variable; fixed python so it knows about string variables; doc typo fixes; part of extract_variable unit test

This commit is contained in:
Karl Hammond
2022-09-29 19:28:15 -05:00
parent 3ab8f6ea16
commit a7071fea78
9 changed files with 861 additions and 86 deletions

View File

@ -389,6 +389,12 @@ Procedures Bound to the lammps Derived Type
:r real(c_double): number of atoms :r real(c_double): number of atoms
.. note::
If you would prefer to get the number of atoms in its native format
(i.e., as a 32- or 64-bit integer, depending on how LAMMPS was compiled),
this can be extracted with :f:func:`extract_global`.
-------- --------
.. f:function:: get_thermo(name) .. f:function:: get_thermo(name)
@ -575,7 +581,26 @@ Procedures Bound to the lammps Derived Type
greater than or equal to the length of the string (not including the greater than or equal to the length of the string (not including the
terminal ``NULL`` character) that LAMMPS returns. If the variable's terminal ``NULL`` character) that LAMMPS returns. If the variable's
length is too short, the string will be truncated. As usual in Fortran, length is too short, the string will be truncated. As usual in Fortran,
strings are padded with spaces at the end. strings are padded with spaces at the end. If you use an allocatable
string, the string **must be allocated** prior to calling this function,
but you can automatically reallocate it to the correct length after the
function returns, viz.,
.. code-block :: Fortran
PROGRAM test
USE LIBLAMMPS
TYPE(lammps) :: lmp
CHARACTER(LEN=:), ALLOCATABLE :: str
lmp = lammps()
CALL lmp%command('units metal')
ALLOCATE ( CHARACTER(LEN=80) :: str )
str = lmp%extract_global('units')
str = TRIM(str) ! re-allocates to length len_trim(str) here
PRINT*, LEN(str), LEN_TRIM(str)
END PROGRAM test
will print the number 5 (the length of the word "metal") twice.
:p character(len=\*) name: string with the name of the property to extract :p character(len=\*) name: string with the name of the property to extract
:r polymorphic: pointer to LAMMPS data. The left-hand side of the assignment :r polymorphic: pointer to LAMMPS data. The left-hand side of the assignment
@ -737,8 +762,8 @@ Procedures Bound to the lammps Derived Type
Two-dimensional arrays returned from :f:func:`extract_compute` will be Two-dimensional arrays returned from :f:func:`extract_compute` will be
**transposed** from equivalent arrays in C, and they will be indexed **transposed** from equivalent arrays in C, and they will be indexed
from 1 instead of 0. See the similar note under from 1 instead of 0. See the note at :f:func:`extract_atom` for
:f:func:`extract_atom` for further details. further details.
The following combinations are possible (assuming ``lmp`` is the name of The following combinations are possible (assuming ``lmp`` is the name of
your LAMMPS instance): your LAMMPS instance):
@ -749,7 +774,7 @@ Procedures Bound to the lammps Derived Type
* - Style * - Style
- Type - Type
- Pointer type to assign to - Type to assign to
- Returned data - Returned data
* - ``lmp%style%global`` * - ``lmp%style%global``
- ``lmp%type%scalar`` - ``lmp%type%scalar``
@ -786,7 +811,7 @@ Procedures Bound to the lammps Derived Type
:p integer(c_int) type: value indicating the type of data to extract :p integer(c_int) type: value indicating the type of data to extract
(scalar, vector, or array) (scalar, vector, or array)
:r polymorphic: pointer to LAMMPS data. The left-hand side of the assignment :r polymorphic: pointer to LAMMPS data. The left-hand side of the assignment
should be a C-compatible pointer (e.g., ``REAL (C_double), POINTER :: x``) should be a C-compatible pointer (e.g., ``REAL (c_double), POINTER :: x``)
to the extracted property. If expecting vector data, the pointer should to the extracted property. If expecting vector data, the pointer should
have dimension ":"; if expecting array (matrix) data, the pointer should have dimension ":"; if expecting array (matrix) data, the pointer should
have dimension ":,:". have dimension ":,:".
@ -828,10 +853,76 @@ Procedures Bound to the lammps Derived Type
user wishes LAMMPS to return. The *ncol* variable is optional for global user wishes LAMMPS to return. The *ncol* variable is optional for global
scalar or vector data, and both *nrow* and *ncol* are optional when a scalar or vector data, and both *nrow* and *ncol* are optional when a
global scalar is requested, as well as when per-atom or local data are global scalar is requested, as well as when per-atom or local data are
requested. requested. The following combinations are possible (assuming ``lmp`` is the
name of your LAMMPS instance):
.. list-table::
:header-rows: 1
:widths: auto
* - Style
- Type
- nrow
- ncol
- Type to assign to
- Returned data
* - ``lmp%style%global``
- ``lmp%type%scalar``
- Ignored
- Ignored
- ``REAL(c_double)``
- Global scalar
* - ``lmp%style%global``
- ``lmp%type%vector``
- Required
- Ignored
- ``REAL(c_double)``
- Element of global vector
* - ``lmp%style%global``
- ``lmp%type%array``
- Required
- Required
- ``REAL(c_double)``
- Element of global array
* - ``lmp%style%atom``
- ``lmp%type%scalar``
-
-
-
- (not allowed)
* - ``lmp%style%atom``
- ``lmp%type%vector``
- Ignored
- Ignored
- ``REAL(c_double), DIMENSION(:), POINTER``
- Per-atom vector
* - ``lmp%style%atom``
- ``lmp%type%array``
- Ignored
- Ignored
- ``REAL(c_double), DIMENSION(:,:), POINTER``
- Per-atom array
* - ``lmp%style%local``
- ``lmp%type%scalar``
-
-
-
- (not allowed)
* - ``lmp%style%local``
- ``lmp%type%vector``
- Ignored
- Ignored
- ``REAL(c_double), DIMENSION(:), POINTER``
- Per-atom vector
* - ``lmp%style%local``
- ``lmp%type%array``
- Ignored
- Ignored
- ``REAL(c_double), DIMENSION(:,:), POINTER``
- Per-atom array
In the case of global data, this function returns a value of type In the case of global data, this function returns a value of type
``real(C_double)``. For per-atom or local data, this function does not ``real(c_double)``. For per-atom or local data, this function does not
return a value but instead associates the pointer on the left side of the return a value but instead associates the pointer on the left side of the
assignment to point to internal LAMMPS data. Pointers must be of the correct assignment to point to internal LAMMPS data. Pointers must be of the correct
data type to point to said data (i.e., ``REAL(c_double)``) and have data type to point to said data (i.e., ``REAL(c_double)``) and have
@ -914,7 +1005,7 @@ Procedures Bound to the lammps Derived Type
:p integer(c_int) ncol: column index (only used for global arrays) :p integer(c_int) ncol: column index (only used for global arrays)
:r polymorphic: LAMMPS data (for global data) or a pointer to LAMMPS data :r polymorphic: LAMMPS data (for global data) or a pointer to LAMMPS data
(for per-atom or local data). The left-hand side of the assignment should (for per-atom or local data). The left-hand side of the assignment should
be of type ``REAL(C_double)`` and have appropriate rank (i.e., be of type ``REAL(c_double)`` and have appropriate rank (i.e.,
``DIMENSION(:)`` if expecting per-atom or local vector data and ``DIMENSION(:)`` if expecting per-atom or local vector data and
``DIMENSION(:,:)`` if expecting per-atom or local array data). If expecting ``DIMENSION(:,:)`` if expecting per-atom or local array data). If expecting
local or per-atom data, it should have the ``POINTER`` attribute, but local or per-atom data, it should have the ``POINTER`` attribute, but
@ -950,7 +1041,7 @@ Procedures Bound to the lammps Derived Type
This function returns the values of the variables, not pointers to them. This function returns the values of the variables, not pointers to them.
Vectors pointing to *atom*-style variables should be of type Vectors pointing to *atom*-style variables should be of type
``REAL(C_double)``, be of rank 1 (i.e., ``DIMENSION(:)``), and either have ``REAL(c_double)``, be of rank 1 (i.e., ``DIMENSION(:)``), and either have
the ``ALLOCATABLE`` attribute or be long enough to contain the data without the ``ALLOCATABLE`` attribute or be long enough to contain the data without
reallocation. reallocation.
@ -977,19 +1068,20 @@ Procedures Bound to the lammps Derived Type
:p character(len=\*) name: variable name to evaluate :p character(len=\*) name: variable name to evaluate
:o character(len=\*) group [optional]: group for which to extract per-atom :o character(len=\*) group [optional]: group for which to extract per-atom
data (if absent, use "all") data (if absent, use "all")
:r polymorphic: scalar of type ``REAL(C_double)`` (for *equal*-style :r polymorphic: scalar of type ``REAL(c_double)`` (for *equal*-style
variables and others that are *equal*-compatible), vector of type variables and others that are *equal*-compatible), vector of type
``REAL(C_double), DIMENSION(nlocal)`` for *atom*-style variables, or ``REAL(c_double), DIMENSION(nlocal)`` for *atom*-style variables, or
``CHARACTER(LEN=:), ALLOCATABLE`` for *string*-style and compatible ``CHARACTER(LEN=*)`` for *string*-style and compatible variables. Strings
variables. Non-allocatable strings whose length is too short to hold the whose length is too short to hold the result will be truncated.
result will be truncated. Allocatable strings must be allocated before this function is called;
see note at :f:func:`extract_global` regarding allocatable strings.
.. note:: .. note::
LAMMPS cannot easily check if it is valid to access the data LAMMPS cannot easily check if it is valid to access the data
referenced by the variables (e.g., computes, fixes, or thermodynamic referenced by the variables (e.g., computes, fixes, or thermodynamic
info), so it may fail with an error. The caller has to make certain info), so it may fail with an error. The caller has to make certain
that the data are extracted only when it safe to evaluate the variable that the data are extracted only when it is safe to evaluate the variable
and thus an error and crash are avoided. and thus an error and crash are avoided.
-------- --------
@ -1003,7 +1095,187 @@ Procedures Bound to the lammps Derived Type
-------- --------
.. f:subroutine:: flush_buffers .. f:subroutine:: get_os_info(buffer)
This function can be used to retrieve detailed information about the hosting
operating system and compiler/runtime environment.
.. versionadded:: TBD
A suitable buffer has to be provided. The assembled text will be truncated
to not overflow this buffer. The string is typically a few hundred bytes
long.
--------
.. f:function:: config_has_mpi_support()
This function is used to query whether LAMMPS was compiled with a real MPI
library or in serial.
.. versionadded:: TBD
:r logical: ``.FALSE.`` when compiled with STUBS, ``.TRUE.`` if complied
with MPI.
--------
.. f:function:: config_has_gzip_support()
Check if the LAMMPS library supports reading or writing compressed
files via a pipe to gzip or similar compression programs.
.. versionadded:: TBD
Several LAMMPS commands (e.g., :doc:`read_data`, :doc:`write_data`,
:doc:`dump styles atom, custom, and xyz <dump>`) support reading and writing
compressed files via creating a pipe to the ``gzip`` program. This function
checks whether this feature was :ref:`enabled at compile time <gzip>`.
It does **not** check whether ``gzip`` or any other supported compression
programs themselves are installed and usable.
:r logical:
--------
.. f:function:: config_has_png_support()
Check if the LAMMPS library supports writing PNG format images.
.. versionadded:: TBD
The LAMMPS :doc:`dump style image <dump_image>` supports writing multiple
image file formats. Most of them, however, need support from an external
library, and using that has to be :ref:`enabled at compile time <graphics>`.
This function checks whether support for the `PNG image file format
<https://en.wikipedia.org/wiki/Portable_Network_Graphics>`_ is available
in the current LAMMPS library.
:r logical:
--------
.. f:function:: config_has_jpeg_support()
Check if the LAMMPS library supports writing JPEG format images.
.. versionadded:: TBD
The LAMMPS :doc:`dump style image <dump_image>` supports writing multiple
image file formats. Most of them, however, need support from an external
library, and using that has to be :ref:`enabled at compile time <graphics>`.
This function checks whether support for the `JPEG image file format
<https://jpeg.org/jpeg/>`_ is available in the current LAMMPS library.
:r logical:
--------
.. f:function:: config_has_ffmpeg_support()
Check if the LAMMPS library supports creating movie files via a pipe to
ffmpeg.
.. versionadded:: TBD
The LAMMPS :doc:`dump style movie <dump_image>` supports generating movies
from images on-the-fly via creating a pipe to the
`ffmpeg <https://ffmpeg.org/ffmpeg/>`_ program.
This function checks whether this feature was
:ref:`enabled at compile time <graphics>`.
It does **not** check whether the ``ffmpeg`` itself is installed and usable.
:r logical:
--------
.. f:function:: config_has_exceptions()
Check whether LAMMPS errors will throw C++ exceptions.
.. versionadded:: TBD
In case of an error, LAMMPS will either abort or throw a C++ exception.
The latter has to be :ref:`enabled at compile time <exceptions>`.
This function checks if exceptions were enabled.
When using the library interface with C++ exceptions enabled, the library
interface functions will "catch" them, and the error status can then be
checked by calling :f:func:`has_error`. The most recent error message can be
retrieved via :f:func:`get_last_error_message`.
This can allow one to restart a calculation or delete and recreate
the LAMMPS instance when a C++ exception occurs. One application
of using exceptions this way is the :ref:`lammps_shell`. If C++
exceptions are disabled and an error happens during a call to
LAMMPS or the Fortran API, the application will terminate.
:r logical:
--------
.. f:function:: config_has_package(name)
Check whether a specific package has been included in LAMMPS
.. versionadded:: TBD
This function checks whether the LAMMPS library in use includes the specific
:doc:`LAMMPS package <Packages>` provided as argument.
:r logical:
--------
.. f:function:: config_package_count()
Count the number of installed packages in the LAMMPS library.
.. versionadded:: TBD
This function counts how many :doc:`LAMMPS packages <Packages>` are
included in the LAMMPS library in use. It directly calls the C library
function :cpp:func:`lammps_config_package_count`.
:r integer(c_int): number of packages installed
--------
.. f:subroutine:: config_package_name(idx, buffer)
Get the name of a package in the list of installed packages in the LAMMPS
library.
.. versionadded:: TBD
This subroutine copies the name of the package with the index *idx* into the
provided string *buffer*. If the name of the package exceeds the length of
the buffer, it will be truncated accordingly. If the index is out of range,
*buffer* is set to an empty string.
:p integer(c_int) idx: index of the package in the list of included packages
:math:`(0 \le idx < \text{package count})`
:p character(len=\*) buffer: string to hold the name of the package
--------
.. f:subroutine:: installed_packages(package[, length])
Obtain a list of the names of enabled packages in the LAMMPS shared library
and store it in *package*.
This function is analogous to the :py:func`installed_packages` function in
the Python API. The optional argument *length* sets the length of each
string in the vector *package* (default: 31).
:p character(len=:) package [dimension(:),allocatable]: list of packages;
*must* have the ``ALLOCATABLE`` attribute and be of rank-1
(``DIMENSION(:)``) with allocatable length.
:o integer length [optional]: length of each string in the list.
Default: 31.
--------
.. f:subroutine:: flush_buffers()
This function calls :cpp:func:`lammps_flush_buffers`, which flushes buffered This function calls :cpp:func:`lammps_flush_buffers`, which flushes buffered
output to be written to screen and logfile. This can simplify capturing output to be written to screen and logfile. This can simplify capturing
@ -1013,7 +1285,7 @@ Procedures Bound to the lammps Derived Type
-------- --------
.. f:function:: is_running .. f:function:: is_running()
Check if LAMMPS is currently inside a run or minimization. Check if LAMMPS is currently inside a run or minimization.
@ -1026,7 +1298,18 @@ Procedures Bound to the lammps Derived Type
-------- --------
.. f:function:: has_error .. f:subroutine:: force_timeout()
Force a timeout to stop an ongoing run cleanly.
.. versionadded:: TBD
This function can be used from signal handlers or multi-threaded
applications to cleanly terminate an ongoing run.
--------
.. f:function:: has_error()
Check if there is a (new) error message available. Check if there is a (new) error message available.
@ -1069,8 +1352,8 @@ Procedures Bound to the lammps Derived Type
This function will do nothing when the LAMMPS library has been This function will do nothing when the LAMMPS library has been
compiled without ``-DLAMMPS_EXCEPTIONS``, which turns errors aborting compiled without ``-DLAMMPS_EXCEPTIONS``, which turns errors aborting
LAMMPS into C++ exceptions. You can use the function LAMMPS into C++ exceptions. You can use the function
:f:func:`config_has_exceptions` to check whethher this is the case. :f:func:`config_has_exceptions` to check whether this is the case.
:p character(len=\*) buffer: string buffer to copy the error message into :p character(len=\*) buffer: string buffer to copy the error message into
:o integer(C_int) status [optional]: 1 when all ranks had the error, :o integer(c_int) status [optional]: 1 when all ranks had the error,
2 on a single-rank error. 2 on a single-rank error.

View File

@ -32,7 +32,6 @@ MODULE LIBLAMMPS
USE, INTRINSIC :: ISO_C_BINDING, ONLY: c_ptr, c_null_ptr, c_associated, & USE, INTRINSIC :: ISO_C_BINDING, ONLY: c_ptr, c_null_ptr, c_associated, &
c_loc, c_int, c_int64_t, c_char, c_null_char, c_double, c_size_t, & c_loc, c_int, c_int64_t, c_char, c_null_char, c_double, c_size_t, &
c_f_pointer c_f_pointer
USE, INTRINSIC :: ISO_FORTRAN_ENV, ONLY : ERROR_UNIT
IMPLICIT NONE IMPLICIT NONE
PRIVATE PRIVATE
@ -80,7 +79,7 @@ MODULE LIBLAMMPS
END TYPE lammps_type END TYPE lammps_type
TYPE lammps TYPE lammps
TYPE(c_ptr) :: handle TYPE(c_ptr) :: handle = c_null_ptr
TYPE(lammps_style) :: style TYPE(lammps_style) :: style
TYPE(lammps_type) :: type TYPE(lammps_type) :: type
CONTAINS CONTAINS
@ -104,10 +103,22 @@ MODULE LIBLAMMPS
PROCEDURE :: extract_variable => lmp_extract_variable PROCEDURE :: extract_variable => lmp_extract_variable
! !
PROCEDURE :: version => lmp_version PROCEDURE :: version => lmp_version
PROCEDURE,NOPASS :: get_os_info => lmp_get_os_info
PROCEDURE,NOPASS :: config_has_mpi_support => lmp_config_has_mpi_support
PROCEDURE,NOPASS :: config_has_gzip_support => lmp_config_has_gzip_support
PROCEDURE,NOPASS :: config_has_png_support => lmp_config_has_png_support
PROCEDURE,NOPASS :: config_has_jpeg_support => lmp_config_has_jpeg_support
PROCEDURE,NOPASS :: config_has_ffmpeg_support &
=> lmp_config_has_ffmpeg_support
PROCEDURE,NOPASS :: config_has_exceptions => lmp_config_has_exceptions
PROCEDURE,NOPASS :: config_has_package => lmp_config_has_package
PROCEDURE,NOPASS :: config_package_count => lammps_config_package_count
PROCEDURE,NOPASS :: config_package_name => lmp_config_package_name
PROCEDURE,NOPASS :: installed_packages => lmp_installed_packages
! !
PROCEDURE :: flush_buffers => lmp_flush_buffers PROCEDURE :: flush_buffers => lmp_flush_buffers
PROCEDURE :: is_running => lmp_is_running PROCEDURE :: is_running => lmp_is_running
! force_timeout PROCEDURE :: force_timeout => lmp_force_timeout
PROCEDURE :: has_error => lmp_has_error PROCEDURE :: has_error => lmp_has_error
PROCEDURE :: get_last_error_message => lmp_get_last_error_message PROCEDURE :: get_last_error_message => lmp_get_last_error_message
END TYPE lammps END TYPE lammps
@ -180,6 +191,9 @@ MODULE LIBLAMMPS
MODULE PROCEDURE assign_double_to_lammps_fix_data, & MODULE PROCEDURE assign_double_to_lammps_fix_data, &
assign_doublevec_to_lammps_fix_data, & assign_doublevec_to_lammps_fix_data, &
assign_doublemat_to_lammps_fix_data assign_doublemat_to_lammps_fix_data
! Variables, too
MODULE PROCEDURE assign_double_to_lammps_variable_data, &
assign_string_to_lammps_variable_data
END INTERFACE END INTERFACE
! interface definitions for calling functions in library.cpp ! interface definitions for calling functions in library.cpp
@ -412,17 +426,69 @@ MODULE LIBLAMMPS
INTEGER(c_int) :: lammps_version INTEGER(c_int) :: lammps_version
END FUNCTION lammps_version END FUNCTION lammps_version
!SUBROUTINE lammps_get_os_info SUBROUTINE lammps_get_os_info (buffer, buf_size) BIND(C)
IMPORT :: C_ptr, C_int
IMPLICIT NONE
TYPE (C_ptr), VALUE :: buffer
INTEGER (C_int), VALUE :: buf_size
END SUBROUTINE lammps_get_os_info
!LOGICAL FUNCTION lammps_config_has_mpi_support FUNCTION lammps_config_has_mpi_support() BIND(C)
!LOGICAL FUNCTION lammps_config_has_gzip_support IMPORT :: c_int
!LOGICAL FUNCTION lammps_config_has_png_support IMPLICIT NONE
!LOGICAL FUNCTION lammps_config_has_jpeg_support INTEGER(c_int) :: lammps_config_has_mpi_support
!LOGICAL FUNCTION lammps_config_has_ffmpeg_support END FUNCTION lammps_config_has_mpi_support
!LOGICAL FUNCTION lammps_config_has_exceptions
!LOGICAL FUNCTION lammps_config_has_package FUNCTION lammps_config_has_gzip_support() BIND(C)
!INTEGER (C_int) FUNCTION lammps_config_package_count IMPORT :: c_int
!SUBROUTINE lammps_config_package_name IMPLICIT NONE
INTEGER(c_int) :: lammps_config_has_gzip_support
END FUNCTION lammps_config_has_gzip_support
FUNCTION lammps_config_has_png_support() BIND(C)
IMPORT :: c_int
IMPLICIT NONE
INTEGER(c_int) :: lammps_config_has_png_support
END FUNCTION lammps_config_has_png_support
FUNCTION lammps_config_has_jpeg_support() BIND(C)
IMPORT :: c_int
IMPLICIT NONE
INTEGER(c_int) :: lammps_config_has_jpeg_support
END FUNCTION lammps_config_has_jpeg_support
FUNCTION lammps_config_has_ffmpeg_support() BIND(C)
IMPORT :: c_int
IMPLICIT NONE
INTEGER(c_int) :: lammps_config_has_ffmpeg_support
END FUNCTION lammps_config_has_ffmpeg_support
FUNCTION lammps_config_has_exceptions() BIND(C)
IMPORT :: c_int
IMPLICIT NONE
INTEGER (c_int) :: lammps_config_has_exceptions
END FUNCTION lammps_config_has_exceptions
FUNCTION lammps_config_has_package(name) BIND(C)
IMPORT :: C_int, C_ptr
IMPLICIT NONE
TYPE (C_ptr), VALUE :: name
INTEGER (c_int) :: lammps_config_has_package
END FUNCTION lammps_config_has_package
FUNCTION lammps_config_package_count() BIND(C)
IMPORT :: C_int
IMPLICIT NONE
INTEGER (C_int) :: lammps_config_package_count
END FUNCTION lammps_config_package_count
FUNCTION lammps_config_package_name (idx, buffer, buf_size) BIND(C)
IMPORT :: C_int, C_ptr
IMPLICIT NONE
INTEGER (C_int) :: lammps_config_package_name
INTEGER (C_int), VALUE :: idx, buf_size
TYPE (C_ptr), VALUE :: buffer
END FUNCTION lammps_config_package_name
!LOGICAL FUNCTION lammps_config_accelerator !LOGICAL FUNCTION lammps_config_accelerator
!LOGICAL FUNCTION lammps_has_gpu_device !LOGICAL FUNCTION lammps_has_gpu_device
@ -474,7 +540,11 @@ MODULE LIBLAMMPS
TYPE(c_ptr), VALUE :: handle TYPE(c_ptr), VALUE :: handle
END FUNCTION lammps_is_running END FUNCTION lammps_is_running
!SUBROUTINE lammps_force_timeout SUBROUTINE lammps_force_timeout (handle) BIND(C)
IMPORT :: c_ptr
IMPLICIT NONE
TYPE(c_ptr), VALUE :: handle
END SUBROUTINE lammps_force_timeout
INTEGER (C_int) FUNCTION lammps_has_error (handle) BIND(C) INTEGER (C_int) FUNCTION lammps_has_error (handle) BIND(C)
IMPORT :: c_ptr, c_int IMPORT :: c_ptr, c_int
@ -622,14 +692,14 @@ CONTAINS
END SUBROUTINE lmp_commands_string END SUBROUTINE lmp_commands_string
! equivalent function to lammps_get_natoms ! equivalent function to lammps_get_natoms
DOUBLE PRECISION FUNCTION lmp_get_natoms(self) REAL (c_double) FUNCTION lmp_get_natoms(self)
CLASS(lammps) :: self CLASS(lammps) :: self
lmp_get_natoms = lammps_get_natoms(self%handle) lmp_get_natoms = lammps_get_natoms(self%handle)
END FUNCTION lmp_get_natoms END FUNCTION lmp_get_natoms
! equivalent function to lammps_get_thermo ! equivalent function to lammps_get_thermo
REAL (C_double) FUNCTION lmp_get_thermo(self,name) REAL (c_double) FUNCTION lmp_get_thermo(self,name)
CLASS(lammps), INTENT(IN) :: self CLASS(lammps), INTENT(IN) :: self
CHARACTER(LEN=*) :: name CHARACTER(LEN=*) :: name
TYPE(C_ptr) :: Cname TYPE(C_ptr) :: Cname
@ -1025,6 +1095,7 @@ CONTAINS
CALL lammps_free(Cname) CALL lammps_free(Cname)
CALL lammps_free(Cgroup) CALL lammps_free(Cgroup)
variable_data%lammps_instance => self
SELECT CASE (datatype) SELECT CASE (datatype)
CASE (LMP_VAR_EQUAL) CASE (LMP_VAR_EQUAL)
variable_data%datatype = DATA_DOUBLE variable_data%datatype = DATA_DOUBLE
@ -1059,12 +1130,125 @@ CONTAINS
lmp_version = lammps_version(self%handle) lmp_version = lammps_version(self%handle)
END FUNCTION lmp_version END FUNCTION lmp_version
! equivalent function to lammps_is_running ! equivalent function to lammps_get_os_info
LOGICAL FUNCTION lmp_is_running(self) SUBROUTINE lmp_get_os_info (buffer)
CLASS(lammps), INTENT(IN) :: self CHARACTER(LEN=*) :: buffer
INTEGER(c_int) :: buf_size
CHARACTER(LEN=1,KIND=c_char), DIMENSION(LEN(buffer)), TARGET :: Cbuffer
TYPE(c_ptr) :: ptr
INTEGER :: i
lmp_is_running = ( lammps_is_running(self%handle) /= 0_C_int ) buffer = ''
END FUNCTION lmp_is_running ptr = C_LOC(Cbuffer(1))
buf_size = LEN(buffer)
CALL lammps_get_os_info (ptr, buf_size)
DO i=1,buf_size
IF ( Cbuffer(i) == C_NULL_CHAR ) EXIT
buffer(i:i) = Cbuffer(i)
END DO
END SUBROUTINE lmp_get_os_info
! equivalent function to lammps_config_has_mpi_support
LOGICAL FUNCTION lmp_config_has_mpi_support()
INTEGER(c_int) :: has_mpi_support
has_mpi_support = lammps_config_has_mpi_support()
lmp_config_has_mpi_support = (has_mpi_support /= 0_c_int)
END FUNCTION lmp_config_has_mpi_support
! equivalent function to lammps_config_has_gzip_support
LOGICAL FUNCTION lmp_config_has_gzip_support()
INTEGER(c_int) :: has_gzip_support
has_gzip_support = lammps_config_has_gzip_support()
lmp_config_has_gzip_support = (has_gzip_support /= 0_c_int)
END FUNCTION lmp_config_has_gzip_support
! equivalent function to lammps_config_has_png_support
LOGICAL FUNCTION lmp_config_has_png_support()
INTEGER(C_int) :: has_png_support
has_png_support = lammps_config_has_png_support()
lmp_config_has_png_support = (has_png_support /= 0_c_int)
END FUNCTION lmp_config_has_png_support
! equivalent function to lammps_config_has_jpeg_support
LOGICAL FUNCTION lmp_config_has_jpeg_support()
INTEGER(c_int) :: has_jpeg_support
has_jpeg_support = lammps_config_has_jpeg_support()
lmp_config_has_jpeg_support = (has_jpeg_support /= 0_c_int)
END FUNCTION lmp_config_has_jpeg_support
! equivalent function to lammps_config_has_ffmpeg_support
LOGICAL FUNCTION lmp_config_has_ffmpeg_support()
INTEGER(c_int) :: has_ffmpeg_support
has_ffmpeg_support = lammps_config_has_ffmpeg_support()
lmp_config_has_ffmpeg_support = (has_ffmpeg_support /= 0_c_int)
END FUNCTION lmp_config_has_ffmpeg_support
! equivalent function to lammps_config_has_exceptions
LOGICAL FUNCTION lmp_config_has_exceptions()
INTEGER(c_int) :: has_exceptions
has_exceptions = lammps_config_has_exceptions()
lmp_config_has_exceptions = (has_exceptions /= 0_c_int)
END FUNCTION lmp_config_has_exceptions
! equivalent function to lammps_config_has_package
LOGICAL FUNCTION lmp_config_has_package(name)
CHARACTER(LEN=*), INTENT(IN) :: name
INTEGER (c_int) :: has_package
TYPE (c_ptr) :: Cname
Cname = f2c_string(name)
has_package = lammps_config_has_package(Cname)
lmp_config_has_package = (has_package /= 0_c_int)
CALL lammps_free(Cname)
END FUNCTION lmp_config_has_package
! equivalent subroutine to lammps_config_package_name
SUBROUTINE lmp_config_package_name (idx, buffer)
INTEGER, INTENT(IN) :: idx
CHARACTER(LEN=*), INTENT(OUT) :: buffer
INTEGER(c_int) :: Cidx, Csuccess
TYPE(c_ptr) :: Cptr
CHARACTER(LEN=1,KIND=c_char), TARGET :: Cbuffer(LEN(buffer)+1)
INTEGER :: i, strlen
Cidx = idx - 1
Cptr = C_LOC(Cbuffer(1))
Csuccess = lammps_config_package_name(Cidx, Cptr, LEN(buffer)+1)
buffer = ''
IF ( Csuccess /= 0_c_int ) THEN
strlen = c_strlen(Cptr)
FORALL ( i = 1:strlen )
buffer(i:i) = Cbuffer(i)
END FORALL
END IF
END SUBROUTINE lmp_config_package_name
! equivalent function to Python routine .installed_packages()
SUBROUTINE lmp_installed_packages (package, length)
CHARACTER(LEN=:), DIMENSION(:), ALLOCATABLE, INTENT(OUT) :: package
INTEGER, INTENT(IN), OPTIONAL :: length
INTEGER, PARAMETER :: MAX_BUFFER_LENGTH = 31
INTEGER :: i, npackage, buf_length
IF ( PRESENT(length) ) THEN
buf_length = length
ELSE
buf_length = MAX_BUFFER_LENGTH
END IF
IF ( ALLOCATED(package) ) DEALLOCATE(package)
npackage = lammps_config_package_count()
ALLOCATE( CHARACTER(LEN=MAX_BUFFER_LENGTH) :: package(npackage) )
DO i=1, npackage
CALL lmp_config_package_name(i, package(i))
END DO
END SUBROUTINE lmp_installed_packages
! equivalent function to lammps_flush_buffers ! equivalent function to lammps_flush_buffers
SUBROUTINE lmp_flush_buffers(self) SUBROUTINE lmp_flush_buffers(self)
@ -1073,6 +1257,20 @@ CONTAINS
CALL lammps_flush_buffers(self%handle) CALL lammps_flush_buffers(self%handle)
END SUBROUTINE lmp_flush_buffers END SUBROUTINE lmp_flush_buffers
! equivalent function to lammps_is_running
LOGICAL FUNCTION lmp_is_running(self)
CLASS(lammps), INTENT(IN) :: self
lmp_is_running = ( lammps_is_running(self%handle) /= 0_C_int )
END FUNCTION lmp_is_running
! equivalent function to lammps_force_timeout
SUBROUTINE lmp_force_timeout (self)
CLASS(lammps), INTENT(IN) :: self
CALL lammps_force_timeout(self%handle)
END SUBROUTINE
! equivalent function to lammps_has_error ! equivalent function to lammps_has_error
LOGICAL FUNCTION lmp_has_error(self) LOGICAL FUNCTION lmp_has_error(self)
CLASS(lammps), INTENT(IN) :: self CLASS(lammps), INTENT(IN) :: self
@ -1264,6 +1462,17 @@ CONTAINS
END IF END IF
END SUBROUTINE assign_doublevec_to_lammps_variable_data END SUBROUTINE assign_doublevec_to_lammps_variable_data
SUBROUTINE assign_string_to_lammps_variable_data (lhs, rhs)
CHARACTER(LEN=*), INTENT(OUT) :: lhs
CLASS(lammps_variable_data), INTENT(IN) :: rhs
IF ( rhs%datatype == DATA_STRING ) THEN
lhs = rhs%str
ELSE
CALL assignment_error(rhs, 'string')
END IF
END SUBROUTINE assign_string_to_lammps_variable_data
! ---------------------------------------------------------------------- ! ----------------------------------------------------------------------
! Generic function to catch all errors in assignments of LAMMPS data to ! Generic function to catch all errors in assignments of LAMMPS data to
! user-space variables/pointers ! user-space variables/pointers
@ -1292,6 +1501,8 @@ CONTAINS
str1 = 'vector of doubles' str1 = 'vector of doubles'
CASE (DATA_DOUBLE_2D) CASE (DATA_DOUBLE_2D)
str1 = 'matrix of doubles' str1 = 'matrix of doubles'
CASE (DATA_STRING)
str1 = 'string'
CASE DEFAULT CASE DEFAULT
str1 = 'that type' str1 = 'that type'
END SELECT END SELECT

View File

@ -301,6 +301,8 @@ class lammps(object):
self.lib.lammps_extract_fix.argtypes = [c_void_p, c_char_p, c_int, c_int, c_int, c_int] self.lib.lammps_extract_fix.argtypes = [c_void_p, c_char_p, c_int, c_int, c_int, c_int]
self.lib.lammps_extract_variable.argtypes = [c_void_p, c_char_p, c_char_p] self.lib.lammps_extract_variable.argtypes = [c_void_p, c_char_p, c_char_p]
self.lib.lammps_extract_variable_datatype.argtypes = [c_void_p, c_char_p]
self.lib.lammps_extract_variable_datatype.restype = c_int
self.lib.lammps_fix_external_get_force.argtypes = [c_void_p, c_char_p] self.lib.lammps_fix_external_get_force.argtypes = [c_void_p, c_char_p]
self.lib.lammps_fix_external_get_force.restype = POINTER(POINTER(c_double)) self.lib.lammps_fix_external_get_force.restype = POINTER(POINTER(c_double))
@ -1083,21 +1085,22 @@ class lammps(object):
# for vector, must copy nlocal returned values to local c_double vector # for vector, must copy nlocal returned values to local c_double vector
# memory was allocated by library interface function # memory was allocated by library interface function
def extract_variable(self, name, group=None, vartype=LMP_VAR_EQUAL): def extract_variable(self, name, group=None, vartype=None):
""" Evaluate a LAMMPS variable and return its data """ Evaluate a LAMMPS variable and return its data
This function is a wrapper around the function This function is a wrapper around the function
:cpp:func:`lammps_extract_variable` of the C-library interface, :cpp:func:`lammps_extract_variable` of the C library interface,
evaluates variable name and returns a copy of the computed data. evaluates variable name and returns a copy of the computed data.
The memory temporarily allocated by the C-interface is deleted The memory temporarily allocated by the C-interface is deleted
after the data is copied to a Python variable or list. after the data is copied to a Python variable or list.
The variable must be either an equal-style (or equivalent) The variable must be either an equal-style (or equivalent)
variable or an atom-style variable. The variable type has to variable or an atom-style variable. The variable type can be
provided as ``vartype`` parameter which may be one of two constants: provided as the ``vartype`` parameter, which may be one of several
``LMP_VAR_EQUAL`` or ``LMP_VAR_ATOM``; it defaults to constants: ``LMP_VAR_EQUAL``, ``LMP_VAR_ATOM``, or ``LMP_VAR_STRING``.
equal-style variables. If omitted or ``None``, LAMMPS will determine its value for you based on
The group parameter is only used for atom-style variables and a call to :cpp:func:`lammps_extract_variable_datatype` from the C library
defaults to the group "all" if set to ``None``, which is the default. interface. The group parameter is only used for atom-style variables and
defaults to the group "all".
:param name: name of the variable to execute :param name: name of the variable to execute
:type name: string :type name: string
@ -1111,6 +1114,9 @@ class lammps(object):
if name: name = name.encode() if name: name = name.encode()
else: return None else: return None
if group: group = group.encode() if group: group = group.encode()
if vartype is None :
vartype = self.lib.lammps_extract_variable_datatype(self.lmp, name)
#vartype = LMP_VAR_EQUAL
if vartype == LMP_VAR_EQUAL: if vartype == LMP_VAR_EQUAL:
self.lib.lammps_extract_variable.restype = POINTER(c_double) self.lib.lammps_extract_variable.restype = POINTER(c_double)
with ExceptionCheck(self): with ExceptionCheck(self):
@ -1130,6 +1136,11 @@ class lammps(object):
self.lib.lammps_free(ptr) self.lib.lammps_free(ptr)
else: return None else: return None
return result return result
elif vartype == LMP_VAR_STRING :
self.lib.lammps_extract_variable.restype = c_char_p
with ExceptionCheck(self) :
ptr = self.lib.lammps_extract_variable(self.lmp, name, group)
return ptr.decode('utf-8')
return None return None
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------

View File

@ -4572,8 +4572,8 @@ int lammps_config_has_gzip_support() {
\verbatim embed:rst \verbatim embed:rst
The LAMMPS :doc:`dump style image <dump_image>` supports writing multiple The LAMMPS :doc:`dump style image <dump_image>` supports writing multiple
image file formats. Most of them need, however, support from an external image file formats. Most of them, however, need support from an external
library and using that has to be :ref:`enabled at compile time <graphics>`. library, and using that has to be :ref:`enabled at compile time <graphics>`.
This function checks whether support for the `PNG image file format This function checks whether support for the `PNG image file format
<https://en.wikipedia.org/wiki/Portable_Network_Graphics>`_ is available <https://en.wikipedia.org/wiki/Portable_Network_Graphics>`_ is available
in the current LAMMPS library. in the current LAMMPS library.
@ -4591,8 +4591,8 @@ int lammps_config_has_png_support() {
\verbatim embed:rst \verbatim embed:rst
The LAMMPS :doc:`dump style image <dump_image>` supports writing multiple The LAMMPS :doc:`dump style image <dump_image>` supports writing multiple
image file formats. Most of them need, however, support from an external image file formats. Most of them, however, need support from an external
library and using that has to be :ref:`enabled at compile time <graphics>`. library, and using that has to be :ref:`enabled at compile time <graphics>`.
This function checks whether support for the `JPEG image file format This function checks whether support for the `JPEG image file format
<https://jpeg.org/jpeg/>`_ is available in the current LAMMPS library. <https://jpeg.org/jpeg/>`_ is available in the current LAMMPS library.
\endverbatim \endverbatim
@ -4623,14 +4623,14 @@ int lammps_config_has_ffmpeg_support() {
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/** Check whether LAMMPS errors will throw a C++ exception /** Check whether LAMMPS errors will throw C++ exceptions.
* *
\verbatim embed:rst \verbatim embed:rst
In case of errors LAMMPS will either abort or throw a C++ exception. In case of an error, LAMMPS will either abort or throw a C++ exception.
The latter has to be :ref:`enabled at compile time <exceptions>`. The latter has to be :ref:`enabled at compile time <exceptions>`.
This function checks if exceptions were enabled. This function checks if exceptions were enabled.
When using the library interface and C++ exceptions are enabled, When using the library interface with C++ exceptions enabled,
the library interface functions will "catch" them and the the library interface functions will "catch" them and the
error status can then be checked by calling error status can then be checked by calling
:cpp:func:`lammps_has_error` and the most recent error message :cpp:func:`lammps_has_error` and the most recent error message
@ -4649,10 +4649,10 @@ int lammps_config_has_exceptions() {
/* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */
/** Check if a specific package has been included in LAMMPS /** Check whether a specific package has been included in LAMMPS
* *
\verbatim embed:rst \verbatim embed:rst
This function checks if the LAMMPS library in use includes the This function checks whether the LAMMPS library in use includes the
specific :doc:`LAMMPS package <Packages>` provided as argument. specific :doc:`LAMMPS package <Packages>` provided as argument.
\endverbatim \endverbatim
* *
@ -5609,7 +5609,7 @@ int lammps_is_running(void *handle)
return lmp->update->whichflag; return lmp->update->whichflag;
} }
/** Force a timeout to cleanly stop an ongoing run /** Force a timeout to stop an ongoing run cleanly.
* *
* This function can be used from signal handlers or multi-threaded * This function can be used from signal handlers or multi-threaded
* applications to cleanly terminate an ongoing run. * applications to cleanly terminate an ongoing run.

View File

@ -69,6 +69,11 @@ if(CMAKE_Fortran_COMPILER)
target_link_libraries(test_fortran_extract_fix PRIVATE flammps lammps MPI::MPI_Fortran GTest::GTestMain) target_link_libraries(test_fortran_extract_fix PRIVATE flammps lammps MPI::MPI_Fortran GTest::GTestMain)
add_test(NAME FortranExtractFix COMMAND test_fortran_extract_fix) add_test(NAME FortranExtractFix COMMAND test_fortran_extract_fix)
add_executable(test_fortran_extract_variable wrap_extract_variable.cpp test_fortran_extract_variable.f90)
target_link_libraries(test_fortran_extract_variable PRIVATE flammps lammps MPI::MPI_Fortran GTest::GTestMain)
add_test(NAME FortranExtractVariable COMMAND test_fortran_extract_variable)
else() else()
message(STATUS "Skipping Tests for the LAMMPS Fortran Module: no Fortran compiler") message(STATUS "Skipping Tests for the LAMMPS Fortran Module: no Fortran compiler")
endif() endif()

View File

@ -0,0 +1,8 @@
3
2 1.6
1 5.2
3 -1.4
2
3 2.5
1 -1.1

View File

@ -0,0 +1,9 @@
hello
god dag
hola
bonjour
guten Tag
konnichiwa
shalom
salve
goedendag

View File

@ -0,0 +1,161 @@
MODULE keepvar
USE liblammps
IMPLICIT NONE
TYPE(LAMMPS) :: lmp
CHARACTER(LEN=40), DIMENSION(3), PARAMETER :: demo_input = &
[ CHARACTER(LEN=40) :: &
'region box block 0 $x 0 3 0 4', &
'create_box 1 box', &
'create_atoms 1 single 1.0 1.0 ${zpos}' ]
CHARACTER(LEN=40), DIMENSION(3), PARAMETER :: cont_input = &
[ CHARACTER(LEN=40) :: &
'create_atoms 1 single &', &
' 0.2 0.1 0.1', &
'create_atoms 1 single 0.5 0.5 0.5' ]
CHARACTER(LEN=40), DIMENSION(3), PARAMETER :: pair_input = &
[ CHARACTER(LEN=40) :: &
'pair_style lj/cut 2.5', &
'pair_coeff 1 1 1.0 1.0', &
'mass 1 2.0' ]
CHARACTER(LEN=60), DIMENSION(4), PARAMETER :: py_input = &
[ CHARACTER(LEN=60) :: &
'python square_it input 1 v_lp return v_square here """', &
'def square_it(N) :', &
' return N*N', &
'"""' ]
CONTAINS
FUNCTION absolute_path(filename)
CHARACTER(LEN=:), ALLOCATABLE :: absolute_path
CHARACTER(LEN=*), INTENT(IN) :: filename
CHARACTER(LEN=:), ALLOCATABLE :: test_input_directory
print *, 'GOT HERE! filename is ', filename
test_input_directory = lmp%extract_variable('input_dir')
print *, ' test_input_directory is ', test_input_directory
absolute_path = test_input_directory // '/' // TRIM(filename)
END FUNCTION absolute_path
END MODULE keepvar
FUNCTION f_lammps_with_C_args(argc, argv) BIND(C)
USE ISO_C_BINDING, ONLY: c_ptr, c_char, c_int, c_size_t, c_f_pointer
USE liblammps
USE keepvar, ONLY: lmp
IMPLICIT NONE
INTEGER(c_int), INTENT(IN), VALUE :: argc
TYPE(c_ptr), VALUE :: argv
TYPE(c_ptr), DIMENSION(:), POINTER :: Fargv
INTEGER, PARAMETER :: ARG_LENGTH = 80
TYPE(c_ptr) :: f_lammps_with_C_args
CHARACTER(LEN=ARG_LENGTH), DIMENSION(argc) :: args
CHARACTER(LEN=1,KIND=c_char), DIMENSION(:), POINTER :: Cstr
INTEGER :: i, length, j
INTERFACE
FUNCTION c_strlen (str) BIND(C,name='strlen')
IMPORT :: c_ptr, c_size_t
IMPLICIT NONE
TYPE(c_ptr), INTENT(IN), VALUE :: str
INTEGER(c_size_t) :: c_strlen
END FUNCTION c_strlen
END INTERFACE
CALL C_F_POINTER(argv, Fargv, [argc])
DO i = 1, argc
args(i) = ''
length = c_strlen(Fargv(i))
CALL C_F_POINTER(Fargv(i), Cstr, [length])
FORALL (j = 1:length)
args(i)(j:j) = Cstr(j)
END FORALL
END DO
lmp = lammps(args)
f_lammps_with_C_args = lmp%handle
END FUNCTION f_lammps_with_C_args
SUBROUTINE f_lammps_close() BIND(C)
USE ISO_C_BINDING, ONLY: c_null_ptr
USE liblammps
USE keepvar, ONLY: lmp
IMPLICIT NONE
CALL lmp%close()
lmp%handle = c_null_ptr
END SUBROUTINE f_lammps_close
SUBROUTINE f_lammps_setup_extract_variable () BIND(C)
USE LIBLAMMPS
USE keepvar, ONLY : lmp, demo_input, cont_input, pair_input, absolute_path
IMPLICIT NONE
CALL lmp%commands_list(demo_input)
CALL lmp%commands_list(cont_input)
CALL lmp%commands_list(pair_input)
CALL lmp%command('variable idx index "hello" "goodbye"')
CALL lmp%command('variable lp loop 10')
CALL lmp%command('variable lp_pad loop 10 pad')
!CALL lmp%command('variable wld world "group1" "group2" "group3"')
CALL lmp%command('variable wld world "group1"')
CALL lmp%command('variable uni universe "universe1" "universeA"')
CALL lmp%command('variable ulp uloop 2')
CALL lmp%command('variable str index "this is a string"')
CALL lmp%command('variable fmt format lp %.6G')
CALL lmp%command('variable fmt_pad format lp %0.6g')
CALL lmp%command('variable shell getenv SHELL')
! CALL lmp%command('variable greet file ' // absolute_path('greetings.txt'))
! CALL lmp%command('variable atfile atomfile ' // absolute_path('atomdata.txt')
IF ( lmp%config_has_package('PYTHON') ) THEN
CALL lmp%command('variable py python square_it')
END IF
CALL lmp%command('variable time timer')
CALL lmp%command('variable int internal 4')
CALL lmp%command("variable nat equal count(all)")
CALL lmp%command("variable ts equal step")
END SUBROUTINE f_lammps_setup_extract_variable
FUNCTION f_lammps_extract_variable_index_1 () BIND(C)
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_int
USE LIBLAMMPS
USE keepvar, ONLY : lmp
IMPLICIT NONE
INTEGER(c_int) :: f_lammps_extract_variable_index_1
CHARACTER(LEN=80) :: str
str = lmp%extract_variable("idx")
IF ( trim(str) == 'hello' ) THEN
f_lammps_extract_variable_index_1 = 1_c_int
ELSE
f_lammps_extract_variable_index_1 = 0_c_int
END IF
END FUNCTION f_lammps_extract_variable_index_1
FUNCTION f_lammps_extract_variable_index_2 () BIND(C)
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_int
USE LIBLAMMPS
USE keepvar, ONLY : lmp
IMPLICIT NONE
INTEGER(c_int) :: f_lammps_extract_variable_index_2
CHARACTER(LEN=80) :: str
str = lmp%extract_variable("idx")
IF ( trim(str) == 'goodbye' ) THEN
f_lammps_extract_variable_index_2 = 1_c_int
ELSE
f_lammps_extract_variable_index_2 = 0_c_int
END IF
END FUNCTION f_lammps_extract_variable_index_2
FUNCTION f_lammps_extract_variable_loop () BIND(C)
USE, INTRINSIC :: ISO_C_BINDING, ONLY : C_int, C_double
USE LIBLAMMPS
USE keepvar, ONLY : lmp
IMPLICIT NONE
INTEGER(c_int) :: f_lammps_extract_variable_loop
CHARACTER(LEN=80) :: loop
loop = lmp%extract_variable('lp')
READ(loop,*) f_lammps_extract_variable_loop
END FUNCTION f_lammps_extract_variable_loop

View File

@ -0,0 +1,87 @@
// unit tests for extracting compute data from a LAMMPS instance through the
// Fortran wrapper
#include <cstdio>
#include "lammps.h"
#include "library.h"
#include <mpi.h>
#include <string>
#include <cstdlib>
#include <cstdint>
#include "gtest/gtest.h"
#define STRINGIFY(val) XSTR(val)
#define XSTR(val) #val
// prototypes for Fortran reverse wrapper functions
extern "C" {
void *f_lammps_with_c_args(int,char**);
void f_lammps_close();
void f_lammps_setup_extract_variable();
int f_lammps_extract_variable_index_1();
int f_lammps_extract_variable_index_2();
int f_lammps_extract_variable_loop();
double f_lammps_extract_variable_loop_pad();
void f_lammps_setup_extract_variable_world();
void f_lammps_setup_extract_variable_universe();
int f_lammps_setup_extract_variable_uloop();
void f_lammps_setup_extract_variable_string();
void f_lammps_setup_extract_variable_format();
void f_lammps_setup_extract_variable_getenv();
void f_lammps_setup_extract_variable_file();
void f_lammps_setup_extract_variable_atomfile();
double f_lammps_setup_extract_variable_python();
double f_lammps_setup_extract_variable_timer();
double f_lammps_setup_extract_variable_internal();
double f_lammps_extract_variable_equal_natoms();
double f_lammps_extract_variable_equal_dt();
double f_lammps_extract_variable_vector(int);
double f_lammps_extract_variable_atom(int);
}
class LAMMPS_extract_variable : public ::testing::Test {
protected:
LAMMPS_NS::LAMMPS *lmp;
LAMMPS_extract_variable() = default;
~LAMMPS_extract_variable() override = default;
void SetUp() override
{
const char *args[] = {"LAMMPS_Fortran_test", "-l", "none",
"-echo", "screen", "-nocite", "-var",
"input_dir", STRINGIFY(TEST_INPUT_FOLDER),
"-var", "zpos", "1.5", "-var", "x", "2"};
char** argv = (char**) args;
int argc = sizeof(args) / sizeof(const char*);
::testing::internal::CaptureStdout();
std::fprintf(stderr,"THIS IS A TEST\n");
lmp = (LAMMPS_NS::LAMMPS*)f_lammps_with_c_args(argc, argv);
std::string output = ::testing::internal::GetCapturedStdout();
EXPECT_STREQ(output.substr(0, 8).c_str(), "LAMMPS (");
}
void TearDown() override
{
::testing::internal::CaptureStdout();
f_lammps_close();
std::string output = ::testing::internal::GetCapturedStdout();
EXPECT_STREQ(output.substr(0, 16).c_str(), "Total wall time:");
lmp = nullptr;
}
};
TEST_F(LAMMPS_extract_variable, index)
{
f_lammps_setup_extract_variable();
EXPECT_EQ(f_lammps_extract_variable_index_1(), 1);
EXPECT_EQ(f_lammps_extract_variable_index_2(), 0);
lammps_command(lmp, "next idx");
EXPECT_EQ(f_lammps_extract_variable_index_1(), 0);
EXPECT_EQ(f_lammps_extract_variable_index_2(), 1);
};
TEST_F(LAMMPS_extract_variable, loop)
{
f_lammps_setup_extract_variable();
EXPECT_EQ(f_lammps_extract_variable_loop(), 1);
};