diff --git a/fortran/lammps.f90 b/fortran/lammps.f90 index b7ce528b58..6ced71be49 100644 --- a/fortran/lammps.f90 +++ b/fortran/lammps.f90 @@ -1496,6 +1496,7 @@ CONTAINS ! First, we dereference the void** pointer to point to the void* CALL C_F_POINTER(Cptr, Catomptr, [nrows]) ! Catomptr(1) now points to the first element of the array + ! rows and columns are swapped in Fortran CALL C_F_POINTER(Catomptr(1), peratom_data%r64_mat, [ncols,nrows]) CASE (-1) CALL lmp_error(self, LMP_ERROR_ALL + LMP_ERROR_WORLD, & diff --git a/unittest/fortran/keepstuff.f90 b/unittest/fortran/keepstuff.f90 index 63184e1006..c964c8a9c6 100644 --- a/unittest/fortran/keepstuff.f90 +++ b/unittest/fortran/keepstuff.f90 @@ -4,9 +4,9 @@ MODULE keepstuff TYPE(LAMMPS), SAVE :: lmp INTEGER, SAVE :: mycomm CHARACTER(LEN=40), DIMENSION(3), PARAMETER :: demo_input = & - [ CHARACTER(LEN=40) :: & - 'region box block 0 $x 0 2 0 2', & - 'create_box 1 box', & + [ CHARACTER(LEN=40) :: & + 'region box block 0 $x 0 2 0 2', & + 'create_box 1 box', & 'create_atoms 1 single 1.0 1.0 ${zpos}' ] CHARACTER(LEN=40), DIMENSION(3), PARAMETER :: big_input = & [ CHARACTER(LEN=40) :: & @@ -14,15 +14,26 @@ MODULE keepstuff 'create_box 1 box', & 'create_atoms 1 single 1.0 1.0 ${zpos}' ] CHARACTER(LEN=40), DIMENSION(2), PARAMETER :: cont_input = & - [ CHARACTER(LEN=40) :: & - 'create_atoms 1 single &', & + [ CHARACTER(LEN=40) :: & + 'create_atoms 1 single &', & ' 0.2 0.1 0.1' ] + CHARACTER(LEN=60), DIMENSION(18), PARAMETER :: prop_input = & + [ CHARACTER(LEN=60) :: 'fix 1 all nve', 'mass 1 3.0', & + 'fix 2 all property/atom mol q rmass ghost yes', & + 'fix 3 all property/atom i_one i2_two 2 d_three d2_four 2', & + 'set group all mass 2.0', 'set atom 1 charge -1', & + 'set atom 2 charge 1', 'set atom 1 mol 2', 'set atom 2 mol 1', & + 'set atom 1 i_one -3', 'set atom 2 i_one 3', & + 'set atom 1 d_three -1.3', 'set atom 2 d_three 3.5', & + 'set atom 1 i_two[1] -3', 'set atom 2 i_two[2] 3', & + 'set atom * d_four[1] -1.3', 'set atom * d_four[2] 3.5', & + 'run 0 post no' ] CHARACTER(LEN=40), DIMENSION(1), PARAMETER :: more_input = & [ CHARACTER(LEN=40) :: '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', & + [ CHARACTER(LEN=40) :: & + 'pair_style lj/cut 2.5', & + 'pair_coeff 1 1 1.0 1.0', & 'mass 1 2.0' ] INTERFACE @@ -63,4 +74,3 @@ CONTAINS END FUNCTION f2c_string END MODULE keepstuff - diff --git a/unittest/fortran/test_fortran_extract_atom.f90 b/unittest/fortran/test_fortran_extract_atom.f90 index 262e5de47d..0c5a52ef25 100644 --- a/unittest/fortran/test_fortran_extract_atom.f90 +++ b/unittest/fortran/test_fortran_extract_atom.f90 @@ -24,12 +24,13 @@ END SUBROUTINE f_lammps_close SUBROUTINE f_lammps_setup_extract_atom() BIND(C) USE LIBLAMMPS - USE keepstuff, ONLY : lmp, big_input, cont_input, pair_input + USE keepstuff, ONLY : lmp, big_input, cont_input, pair_input, prop_input IMPLICIT NONE CALL lmp%commands_list(big_input) CALL lmp%commands_list(cont_input) CALL lmp%commands_list(pair_input) + CALL lmp%commands_list(prop_input) END SUBROUTINE f_lammps_setup_extract_atom FUNCTION f_lammps_extract_atom_mass() BIND(C) @@ -44,6 +45,19 @@ FUNCTION f_lammps_extract_atom_mass() BIND(C) f_lammps_extract_atom_mass = mass(1) END FUNCTION f_lammps_extract_atom_mass +FUNCTION f_lammps_extract_atom_mass_size() BIND(C) + USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_double, c_int + USE LIBLAMMPS + USE keepstuff, ONLY : lmp + IMPLICIT NONE + INTEGER(c_int) :: f_lammps_extract_atom_mass_size, ntypes + REAL(c_double), DIMENSION(:), POINTER :: mass => NULL() + + ntypes = lmp%extract_setting('ntypes') + mass = lmp%extract_atom('mass') + f_lammps_extract_atom_mass_size = SIZE(mass) +END FUNCTION f_lammps_extract_atom_mass_size + FUNCTION f_lammps_extract_atom_tag_int(i) BIND(C) USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_double, c_int USE LIBLAMMPS @@ -83,6 +97,18 @@ FUNCTION f_lammps_extract_atom_type(i) BIND(C) f_lammps_extract_atom_type = atype(i) END FUNCTION f_lammps_extract_atom_type +FUNCTION f_lammps_extract_atom_type_size() BIND(C) + USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_int + USE LIBLAMMPS + USE keepstuff, ONLY : lmp + IMPLICIT NONE + INTEGER(c_int) :: f_lammps_extract_atom_type_size + INTEGER(c_int), DIMENSION(:), POINTER :: atype => NULL() + + atype = lmp%extract_atom('type') + f_lammps_extract_atom_type_size = size(atype) +END FUNCTION f_lammps_extract_atom_type_size + FUNCTION f_lammps_extract_atom_mask(i) BIND(C) USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_int USE LIBLAMMPS @@ -109,6 +135,19 @@ SUBROUTINE f_lammps_extract_atom_x(i, x) BIND(C) x = xptr(:,i) END SUBROUTINE f_lammps_extract_atom_x +FUNCTION f_lammps_extract_atom_x_size(i) BIND(C) + USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_double, c_int + USE LIBLAMMPS + USE keepstuff, ONLY : lmp + IMPLICIT NONE + INTEGER(c_int), INTENT(IN), VALUE :: i + INTEGER(c_int) :: f_lammps_extract_atom_x_size + REAL(c_double), DIMENSION(:,:), POINTER :: xptr => NULL() + + xptr = lmp%extract_atom('x') + f_lammps_extract_atom_x_size = SIZE(xptr, i) +END FUNCTION f_lammps_extract_atom_x_size + SUBROUTINE f_lammps_extract_atom_v(i, v) BIND(C) USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_double, c_int USE LIBLAMMPS @@ -121,3 +160,16 @@ SUBROUTINE f_lammps_extract_atom_v(i, v) BIND(C) vptr = lmp%extract_atom('v') v = vptr(:,i) END SUBROUTINE f_lammps_extract_atom_v + +FUNCTION f_lammps_extract_atom_v_size(i) BIND(C) + USE, INTRINSIC :: ISO_C_BINDING, ONLY : c_double, c_int + USE LIBLAMMPS + USE keepstuff, ONLY : lmp + IMPLICIT NONE + INTEGER(c_int), INTENT(IN), VALUE :: i + INTEGER(c_int) :: f_lammps_extract_atom_v_size + REAL(c_double), DIMENSION(:,:), POINTER :: xptr => NULL() + + xptr = lmp%extract_atom('v') + f_lammps_extract_atom_v_size = SIZE(xptr, i) +END FUNCTION f_lammps_extract_atom_v_size diff --git a/unittest/fortran/wrap_extract_atom.cpp b/unittest/fortran/wrap_extract_atom.cpp index 2552d6a10f..9430959b2b 100644 --- a/unittest/fortran/wrap_extract_atom.cpp +++ b/unittest/fortran/wrap_extract_atom.cpp @@ -1,6 +1,7 @@ // unit tests for extracting Atom class data from a LAMMPS instance through the // Fortran wrapper +#include "atom.h" #include "lammps.h" #include "library.h" #include @@ -16,12 +17,16 @@ void *f_lammps_with_args(); void f_lammps_close(); void f_lammps_setup_extract_atom(); double f_lammps_extract_atom_mass(); +int f_lammps_extract_atom_mass_size(); int f_lammps_extract_atom_tag_int(int); int64_t f_lammps_extract_atom_tag_int64(int64_t); int f_lammps_extract_atom_type(int); +int f_lammps_extract_atom_type_size(); int f_lammps_extract_atom_mask(int); void f_lammps_extract_atom_x(int, double *); +int f_lammps_extract_atom_x_size(int); void f_lammps_extract_atom_v(int, double *); +int f_lammps_extract_atom_v_size(int); } class LAMMPS_extract_atom : public ::testing::Test { @@ -50,7 +55,9 @@ protected: TEST_F(LAMMPS_extract_atom, mass) { f_lammps_setup_extract_atom(); - EXPECT_DOUBLE_EQ(f_lammps_extract_atom_mass(), 2.0); + int ntypes = lmp->atom->ntypes; + EXPECT_DOUBLE_EQ(f_lammps_extract_atom_mass(), 3.0); + EXPECT_EQ(f_lammps_extract_atom_mass_size(), ntypes + 1); }; TEST_F(LAMMPS_extract_atom, tag) @@ -68,8 +75,10 @@ TEST_F(LAMMPS_extract_atom, tag) TEST_F(LAMMPS_extract_atom, type) { f_lammps_setup_extract_atom(); + int nall = lmp->atom->nlocal + lmp->atom->nghost; EXPECT_EQ(f_lammps_extract_atom_type(1), 1); EXPECT_EQ(f_lammps_extract_atom_type(2), 1); + EXPECT_EQ(f_lammps_extract_atom_type_size(), nall); }; TEST_F(LAMMPS_extract_atom, mask) @@ -86,6 +95,7 @@ TEST_F(LAMMPS_extract_atom, mask) TEST_F(LAMMPS_extract_atom, x) { f_lammps_setup_extract_atom(); + int nall = lmp->atom->nlocal + lmp->atom->nghost; double x1[3]; double x2[3]; f_lammps_extract_atom_x(1, x1); @@ -96,11 +106,15 @@ TEST_F(LAMMPS_extract_atom, x) EXPECT_DOUBLE_EQ(x2[0], 0.2); EXPECT_DOUBLE_EQ(x2[1], 0.1); EXPECT_DOUBLE_EQ(x2[2], 0.1); + // in Fortran row and column are swapped + EXPECT_EQ(f_lammps_extract_atom_x_size(1), 3); + EXPECT_EQ(f_lammps_extract_atom_x_size(2), nall); } TEST_F(LAMMPS_extract_atom, v) { f_lammps_setup_extract_atom(); + int nall = lmp->atom->nlocal + lmp->atom->nghost; double v1[3]; double v2[3]; f_lammps_extract_atom_v(1, v1); @@ -117,4 +131,13 @@ TEST_F(LAMMPS_extract_atom, v) EXPECT_DOUBLE_EQ(v1[0], 1.0); EXPECT_DOUBLE_EQ(v1[1], 2.0); EXPECT_DOUBLE_EQ(v1[2], 3.0); + // in Fortran row and column are swapped! + EXPECT_EQ(f_lammps_extract_atom_v_size(1), 3); + EXPECT_EQ(f_lammps_extract_atom_v_size(2), lmp->atom->nlocal); + lammps_command(lmp, "comm_modify vel yes"); + lammps_command(lmp, "run 0 post no"); + EXPECT_EQ(f_lammps_extract_atom_v_size(1), 3); + EXPECT_EQ(f_lammps_extract_atom_v_size(2), nall); } + +// TODO: write tests for custom properties