Implemented scatter_atoms and scatter_atoms_subset + unit tests + documentation + typos/edits
This commit is contained in:
@ -1,14 +1,14 @@
|
||||
The ``LIBLAMMPS`` Fortran Module
|
||||
********************************
|
||||
|
||||
The ``LIBLAMMPS`` module provides an interface to call LAMMPS from a
|
||||
Fortran code. It is based on the LAMMPS C-library interface and
|
||||
requires a Fortran 2003 compatible compiler to be compiled. It is
|
||||
The ``LIBLAMMPS`` module provides an interface to call LAMMPS from Fortran.
|
||||
It is based on the LAMMPS C library interface and
|
||||
requires a Fortran 2003-compatible compiler to be compiled. It is
|
||||
designed to be self-contained and not require any support functions
|
||||
written in C, C++, or Fortran.
|
||||
written in C, C++, or Fortran other than those in the C library interface.
|
||||
|
||||
While C libraries have a defined binary interface (ABI) and can thus be
|
||||
used from multiple compiler versions from different vendors for as long
|
||||
used from multiple compiler versions from different vendors as long
|
||||
as they are compatible with the hosting operating system, the same is
|
||||
not true for Fortran programs. Thus, the LAMMPS Fortran module needs to be
|
||||
compiled alongside the code using it from the source code in
|
||||
@ -49,7 +49,7 @@ folder of the LAMMPS distribution.
|
||||
.. note::
|
||||
|
||||
A contributed (and more complete!) Fortran interface that more
|
||||
closely resembles the C-library interface is available in the
|
||||
closely resembles the C library interface is available in the
|
||||
``examples/COUPLE/fortran2`` folder. Please see the ``README`` file
|
||||
in that folder for more information about it and how to contact its
|
||||
author and maintainer.
|
||||
@ -62,8 +62,8 @@ Creating or deleting a LAMMPS object
|
||||
With the Fortran interface, the creation of a :cpp:class:`LAMMPS
|
||||
<LAMMPS_NS::LAMMPS>` instance is included in the constructor for
|
||||
creating the :f:func:`lammps` derived type. To import the definition of
|
||||
that type and its type-bound procedures, you need to add a ``USE
|
||||
LIBLAMMPS`` statement. Internally, it will call either
|
||||
that type and its type-bound procedures, you need to add a ``USE LIBLAMMPS``
|
||||
statement. Internally, it will call either
|
||||
:cpp:func:`lammps_open_fortran` or :cpp:func:`lammps_open_no_mpi` from
|
||||
the C library API to create the class instance. All arguments are
|
||||
optional and :cpp:func:`lammps_mpi_init` will be called automatically
|
||||
@ -178,11 +178,13 @@ Accessing system properties
|
||||
|
||||
The C library interface allows the :doc:`extraction of different kinds
|
||||
of information <Library_properties>` about the active simulation
|
||||
instance and also---in some cases---to apply modifications to it. In
|
||||
some cases, the C library interface makes pointers to internal data
|
||||
structures accessible; when accessing them through the library interfaces,
|
||||
special care is needed to avoid data corruption and crashes. Please see
|
||||
the documentation of the individual type-bound procedures for details.
|
||||
instance and also---in some cases---to apply modifications to it, and the
|
||||
Fortran interface provides access to the same data using Fortran-style,
|
||||
C-interoperable data types. In some cases, the Fortran library interface makes
|
||||
pointers to internal LAMMPS data structures accessible; when accessing them
|
||||
through the library interfaces, special care is needed to avoid data corruption
|
||||
and crashes. Please see the documentation of the individual type-bound
|
||||
procedures for details.
|
||||
|
||||
Below is an example demonstrating some of the possible uses.
|
||||
|
||||
@ -258,6 +260,11 @@ of the contents of the ``LIBLAMMPS`` Fortran interface to LAMMPS.
|
||||
:f function extract_compute: :f:func:`extract_compute`
|
||||
:f function extract_fix: :f:func:`extract_fix`
|
||||
:f function extract_variable: :f:func:`extract_variable`
|
||||
:f subroutine gather_atoms: :f:func:`gather_atoms`
|
||||
:f subroutine gather_atoms_concat: :f:func:`gather_atoms_concat`
|
||||
:f subroutine gather_atoms_subset: :f:func:`gather_atoms_subset`
|
||||
:f subroutine scatter_atoms: :f:func:`scatter_atoms`
|
||||
:f subroutine scatter_atoms_subset: :f:func:`scatter_atoms_subset`
|
||||
:f function version: :f:func:`version`
|
||||
:f subroutine flush_buffers: :f:func:`flush_buffers`
|
||||
:f function is_running: :f:func:`is_running`
|
||||
@ -1041,9 +1048,8 @@ Procedures Bound to the lammps Derived Type
|
||||
|
||||
This function returns the values of the variables, not pointers to them.
|
||||
Vectors pointing to *atom*-style variables should be of type
|
||||
``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
|
||||
reallocation.
|
||||
``REAL(c_double)``, be of rank 1 (i.e., ``DIMENSION(:)``), and have the
|
||||
``ALLOCATABLE`` attribute.
|
||||
|
||||
.. note::
|
||||
|
||||
@ -1088,7 +1094,7 @@ Procedures Bound to the lammps Derived Type
|
||||
|
||||
--------
|
||||
|
||||
.. f:function:: gather_atoms(name, count, data)
|
||||
.. f:subroutine:: gather_atoms(name, count, data)
|
||||
|
||||
This function calls :c:func:`lammps_gather_atoms` to gather the named
|
||||
atom-based entity for all atoms on all processors and return it in the
|
||||
@ -1135,10 +1141,11 @@ Procedures Bound to the lammps Derived Type
|
||||
x(1:3,1:size(xdata)/3) => xdata
|
||||
|
||||
You can then access the *y*\ -component of atom 3 with ``x(2,3)``.
|
||||
See the note about array index order at :f:func:`extract_atom`.
|
||||
|
||||
--------
|
||||
|
||||
.. f:function:: gather_atoms_concat(name, count, data)
|
||||
.. f:subroutine:: gather_atoms_concat(name, count, data)
|
||||
|
||||
This function calls :c:func:`lammps_gather_atoms_concat` to gather the named
|
||||
atom-based entity for all atoms on all processors and return it in the
|
||||
@ -1166,6 +1173,100 @@ Procedures Bound to the lammps Derived Type
|
||||
|
||||
--------
|
||||
|
||||
.. f:subroutine:: gather_atoms_subset(name, count, ids, data)
|
||||
|
||||
This function calls :c:func:`lammps_gather_atoms_subset` to gather the named
|
||||
atom-based entity for the atoms in the array *ids* from all processors and
|
||||
return it in the vector *data*.
|
||||
|
||||
.. versionadded: TBD
|
||||
|
||||
This subroutine gathers data for the requested atom IDs and stores them in a
|
||||
one-dimensional array allocated by the user. The data will be ordered by
|
||||
atom ID, but there is no requirement that the IDs be consecutive. If you
|
||||
wish to return a similar array for *all* the atoms, use
|
||||
:f:func:`gather_atoms` or :f:func:`gather_atoms_concat`.
|
||||
|
||||
The *data* array will be in groups of *count* values, sorted by atom ID
|
||||
in the same order as the array *ids* (e.g., if *name* is *x*, *count* = 3,
|
||||
and *ids* is [100, 57, 210], then *data* might look like
|
||||
[x(1,100), x(2,100), x(3,100), x(1,57), x(2,57), x(3,57), x(1,210),
|
||||
:math:`\dots`]; *ids* must be provided by the user, and *data* must be
|
||||
of rank 1 (i.e., ``DIMENSION(:)``) and have the ``ALLOCATABLE`` attribute.
|
||||
|
||||
:p character(len=\*) name: desired quantity (e.g., *x* or *mask*)
|
||||
:p integer(c_int) count: number of per-atom values you expect per atom
|
||||
(e.g., 1 for *type*, *mask*, or *charge*; 3 for *x*, *v*, or *f*). Use
|
||||
*count* = 3 with *image* if you want a single image flag unpacked into
|
||||
*x*/*y*/*z* components.
|
||||
:p integer(c_int) ids [dimension(:)]: atom IDs corresponding to the atoms
|
||||
to be gathered
|
||||
:p real(c_double) data [dimension(:),allocatable]: array into which to store
|
||||
the data. Array *must* have the ``ALLOCATABLE`` attribute and be of rank 1
|
||||
(i.e., ``DIMENSION(:)``). If this array is already allocated, it will be
|
||||
reallocated to fit the length of the incoming data.
|
||||
|
||||
--------
|
||||
|
||||
.. f:subroutine:: scatter_atoms(name, data)
|
||||
|
||||
This function calls :c:func:`lammps_scatter_atoms` to scatter the named
|
||||
atom-based entities in *data* to all processors.
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
This subroutine takes data stored in a one-dimensional array supplied by the
|
||||
user and scatters them to all atoms on all processors. The data must be
|
||||
ordered by atom ID, with the requirement that the IDs be consecutive.
|
||||
Use :f:func:`scatter_atoms_subset` to scatter data for some (or all)
|
||||
atoms, in any order.
|
||||
|
||||
The *data* array needs to be ordered in groups of *count* values, sorted by
|
||||
atom ID (e.g., if *name* is *x* and *count* = 3, then
|
||||
*data* = [x(1,1) x(2,1) x(3,1) x(1,2) x(2,2) x(3,2) x(1,3) :math:`\dots`];
|
||||
*data* must be of length (*count* :math:`\times` *natoms*).
|
||||
|
||||
:p character(len=\*) name: quantity to be scattered (e.g., *x* or *charge*)
|
||||
:p polymorphic data [dimension(:)]: per-atom values packed in a one-dimensional array
|
||||
containing the data to be scattered. This array must have length *natoms*
|
||||
(e.g., for *type* or *charge*) or length *natoms*\ :math:`\times 3`
|
||||
(e.g., for *x* or *f*). The array *data* must be rank 1 (i.e.,
|
||||
``DIMENSION(:)``) and be of type ``INTEGER(c_int)`` (e.g., for *mask* or
|
||||
*type*) or of type ``REAL(c_double)`` (e.g., for *x* or *charge* or *f*).
|
||||
|
||||
--------
|
||||
|
||||
.. f:subroutine:: scatter_atoms_subset(name, ids, data)
|
||||
|
||||
This function calls :c:func:`lammps_scatter_atoms_subset` to scatter the
|
||||
named atom-based entities in *data* to all processors.
|
||||
|
||||
.. versionadded:: TBD
|
||||
|
||||
This subroutine takes data stored in a one-dimensional array supplied by the
|
||||
user and scatters them to a subset of atoms on all processors. The array
|
||||
*data* contains data associated with atom IDs, but there is no requirement
|
||||
that the IDs be consecutive, as they are provided in a separate array,
|
||||
*ids*. Use :f:func:`scatter_atoms` to scatter data for all atoms, in order.
|
||||
|
||||
The *data* array needs to be organized in groups of 1 or 3 values,
|
||||
depending on which quantity is being scattered, with the groups in the same
|
||||
order as the array *ids*. For example, if you want *data* to be the array
|
||||
[x(1,1) x(2,1) x(3,1) x(1,100) x(2,100) x(3,100) x(1,57) x(2,57) x(3,57)],
|
||||
then *ids* would be [1 100 57] and *name* would be *x*.
|
||||
|
||||
:p character(len=\*) name: quantity to be scattered (e.g., *x* or *charge*)
|
||||
:p integer(c_int) ids [dimension(:)]: atom IDs corresponding to the atoms
|
||||
being scattered
|
||||
:p polymorphic data [dimension(:)]: per-atom values packed into a
|
||||
one-dimensional array containing the data to be scattered. This array must
|
||||
have either the same length as *ids* (for *mask*, *type*, etc.) or three
|
||||
times its length (for *x*, *f*, etc.); the array must be rank 1
|
||||
and be of type ``INTEGER(c_int)`` (e.g., for *mask* or *type*) or of type
|
||||
``REAL(c_double)`` (e.g., *charge*, *x*, or *f*).
|
||||
|
||||
--------
|
||||
|
||||
.. f:function:: version()
|
||||
|
||||
This method returns the numeric LAMMPS version like
|
||||
@ -1183,8 +1284,8 @@ Procedures Bound to the lammps Derived Type
|
||||
.. 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.
|
||||
so as not to overflow this buffer. The string is typically a few hundred
|
||||
bytes long.
|
||||
|
||||
--------
|
||||
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
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 directory contains Fortran code that acts as an interface to LAMMPS as a
|
||||
library and allows the LAMMPS library interface to be invoked from Fortran
|
||||
code. 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
|
||||
in the examples/COUPLE/fortran* folders, but it 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
|
||||
|
||||
@ -114,7 +114,14 @@ MODULE LIBLAMMPS
|
||||
PROCEDURE, PRIVATE :: lmp_gather_atoms_subset_double
|
||||
GENERIC :: gather_atoms_subset => lmp_gather_atoms_subset_int, &
|
||||
lmp_gather_atoms_subset_double
|
||||
PROCEDURE, PRIVATE :: lmp_scatter_atoms_int, lmp_scatter_atoms_double
|
||||
GENERIC :: scatter_atoms => lmp_scatter_atoms_int, &
|
||||
lmp_scatter_atoms_double
|
||||
!
|
||||
PROCEDURE, PRIVATE :: lmp_scatter_atoms_subset_int
|
||||
PROCEDURE, PRIVATE :: lmp_scatter_atoms_subset_double
|
||||
GENERIC :: scatter_atoms_subset => lmp_scatter_atoms_subset_int, &
|
||||
lmp_scatter_atoms_subset_double
|
||||
PROCEDURE :: version => lmp_version
|
||||
PROCEDURE,NOPASS :: get_os_info => lmp_get_os_info
|
||||
PROCEDURE,NOPASS :: config_has_mpi_support => lmp_config_has_mpi_support
|
||||
@ -428,9 +435,20 @@ MODULE LIBLAMMPS
|
||||
INTEGER(c_int), VALUE :: type, count, ndata
|
||||
END SUBROUTINE lammps_gather_atoms_subset
|
||||
|
||||
!SUBROUTINE lammps_scatter_atoms
|
||||
SUBROUTINE lammps_scatter_atoms(handle, name, type, count, data) BIND(C)
|
||||
IMPORT :: c_ptr, c_int
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr), VALUE :: handle, name, data
|
||||
INTEGER(c_int), VALUE :: type, count
|
||||
END SUBROUTINE lammps_scatter_atoms
|
||||
|
||||
!SUBROUTINE lammps_scatter_atoms_subset
|
||||
SUBROUTINE lammps_scatter_atoms_subset(handle, name, type, count, &
|
||||
ndata, ids, data) BIND(C)
|
||||
IMPORT :: c_ptr, c_int
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr), VALUE :: handle, name, ids, data
|
||||
INTEGER(c_int), VALUE :: count, ndata, type
|
||||
END SUBROUTINE lammps_scatter_atoms_subset
|
||||
|
||||
!SUBROUTINE lammps_gather_bonds
|
||||
|
||||
@ -1212,8 +1230,8 @@ CONTAINS
|
||||
TYPE(c_ptr) :: Cdata, Cname
|
||||
INTEGER(c_int) :: natoms
|
||||
INTEGER(c_int), PARAMETER :: Ctype = 0_c_int
|
||||
REAL(C_double) :: dnatoms
|
||||
CHARACTER(LEN=80) :: error_msg
|
||||
REAL(c_double) :: dnatoms
|
||||
CHARACTER(LEN=100) :: error_msg
|
||||
|
||||
IF ( count /= 1 .AND. count /= 3 ) THEN
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, 'gather_atoms&
|
||||
@ -1247,7 +1265,7 @@ CONTAINS
|
||||
INTEGER(c_int) :: natoms
|
||||
INTEGER(c_int), PARAMETER :: Ctype = 1_c_int
|
||||
REAL(C_double) :: dnatoms
|
||||
CHARACTER(LEN=80) :: error_msg
|
||||
CHARACTER(LEN=100) :: error_msg
|
||||
|
||||
IF ( count /= 1 .AND. count /= 3 ) THEN
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, 'gather_atoms&
|
||||
@ -1281,7 +1299,7 @@ CONTAINS
|
||||
INTEGER(c_int) :: natoms
|
||||
INTEGER(c_int), PARAMETER :: Ctype = 0_c_int
|
||||
REAL(C_double) :: dnatoms
|
||||
CHARACTER(LEN=80) :: error_msg
|
||||
CHARACTER(LEN=100) :: error_msg
|
||||
|
||||
IF ( count /= 1 .AND. count /= 3 ) THEN
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, &
|
||||
@ -1316,7 +1334,7 @@ CONTAINS
|
||||
INTEGER(c_int) :: natoms
|
||||
INTEGER(c_int), PARAMETER :: Ctype = 1_c_int
|
||||
REAL(C_double) :: dnatoms
|
||||
CHARACTER(LEN=80) :: error_msg
|
||||
CHARACTER(LEN=100) :: error_msg
|
||||
|
||||
IF ( count /= 1 .AND. count /= 3 ) THEN
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, &
|
||||
@ -1351,11 +1369,12 @@ CONTAINS
|
||||
INTEGER(c_int) :: ndata
|
||||
TYPE(c_ptr) :: Cdata, Cname, Cids
|
||||
INTEGER(c_int), PARAMETER :: Ctype = 0_c_int
|
||||
CHARACTER(LEN=80) :: error_msg
|
||||
CHARACTER(LEN=100) :: error_msg
|
||||
|
||||
IF ( count /= 1 .AND. count /= 3 ) THEN
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, 'gather_atoms&
|
||||
& requires "count" to be 1 or 3 [Fortran/gather_atoms]')
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, &
|
||||
'gather_atoms_subset requires "count" to be 1 or 3 &
|
||||
&[Fortran/gather_atoms]')
|
||||
END IF
|
||||
|
||||
ndata = SIZE(ids, KIND=c_int)
|
||||
@ -1381,11 +1400,12 @@ CONTAINS
|
||||
INTEGER(c_int) :: ndata
|
||||
TYPE(c_ptr) :: Cdata, Cname, Cids
|
||||
INTEGER(c_int), PARAMETER :: Ctype = 1_c_int
|
||||
CHARACTER(LEN=80) :: error_msg
|
||||
CHARACTER(LEN=100) :: error_msg
|
||||
|
||||
IF ( count /= 1 .AND. count /= 3 ) THEN
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, 'gather_atoms&
|
||||
& requires "count" to be 1 or 3 [Fortran/gather_atoms]')
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, &
|
||||
'gather_atoms_subset requires "count" to be 1 or 3 &
|
||||
&[Fortran/gather_atoms]')
|
||||
END IF
|
||||
|
||||
ndata = SIZE(ids, KIND=c_int)
|
||||
@ -1400,6 +1420,121 @@ CONTAINS
|
||||
CALL lammps_free(Cname)
|
||||
END SUBROUTINE lmp_gather_atoms_subset_double
|
||||
|
||||
! equivalent function to lammps_scatter_atoms (for integers)
|
||||
SUBROUTINE lmp_scatter_atoms_int(self, name, data)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
CHARACTER(LEN=*), INTENT(IN) :: name
|
||||
INTEGER(c_int), DIMENSION(:), TARGET :: data
|
||||
INTEGER(c_int) :: natoms, Ccount
|
||||
INTEGER(c_int), PARAMETER :: Ctype = 0_c_int
|
||||
TYPE(c_ptr) :: Cname, Cdata
|
||||
REAL(c_double) :: dnatoms
|
||||
CHARACTER(LEN=100) :: error_msg
|
||||
|
||||
dnatoms = lmp_get_natoms(self)
|
||||
IF ( dnatoms > HUGE(1_c_int) ) THEN
|
||||
WRITE(error_msg,'(A,1X,I0,1X,A)') &
|
||||
'Cannot use library function scatter_atoms with more than', &
|
||||
HUGE(0_c_int), 'atoms [Fortran/scatter_atoms]'
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, error_msg)
|
||||
END IF
|
||||
natoms = NINT(dnatoms, c_int)
|
||||
|
||||
Cname = f2c_string(name)
|
||||
Cdata = C_LOC(data(1))
|
||||
Ccount = SIZE(data) / natoms
|
||||
|
||||
IF ( Ccount /= 1 .AND. Ccount /= 3 ) THEN
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, &
|
||||
'lammps_scatter_atoms requires either 1 or 3 data per atom')
|
||||
END IF
|
||||
CALL lammps_scatter_atoms(self%handle, Cname, Ctype, Ccount, Cdata)
|
||||
CALL lammps_free(Cname)
|
||||
END SUBROUTINE lmp_scatter_atoms_int
|
||||
|
||||
! equivalent function to lammps_scatter_atoms (for doubles)
|
||||
SUBROUTINE lmp_scatter_atoms_double(self, name, data)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
CHARACTER(LEN=*), INTENT(IN) :: name
|
||||
REAL(c_double), DIMENSION(:), TARGET :: data
|
||||
INTEGER(c_int) :: natoms, Ccount
|
||||
INTEGER(c_int), PARAMETER :: Ctype = 1_c_int
|
||||
TYPE(c_ptr) :: Cname, Cdata
|
||||
REAL(c_double) :: dnatoms
|
||||
CHARACTER(LEN=100) :: error_msg
|
||||
|
||||
dnatoms = lmp_get_natoms(self)
|
||||
IF ( dnatoms > HUGE(1_c_int) ) THEN
|
||||
WRITE(error_msg,'(A,1X,I0,1X,A)') &
|
||||
'Cannot use library function scatter_atoms with more than', &
|
||||
HUGE(0_c_int), 'atoms [Fortran/scatter_atoms]'
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, error_msg)
|
||||
END IF
|
||||
natoms = NINT(dnatoms, c_int)
|
||||
|
||||
Cname = f2c_string(name)
|
||||
Cdata = C_LOC(data(1))
|
||||
Ccount = SIZE(data) / natoms
|
||||
|
||||
IF ( Ccount /= 1 .AND. Ccount /= 3 ) THEN
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, &
|
||||
'scatter_atoms requires either 1 or 3 data per atom &
|
||||
&[Fortran/scatter_atoms]')
|
||||
END IF
|
||||
CALL lammps_scatter_atoms(self%handle, Cname, Ctype, Ccount, Cdata)
|
||||
CALL lammps_free(Cname)
|
||||
END SUBROUTINE lmp_scatter_atoms_double
|
||||
|
||||
SUBROUTINE lmp_scatter_atoms_subset_int(self, name, ids, data)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
CHARACTER(LEN=*), INTENT(IN) :: name
|
||||
INTEGER(c_int), DIMENSION(:), TARGET :: ids
|
||||
INTEGER(c_int), DIMENSION(:), TARGET :: data
|
||||
INTEGER(c_int), PARAMETER :: Ctype = 0_c_int
|
||||
INTEGER(c_int) :: Cndata, Ccount
|
||||
TYPE(c_ptr) :: Cdata, Cname, Cids
|
||||
CHARACTER(LEN=100) :: error_msg
|
||||
|
||||
Cndata = SIZE(ids, KIND=c_int)
|
||||
Ccount = SIZE(data, KIND=c_int) / Cndata
|
||||
IF ( Ccount /= 1 .AND. Ccount /= 3 ) THEN
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, &
|
||||
'scatter_atoms_subset requires either 1 or 3 data per atom')
|
||||
END IF
|
||||
|
||||
Cname = f2c_string(name)
|
||||
Cdata = C_LOC(data(1))
|
||||
Cids = C_LOC(ids)
|
||||
CALL lammps_scatter_atoms_subset(self%handle, Cname, Ctype, Ccount, &
|
||||
Cndata, Cids, Cdata)
|
||||
CALL lammps_free(Cname)
|
||||
END SUBROUTINE lmp_scatter_atoms_subset_int
|
||||
|
||||
SUBROUTINE lmp_scatter_atoms_subset_double(self, name, ids, data)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
CHARACTER(LEN=*), INTENT(IN) :: name
|
||||
INTEGER(c_int), DIMENSION(:), TARGET :: ids
|
||||
REAL(c_double), DIMENSION(:), TARGET :: data
|
||||
INTEGER(c_int), PARAMETER :: Ctype = 1_c_int
|
||||
INTEGER(c_int) :: Cndata, Ccount
|
||||
TYPE(c_ptr) :: Cdata, Cname, Cids
|
||||
CHARACTER(LEN=100) :: error_msg
|
||||
|
||||
Cndata = SIZE(ids, KIND=c_int)
|
||||
Ccount = SIZE(data, KIND=c_int) / Cndata
|
||||
IF ( Ccount /= 1 .AND. Ccount /= 3 ) THEN
|
||||
CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, &
|
||||
'scatter_atoms_subset requires either 1 or 3 data per atom')
|
||||
END IF
|
||||
|
||||
Cname = f2c_string(name)
|
||||
Cdata = C_LOC(data(1))
|
||||
Cids = C_LOC(ids)
|
||||
CALL lammps_scatter_atoms_subset(self%handle, Cname, Ctype, Ccount, &
|
||||
Cndata, Cids, Cdata)
|
||||
CALL lammps_free(Cname)
|
||||
END SUBROUTINE lmp_scatter_atoms_subset_double
|
||||
|
||||
! equivalent function to lammps_version
|
||||
INTEGER FUNCTION lmp_version(self)
|
||||
CLASS(lammps), INTENT(IN) :: self
|
||||
|
||||
@ -2551,10 +2551,12 @@ return a similar array for *all* the atoms, use :cpp:func:`lammps_gather_atoms`
|
||||
or :cpp:func:`lammps_gather_atoms_concat`.
|
||||
|
||||
The *data* array will be in groups of *count* values, sorted by atom ID
|
||||
(e.g., if *name* is *x* and *count* = 3, then *data* might look like
|
||||
x[100][0], x[100][1], x[100][2], x[101][0], x[101][1], x[101][2], x[102][0],
|
||||
:math:`\dots`); *data* must be pre-allocated by the caller to length (*count*
|
||||
:math:`\times` *ndata*).
|
||||
in the same order as the array *ids* (e.g., if *name* is *x*, *count* = 3, and
|
||||
*ids* is {100, 57, 210}, then *data* might look like {x[100][0], x[100][1],
|
||||
x[100][2], x[57][0], x[57][1], x[57][2], x[210][0], :math:`\dots`);
|
||||
*ids* must be provided by the user with length *ndata*, and
|
||||
*data* must be pre-allocated by the caller to length
|
||||
(*count* :math:`\times` *ndata*).
|
||||
|
||||
\endverbatim
|
||||
*
|
||||
@ -2601,7 +2603,7 @@ void lammps_gather_atoms_subset(void *handle, char *name, int type, int count,
|
||||
if (lmp->atom->map_style == Atom::MAP_NONE) flag = 1;
|
||||
if (flag) {
|
||||
if (lmp->comm->me == 0)
|
||||
lmp->error->warning(FLERR,"Library error in lammps_gather_atoms_subset");
|
||||
lmp->error->warning(FLERR,"Library error in lammps_gather_atoms_subset: atoms must have mappable ids");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2757,7 +2759,7 @@ void lammps_scatter_atoms(void *handle, char *name, int type, int count, void *d
|
||||
if (lmp->atom->map_style == Atom::MAP_NONE) flag = 1;
|
||||
if (flag) {
|
||||
if (lmp->comm->me == 0)
|
||||
lmp->error->warning(FLERR,"Library error in lammps_scatter_atoms");
|
||||
lmp->error->warning(FLERR,"Library error in lammps_scatter_atoms: ids must exist, be consecutive, and be mapped");
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2908,7 +2910,7 @@ void lammps_scatter_atoms_subset(void *handle, char *name, int type, int count,
|
||||
if (lmp->atom->map_style == Atom::MAP_NONE) flag = 1;
|
||||
if (flag) {
|
||||
if (lmp->comm->me == 0)
|
||||
lmp->error->warning(FLERR,"Library error in lammps_scatter_atoms_subset");
|
||||
lmp->error->warning(FLERR,"Library error in lammps_scatter_atoms_subset: atoms must have mapped ids");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@ -33,39 +33,39 @@ SUBROUTINE f_lammps_setup_gather_scatter () BIND(C)
|
||||
CALL lmp%commands_list(more_input)
|
||||
END SUBROUTINE f_lammps_setup_gather_scatter
|
||||
|
||||
FUNCTION f_lammps_gather_mask (i) BIND(C)
|
||||
FUNCTION f_lammps_gather_atoms_mask (i) BIND(C)
|
||||
USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_int
|
||||
USE LIBLAMMPS
|
||||
USE keepstuff, ONLY : lmp
|
||||
IMPLICIT NONE
|
||||
INTEGER(c_int), INTENT(IN), VALUE :: i
|
||||
INTEGER(c_int) :: f_lammps_gather_mask
|
||||
INTEGER(c_int) :: f_lammps_gather_atoms_mask
|
||||
INTEGER(c_int), DIMENSION(:), ALLOCATABLE :: mask
|
||||
|
||||
CALL lmp%gather_atoms('mask', 1_c_int, mask)
|
||||
f_lammps_gather_mask = mask(i)
|
||||
END FUNCTION f_lammps_gather_mask
|
||||
f_lammps_gather_atoms_mask = mask(i)
|
||||
END FUNCTION f_lammps_gather_atoms_mask
|
||||
|
||||
FUNCTION f_lammps_gather_position (i) BIND(C)
|
||||
FUNCTION f_lammps_gather_atoms_position (i) BIND(C)
|
||||
USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_int, c_double
|
||||
USE LIBLAMMPS
|
||||
USE keepstuff, ONLY : lmp
|
||||
IMPLICIT NONE
|
||||
INTEGER(c_int), INTENT(IN), VALUE :: i
|
||||
REAL(c_double) :: f_lammps_gather_position
|
||||
REAL(c_double) :: f_lammps_gather_atoms_position
|
||||
REAL(c_double), DIMENSION(:), ALLOCATABLE :: positions
|
||||
|
||||
CALL lmp%gather_atoms('x', 3_c_int, positions)
|
||||
f_lammps_gather_position = positions(i)
|
||||
END FUNCTION f_lammps_gather_position
|
||||
f_lammps_gather_atoms_position = positions(i)
|
||||
END FUNCTION f_lammps_gather_atoms_position
|
||||
|
||||
FUNCTION f_lammps_gather_concat_mask (i) BIND(C)
|
||||
FUNCTION f_lammps_gather_atoms_concat_mask (i) BIND(C)
|
||||
USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_int
|
||||
USE LIBLAMMPS
|
||||
USE keepstuff, ONLY : lmp
|
||||
IMPLICIT NONE
|
||||
INTEGER(c_int), INTENT(IN), VALUE :: i
|
||||
INTEGER(c_int) :: f_lammps_gather_concat_mask
|
||||
INTEGER(c_int) :: f_lammps_gather_atoms_concat_mask
|
||||
INTEGER(c_int), DIMENSION(:), ALLOCATABLE :: mask, tag
|
||||
INTEGER :: j
|
||||
|
||||
@ -73,20 +73,20 @@ FUNCTION f_lammps_gather_concat_mask (i) BIND(C)
|
||||
CALL lmp%gather_atoms_concat('id', 1_c_int, tag)
|
||||
DO j = 1, SIZE(tag)
|
||||
IF ( tag(j) == i ) THEN
|
||||
f_lammps_gather_concat_mask = mask(j)
|
||||
f_lammps_gather_atoms_concat_mask = mask(j)
|
||||
RETURN
|
||||
END IF
|
||||
END DO
|
||||
f_lammps_gather_concat_mask = -1
|
||||
END FUNCTION f_lammps_gather_concat_mask
|
||||
f_lammps_gather_atoms_concat_mask = -1
|
||||
END FUNCTION f_lammps_gather_atoms_concat_mask
|
||||
|
||||
FUNCTION f_lammps_gather_concat_position (xyz, id) BIND(C)
|
||||
FUNCTION f_lammps_gather_atoms_concat_position (xyz, id) BIND(C)
|
||||
USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_int, c_double
|
||||
USE LIBLAMMPS
|
||||
USE keepstuff, ONLY : lmp
|
||||
IMPLICIT NONE
|
||||
INTEGER(c_int), INTENT(IN), VALUE :: id, xyz
|
||||
REAL(c_double) :: f_lammps_gather_concat_position
|
||||
REAL(c_double) :: f_lammps_gather_atoms_concat_position
|
||||
REAL(c_double), DIMENSION(:), ALLOCATABLE :: positions
|
||||
INTEGER(c_int), DIMENSION(:), ALLOCATABLE :: tag
|
||||
INTEGER :: j
|
||||
@ -95,18 +95,18 @@ FUNCTION f_lammps_gather_concat_position (xyz, id) BIND(C)
|
||||
CALL lmp%gather_atoms_concat('id', 1_c_int, tag)
|
||||
DO j = 1, SIZE(tag)
|
||||
IF ( tag(j) == id ) THEN
|
||||
f_lammps_gather_concat_position = positions((j-1)*3 + xyz)
|
||||
f_lammps_gather_atoms_concat_position = positions((j-1)*3 + xyz)
|
||||
END IF
|
||||
END DO
|
||||
END FUNCTION f_lammps_gather_concat_position
|
||||
END FUNCTION f_lammps_gather_atoms_concat_position
|
||||
|
||||
FUNCTION f_lammps_gather_subset_mask (i) BIND(C)
|
||||
FUNCTION f_lammps_gather_atoms_subset_mask (i) BIND(C)
|
||||
USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_int
|
||||
USE LIBLAMMPS
|
||||
USE keepstuff, ONLY : lmp
|
||||
IMPLICIT NONE
|
||||
INTEGER(c_int), INTENT(IN), VALUE :: i
|
||||
INTEGER(c_int) :: f_lammps_gather_subset_mask
|
||||
INTEGER(c_int) :: f_lammps_gather_atoms_subset_mask
|
||||
INTEGER(c_int), DIMENSION(:), ALLOCATABLE :: mask
|
||||
INTEGER :: j
|
||||
INTEGER(c_int), DIMENSION(*), PARAMETER :: tag = [3,2]
|
||||
@ -114,20 +114,20 @@ FUNCTION f_lammps_gather_subset_mask (i) BIND(C)
|
||||
CALL lmp%gather_atoms_subset('mask', 1_c_int, tag, mask)
|
||||
DO j = 1, SIZE(tag)
|
||||
IF ( tag(j) == i ) THEN
|
||||
f_lammps_gather_subset_mask = mask(j)
|
||||
f_lammps_gather_atoms_subset_mask = mask(j)
|
||||
RETURN
|
||||
END IF
|
||||
END DO
|
||||
f_lammps_gather_subset_mask = -1
|
||||
END FUNCTION f_lammps_gather_subset_mask
|
||||
f_lammps_gather_atoms_subset_mask = -1
|
||||
END FUNCTION f_lammps_gather_atoms_subset_mask
|
||||
|
||||
FUNCTION f_lammps_gather_subset_position (xyz,id) BIND(C)
|
||||
FUNCTION f_lammps_gather_atoms_subset_position (xyz,id) BIND(C)
|
||||
USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_int, c_double
|
||||
USE LIBLAMMPS
|
||||
USE keepstuff, ONLY : lmp
|
||||
IMPLICIT NONE
|
||||
INTEGER(c_int), INTENT(IN), VALUE :: id, xyz
|
||||
REAL(c_double) :: f_lammps_gather_subset_position
|
||||
REAL(c_double) :: f_lammps_gather_atoms_subset_position
|
||||
REAL(c_double), DIMENSION(:), ALLOCATABLE :: positions
|
||||
INTEGER(c_int), DIMENSION(*), PARAMETER :: tag = [3,2]
|
||||
INTEGER :: j
|
||||
@ -135,9 +135,68 @@ FUNCTION f_lammps_gather_subset_position (xyz,id) BIND(C)
|
||||
CALL lmp%gather_atoms_subset('x', 3_c_int, tag, positions)
|
||||
DO j = 1, SIZE(tag)
|
||||
IF ( tag(j) == id ) THEN
|
||||
f_lammps_gather_subset_position = positions((j-1)*3 + xyz)
|
||||
f_lammps_gather_atoms_subset_position = positions((j-1)*3 + xyz)
|
||||
RETURN
|
||||
END IF
|
||||
END DO
|
||||
f_lammps_gather_subset_position = -1.0D0
|
||||
END FUNCTION f_lammps_gather_subset_position
|
||||
f_lammps_gather_atoms_subset_position = -1.0D0
|
||||
END FUNCTION f_lammps_gather_atoms_subset_position
|
||||
|
||||
SUBROUTINE f_lammps_scatter_atoms_masks() BIND(C)
|
||||
USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_int, c_double
|
||||
USE LIBLAMMPS
|
||||
USE keepstuff, ONLY : lmp
|
||||
IMPLICIT NONE
|
||||
INTEGER(c_int), DIMENSION(:), ALLOCATABLE :: masks
|
||||
INTEGER(c_int) :: swap
|
||||
|
||||
CALL lmp%gather_atoms('mask', 1_c_int, masks)
|
||||
|
||||
! swap masks of atoms 1 and 3
|
||||
swap=masks(1)
|
||||
masks(1) = masks(3)
|
||||
masks(3) = swap
|
||||
|
||||
CALL lmp%scatter_atoms('mask', masks) ! push the swap back to LAMMPS
|
||||
END SUBROUTINE f_lammps_scatter_atoms_masks
|
||||
|
||||
SUBROUTINE f_lammps_scatter_atoms_positions() BIND(C)
|
||||
USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_int, c_double
|
||||
USE LIBLAMMPS
|
||||
USE keepstuff, ONLY : lmp
|
||||
IMPLICIT NONE
|
||||
INTEGER(c_int), DIMENSION(:), ALLOCATABLE :: tags
|
||||
REAL(c_double), DIMENSION(:), ALLOCATABLE, TARGET :: xvec
|
||||
REAL(c_double), DIMENSION(:,:), POINTER :: x
|
||||
REAL(c_double) :: swap(3)
|
||||
|
||||
CALL lmp%gather_atoms('id',1_c_int,tags)
|
||||
CALL lmp%gather_atoms('x',3_c_int,xvec)
|
||||
x(1:3,1:SIZE(xvec)/3) => xvec
|
||||
|
||||
! swap positions of atoms 1 and 3
|
||||
swap=x(:,1)
|
||||
x(:,1) = x(:,3)
|
||||
x(:,3) = swap
|
||||
|
||||
CALL lmp%scatter_atoms('x', xvec) ! push the swap back to LAMMPS
|
||||
END SUBROUTINE f_lammps_scatter_atoms_positions
|
||||
|
||||
SUBROUTINE f_lammps_scatter_atoms_subset_mask() BIND(C)
|
||||
USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_int, c_double
|
||||
USE LIBLAMMPS
|
||||
USE keepstuff, ONLY : lmp
|
||||
IMPLICIT NONE
|
||||
INTEGER(c_int), DIMENSION(:), ALLOCATABLE :: all_masks
|
||||
INTEGER(c_int), DIMENSION(*), PARAMETER :: tags = [3,1]
|
||||
INTEGER(c_int), DIMENSION(2) :: masks
|
||||
INTEGER(c_int) :: swap
|
||||
|
||||
CALL lmp%gather_atoms('mask', 1_c_int, all_masks)
|
||||
|
||||
! swap masks of atoms 1 and 3 in the new array (because 'tags' is reversed)
|
||||
masks(1) = all_masks(1)
|
||||
masks(2) = all_masks(3)
|
||||
|
||||
CALL lmp%scatter_atoms_subset('mask', tags, masks) ! push the swap to LAMMPS
|
||||
END SUBROUTINE f_lammps_scatter_atoms_subset_mask
|
||||
|
||||
@ -15,12 +15,14 @@ extern "C" {
|
||||
void *f_lammps_with_args();
|
||||
void f_lammps_close();
|
||||
void f_lammps_setup_gather_scatter();
|
||||
int f_lammps_gather_mask(int);
|
||||
double f_lammps_gather_position(int);
|
||||
int f_lammps_gather_concat_mask(int);
|
||||
double f_lammps_gather_concat_position(int,int);
|
||||
int f_lammps_gather_subset_mask(int);
|
||||
double f_lammps_gather_subset_position(int,int);
|
||||
int f_lammps_gather_atoms_mask(int);
|
||||
double f_lammps_gather_atoms_position(int);
|
||||
int f_lammps_gather_atoms_concat_mask(int);
|
||||
double f_lammps_gather_atoms_concat_position(int,int);
|
||||
int f_lammps_gather_atoms_subset_mask(int);
|
||||
double f_lammps_gather_atoms_subset_position(int,int);
|
||||
void f_lammps_scatter_atoms_masks();
|
||||
void f_lammps_scatter_atoms_positions();
|
||||
}
|
||||
|
||||
class LAMMPS_gather_scatter : public ::testing::Test {
|
||||
@ -46,95 +48,146 @@ protected:
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_gather_scatter, gather_masks)
|
||||
TEST_F(LAMMPS_gather_scatter, gather_atoms_masks)
|
||||
{
|
||||
f_lammps_setup_gather_scatter();
|
||||
EXPECT_EQ(f_lammps_gather_mask(1), 1);
|
||||
EXPECT_EQ(f_lammps_gather_mask(2), 1);
|
||||
EXPECT_EQ(f_lammps_gather_mask(3), 1);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(1), 1);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(2), 1);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(3), 1);
|
||||
lammps_command(lmp, "group special id 1");
|
||||
lammps_command(lmp, "group other id 2");
|
||||
lammps_command(lmp, "group spiffy id 3");
|
||||
EXPECT_EQ(f_lammps_gather_mask(1), 3);
|
||||
EXPECT_EQ(f_lammps_gather_mask(2), 5);
|
||||
EXPECT_EQ(f_lammps_gather_mask(3), 9);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(1), 3);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(2), 5);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(3), 9);
|
||||
lammps_command(lmp, "group other id 1");
|
||||
EXPECT_EQ(f_lammps_gather_mask(1), 7);
|
||||
EXPECT_EQ(f_lammps_gather_mask(2), 5);
|
||||
EXPECT_EQ(f_lammps_gather_mask(3), 9);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(1), 7);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(2), 5);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(3), 9);
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_gather_scatter, gather_positions)
|
||||
TEST_F(LAMMPS_gather_scatter, gather_atoms_positions)
|
||||
{
|
||||
f_lammps_setup_gather_scatter();
|
||||
EXPECT_EQ(f_lammps_gather_position(1), 1.0);
|
||||
EXPECT_EQ(f_lammps_gather_position(2), 1.0);
|
||||
EXPECT_EQ(f_lammps_gather_position(3), 1.5);
|
||||
EXPECT_EQ(f_lammps_gather_position(4), 0.2);
|
||||
EXPECT_EQ(f_lammps_gather_position(5), 0.1);
|
||||
EXPECT_EQ(f_lammps_gather_position(6), 0.1);
|
||||
EXPECT_EQ(f_lammps_gather_position(7), 0.5);
|
||||
EXPECT_EQ(f_lammps_gather_position(8), 0.5);
|
||||
EXPECT_EQ(f_lammps_gather_position(9), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_position(1), 1.0);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_position(2), 1.0);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_position(3), 1.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_position(4), 0.2);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_position(5), 0.1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_position(6), 0.1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_position(7), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_position(8), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_position(9), 0.5);
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_gather_scatter, gather_masks_concat)
|
||||
TEST_F(LAMMPS_gather_scatter, gather_atoms_concat_masks)
|
||||
{
|
||||
f_lammps_setup_gather_scatter();
|
||||
EXPECT_EQ(f_lammps_gather_concat_mask(1), 1);
|
||||
EXPECT_EQ(f_lammps_gather_concat_mask(2), 1);
|
||||
EXPECT_EQ(f_lammps_gather_concat_mask(3), 1);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_concat_mask(1), 1);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_concat_mask(2), 1);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_concat_mask(3), 1);
|
||||
lammps_command(lmp, "group special id 1");
|
||||
lammps_command(lmp, "group other id 2");
|
||||
lammps_command(lmp, "group spiffy id 3");
|
||||
EXPECT_EQ(f_lammps_gather_concat_mask(1), 3);
|
||||
EXPECT_EQ(f_lammps_gather_concat_mask(2), 5);
|
||||
EXPECT_EQ(f_lammps_gather_concat_mask(3), 9);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_concat_mask(1), 3);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_concat_mask(2), 5);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_concat_mask(3), 9);
|
||||
lammps_command(lmp, "group other id 1");
|
||||
EXPECT_EQ(f_lammps_gather_concat_mask(1), 7);
|
||||
EXPECT_EQ(f_lammps_gather_concat_mask(2), 5);
|
||||
EXPECT_EQ(f_lammps_gather_concat_mask(3), 9);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_concat_mask(1), 7);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_concat_mask(2), 5);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_concat_mask(3), 9);
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_gather_scatter, gather_positions_concat)
|
||||
TEST_F(LAMMPS_gather_scatter, gather_atoms_concat_positions)
|
||||
{
|
||||
f_lammps_setup_gather_scatter();
|
||||
EXPECT_EQ(f_lammps_gather_concat_position(1,1), 1.0);
|
||||
EXPECT_EQ(f_lammps_gather_concat_position(2,1), 1.0);
|
||||
EXPECT_EQ(f_lammps_gather_concat_position(3,1), 1.5);
|
||||
EXPECT_EQ(f_lammps_gather_concat_position(1,2), 0.2);
|
||||
EXPECT_EQ(f_lammps_gather_concat_position(2,2), 0.1);
|
||||
EXPECT_EQ(f_lammps_gather_concat_position(3,2), 0.1);
|
||||
EXPECT_EQ(f_lammps_gather_concat_position(1,3), 0.5);
|
||||
EXPECT_EQ(f_lammps_gather_concat_position(2,3), 0.5);
|
||||
EXPECT_EQ(f_lammps_gather_concat_position(3,3), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(1,1), 1.0);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(2,1), 1.0);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(3,1), 1.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(1,2), 0.2);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(2,2), 0.1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(3,2), 0.1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(1,3), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(2,3), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(3,3), 0.5);
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_gather_scatter, gather_masks_subset)
|
||||
TEST_F(LAMMPS_gather_scatter, gather_atoms_subset_masks)
|
||||
{
|
||||
f_lammps_setup_gather_scatter();
|
||||
EXPECT_EQ(f_lammps_gather_subset_mask(2), 1);
|
||||
EXPECT_EQ(f_lammps_gather_subset_mask(3), 1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_mask(2), 1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_mask(3), 1);
|
||||
lammps_command(lmp, "group special id 1");
|
||||
lammps_command(lmp, "group other id 2");
|
||||
lammps_command(lmp, "group spiffy id 3");
|
||||
EXPECT_EQ(f_lammps_gather_subset_mask(2), 5);
|
||||
EXPECT_EQ(f_lammps_gather_subset_mask(3), 9);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_mask(2), 5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_mask(3), 9);
|
||||
lammps_command(lmp, "group other id 3");
|
||||
EXPECT_EQ(f_lammps_gather_subset_mask(2), 5);
|
||||
EXPECT_EQ(f_lammps_gather_subset_mask(3), 13);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_mask(2), 5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_mask(3), 13);
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_gather_scatter, gather_positions_subset)
|
||||
TEST_F(LAMMPS_gather_scatter, gather_atoms_subset_positions)
|
||||
{
|
||||
f_lammps_setup_gather_scatter();
|
||||
// EXPECT_EQ(f_lammps_gather_subset_position(1,1), 1.0);
|
||||
// EXPECT_EQ(f_lammps_gather_subset_position(2,1), 1.0);
|
||||
// EXPECT_EQ(f_lammps_gather_subset_position(3,1), 1.5);
|
||||
EXPECT_EQ(f_lammps_gather_subset_position(1,2), 0.2);
|
||||
EXPECT_EQ(f_lammps_gather_subset_position(2,2), 0.1);
|
||||
EXPECT_EQ(f_lammps_gather_subset_position(3,2), 0.1);
|
||||
EXPECT_EQ(f_lammps_gather_subset_position(1,3), 0.5);
|
||||
EXPECT_EQ(f_lammps_gather_subset_position(2,3), 0.5);
|
||||
EXPECT_EQ(f_lammps_gather_subset_position(3,3), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_position(1,2), 0.2);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_position(2,2), 0.1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_position(3,2), 0.1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_position(1,3), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_position(2,3), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_subset_position(3,3), 0.5);
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_gather_scatter, scatter_atoms_masks)
|
||||
{
|
||||
f_lammps_setup_gather_scatter();
|
||||
lammps_command(lmp, "group special id 1");
|
||||
lammps_command(lmp, "group other id 2");
|
||||
lammps_command(lmp, "group spiffy id 3");
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_mask(1), 3);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_mask(2), 5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_mask(3), 9);
|
||||
f_lammps_scatter_atoms_masks();
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_mask(1), 9);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_mask(2), 5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_mask(3), 3);
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_gather_scatter, scatter_atoms_positions)
|
||||
{
|
||||
f_lammps_setup_gather_scatter();
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(1,1), 1.0);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(2,1), 1.0);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(3,1), 1.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(1,2), 0.2);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(2,2), 0.1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(3,2), 0.1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(1,3), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(2,3), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(3,3), 0.5);
|
||||
f_lammps_scatter_atoms_positions();
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(1,3), 1.0);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(2,3), 1.0);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(3,3), 1.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(1,2), 0.2);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(2,2), 0.1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(3,2), 0.1);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(1,1), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(2,1), 0.5);
|
||||
EXPECT_DOUBLE_EQ(f_lammps_gather_atoms_concat_position(3,1), 0.5);
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_gather_scatter, scatter_atoms_subset_mask)
|
||||
{
|
||||
f_lammps_setup_gather_scatter();
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(1), 1);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(3), 1);
|
||||
lammps_command(lmp, "group special id 1");
|
||||
lammps_command(lmp, "group other id 2");
|
||||
lammps_command(lmp, "group spiffy id 3");
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(1), 3);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(3), 9);
|
||||
f_lammps_scatter_atoms_masks();
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(1), 9);
|
||||
EXPECT_EQ(f_lammps_gather_atoms_mask(3), 3);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user