add unittest support for the fortran interface to LAMMPS
This commit is contained in:
@ -5,6 +5,7 @@ add_subdirectory(formats)
|
||||
add_subdirectory(commands)
|
||||
add_subdirectory(c-library)
|
||||
add_subdirectory(cplusplus)
|
||||
add_subdirectory(fortran)
|
||||
add_subdirectory(python)
|
||||
add_subdirectory(force-styles)
|
||||
|
||||
|
||||
30
unittest/fortran/CMakeLists.txt
Normal file
30
unittest/fortran/CMakeLists.txt
Normal file
@ -0,0 +1,30 @@
|
||||
include(CheckGeneratorSupport)
|
||||
if(NOT CMAKE_GENERATOR_SUPPORT_FORTRAN)
|
||||
message(STATUS "Skipping Tests for the LAMMPS Fortran Module: no Fortran support in build tool")
|
||||
return()
|
||||
endif()
|
||||
|
||||
include(CheckLanguage)
|
||||
check_language(Fortran)
|
||||
if(CMAKE_Fortran_COMPILER)
|
||||
enable_language(Fortran)
|
||||
get_filename_component(LAMMPS_FORTRAN_MODULE ${LAMMPS_SOURCE_DIR}/../fortran/lammps.f90 ABSOLUTE)
|
||||
if(BUILD_MPI)
|
||||
find_package(MPI REQUIRED)
|
||||
else()
|
||||
add_library(fmpi_stubs STATIC mpi_stubs.f90)
|
||||
add_library(MPI::MPI_Fortran ALIAS fmpi_stubs)
|
||||
endif()
|
||||
|
||||
add_library(flammps STATIC ${LAMMPS_FORTRAN_MODULE})
|
||||
|
||||
add_executable(fortran-create wrap-create.cpp fortran-create.f90)
|
||||
target_link_libraries(fortran-create PRIVATE flammps lammps MPI::MPI_Fortran GTest::GTest GTest::GTestMain)
|
||||
add_test(FortranOpen fortran-create)
|
||||
|
||||
add_executable(fortran-commands wrap-commands.cpp fortran-commands.f90)
|
||||
target_link_libraries(fortran-commands PRIVATE flammps lammps MPI::MPI_Fortran GTest::GTest GTest::GTestMain)
|
||||
add_test(FortranCommands fortran-commands)
|
||||
else()
|
||||
message(STATUS "Skipping Tests for the LAMMPS Fortran Module: no Fortran compiler")
|
||||
endif()
|
||||
111
unittest/fortran/fortran-commands.f90
Normal file
111
unittest/fortran/fortran-commands.f90
Normal file
@ -0,0 +1,111 @@
|
||||
MODULE keepcmds
|
||||
USE liblammps
|
||||
TYPE(LAMMPS) :: lmp
|
||||
CHARACTER(len=*), DIMENSION(*), PARAMETER :: demo_input = &
|
||||
[ 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=*), DIMENSION(*), PARAMETER :: cont_input = &
|
||||
[ CHARACTER(len=40) :: &
|
||||
'create_atoms 1 single &', &
|
||||
' 0.2 0.1 0.1' ]
|
||||
END MODULE keepcmds
|
||||
|
||||
FUNCTION f_lammps_with_args() BIND(C, name="f_lammps_with_args")
|
||||
USE ISO_C_BINDING, ONLY: c_ptr
|
||||
USE liblammps
|
||||
USE keepcmds, ONLY: lmp
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr) :: f_lammps_with_args
|
||||
|
||||
CHARACTER(len=*), DIMENSION(*), PARAMETER :: args = &
|
||||
[ CHARACTER(len=12) :: 'liblammps', '-log', 'none', &
|
||||
'-echo','screen','-nocite','-var','zpos','1.5','-var','x','2']
|
||||
|
||||
lmp = lammps(args)
|
||||
f_lammps_with_args = lmp%handle
|
||||
END FUNCTION f_lammps_with_args
|
||||
|
||||
SUBROUTINE f_lammps_close() BIND(C, name="f_lammps_close")
|
||||
USE ISO_C_BINDING, ONLY: c_null_ptr
|
||||
USE liblammps
|
||||
USE keepcmds, ONLY: lmp
|
||||
IMPLICIT NONE
|
||||
|
||||
CALL lmp%close()
|
||||
lmp%handle = c_null_ptr
|
||||
END SUBROUTINE f_lammps_close
|
||||
|
||||
FUNCTION f_lammps_get_natoms() BIND(C, name="f_lammps_get_natoms")
|
||||
USE ISO_C_BINDING, ONLY: c_null_ptr, c_double
|
||||
USE liblammps
|
||||
USE keepcmds, ONLY: lmp
|
||||
IMPLICIT NONE
|
||||
REAL(c_double) :: f_lammps_get_natoms
|
||||
|
||||
f_lammps_get_natoms = lmp%get_natoms()
|
||||
END FUNCTION f_lammps_get_natoms
|
||||
|
||||
SUBROUTINE f_lammps_file() BIND(C, name="f_lammps_file")
|
||||
USE ISO_C_BINDING, ONLY: c_null_ptr
|
||||
USE liblammps
|
||||
USE keepcmds, ONLY: lmp, demo_input, cont_input
|
||||
IMPLICIT NONE
|
||||
INTEGER :: i
|
||||
CHARACTER(len=*), PARAMETER :: demo_file = 'in.test', cont_file = 'in.cont'
|
||||
|
||||
OPEN(10, file=demo_file, status='replace')
|
||||
WRITE(10, fmt='(A)') (demo_input(i),i=1,SIZE(demo_input))
|
||||
CLOSE(10)
|
||||
OPEN(11, file=cont_file, status='replace')
|
||||
WRITE(11, fmt='(A)') (cont_input(i),i=1,SIZE(cont_input))
|
||||
CLOSE(11)
|
||||
CALL lmp%file(demo_file)
|
||||
CALL lmp%file(cont_file)
|
||||
OPEN(12, file=demo_file, status='old')
|
||||
CLOSE(12, status='delete')
|
||||
OPEN(13, file=cont_file, status='old')
|
||||
CLOSE(13, status='delete')
|
||||
END SUBROUTINE f_lammps_file
|
||||
|
||||
SUBROUTINE f_lammps_command() BIND(C, name="f_lammps_command")
|
||||
USE ISO_C_BINDING, ONLY: c_null_ptr
|
||||
USE liblammps
|
||||
USE keepcmds, ONLY: lmp, demo_input
|
||||
IMPLICIT NONE
|
||||
INTEGER :: i
|
||||
|
||||
DO i=1,SIZE(demo_input)
|
||||
call lmp%command(demo_input(i))
|
||||
END DO
|
||||
END SUBROUTINE f_lammps_command
|
||||
|
||||
SUBROUTINE f_lammps_commands_list() BIND(C, name="f_lammps_commands_list")
|
||||
USE ISO_C_BINDING, ONLY: c_null_ptr
|
||||
USE liblammps
|
||||
USE keepcmds, ONLY: lmp, demo_input, cont_input
|
||||
IMPLICIT NONE
|
||||
|
||||
CALL lmp%commands_list(demo_input)
|
||||
CALL lmp%commands_list(cont_input)
|
||||
END SUBROUTINE f_lammps_commands_list
|
||||
|
||||
SUBROUTINE f_lammps_commands_string() BIND(C, name="f_lammps_commands_string")
|
||||
USE ISO_C_BINDING, ONLY: c_null_ptr
|
||||
USE liblammps
|
||||
USE keepcmds, ONLY: lmp, demo_input, cont_input
|
||||
IMPLICIT NONE
|
||||
INTEGER :: i
|
||||
CHARACTER(len=512) :: cmds
|
||||
|
||||
cmds = ''
|
||||
DO i=1,SIZE(demo_input)
|
||||
cmds = TRIM(cmds) // TRIM(demo_input(i)) // NEW_LINE('A')
|
||||
END DO
|
||||
DO i=1,SIZE(cont_input)
|
||||
cmds = TRIM(cmds) // TRIM(cont_input(i)) // NEW_LINE('A')
|
||||
END DO
|
||||
|
||||
CALL lmp%commands_string(cmds)
|
||||
END SUBROUTINE f_lammps_commands_string
|
||||
86
unittest/fortran/fortran-create.f90
Normal file
86
unittest/fortran/fortran-create.f90
Normal file
@ -0,0 +1,86 @@
|
||||
MODULE keepcreate
|
||||
USE liblammps
|
||||
TYPE(LAMMPS) :: lmp
|
||||
INTEGER :: mycomm
|
||||
END MODULE keepcreate
|
||||
|
||||
FUNCTION f_lammps_no_mpi_no_args() BIND(C, name="f_lammps_no_mpi_no_args")
|
||||
USE ISO_C_BINDING, ONLY: c_ptr
|
||||
USE liblammps
|
||||
USE keepcreate, ONLY: lmp
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr) :: f_lammps_no_mpi_no_args
|
||||
|
||||
lmp = lammps()
|
||||
f_lammps_no_mpi_no_args = lmp%handle
|
||||
END FUNCTION f_lammps_no_mpi_no_args
|
||||
|
||||
FUNCTION f_lammps_no_mpi_with_args() BIND(C, name="f_lammps_no_mpi_with_args")
|
||||
USE ISO_C_BINDING, ONLY: c_ptr
|
||||
USE liblammps
|
||||
USE keepcreate, ONLY: lmp
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr) :: f_lammps_no_mpi_with_args
|
||||
|
||||
CHARACTER(len=*), DIMENSION(*), PARAMETER :: args = &
|
||||
[ CHARACTER(len=12) :: 'liblammps', '-log', 'none', '-nocite' ]
|
||||
|
||||
lmp = lammps(args)
|
||||
f_lammps_no_mpi_with_args = lmp%handle
|
||||
END FUNCTION f_lammps_no_mpi_with_args
|
||||
|
||||
FUNCTION f_lammps_open_no_args() BIND(C, name="f_lammps_open_no_args")
|
||||
USE ISO_C_BINDING, ONLY: c_ptr
|
||||
USE MPI, ONLY: MPI_COMM_WORLD, mpi_comm_split
|
||||
USE liblammps
|
||||
USE keepcreate, ONLY: lmp,mycomm
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr) :: f_lammps_open_no_args
|
||||
INTEGER :: color, key, ierr
|
||||
|
||||
color = 1
|
||||
key = 1
|
||||
CALL mpi_comm_split(MPI_COMM_WORLD, color, key, mycomm, ierr)
|
||||
lmp = lammps(comm=mycomm)
|
||||
f_lammps_open_no_args = lmp%handle
|
||||
END FUNCTION f_lammps_open_no_args
|
||||
|
||||
FUNCTION f_lammps_open_with_args() BIND(C, name="f_lammps_open_with_args")
|
||||
USE ISO_C_BINDING, ONLY: c_ptr
|
||||
USE MPI, ONLY: MPI_COMM_WORLD, mpi_comm_split
|
||||
USE liblammps
|
||||
USE keepcreate, ONLY: lmp,mycomm
|
||||
IMPLICIT NONE
|
||||
TYPE(c_ptr) :: f_lammps_open_with_args
|
||||
INTEGER :: color, key, ierr
|
||||
|
||||
CHARACTER(len=*), DIMENSION(*), PARAMETER :: args = &
|
||||
[ CHARACTER(len=12) :: 'liblammps', '-log', 'none', '-nocite' ]
|
||||
|
||||
color = 2
|
||||
key = 1
|
||||
CALL mpi_comm_split(MPI_COMM_WORLD, color, key, mycomm, ierr)
|
||||
lmp = lammps(args,mycomm)
|
||||
f_lammps_open_with_args = lmp%handle
|
||||
END FUNCTION f_lammps_open_with_args
|
||||
|
||||
SUBROUTINE f_lammps_close() BIND(C, name="f_lammps_close")
|
||||
USE ISO_C_BINDING, ONLY: c_null_ptr
|
||||
USE liblammps
|
||||
USE keepcreate, ONLY: lmp
|
||||
IMPLICIT NONE
|
||||
|
||||
CALL lmp%close()
|
||||
lmp%handle = c_null_ptr
|
||||
END SUBROUTINE f_lammps_close
|
||||
|
||||
FUNCTION f_lammps_get_comm() BIND(C, name="f_lammps_get_comm")
|
||||
USE liblammps
|
||||
USE keepcreate, ONLY: mycomm
|
||||
IMPLICIT NONE
|
||||
INTEGER :: f_lammps_get_comm
|
||||
|
||||
f_lammps_get_comm = mycomm
|
||||
END FUNCTION f_lammps_get_comm
|
||||
|
||||
|
||||
20
unittest/fortran/mpi_stubs.f90
Normal file
20
unittest/fortran/mpi_stubs.f90
Normal file
@ -0,0 +1,20 @@
|
||||
MODULE MPI
|
||||
IMPLICIT NONE
|
||||
PRIVATE
|
||||
|
||||
INTEGER, PARAMETER :: MPI_COMM_WORLD=0
|
||||
INTEGER, PARAMETER :: MPI_SUCCESS=0
|
||||
|
||||
PUBLIC :: MPI_COMM_WORLD, MPI_SUCCESS, &
|
||||
mpi_comm_split
|
||||
|
||||
CONTAINS
|
||||
|
||||
SUBROUTINE mpi_comm_split(comm,color,key,newcomm,ierr)
|
||||
INTEGER, INTENT(in) :: comm,color,key
|
||||
INTEGER, INTENT(out) :: newcomm,ierr
|
||||
|
||||
newcomm = comm + 1
|
||||
ierr = 0
|
||||
END SUBROUTINE mpi_comm_split
|
||||
END MODULE MPI
|
||||
65
unittest/fortran/wrap-commands.cpp
Normal file
65
unittest/fortran/wrap-commands.cpp
Normal file
@ -0,0 +1,65 @@
|
||||
// unit tests for issuing command to a LAMMPS instance through the Fortran wrapper
|
||||
|
||||
#include "lammps.h"
|
||||
#include <mpi.h>
|
||||
#include <cstdio> // for stdin, stdout
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
// prototypes for fortran reverse wrapper functions
|
||||
extern "C" {
|
||||
void *f_lammps_with_args();
|
||||
void f_lammps_close();
|
||||
void f_lammps_file();
|
||||
void f_lammps_command();
|
||||
void f_lammps_commands_list();
|
||||
void f_lammps_commands_string();
|
||||
double f_lammps_get_natoms();
|
||||
}
|
||||
|
||||
class LAMMPS_commands : public ::testing::Test
|
||||
{
|
||||
protected:
|
||||
LAMMPS_NS::LAMMPS *lmp;
|
||||
LAMMPS_commands() {};
|
||||
~LAMMPS_commands() override {};
|
||||
|
||||
void SetUp() override {
|
||||
::testing::internal::CaptureStdout();
|
||||
lmp = (LAMMPS_NS::LAMMPS *)f_lammps_with_args();
|
||||
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_commands, from_file) {
|
||||
EXPECT_EQ(f_lammps_get_natoms(),0);
|
||||
f_lammps_file();
|
||||
EXPECT_EQ(f_lammps_get_natoms(),2);
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_commands, from_line) {
|
||||
EXPECT_EQ(f_lammps_get_natoms(),0);
|
||||
f_lammps_command();
|
||||
EXPECT_EQ(f_lammps_get_natoms(),1);
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_commands, from_list) {
|
||||
EXPECT_EQ(f_lammps_get_natoms(),0);
|
||||
f_lammps_commands_list();
|
||||
EXPECT_EQ(f_lammps_get_natoms(),2);
|
||||
};
|
||||
|
||||
TEST_F(LAMMPS_commands, from_string) {
|
||||
EXPECT_EQ(f_lammps_get_natoms(),0);
|
||||
f_lammps_commands_string();
|
||||
EXPECT_EQ(f_lammps_get_natoms(),2);
|
||||
};
|
||||
97
unittest/fortran/wrap-create.cpp
Normal file
97
unittest/fortran/wrap-create.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
// unit tests for the LAMMPS base class
|
||||
|
||||
#include "lammps.h"
|
||||
#include <mpi.h>
|
||||
#include <cstdio> // for stdin, stdout
|
||||
#include <string>
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
// prototypes for fortran reverse wrapper functions
|
||||
extern "C" {
|
||||
void *f_lammps_open_no_args();
|
||||
void *f_lammps_open_with_args();
|
||||
void *f_lammps_no_mpi_no_args();
|
||||
void *f_lammps_no_mpi_with_args();
|
||||
void f_lammps_close();
|
||||
int f_lammps_get_comm();
|
||||
}
|
||||
|
||||
TEST(open_no_mpi, no_args) {
|
||||
::testing::internal::CaptureStdout();
|
||||
int mpi_init=0;
|
||||
MPI_Initialized(&mpi_init);
|
||||
EXPECT_EQ(mpi_init,0);
|
||||
void *handle = f_lammps_no_mpi_no_args();
|
||||
std::string output = ::testing::internal::GetCapturedStdout();
|
||||
EXPECT_STREQ(output.substr(0,6).c_str(),"LAMMPS");
|
||||
LAMMPS_NS::LAMMPS *lmp = (LAMMPS_NS::LAMMPS *)handle;
|
||||
MPI_Initialized(&mpi_init);
|
||||
EXPECT_NE(mpi_init,0);
|
||||
EXPECT_EQ(lmp->world, MPI_COMM_WORLD);
|
||||
EXPECT_EQ(lmp->infile, stdin);
|
||||
EXPECT_EQ(lmp->screen, stdout);
|
||||
EXPECT_NE(lmp->citeme, nullptr);
|
||||
::testing::internal::CaptureStdout();
|
||||
f_lammps_close();
|
||||
output = ::testing::internal::GetCapturedStdout();
|
||||
EXPECT_STREQ(output.substr(0,16).c_str(), "Total wall time:");
|
||||
}
|
||||
|
||||
TEST(open_no_mpi, with_args) {
|
||||
::testing::internal::CaptureStdout();
|
||||
void *handle = f_lammps_no_mpi_with_args();
|
||||
std::string output = ::testing::internal::GetCapturedStdout();
|
||||
EXPECT_STREQ(output.substr(0,6).c_str(),"LAMMPS");
|
||||
LAMMPS_NS::LAMMPS *lmp = (LAMMPS_NS::LAMMPS *)handle;
|
||||
EXPECT_EQ(lmp->infile, stdin);
|
||||
EXPECT_EQ(lmp->screen, stdout);
|
||||
EXPECT_EQ(lmp->logfile, nullptr);
|
||||
EXPECT_EQ(lmp->citeme, nullptr);
|
||||
EXPECT_EQ(lmp->world, MPI_COMM_WORLD);
|
||||
|
||||
::testing::internal::CaptureStdout();
|
||||
f_lammps_close();
|
||||
output = ::testing::internal::GetCapturedStdout();
|
||||
EXPECT_STREQ(output.substr(0,16).c_str(), "Total wall time:");
|
||||
}
|
||||
|
||||
TEST(fortran_open, no_args) {
|
||||
::testing::internal::CaptureStdout();
|
||||
void *handle = f_lammps_open_no_args();
|
||||
std::string output = ::testing::internal::GetCapturedStdout();
|
||||
EXPECT_STREQ(output.substr(0,6).c_str(),"LAMMPS");
|
||||
LAMMPS_NS::LAMMPS *lmp = (LAMMPS_NS::LAMMPS *)handle;
|
||||
|
||||
int f_comm = f_lammps_get_comm();
|
||||
MPI_Comm mycomm = MPI_Comm_f2c(f_comm);
|
||||
EXPECT_EQ(lmp->world, mycomm);
|
||||
EXPECT_EQ(lmp->infile, stdin);
|
||||
EXPECT_EQ(lmp->screen, stdout);
|
||||
EXPECT_NE(lmp->citeme, nullptr);
|
||||
::testing::internal::CaptureStdout();
|
||||
f_lammps_close();
|
||||
output = ::testing::internal::GetCapturedStdout();
|
||||
EXPECT_STREQ(output.substr(0,16).c_str(), "Total wall time:");
|
||||
}
|
||||
|
||||
TEST(fortran_open, with_args) {
|
||||
::testing::internal::CaptureStdout();
|
||||
void *handle = f_lammps_open_with_args();
|
||||
std::string output = ::testing::internal::GetCapturedStdout();
|
||||
EXPECT_STREQ(output.substr(0,6).c_str(),"LAMMPS");
|
||||
LAMMPS_NS::LAMMPS *lmp = (LAMMPS_NS::LAMMPS *)handle;
|
||||
|
||||
int f_comm = f_lammps_get_comm();
|
||||
MPI_Comm mycomm = MPI_Comm_f2c(f_comm);
|
||||
EXPECT_EQ(lmp->world, mycomm);
|
||||
EXPECT_EQ(lmp->infile, stdin);
|
||||
EXPECT_EQ(lmp->screen, stdout);
|
||||
EXPECT_EQ(lmp->logfile, nullptr);
|
||||
EXPECT_EQ(lmp->citeme, nullptr);
|
||||
|
||||
::testing::internal::CaptureStdout();
|
||||
f_lammps_close();
|
||||
output = ::testing::internal::GetCapturedStdout();
|
||||
EXPECT_STREQ(output.substr(0,16).c_str(), "Total wall time:");
|
||||
}
|
||||
Reference in New Issue
Block a user