Merge branch 'develop' into always-exceptions

This commit is contained in:
Axel Kohlmeyer
2023-06-22 10:53:36 -04:00
561 changed files with 26484 additions and 14127 deletions

View File

@ -19,12 +19,12 @@ See these sections of the LAMMPS manual for details:
Build LAMMPS as a library (doc/html/Build_basics.html)
Link LAMMPS as a library to another code (doc/html/Build_link.html)
Coupling LAMMPS to other codes (doc/html/Howto_couple.html)
Using LAMMPS in client/server mode (doc/html/Howto_client_server.html)
Library interface to LAMMPS (doc/html/Howto_library.html)
Detailed documentation of the LAMMPS interfaces (doc/html/Library.html)
The library interface to LAMMPS is in src/library.cpp. Routines can
be easily added to this file so an external program can perform the
LAMMPS tasks desired.
The core library interface to LAMMPS is in src/library.cpp. Routines
can be easily added to this file so an external program can perform
the LAMMPS tasks desired.
-------------------------------------------------------------------
@ -36,10 +36,5 @@ plugin example for loading LAMMPS at runtime from a shared library
lammps_spparks grain-growth Monte Carlo with strain via MD,
coupling to SPPARKS kinetic MC code
library collection of useful inter-code communication routines
fortran2 a more sophisticated wrapper on the LAMMPS library API that
can be called from Fortran
fortran_dftb wrapper written by Nir Goldman (LLNL), as an
extension to fortran2, used for calling LAMMPS
from Fortran DFTB+ tight-binding code
Each sub-directory has its own README with more details.

View File

@ -1 +0,0 @@
*.mod

View File

@ -1,96 +0,0 @@
/* -----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------
Contributing author: Karl D. Hammond <hammondkd@missouri.edu>
University of Missouri (USA), 2012
------------------------------------------------------------------------- */
/* This is set of "wrapper" functions to assist LAMMPS.F90, which itself
provides a (I hope) robust Fortran interface to library.cpp and
library.h. All functions herein COULD be added to library.cpp instead of
including this as a separate file. See the README for instructions. */
#include <mpi.h>
#include "LAMMPS-wrapper.h"
#define LAMMPS_LIB_MPI 1
#include <library.h>
#include <lammps.h>
#include <atom.h>
#include <fix.h>
#include <compute.h>
#include <modify.h>
#include <error.h>
#include <cstdlib>
using namespace LAMMPS_NS;
void lammps_open_fortran_wrapper (int argc, char **argv,
MPI_Fint communicator, void **ptr)
{
MPI_Comm C_communicator = MPI_Comm_f2c (communicator);
lammps_open (argc, argv, C_communicator, ptr);
}
int lammps_get_ntypes (void *ptr)
{
class LAMMPS *lmp = (class LAMMPS *) ptr;
int ntypes = lmp->atom->ntypes;
return ntypes;
}
void lammps_error_all (void *ptr, const char *file, int line, const char *str)
{
class LAMMPS *lmp = (class LAMMPS *) ptr;
lmp->error->all (file, line, str);
}
int lammps_extract_compute_vectorsize (void *ptr, char *id, int style)
{
int *size;
size = (int *) lammps_extract_compute(ptr, id, style, LMP_SIZE_VECTOR);
if (size) return *size;
return 0;
}
void lammps_extract_compute_arraysize (void *ptr, char *id, int style,
int *nrows, int *ncols)
{
int *tmp;
tmp = (int *) lammps_extract_compute(ptr, id, style, LMP_SIZE_ROWS);
if (tmp) *nrows = *tmp;
tmp = (int *) lammps_extract_compute(ptr, id, style, LMP_SIZE_COLS);
if (tmp) *ncols = *tmp;
return;
}
int lammps_extract_fix_vectorsize (void *ptr, char *id, int style)
{
int *size;
size = (int *) lammps_extract_fix(ptr, id, style, LMP_SIZE_VECTOR, 0, 0);
if (size) return *size;
return 0;
}
void lammps_extract_fix_arraysize (void *ptr, char *id, int style,
int *nrows, int *ncols)
{
int *tmp;
tmp = (int *) lammps_extract_fix(ptr, id, style, LMP_SIZE_ROWS, 0, 0);
if (tmp) *nrows = *tmp;
tmp = (int *) lammps_extract_fix(ptr, id, style, LMP_SIZE_COLS, 0, 0);
if (tmp) *ncols = *tmp;
return;
}
/* vim: set ts=3 sts=3 expandtab: */

View File

@ -1,41 +0,0 @@
/* -----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------
Contributing author: Karl D. Hammond <hammondkd@missouri.edu>
University of Missouri (USA), 2012
------------------------------------------------------------------------- */
/* This is set of "wrapper" functions to assist LAMMPS.F90, which itself
provides a (I hope) robust Fortran interface to library.cpp and
library.h. All prototypes herein COULD be added to library.h instead of
including this as a separate file. See the README for instructions. */
#ifdef __cplusplus
extern "C" {
#endif
/* Prototypes for auxiliary functions */
void lammps_open_fortran_wrapper (int, char**, MPI_Fint, void**);
int lammps_get_ntypes (void*);
int lammps_extract_compute_vectorsize (void*, char*, int);
void lammps_extract_compute_arraysize (void*, char*, int, int*, int*);
int lammps_extract_fix_vectorsize (void*, char*, int);
void lammps_extract_fix_arraysize (void*, char*, int, int*, int*);
void lammps_error_all (void*, const char*, int, const char*);
#ifdef __cplusplus
}
#endif
/* vim: set ts=3 sts=3 expandtab: */

File diff suppressed because it is too large Load Diff

View File

@ -1,41 +0,0 @@
SHELL = /bin/sh
# Path to LAMMPS extraction directory
LAMMPS_ROOT = ../../..
LAMMPS_SRC = $(LAMMPS_ROOT)/src
# Uncomment the line below if using the MPI stubs library
MPI_STUBS = #-I$(LAMMPS_SRC)/STUBS
FC = mpifort # replace with your Fortran compiler
CXX = mpicxx # replace with your C++ compiler
CXXLIB = -lstdc++ # replace with your C++ runtime libs
# Flags for Fortran compiler, C++ compiler, and C preprocessor, respectively
FFLAGS = -O2 -fPIC
CXXFLAGS = -O2 -fPIC
CPPFLAGS = -DOMPI_SKIP_MPICXX=1 -DMPICH_SKIP_MPICXX
all : liblammps_fortran.a liblammps_fortran.so
@echo "WARNING: this Fortran interface is obsolete and is no longer
maintained. See $(LAMMPS_ROOT)/fortran for the new, maintained interface
(largely written by the same author). You may continue to use this interface if
desired, but it may eventually be removed from LAMMPS."
liblammps_fortran.so : LAMMPS.o LAMMPS-wrapper.o
$(FC) $(FFLAGS) -shared -o $@ $^ $(CXXLIB)
liblammps_fortran.a : LAMMPS.o LAMMPS-wrapper.o
$(AR) rs $@ $^
LAMMPS.o lammps.mod : LAMMPS.F90
$(FC) $(CPPFLAGS) $(FFLAGS) -c $<
LAMMPS-wrapper.o : LAMMPS-wrapper.cpp LAMMPS-wrapper.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -I$(LAMMPS_SRC) $(MPI_STUBS)
clean :
$(RM) *.o *.mod liblammps_fortran.a liblammps_fortran.so
dist :
tar -czf Fortran-interface.tar.gz LAMMPS-wrapper.h LAMMPS-wrapper.cpp LAMMPS.F90 makefile README

View File

@ -1,273 +0,0 @@
!! NOTE -------------------------------------------------------------------
! This interface is obsolete and may be removed in a future release of
! LAMMPS. The interface in fortran/lammps.f90 replaces this one. That API
! is maintained by the LAMMPS developers and has documentation written for
! it; it is based loosely on this one, but binds all procedures to a lammps
! derived type. That interface was written in large
! part by the same author, but is also supported by other developers.
!--------------------------------------------------------------------------
LAMMPS.F90 defines a Fortran 2003 module, LAMMPS, which wraps all functions in
src/library.h so they can be used directly from Fortran-encoded programs.
All functions in src/library.h that use and/or return C-style pointers have
Fortran wrapper functions that use Fortran-style arrays, pointers, and
strings; all C-style memory management is handled internally with no user
intervention. See --USE-- for notes on how this interface differs from the
C interface (and the Python interface).
This interface was created by Karl Hammond who you can contact with
questions:
Karl D. Hammond
University of Missouri
hammondkd at missouri.edu
-------------------------------------
--COMPILATION--
First, be advised that mixed-language programming is not trivial. It requires
you to link in the required libraries of all languages you use (in this case,
those for Fortran, C, and C++), as well as any other libraries required.
You are also advised to read the --USE-- section below before trying to
compile.
The following steps will work to compile this module (replace ${LAMMPS_SRC}
with the path to your LAMMPS source directory).
Steps 3-5 are accomplished, possibly after some modifications to
the makefile, by make using the attached makefile. Said makefile also builds
the dynamically-linkable library (liblammps_fortran.so).
** STATIC LIBRARY INSTRUCTIONS **
(1) Compile LAMMPS as a static library.
Call the resulting file ${LAMMPS_LIB}, which will have an actual name
like liblmp_openmpi.a. If compiling using the MPI stubs in
${LAMMPS_SRC}/STUBS, you will need to know where libmpi_stubs.a
is as well (I'll call it ${MPI_STUBS} hereafter)
(2) Copy said library to your Fortran program's source directory or replace
${LAMMPS_LIB} with its full path in the instructions below.
(3) Compile (but don't link!) LAMMPS.F90. Example:
mpifort -c LAMMPS.f90
OR
gfortran -c LAMMPS.F90
NOTE: you may get a warning such as,
subroutine lammps_open_wrapper (argc, argv, communicator, ptr) &
Variable 'communicator' at (1) is a parameter to the BIND(C)
procedure 'lammps_open_wrapper' but may not be C interoperable
This is normal (see --IMPLEMENTATION NOTES--).
(4) Compile (but don't link) LAMMPS-wrapper.cpp. You will need its header
file as well. You will have to provide the locations of LAMMPS's
header files. For example,
mpicxx -c -I${LAMMPS_SRC} LAMMPS-wrapper.cpp
OR
g++ -c -I${LAMMPS_SRC} -I${LAMMPS_SRC}/STUBS LAMMPS-wrapper.cpp
OR
icpc -c -I${LAMMPS_SRC} -I${LAMMPS_SRC}/STUBS LAMMPS-wrapper.cpp
(5) OPTIONAL: Make a library from the object files so you can carry around
two files instead of three. Example:
ar rs liblammps_fortran.a LAMMPS.o LAMMPS-wrapper.o
This will create the file liblammps_fortran.a that you can use in place
of "LAMMPS.o LAMMPS-wrapper.o" later. Note that you will still
need to have the .mod file from part (3).
It is also possible to add LAMMPS.o and LAMMPS-wrapper.o into the
LAMMPS library (e.g., liblmp_openmpi.a) instead of creating a separate
library, like so:
ar rs ${LAMMPS_LIB} LAMMPS.o LAMMPS-wrapper.o
In this case, you can now use the Fortran wrapper functions as if they
were part of the usual LAMMPS library interface (if you have the module
file visible to the compiler, that is).
(6) Compile (but don't link) your Fortran program. Example:
mpifort -c myfreeformatfile.f90
mpifort -c myfixedformatfile.f
OR
gfortran -c myfreeformatfile.f90
gfortran -c myfixedformatfile.f
The object files generated by these steps are collectively referred to
as ${my_object_files} in the next step(s).
IMPORTANT: If the Fortran module from part (3) is not in the current
directory or in one searched by the compiler for module files, you will
need to include that location via the -I flag to the compiler, like so:
mpifort -I${LAMMPS_SRC}/examples/COUPLE/fortran2 -c myfreeformatfile.f90
(7) Link everything together, including any libraries needed by LAMMPS (such
as the C++ standard library, the C math library, the JPEG library, fftw,
etc.) For example,
mpifort LAMMPS.o LAMMPS-wrapper.o ${my_object_files} \
${LAMMPS_LIB} -lmpi_cxx -lstdc++ -lm
OR
gfortran LAMMPS.o LAMMPS-wrapper.o ${my_object_files} \
${LAMMPS_LIB} ${MPI_STUBS} -lstdc++ -lm
OR
ifort LAMMPS.o LAMMPS-wrapper.o ${my_object_files} \
${LAMMPS_LIB} ${MPI_STUBS} -cxxlib -lm
Any other required libraries (e.g. -ljpeg, -lfftw) should be added to
the end of this line.
You should now have a working executable.
** DYNAMIC LIBRARY INSTRUCTIONS **
(1) Compile LAMMPS as a dynamic library
(make makeshlib && make -f Makefile.shlib [targetname]).
(2) Compile, but don't link, LAMMPS.F90 using the -fPIC flag, such as
mpifort -fPIC -c LAMMPS.f90
(3) Compile, but don't link, LAMMPS-wrapper.cpp in the same manner, e.g.
mpicxx -fPIC -c LAMMPS-wrapper.cpp
(4) Make the dynamic library, like so:
mpifort -fPIC -shared -o liblammps_fortran.so LAMMPS.o LAMMPS-wrapper.o
(5) Compile your program, such as,
mpifort -I${LAMMPS_SRC}/examples/COUPLE/fortran2 -c myfreeformatfile.f90
where ${LAMMPS_SRC}/examples/COUPLE/fortran2 contains the .mod file from
step (3)
(6) Link everything together, such as
mpifort ${my_object_files} -L${LAMMPS_SRC} \
-L${LAMMPS_SRC}/examples/COUPLE/fortran2 -llammps_fortran \
-llammps_openmpi -lmpi_cxx -lstdc++ -lm
If you wish to avoid the -L flags, add the directories containing your
shared libraries to the LIBRARY_PATH environment variable. At run time, you
will have to add these directories to LD_LIBRARY_PATH as well; otherwise,
your executable will not find the libraries it needs.
-------------------------------------
--USAGE--
To use this API, your program unit (PROGRAM/SUBROUTINE/FUNCTION/MODULE/etc.)
should look something like this:
program call_lammps
use LAMMPS
! Other modules, etc.
implicit none
type (lammps_instance) :: lmp ! This is a pointer to your LAMMPS instance
real (C_double) :: fix
real (C_double), dimension(:), pointer :: fix2
! Rest of declarations
call lammps_open_no_mpi ('lmp -in /dev/null -screen out.lammps',lmp)
! Set up rest of program here
call lammps_file (lmp, 'in.example')
call lammps_extract_fix (fix, lmp, '2', 0, 1, 1, 1)
call lammps_extract_fix (fix2, lmp, '4', 0, 2, 1, 1)
call lammps_close (lmp)
end program call_lammps
Important notes:
* Though I dislike the use of pointers, they are necessary when communicating
with C and C++, which do not support Fortran's ALLOCATABLE attribute.
* There is no need to deallocate C-allocated memory; this is done for you in
the cases when it is done (which are all cases when pointers are not
accepted, such as global fix data)
* All arguments which are char* variables in library.cpp are character (len=*)
variables here. For example,
call lammps_command (lmp, 'units metal')
will work as expected.
* The public functions (the only ones you can use) have interfaces as
described in the comments at the top of LAMMPS.F90. They are not always
the same as those in library.h, since C strings are replaced by Fortran
strings and the like.
* The module attempts to check whether you have done something stupid (such
as assign a 2D array to a scalar), but it's not perfect. For example, the
command
call lammps_extract_global (nlocal, ptr, 'nlocal')
will give nlocal correctly if nlocal is a pointer to type INTEGER, but it
will give the wrong answer if nlocal is a pointer to type REAL. This is a
feature of the (void*) type cast in library.cpp. There is no way I can
check this for you! It WILL catch you if you pass it an allocatable or
fixed-size array when it expects a pointer.
* Arrays constructed from temporary data from LAMMPS are ALLOCATABLE, and
represent COPIES of data, not the originals. Functions like
lammps_extract_atom, which return actual LAMMPS data, are pointers.
* IMPORTANT: Due to the differences between C and Fortran arrays (C uses
row-major vectors, Fortran uses column-major vectors), all arrays returned
from LAMMPS have their indices swapped.
* An example of a complete program, simple.f90, is included with this
package.
-------------------------------------
--TROUBLESHOOTING--
Compile-time errors (when compiling LAMMPS.F90, that is) probably indicate
that your compiler is not new enough to support Fortran 2003 features. For
example, GCC 4.1.2 will not compile this module, but GCC 4.4.0 will.
If your compiler balks at 'use, intrinsic :: ISO_C_binding,' try removing the
intrinsic part so it looks like an ordinary module. However, it is likely
that such a compiler will also have problems with everything else in the
file as well.
If you get a segfault as soon as the lammps_open call is made, check that you
compiled your program AND LAMMPS-wrapper.cpp using the same MPI headers. Using
the stubs for one and the actual MPI library for the other will cause Bad
Things to happen.
If you find run-time errors, please pass them along via the LAMMPS Users
mailing list (please CC me as well; address above). Please provide a minimal
working example along with the names and versions of the compilers you are
using. Please make sure the error is repeatable and is in MY code, not yours
(generating a minimal working example will usually ensure this anyway).
-------------------------------------
--IMPLEMENTATION NOTES--
The Fortran procedures have the same names as the C procedures, and
their purpose is the same, but they may take different arguments. Here are
some of the important differences:
* lammps_open and lammps_open_no_mpi take a string instead of argc and
argv. This is necessary because C and C++ have a very different way
of treating strings than Fortran. If you want the command line to be
passed to lammps_open (as it often would be from C/C++), use the
GET_COMMAND intrinsic to obtain it.
* All C++ functions that accept char* pointers now accept Fortran-style
strings within this interface instead.
* All of the lammps_extract_[something] functions, which return void*
C-style pointers, have been replaced by generic subroutines that return
Fortran variables (which may be arrays). The first argument houses the
variable/pointer to be returned (pretend it's on the left-hand side); all
other arguments are identical except as stipulated above.
Note that it is not possible to declare generic functions that are selected
based solely on the type/kind/rank (TKR) signature of the return value,
only based on the TKR of the arguments.
* The SHAPE of the first argument to lammps_extract_[something] is checked
against the "shape" of the C array (e.g., double vs. double* vs. double**).
Calling a subroutine with arguments of inappropriate rank will result in an
error at run time.
* The indices i and j in lammps_extract_fix are used the same way they
are in f_ID[i][j] references in LAMMPS (i.e., starting from 1). This is
different than the way library.cpp uses these numbers, but is more
consistent with the way arrays are accessed in LAMMPS and in Fortran.
* The char* pointer normally returned by lammps_command is thrown away
in this version; note also that lammps_command is now a subroutine
instead of a function.
* The pointer to LAMMPS itself is of type(lammps_instance), which is itself
a synonym for type(C_ptr), part of ISO_C_BINDING. Type (C_ptr) is
C's void* data type.
* This module will almost certainly generate a compile-time warning,
such as,
subroutine lammps_open_wrapper (argc, argv, communicator, ptr) &
Variable 'communicator' at (1) is a parameter to the BIND(C)
procedure 'lammps_open_wrapper' but may not be C interoperable
This happens because lammps_open_wrapper actually takes a Fortran
INTEGER argument, whose type is defined by the MPI library itself. The
Fortran integer is converted to a C integer by the MPI library (if such
conversion is actually necessary).
* lammps_extract_global returns COPIES of the (scalar) data, as does the
C version.
* lammps_extract_atom, lammps_extract_compute, and lammps_extract_fix
have a first argument that will be associated with ACTUAL LAMMPS DATA.
This means the first argument must be:
* The right rank (via the DIMENSION modifier)
* A C-interoperable POINTER type (i.e., INTEGER (C_int) or
REAL (C_double)).
* lammps_extract_variable returns COPIES of the data, as the C library
interface does. There is no need to deallocate using lammps_free.
* The 'data' argument to lammps_gather_atoms and lammps_scatter atoms must
be ALLOCATABLE. It should be of type INTEGER or DOUBLE PRECISION. It
does NOT need to be C inter-operable (and indeed should not be).
* The 'count' argument of lammps_scatter_atoms is unnecessary; the shape of
the array determines the number of elements LAMMPS will read.

View File

@ -1,16 +0,0 @@
units lj
atom_modify map array
lattice bcc 1.0
region simbox block 0 10 0 10 0 10
create_box 2 simbox
create_atoms 1 region simbox
pair_style lj/cut 2.5
pair_coeff * * 1.0 1.0
mass 1 58.2 # These are made-up numbers
mass 2 28.3
velocity all create 1200.0 7474848 dist gaussian
fix 1 all nve
fix 2 all dt/reset 1 1E-5 1E-3 0.01 units box
fix 4 all ave/histo 10 5 100 0.5 1.5 50 f_2 file temp.histo ave running
thermo_style custom step dt temp press etotal f_4[1][1]
thermo 100

View File

@ -1,112 +0,0 @@
program simple
use MPI
use LAMMPS
! The following line is unnecessary, as I have included these three entities
! with the LAMMPS module, but I leave them in anyway to remind people where
! they came from
use, intrinsic :: ISO_C_binding, only : C_double, C_ptr, C_int
implicit none
! Notes:
! * If LAMMPS returns a scalar that is allocated by the library interface
! (see library.cpp), then that memory is deallocated automatically and
! the argument to lammps_extract_fix must be a SCALAR.
! * If LAMMPS returns a pointer to an array, consisting of internal LAMMPS
! data, then the argument must be an interoperable Fortran pointer.
! Interoperable means it is of type INTEGER (C_INT) or of type
! REAL (C_DOUBLE) in this context.
! * Pointers should NEVER be deallocated, as that would deallocate internal
! LAMMPS data!
! * Note that just because you can read the values of, say, a compute at
! any time does not mean those values represent the "correct" values.
! LAMMPS will abort you if you try to grab a pointer to a non-current
! entity, but once it's bound, it's your responsibility to check that
! it's current before evaluating.
! * IMPORTANT: Two-dimensional arrays (such as 'x' from extract_atom)
! will be transposed from what they might look like in C++. This is
! because of different bookkeeping conventions between Fortran and C
! that date back to about 1970 or so (when C was written).
! * Arrays start from 1, EXCEPT for mass from extract_atom, which
! starts from 0. This is because the C array actually has a blank
! first element (and thus mass[1] corresponds to the mass of type 1)
type (C_ptr) :: lmp
real (C_double), pointer :: compute => NULL()
real (C_double) :: fix, fix2
real (C_double), dimension(:), pointer :: compute_v => NULL()
real (C_double), dimension(:,:), pointer :: x => NULL()
real (C_double), dimension(:), pointer :: mass => NULL()
integer, dimension(:), allocatable :: types
double precision, dimension(:), allocatable :: r
integer :: error, narg, me, nprocs
character (len=1024) :: command_line
call MPI_Init (error)
call MPI_Comm_rank (MPI_COMM_WORLD, me, error)
call MPI_Comm_size (MPI_COMM_WORLD, nprocs, error)
! You are free to pass any string you like to lammps_open or
! lammps_open_no_mpi; here is how you pass it the command line
!call get_command (command_line)
!call lammps_open (command_line, MPI_COMM_WORLD, lmp)
! And here's how to to it with a string constant of your choice
call lammps_open_no_mpi ('lmp -log log.simple', lmp)
call lammps_file (lmp, 'in.simple')
call lammps_command (lmp, 'run 500')
! This extracts f_2 as a scalar (the last two arguments can be arbitrary)
call lammps_extract_fix (fix, lmp, '2', LMP_STYLE_GLOBAL, LMP_TYPE_SCALAR, 1, 1)
print *, 'Fix is ', fix
! This extracts f_4[1][1] as a scalar
call lammps_extract_fix (fix2, lmp, '4', LMP_STYLE_GLOBAL, LMP_TYPE_ARRAY, 1, 1)
print *, 'Fix 2 is ', fix2
! This extracts the scalar compute of compute thermo_temp
call lammps_extract_compute (compute, lmp, 'thermo_temp', LMP_STYLE_GLOBAL, LMP_TYPE_SCALAR)
print *, 'Compute is ', compute
! This extracts the vector compute of compute thermo_temp
call lammps_extract_compute (compute_v, lmp, 'thermo_temp', LMP_STYLE_GLOBAL, LMP_TYPE_VECTOR)
print *, 'Vector is ', compute_v
! This extracts the masses
call lammps_extract_atom (mass, lmp, 'mass')
print *, 'Mass is ', mass(1:)
! Extracts a pointer to the arrays of positions for all atoms
call lammps_extract_atom (x, lmp, 'x')
if ( .not. associated (x) ) print *, 'x is not associated'
print *, 'x is ', x(:,1) ! Prints x, y, z for atom 1
! Extracts pointer to atom types
call lammps_gather_atoms (lmp, 'type', 1, types)
print *, 'types is ', types(1:3)
! Allocates an array and assigns all positions to it
call lammps_gather_atoms (lmp, 'x', 3, r)
print *, 'natoms = ', int(lammps_get_natoms(lmp))
print *, 'size(r) = ', size(r)
print *, 'r is ', r(1:6)
! Puts those position data back
call lammps_scatter_atoms (lmp, 'x', r)
call lammps_command (lmp, 'run 1')
print *, 'x is ', x(:,1) ! Note that the position updates!
print *, 'Compute is ', compute ! This did only because "temp" is part of
! the thermo output; the vector part did
! not, and won't until we give LAMMPS a
! thermo output or other command that
! requires its value
call lammps_close (lmp)
call MPI_Finalize (error)
end program simple

View File

@ -1,96 +0,0 @@
/* -----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------
Contributing author: Karl D. Hammond <hammondkd@missouri.edu>
University of Missouri (USA), 2012
------------------------------------------------------------------------- */
/* This is set of "wrapper" functions to assist LAMMPS.F90, which itself
provides a (I hope) robust Fortran interface to library.cpp and
library.h. All functions herein COULD be added to library.cpp instead of
including this as a separate file. See the README for instructions. */
#include <mpi.h>
#include "LAMMPS-wrapper.h"
#define LAMMPS_LIB_MPI 1
#include <library.h>
#include <lammps.h>
#include <atom.h>
#include <fix.h>
#include <compute.h>
#include <modify.h>
#include <error.h>
#include <cstdlib>
using namespace LAMMPS_NS;
void lammps_open_fortran_wrapper (int argc, char **argv,
MPI_Fint communicator, void **ptr)
{
MPI_Comm C_communicator = MPI_Comm_f2c (communicator);
lammps_open (argc, argv, C_communicator, ptr);
}
int lammps_get_ntypes (void *ptr)
{
class LAMMPS *lmp = (class LAMMPS *) ptr;
int ntypes = lmp->atom->ntypes;
return ntypes;
}
void lammps_error_all (void *ptr, const char *file, int line, const char *str)
{
class LAMMPS *lmp = (class LAMMPS *) ptr;
lmp->error->all (file, line, str);
}
int lammps_extract_compute_vectorsize (void *ptr, char *id, int style)
{
int *size;
size = (int *) lammps_extract_compute(ptr, id, style, LMP_SIZE_VECTOR);
if (size) return *size;
return 0;
}
void lammps_extract_compute_arraysize (void *ptr, char *id, int style,
int *nrows, int *ncols)
{
int *tmp;
tmp = (int *) lammps_extract_compute(ptr, id, style, LMP_SIZE_ROWS);
if (tmp) *nrows = *tmp;
tmp = (int *) lammps_extract_compute(ptr, id, style, LMP_SIZE_COLS);
if (tmp) *ncols = *tmp;
return;
}
int lammps_extract_fix_vectorsize (void *ptr, char *id, int style)
{
int *size;
size = (int *) lammps_extract_fix(ptr, id, style, LMP_SIZE_VECTOR, 0, 0);
if (size) return *size;
return 0;
}
void lammps_extract_fix_arraysize (void *ptr, char *id, int style,
int *nrows, int *ncols)
{
int *tmp;
tmp = (int *) lammps_extract_fix(ptr, id, style, LMP_SIZE_ROWS, 0, 0);
if (tmp) *nrows = *tmp;
tmp = (int *) lammps_extract_fix(ptr, id, style, LMP_SIZE_COLS, 0, 0);
if (tmp) *ncols = *tmp;
return;
}
/* vim: set ts=3 sts=3 expandtab: */

View File

@ -1,40 +0,0 @@
/* -----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------
Contributing author: Karl D. Hammond <hammondkd@missouri.edu>
University of Missouri (USA), 2012
------------------------------------------------------------------------- */
/* This is set of "wrapper" functions to assist LAMMPS.F90, which itself
provides a (I hope) robust Fortran interface to library.cpp and
library.h. All prototypes herein COULD be added to library.h instead of
including this as a separate file. See the README for instructions. */
#ifdef __cplusplus
extern "C" {
#endif
/* Prototypes for auxiliary functions */
void lammps_open_fortran_wrapper (int, char**, MPI_Fint, void**);
int lammps_get_ntypes (void*);
int lammps_extract_compute_vectorsize (void*, char*, int);
void lammps_extract_compute_arraysize (void*, char*, int, int*, int*);
int lammps_extract_fix_vectorsize (void*, char*, int);
void lammps_extract_fix_arraysize (void*, char*, int, int*, int*);
void lammps_error_all (void*, const char*, int, const char*);
#ifdef __cplusplus
}
#endif
/* vim: set ts=3 sts=3 expandtab: */

View File

@ -1,80 +0,0 @@
/* -----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------
Contributing author: Nir Goldman, LLNL <ngoldman@llnl.gov>, 2016
------------------------------------------------------------------------- */
/* This is set of "wrapper" functions to assist LAMMPS.F90, which itself
provides a (I hope) robust Fortran interface to library.cpp and
library.h. All functions herein COULD be added to library.cpp instead of
including this as a separate file. See the README for instructions. */
#include <mpi.h>
#include "LAMMPS-wrapper2.h"
#include <library.h>
#include <lammps.h>
#include <atom.h>
#include <input.h>
#include <modify.h>
#include <fix.h>
#include <fix_external.h>
#include <compute.h>
#include <modify.h>
#include <error.h>
#include <cstdlib>
using namespace LAMMPS_NS;
extern "C" void f_callback(void *, bigint, int, tagint *, double **, double **);
void lammps_set_callback (void *ptr) {
class LAMMPS *lmp = (class LAMMPS *) ptr;
int ifix = lmp->modify->find_fix_by_style("external");
FixExternal *fix = (FixExternal *) lmp->modify->fix[ifix];
fix->set_callback(f_callback, ptr);
return;
}
void lammps_set_external_vector_length (void *ptr, int n) {
class LAMMPS *lmp = (class LAMMPS *) ptr;
int ifix = lmp->modify->find_fix_by_style("external");
FixExternal *fix = (FixExternal *) lmp->modify->fix[ifix];
fix->set_vector_length(n);
return;
}
void lammps_set_external_vector (void *ptr, int n, double val) {
class LAMMPS *lmp = (class LAMMPS *) ptr;
int ifix = lmp->modify->find_fix_by_style("external");
FixExternal *fix = (FixExternal *) lmp->modify->fix[ifix];
fix->set_vector (n, val);
return;
}
void lammps_set_user_energy (void *ptr, double energy) {
class LAMMPS *lmp = (class LAMMPS *) ptr;
int ifix = lmp->modify->find_fix_by_style("external");
FixExternal *fix = (FixExternal *) lmp->modify->fix[ifix];
fix->set_energy_global(energy);
return;
}
void lammps_set_user_virial (void *ptr, double *virial) {
class LAMMPS *lmp = (class LAMMPS *) ptr;
int ifix = lmp->modify->find_fix_by_style("external");
FixExternal *fix = (FixExternal *) lmp->modify->fix[ifix];
fix->set_virial_global(virial);
return;
}

View File

@ -1,37 +0,0 @@
/* -----------------------------------------------------------------------
LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
https://www.lammps.org/, Sandia National Laboratories
LAMMPS development team: developers@lammps.org
Copyright (2003) Sandia Corporation. Under the terms of Contract
DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
certain rights in this software. This software is distributed under
the GNU General Public License.
See the README file in the top-level LAMMPS directory.
------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------
Contributing author: Nir Goldman, LLNL <ngoldman@llnl.gov>, 2016
------------------------------------------------------------------------- */
/* This is set of "wrapper" functions to assist LAMMPS.F90, which itself
provides a (I hope) robust Fortran interface to library.cpp and
library.h. All prototypes herein COULD be added to library.h instead of
including this as a separate file. See the README for instructions. */
#ifdef __cplusplus
extern "C" {
#endif
/* Prototypes for auxiliary functions */
void lammps_set_callback (void *);
void lammps_set_user_energy (void*, double);
void lammps_set_user_virial (void*, double*);
void lammps_set_external_vector_length (void*, int);
void lammps_set_external_vector (void*, int, double);
#ifdef __cplusplus
}
#endif
/* vim: set ts=3 sts=3 expandtab: */

View File

@ -1,982 +0,0 @@
!! -----------------------------------------------------------------------
! LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
! www.cs.sandia.gov/~sjplimp/lammps.html
! Steve Plimpton, sjplimp@sandia.gov, Sandia National Laboratories
!
! Copyright (2003) Sandia Corporation. Under the terms of Contract
! DE-AC04-94AL85000 with Sandia Corporation, the U.S. Government retains
! certain rights in this software. This software is distributed under
! the GNU General Public License.
!
! See the README file in the top-level LAMMPS directory.
!--------------------------------------------------------------------------
!! ------------------------------------------------------------------------
! Contributing author: Karl D. Hammond <hammondkd@missouri.edu>
! University of Missouri (USA), 2012
!--------------------------------------------------------------------------
!! LAMMPS, a Fortran 2003 module containing an interface between Fortran
!! programs and the C-style functions in library.cpp that ship with LAMMPS.
!! This file should be accompanied by LAMMPS-wrapper.cpp and LAMMPS-wrapper.h,
!! which define wrapper functions that ease portability and enforce array
!! dimensions.
!!
!! Everything in this module should be 100% portable by way of Fortran 2003's
!! ISO_C_BINDING intrinsic module. See the README for instructions for
!! compilation and use.
!!
!! Here are the PUBLIC functions and subroutines included in this module.
!! subroutine lammps_open (command_line, communicator, ptr)
!! subroutine lammps_open_no_mpi (command_line, ptr)
!! subroutine lammps_close (ptr)
!! subroutine lammps_file (ptr, str)
!! subroutine lammps_command (ptr, str)
!! subroutine lammps_free (ptr)
!! subroutine lammps_extract_global (global, ptr, name)
!! subroutine lammps_extract_atom (atom, ptr, name)
!! subroutine lammps_extract_fix (fix, ptr, id, style, type, i, j)
!! subroutine lammps_extract_compute (compute, ptr, id, style, type)
!! subroutine lammps_extract_variable (variable, ptr, name, group)
!! function lammps_get_natoms (ptr)
!! subroutine lammps_gather_atoms (ptr, name, count, data)
!! subroutine lammps_scatter_atoms (ptr, name, data)
#define FLERR __FILE__,__LINE__
! The above line allows for similar error checking as is done with standard
! LAMMPS files.
module LAMMPS
use, intrinsic :: ISO_C_binding, only : C_double, C_int, C_ptr, C_char, &
C_NULL_CHAR, C_loc, C_F_pointer, lammps_instance => C_ptr
implicit none
private
public :: lammps_set_user_virial
public :: lammps_set_external_vector_length
public :: lammps_set_external_vector
public :: lammps_set_user_energy
public :: lammps_open, lammps_open_no_mpi, lammps_close, lammps_file, &
lammps_command, lammps_free, lammps_extract_global, &
lammps_extract_atom, lammps_extract_compute, lammps_extract_fix, &
lammps_extract_variable, lammps_get_natoms, lammps_gather_atoms, &
lammps_set_callback
public :: lammps_scatter_atoms, lammps_instance, C_ptr, C_double, C_int
!! Functions supplemental to the prototypes in library.h. {{{1
!! The function definitions (in C++) are contained in LAMMPS-wrapper.cpp.
!! I would have written the first in Fortran, but the MPI libraries (which
!! were written in C) have C-based functions to convert from Fortran MPI
!! handles to C MPI handles, and there is no Fortran equivalent for those
!! functions.
interface
subroutine lammps_open_wrapper (argc, argv, communicator, ptr) &
bind (C, name='lammps_open_fortran_wrapper')
import :: C_int, C_ptr
integer (C_int), value :: argc
type (C_ptr), dimension(*) :: argv
integer, value :: communicator
type (C_ptr) :: ptr
end subroutine lammps_open_wrapper
subroutine lammps_actual_error_all (ptr, file, line, str) &
bind (C, name='lammps_error_all')
import :: C_int, C_char, C_ptr
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*), intent(in) :: file, str
integer (C_int), value :: line
end subroutine lammps_actual_error_all
function lammps_get_ntypes (ptr) result (ntypes) &
bind (C, name='lammps_get_ntypes')
import :: C_int, C_ptr
type (C_ptr), value :: ptr
integer (C_int) :: ntypes
end function lammps_get_ntypes
function lammps_actual_extract_compute_vectorsize (ptr, id, style) &
result (vectorsize) bind (C, name='lammps_extract_compute_vectorsize')
import :: C_int, C_char, C_ptr
integer (C_int) :: vectorsize
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*) :: id
integer (C_int), value :: style
end function lammps_actual_extract_compute_vectorsize
subroutine lammps_actual_extract_compute_arraysize (ptr, id, style, &
nrows, ncols) bind (C, name='lammps_extract_compute_arraysize')
import :: C_int, C_char, C_ptr
integer (C_int) :: arraysize
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*) :: id
integer (C_int), value :: style
integer (C_int) :: nrows, ncols
end subroutine lammps_actual_extract_compute_arraysize
function lammps_actual_extract_fix_vectorsize (ptr, id, style) &
result (vectorsize) bind (C, name='lammps_extract_fix_vectorsize')
import :: C_int, C_char, C_ptr
integer (C_int) :: vectorsize
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*) :: id
integer (C_int), value :: style
end function lammps_actual_extract_fix_vectorsize
subroutine lammps_actual_extract_fix_arraysize (ptr, id, style, &
nrows, ncols) bind (C, name='lammps_extract_fix_arraysize')
import :: C_int, C_char, C_ptr
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*) :: id
integer (C_int), value :: style
integer (C_int) :: nrows, ncols
end subroutine lammps_actual_extract_fix_arraysize
end interface
!! Functions/subroutines defined in library.h and library.cpp {{{1
interface
subroutine lammps_actual_open_no_mpi (argc, argv, ptr) &
bind (C, name='lammps_open_no_mpi')
import :: C_int, C_ptr
integer (C_int), value :: argc
type (C_ptr), dimension(*) :: argv
type (C_ptr) :: ptr
end subroutine lammps_actual_open_no_mpi
subroutine lammps_close (ptr) bind (C, name='lammps_close')
import :: C_ptr
type (C_ptr), value :: ptr
end subroutine lammps_close
subroutine lammps_actual_file (ptr, str) bind (C, name='lammps_file')
import :: C_ptr, C_char
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*) :: str
end subroutine lammps_actual_file
function lammps_actual_command (ptr, str) result (command) &
bind (C, name='lammps_command')
import :: C_ptr, C_char
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*) :: str
type (C_ptr) :: command
end function lammps_actual_command
subroutine lammps_free (ptr) bind (C, name='lammps_free')
import :: C_ptr
type (C_ptr), value :: ptr
end subroutine lammps_free
function lammps_actual_extract_global (ptr, name) &
bind (C, name='lammps_extract_global') result (global)
import :: C_ptr, C_char
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*) :: name
type (C_ptr) :: global
end function lammps_actual_extract_global
function lammps_actual_extract_atom (ptr, name) &
bind (C, name='lammps_extract_atom') result (atom)
import :: C_ptr, C_char
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*) :: name
type (C_ptr) :: atom
end function lammps_actual_extract_atom
function lammps_actual_extract_compute (ptr, id, style, type) &
result (compute) bind (C, name='lammps_extract_compute')
import :: C_ptr, C_char, C_int
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*) :: id
integer (C_int), value :: style, type
type (C_ptr) :: compute
end function lammps_actual_extract_compute
function lammps_actual_extract_fix (ptr, id, style, type, i, j) &
result (fix) bind (C, name='lammps_extract_fix')
import :: C_ptr, C_char, C_int
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*) :: id
integer (C_int), value :: style, type, i, j
type (C_ptr) :: fix
end function lammps_actual_extract_fix
function lammps_actual_extract_variable (ptr, name, group) &
result (variable) bind (C, name='lammps_extract_variable')
import :: C_ptr, C_char
type (C_ptr), value :: ptr
character (kind=C_char), dimension(*) :: name, group
type (C_ptr) :: variable
end function lammps_actual_extract_variable
function lammps_get_natoms (ptr) result (natoms) &
bind (C, name='lammps_get_natoms')
import :: C_ptr, C_int
type (C_ptr), value :: ptr
integer (C_int) :: natoms
end function lammps_get_natoms
subroutine lammps_set_callback (ptr) &
bind (C, name='lammps_set_callback')
import :: C_ptr
type (C_ptr), value :: ptr
end subroutine lammps_set_callback
subroutine lammps_set_user_energy (ptr, energy) &
bind (C, name='lammps_set_user_energy')
import :: C_ptr, C_double
type (C_ptr), value :: ptr
real(C_double), value :: energy
end subroutine lammps_set_user_energy
subroutine lammps_set_user_virial (ptr, virial) &
bind (C, name='lammps_set_user_virial')
import :: C_ptr, C_double
type (C_ptr), value :: ptr
real(C_double) :: virial(6)
end subroutine lammps_set_user_virial
subroutine lammps_set_external_vector_length (ptr, n) &
bind (C, name='lammps_set_external_vector_length')
import :: C_ptr, C_double, C_int
type(C_ptr), value :: ptr
integer (C_int), value :: n
end subroutine lammps_set_external_vector_length
subroutine lammps_set_external_vector (ptr, n, val) &
bind (C, name='lammps_set_external_vector')
import :: C_ptr, C_int, C_double
type (C_ptr), value :: ptr
integer (C_int), value :: n
real(C_double), value :: val
end subroutine lammps_set_external_vector
subroutine lammps_actual_gather_atoms (ptr, name, type, count, data) &
bind (C, name='lammps_gather_atoms')
import :: C_ptr, C_int, C_char
type (C_ptr), value :: ptr, data
character (kind=C_char), dimension(*) :: name
integer (C_int), value :: type, count
end subroutine lammps_actual_gather_atoms
subroutine lammps_actual_scatter_atoms (ptr, name, type, count, data) &
bind (C, name='lammps_scatter_atoms')
import :: C_ptr, C_int, C_char
type (C_ptr), value :: ptr, data
character (kind=C_char), dimension(*) :: name
integer (C_int), value :: type, count
end subroutine lammps_actual_scatter_atoms
end interface
! Generic functions for the wrappers below {{{1
interface lammps_extract_global
module procedure lammps_extract_global_i, &
lammps_extract_global_dp
end interface lammps_extract_global
interface lammps_extract_atom
module procedure lammps_extract_atom_ia, &
lammps_extract_atom_dpa, &
lammps_extract_atom_dp2a
end interface lammps_extract_atom
interface lammps_extract_compute
module procedure lammps_extract_compute_dp, &
lammps_extract_compute_dpa, &
lammps_extract_compute_dp2a
end interface lammps_extract_compute
interface lammps_extract_fix
module procedure lammps_extract_fix_dp, &
lammps_extract_fix_dpa, &
lammps_extract_fix_dp2a
end interface lammps_extract_fix
interface lammps_extract_variable
module procedure lammps_extract_variable_dp, &
lammps_extract_variable_dpa
end interface lammps_extract_variable
interface lammps_gather_atoms
module procedure lammps_gather_atoms_ia, lammps_gather_atoms_dpa
end interface lammps_gather_atoms
interface lammps_scatter_atoms
module procedure lammps_scatter_atoms_ia, lammps_scatter_atoms_dpa
end interface lammps_scatter_atoms
contains !! Wrapper functions local to this module {{{1
subroutine lammps_open (command_line, communicator, ptr)
character (len=*), intent(in) :: command_line
integer, intent(in) :: communicator
type (C_ptr) :: ptr
integer (C_int) :: argc
type (C_ptr), dimension(:), allocatable :: argv
character (kind=C_char), dimension(len_trim(command_line)+1), target :: &
c_command_line
c_command_line = string2Cstring (command_line)
call Cstring2argcargv (c_command_line, argc, argv)
call lammps_open_wrapper (argc, argv, communicator, ptr)
deallocate (argv)
end subroutine lammps_open
!-----------------------------------------------------------------------------
subroutine lammps_open_no_mpi (command_line, ptr)
character (len=*), intent(in) :: command_line
type (C_ptr) :: ptr
integer (C_int) :: argc
type (C_ptr), dimension(:), allocatable :: argv
character (kind=C_char), dimension(len_trim(command_line)+1), target :: &
c_command_line
c_command_line = string2Cstring (command_line)
call Cstring2argcargv (c_command_line, argc, argv)
call lammps_actual_open_no_mpi (argc, argv, ptr)
deallocate (argv)
end subroutine lammps_open_no_mpi
!-----------------------------------------------------------------------------
subroutine lammps_file (ptr, str)
type (C_ptr) :: ptr
character (len=*) :: str
character (kind=C_char), dimension(len_trim(str)+1) :: Cstr
Cstr = string2Cstring (str)
call lammps_actual_file (ptr, Cstr)
end subroutine lammps_file
!-----------------------------------------------------------------------------
subroutine lammps_command (ptr, str)
type (C_ptr) :: ptr
character (len=*) :: str
character (kind=C_char), dimension(len_trim(str)+1) :: Cstr
type (C_ptr) :: dummy
Cstr = string2Cstring (str)
dummy = lammps_actual_command (ptr, Cstr)
end subroutine lammps_command
!-----------------------------------------------------------------------------
! lammps_extract_global {{{2
function lammps_extract_global_Cptr (ptr, name) result (global)
type (C_ptr) :: global
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
character (kind=C_char), dimension(len_trim(name)+1) :: Cname
Cname = string2Cstring (name)
global = lammps_actual_extract_global (ptr, Cname)
end function lammps_extract_global_Cptr
subroutine lammps_extract_global_i (global, ptr, name)
integer (C_int), pointer, intent(out) :: global
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
type (C_ptr) :: Cptr
Cptr = lammps_extract_global_Cptr (ptr, name)
call C_F_pointer (Cptr, global)
end subroutine lammps_extract_global_i
subroutine lammps_extract_global_dp (global, ptr, name)
real (C_double), pointer, intent(out) :: global
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
type (C_ptr) :: Cptr
Cptr = lammps_extract_global_Cptr (ptr, name)
call C_F_pointer (Cptr, global)
end subroutine lammps_extract_global_dp
!-----------------------------------------------------------------------------
! lammps_extract_atom {{{2
function lammps_extract_atom_Cptr (ptr, name) result (atom)
type (C_ptr) :: atom
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
character (kind=C_char), dimension(len_trim(name)+1) :: Cname
Cname = string2Cstring (name)
atom = lammps_actual_extract_atom (ptr, Cname)
end function lammps_extract_atom_Cptr
subroutine lammps_extract_atom_ia (atom, ptr, name)
integer (C_int), dimension(:), pointer, intent(out) :: atom
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
type (C_ptr) :: Cptr
integer (C_int), pointer :: nelements
call lammps_extract_global_i (nelements, ptr, 'nlocal')
Cptr = lammps_extract_atom_Cptr (ptr, name)
call C_F_pointer (Cptr, atom, (/nelements/))
end subroutine lammps_extract_atom_ia
subroutine lammps_extract_atom_dpa (atom, ptr, name)
real (C_double), dimension(:), pointer, intent(out) :: atom
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
type (C_ptr) :: Cptr
integer (C_int), pointer :: nlocal
integer :: nelements
real (C_double), dimension(:), pointer :: Fptr
if ( name == 'mass' ) then
nelements = lammps_get_ntypes (ptr) + 1
else if ( name == 'x' .or. name == 'v' .or. name == 'f' .or. &
name == 'mu' .or. name == 'omega' .or. name == 'torque' .or. &
name == 'angmom' ) then
! We should not be getting a rank-2 array here!
call lammps_error_all (ptr, FLERR, 'You cannot extract those atom&
& data (' // trim(name) // ') into a rank 1 array.')
return
else
! Everything else we can get is probably nlocal units long
call lammps_extract_global_i (nlocal, ptr, 'nlocal')
nelements = nlocal
end if
Cptr = lammps_extract_atom_Cptr (ptr, name)
call C_F_pointer (Cptr, Fptr, (/nelements/))
if ( name == 'mass' ) then
!atom(0:) => Fptr
atom => Fptr
else
atom => Fptr
end if
end subroutine lammps_extract_atom_dpa
subroutine lammps_extract_atom_dp2a (atom, ptr, name)
real (C_double), dimension(:,:), pointer, intent(out) :: atom
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
type (C_ptr) :: Cptr
type (C_ptr), pointer, dimension(:) :: Catom
integer (C_int), pointer :: nelements
if ( name /= 'x' .and. name /= 'v' .and. name /= 'f' .and. &
name /= 'mu' .and. name /= 'omega' .and. name /= 'tandque' .and. &
name /= 'angmom' .and. name /= 'fexternal' ) then
! We should not be getting a rank-2 array here!
call lammps_error_all (ptr, FLERR, 'You cannot extract those atom&
& data (' // trim(name) // ') into a rank 2 array.')
return
end if
Cptr = lammps_extract_atom_Cptr (ptr, name)
call lammps_extract_global_i (nelements, ptr, 'nlocal')
! Catom will now be the array of void* pointers that the void** pointer
! pointed to. Catom(1) is now the pointer to the first element.
call C_F_pointer (Cptr, Catom, (/nelements/))
! Now get the actual array, which has its shape transposed from what we
! might think of it in C
call C_F_pointer (Catom(1), atom, (/3, nelements/))
end subroutine lammps_extract_atom_dp2a
!-----------------------------------------------------------------------------
! lammps_extract_compute {{{2
function lammps_extract_compute_Cptr (ptr, id, style, type) result (compute)
type (C_ptr) :: compute
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style, type
integer (kind=C_int) :: Cstyle, Ctype
character (kind=C_char), dimension(len_trim(id)+1) :: Cid
Cid = string2Cstring (id)
Cstyle = style
Ctype = type
compute = lammps_actual_extract_compute (ptr, Cid, Cstyle, Ctype)
end function lammps_extract_compute_Cptr
subroutine lammps_extract_compute_dp (compute, ptr, id, style, type)
real (C_double), pointer, intent(out) :: compute
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style, type
type (C_ptr) :: Cptr
! The only valid values of (style,type) are (0,0) for scalar 'compute'
if ( style /= 0 ) then
call lammps_error_all (ptr, FLERR, 'You cannot pack per-atom/local&
& data into a scalar.')
return
end if
if ( type == 1 ) then
call lammps_error_all (ptr, FLERR, 'You cannot extract a compute&
& vector (rank 1) into a scalar.')
return
else if ( type == 2 ) then
call lammps_error_all (ptr, FLERR, 'You cannot extract a compute&
& array (rank 2) into a scalar.')
return
end if
Cptr = lammps_extract_compute_Cptr (ptr, id, style, type)
call C_F_pointer (Cptr, compute)
end subroutine lammps_extract_compute_dp
subroutine lammps_extract_compute_dpa (compute, ptr, id, style, type)
real (C_double), dimension(:), pointer, intent(out) :: compute
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style, type
type (C_ptr) :: Cptr
integer :: nelements
! Check for the correct dimensionality
if ( type == 0 ) then
call lammps_error_all (ptr, FLERR, 'You cannot extract a compute&
& scalar (rank 0) into a rank 1 variable.')
return
else if ( type == 2 ) then
call lammps_error_all (ptr, FLERR, 'You cannot extract a compute&
& array (rank 2) into a rank 1 variable.')
return
end if
nelements = lammps_extract_compute_vectorsize (ptr, id, style)
Cptr = lammps_extract_compute_Cptr (ptr, id, style, type)
call C_F_pointer (Cptr, compute, (/nelements/))
end subroutine lammps_extract_compute_dpa
subroutine lammps_extract_compute_dp2a (compute, ptr, id, style, type)
real (C_double), dimension(:,:), pointer, intent(out) :: compute
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style, type
type (C_ptr) :: Cptr
type (C_ptr), pointer, dimension(:) :: Ccompute
integer :: nr, nc
! Check for the correct dimensionality
if ( type == 0 ) then
call lammps_error_all (ptr, FLERR, 'You cannot extract a compute&
& scalar (rank 0) into a rank 2 variable.')
return
else if ( type == 1 ) then
call lammps_error_all (ptr, FLERR, 'You cannot extract a compute&
& array (rank 1) into a rank 2 variable.')
return
end if
call lammps_extract_compute_arraysize (ptr, id, style, nr, nc)
Cptr = lammps_extract_compute_Cptr (ptr, id, style, type)
call C_F_pointer (Cptr, Ccompute, (/nr/))
! Note that the matrix is transposed, from Fortran's perspective
call C_F_pointer (Ccompute(1), compute, (/nc, nr/))
end subroutine lammps_extract_compute_dp2a
!-----------------------------------------------------------------------------
! lammps_extract_fix {{{2
function lammps_extract_fix_Cptr (ptr, id, style, type, i, j) &
result (fix)
type (C_ptr) :: fix
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style, type, i, j
character (kind=C_char), dimension(len_trim(id)+1) :: Cid
integer (kind=C_int) :: Cstyle, Ctype, Ci, Cj
Cid = string2Cstring (id)
Cstyle = style
Ctype = type
Ci = i - 1 ! This is for consistency with the values from f_ID[i],
Cj = j - 1 ! which is different from what library.cpp uses!
if ( (type >= 1 .and. Ci < 0) .or. &
(type == 2 .and. (Ci < 0 .or. Cj < 0) ) ) then
call lammps_error_all (ptr, FLERR, 'Index out of range in&
& lammps_extract_fix')
end if
fix = lammps_actual_extract_fix (ptr, Cid, Cstyle, Ctype, Ci, Cj)
end function lammps_extract_fix_Cptr
subroutine lammps_extract_fix_dp (fix, ptr, id, style, type, i, j)
real (C_double), intent(out) :: fix
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style, type, i, j
type (C_ptr) :: Cptr
real (C_double), pointer :: Fptr
! Check for the correct dimensionality
if ( style /= 0 ) then
select case (type)
case (0)
call lammps_error_all (ptr, FLERR, 'There is no per-atom or local&
& scalar data available from fixes.')
case (1)
call lammps_error_all (ptr, FLERR, 'You cannot extract a fix''s &
&per-atom/local vector (rank 1) into a scalar.')
case (2)
call lammps_error_all (ptr, FLERR, 'You cannot extract a fix''s &
&per-atom/local array (rank 2) into a scalar.')
case default
call lammps_error_all (ptr, FLERR, 'Invalid extract_fix style/&
&type combination.')
end select
return
end if
Cptr = lammps_extract_fix_Cptr (ptr, id, style, type, i, j)
call C_F_pointer (Cptr, Fptr)
fix = Fptr
nullify (Fptr)
! Memory is only allocated for "global" fix variables
if ( style == 0 ) call lammps_free (Cptr)
end subroutine lammps_extract_fix_dp
subroutine lammps_extract_fix_dpa (fix, ptr, id, style, type, i, j)
real (C_double), dimension(:), pointer, intent(out) :: fix
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style, type, i, j
type (C_ptr) :: Cptr
integer :: fix_len
! Check for the correct dimensionality
if ( style == 0 ) then
call lammps_error_all (ptr, FLERR, 'You can''t extract the&
& whole vector from global fix data')
return
else if ( type == 0 ) then
call lammps_error_all (ptr, FLERR, 'You can''t extract a fix&
& scalar into a rank 1 variable')
return
else if ( type == 2 ) then
call lammps_error_all (ptr, FLERR, 'You cannot extract a fix&
& array into a rank 1 variable.')
return
else if ( type /= 1 ) then
call lammps_error_all (ptr, FLERR, 'Invalid type for fix extraction.')
return
end if
fix_len = lammps_extract_fix_vectorsize (ptr, id, style)
call C_F_pointer (Cptr, fix, (/fix_len/))
! Memory is only allocated for "global" fix variables, which we should
! never get here, so no need to call lammps_free!
end subroutine lammps_extract_fix_dpa
subroutine lammps_extract_fix_dp2a (fix, ptr, id, style, type, i, j)
real (C_double), dimension(:,:), pointer, intent(out) :: fix
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style, type, i, j
type (C_ptr) :: Cptr
type (C_ptr), pointer, dimension(:) :: Cfix
integer :: nr, nc
! Check for the correct dimensionality
if ( style == 0 ) then
call lammps_error_all (ptr, FLERR, 'It is not possible to extract the&
& entire array from global fix data.')
return
else if ( type == 0 ) then
call lammps_error_all (ptr, FLERR, 'You cannot extract a fix&
& scalar (rank 0) into a rank 2 variable.')
return
else if ( type == 1 ) then
call lammps_error_all (ptr, FLERR, 'You cannot extract a fix&
& vector (rank 1) into a rank 2 variable.')
return
end if
call lammps_extract_fix_arraysize (ptr, id, style, nr, nc)
! Extract pointer to first element as Cfix(1)
call C_F_pointer (Cptr, Cfix, (/nr/))
! Now extract the array, which is transposed
call C_F_pointer (Cfix(1), fix, (/nc, nr/))
end subroutine lammps_extract_fix_dp2a
!-----------------------------------------------------------------------------
! lammps_extract_variable {{{2
function lammps_extract_variable_Cptr (ptr, name, group) result (variable)
type (C_ptr) :: ptr, variable
character (len=*) :: name
character (len=*), optional :: group
character (kind=C_char), dimension(len_trim(name)+1) :: Cname
character (kind=C_char), dimension(:), allocatable :: Cgroup
Cname = string2Cstring (name)
if ( present(group) ) then
allocate (Cgroup(len_trim(group)+1))
Cgroup = string2Cstring (group)
else
allocate (Cgroup(1))
Cgroup(1) = C_NULL_CHAR
end if
variable = lammps_actual_extract_variable (ptr, Cname, Cgroup)
deallocate (Cgroup)
end function lammps_extract_variable_Cptr
subroutine lammps_extract_variable_dp (variable, ptr, name, group)
real (C_double), intent(out) :: variable
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
character (len=*), intent(in), optional :: group
type (C_ptr) :: Cptr
real (C_double), pointer :: Fptr
if ( present(group) ) then
Cptr = lammps_extract_variable_Cptr (ptr, name, group)
else
Cptr = lammps_extract_variable_Cptr (ptr, name)
end if
call C_F_pointer (Cptr, Fptr)
variable = Fptr
nullify (Fptr)
call lammps_free (Cptr)
end subroutine lammps_extract_variable_dp
subroutine lammps_extract_variable_dpa (variable, ptr, name, group)
real (C_double), dimension(:), allocatable, intent(out) :: variable
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
character (len=*), intent(in), optional :: group
type (C_ptr) :: Cptr
real (C_double), dimension(:), pointer :: Fptr
integer :: natoms
if ( present(group) ) then
Cptr = lammps_extract_variable_Cptr (ptr, name, group)
else
Cptr = lammps_extract_variable_Cptr (ptr, name)
end if
natoms = lammps_get_natoms (ptr)
allocate (variable(natoms))
call C_F_pointer (Cptr, Fptr, (/natoms/))
variable = Fptr
nullify (Fptr)
call lammps_free (Cptr)
end subroutine lammps_extract_variable_dpa
!-------------------------------------------------------------------------2}}}
subroutine lammps_gather_atoms_ia (ptr, name, count, data)
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
integer, intent(in) :: count
integer, dimension(:), allocatable, intent(out) :: data
type (C_ptr) :: Cdata
integer (C_int), dimension(:), pointer :: Fdata
integer (C_int) :: natoms
character (kind=C_char), dimension(len_trim(name)+1) :: Cname
integer (C_int), parameter :: Ctype = 0_C_int
integer (C_int) :: Ccount
natoms = lammps_get_natoms (ptr)
Cname = string2Cstring (name)
if ( count /= 1 .and. count /= 3 ) then
call lammps_error_all (ptr, FLERR, 'lammps_gather_atoms requires&
& count to be either 1 or 3')
else
Ccount = count
end if
allocate ( Fdata(count*natoms) )
allocate ( data(count*natoms) )
Cdata = C_loc (Fdata(1))
call lammps_actual_gather_atoms (ptr, Cname, Ctype, Ccount, Cdata)
data = Fdata
deallocate (Fdata)
end subroutine lammps_gather_atoms_ia
subroutine lammps_gather_atoms_dpa (ptr, name, count, data)
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
integer, intent(in) :: count
double precision, dimension(:), allocatable, intent(out) :: data
type (C_ptr) :: Cdata
real (C_double), dimension(:), pointer :: Fdata
integer (C_int) :: natoms
character (kind=C_char), dimension(len_trim(name)+1) :: Cname
integer (C_int), parameter :: Ctype = 1_C_int
integer (C_int) :: Ccount
natoms = lammps_get_natoms (ptr)
Cname = string2Cstring (name)
if ( count /= 1 .and. count /= 3 ) then
call lammps_error_all (ptr, FLERR, 'lammps_gather_atoms requires&
& count to be either 1 or 3')
else
Ccount = count
end if
allocate ( Fdata(count*natoms) )
allocate ( data(count*natoms) )
Cdata = C_loc (Fdata(1))
call lammps_actual_gather_atoms (ptr, Cname, Ctype, Ccount, Cdata)
data = Fdata(:)
deallocate (Fdata)
end subroutine lammps_gather_atoms_dpa
!-----------------------------------------------------------------------------
subroutine lammps_scatter_atoms_ia (ptr, name, data)
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
integer, dimension(:), intent(in) :: data
integer (kind=C_int) :: natoms, Ccount
integer (kind=C_int), parameter :: Ctype = 0_C_int
character (kind=C_char), dimension(len_trim(name)+1) :: Cname
integer (C_int), dimension(size(data)), target :: Fdata
type (C_ptr) :: Cdata
natoms = lammps_get_natoms (ptr)
Cname = string2Cstring (name)
Ccount = size(data) / natoms
if ( Ccount /= 1 .and. Ccount /= 3 ) &
call lammps_error_all (ptr, FLERR, 'lammps_gather_atoms requires&
& count to be either 1 or 3')
Fdata = data
Cdata = C_loc (Fdata(1))
call lammps_actual_scatter_atoms (ptr, Cname, Ctype, Ccount, Cdata)
end subroutine lammps_scatter_atoms_ia
subroutine lammps_scatter_atoms_dpa (ptr, name, data)
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: name
double precision, dimension(:), intent(in) :: data
integer (kind=C_int) :: natoms, Ccount
integer (kind=C_int), parameter :: Ctype = 1_C_int
character (kind=C_char), dimension(len_trim(name)+1) :: Cname
real (C_double), dimension(size(data)), target :: Fdata
type (C_ptr) :: Cdata
natoms = lammps_get_natoms (ptr)
Cname = string2Cstring (name)
Ccount = size(data) / natoms
if ( Ccount /= 1 .and. Ccount /= 3 ) &
call lammps_error_all (ptr, FLERR, 'lammps_gather_atoms requires&
& count to be either 1 or 3')
Fdata = data
Cdata = C_loc (Fdata(1))
call lammps_actual_scatter_atoms (ptr, Cname, Ctype, Ccount, Cdata)
end subroutine lammps_scatter_atoms_dpa
!-----------------------------------------------------------------------------
function lammps_extract_compute_vectorsize (ptr, id, style) &
result (vectorsize)
integer :: vectorsize
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style
integer (C_int) :: Cvectorsize, Cstyle
character (kind=C_char), dimension(len_trim(id)+1) :: Cid
Cid = string2Cstring (id)
Cstyle = int(style, C_int)
Cvectorsize = lammps_actual_extract_compute_vectorsize (ptr, Cid, Cstyle)
vectorsize = int(Cvectorsize, kind(vectorsize))
end function lammps_extract_compute_vectorsize
!-----------------------------------------------------------------------------
function lammps_extract_fix_vectorsize (ptr, id, style) &
result (vectorsize)
integer :: vectorsize
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style
integer (C_int) :: Cvectorsize, Cstyle
character (kind=C_char), dimension(len_trim(id)+1) :: Cid
Cid = string2Cstring (id)
Cstyle = int(style, C_int)
Cvectorsize = lammps_actual_extract_fix_vectorsize (ptr, Cid, Cstyle)
vectorsize = int(Cvectorsize, kind(vectorsize))
end function lammps_extract_fix_vectorsize
!-----------------------------------------------------------------------------
subroutine lammps_extract_compute_arraysize (ptr, id, style, nrows, ncols)
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style
integer, intent(out) :: nrows, ncols
integer (C_int) :: Cstyle, Cnrows, Cncols
character (kind=C_char), dimension(len_trim(id)+1) :: Cid
Cid = string2Cstring (id)
Cstyle = int (style, C_int)
call lammps_actual_extract_compute_arraysize (ptr, Cid, Cstyle, &
Cnrows, Cncols)
nrows = int (Cnrows, kind(nrows))
ncols = int (Cncols, kind(ncols))
end subroutine lammps_extract_compute_arraysize
!-----------------------------------------------------------------------------
subroutine lammps_extract_fix_arraysize (ptr, id, style, nrows, ncols)
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: id
integer, intent(in) :: style
integer, intent(out) :: nrows, ncols
integer (C_int) :: Cstyle, Cnrows, Cncols
character (kind=C_char), dimension(len_trim(id)+1) :: Cid
Cid = string2Cstring (id)
Cstyle = int (style, kind(Cstyle))
call lammps_actual_extract_fix_arraysize (ptr, Cid, Cstyle, &
Cnrows, Cncols)
nrows = int (Cnrows, kind(nrows))
ncols = int (Cncols, kind(ncols))
end subroutine lammps_extract_fix_arraysize
!-----------------------------------------------------------------------------
subroutine lammps_error_all (ptr, file, line, str)
type (C_ptr), intent(in) :: ptr
character (len=*), intent(in) :: file, str
integer, intent(in) :: line
character (kind=C_char), dimension(len_trim(file)+1) :: Cfile
character (kind=C_char), dimension(len_trim(str)+1) :: Cstr
integer (C_int) :: Cline
Cline = int(line, kind(Cline))
Cfile = string2Cstring (file)
Cstr = string2Cstring (str)
call lammps_actual_error_all (ptr, Cfile, Cline, Cstr)
end subroutine lammps_error_all
!-----------------------------------------------------------------------------
! Locally defined helper functions {{{1
pure function string2Cstring (string) result (C_string)
use, intrinsic :: ISO_C_binding, only : C_char, C_NULL_CHAR
character (len=*), intent(in) :: string
character (len=1, kind=C_char) :: C_string (len_trim(string)+1)
integer :: i, n
n = len_trim (string)
forall (i = 1:n)
C_string(i) = string(i:i)
end forall
C_string(n+1) = C_NULL_CHAR
end function string2Cstring
!-----------------------------------------------------------------------------
subroutine Cstring2argcargv (Cstring, argc, argv)
!! Converts a C-style string to argc and argv, that is, words in Cstring
!! become C-style strings in argv. IMPORTANT: Cstring is modified by
!! this routine! I would make Cstring local TO this routine and accept
!! a Fortran-style string instead, but we run into scoping and
!! allocation problems that way. This routine assumes the string is
!! null-terminated, as all C-style strings must be.
character (kind=C_char), dimension(*), target, intent(inout) :: Cstring
integer (C_int), intent(out) :: argc
type (C_ptr), dimension(:), allocatable, intent(out) :: argv
integer :: StringStart, SpaceIndex, strlen, argnum
argc = 1_C_int
! Find the length of the string
strlen = 1
do while ( Cstring(strlen) /= C_NULL_CHAR )
strlen = strlen + 1
end do
! Find the number of non-escaped spaces
SpaceIndex = 2
do while ( SpaceIndex < strlen )
if ( Cstring(SpaceIndex) == ' ' .and. &
Cstring(SpaceIndex-1) /= '\' ) then
argc = argc + 1_C_int
! Find the next non-space character
do while ( Cstring(SpaceIndex+1) == ' ')
SpaceIndex = SpaceIndex + 1
end do
end if
SpaceIndex = SpaceIndex + 1
end do
! Now allocate memory for argv
allocate (argv(argc))
! Now find the string starting and ending locations
StringStart = 1
SpaceIndex = 2
argnum = 1
do while ( SpaceIndex < strlen )
if ( Cstring(SpaceIndex) == ' ' .and. &
Cstring(SpaceIndex-1) /= '\' ) then
! Found a real space => split strings and store this one
Cstring(Spaceindex) = C_NULL_CHAR ! Replaces space with NULL
argv(argnum) = C_loc(Cstring(StringStart))
argnum = argnum + 1
! Find the next non-space character
do while ( Cstring(SpaceIndex+1) == ' ')
SpaceIndex = SpaceIndex + 1
end do
StringStart = SpaceIndex + 1
else if ( Cstring(SpaceIndex) == ' ' .and. &
Cstring(SpaceIndex-1) == '\' ) then
! Escaped space => remove backslash and move rest of array
Cstring(SpaceIndex-1:strlen-1) = Cstring(SpaceIndex:strlen)
strlen = strlen - 1 ! Last character is still C_NULL_CHAR
end if
SpaceIndex = SpaceIndex + 1
end do
! Now handle the last argument
argv(argnum) = C_loc(Cstring(StringStart))
end subroutine Cstring2argcargv
! 1}}}
end module LAMMPS
! vim: foldmethod=marker tabstop=3 softtabstop=3 shiftwidth=3 expandtab

View File

@ -1,37 +0,0 @@
This directory has an example of using a callback function to obtain
forces from a fortran code for a LAMMPS simulation. The reader should
refer to the README file in COUPLE/fortran2 before proceeding. Here,
the LAMMPS.F90 file has been modified slightly and additional files
named LAMMPS-wrapper2.h and LAMMPS-wrapper2.cpp have been included in
order to supply wrapper functions to set the LAMMPS callback function,
total energy, virial, and electronic entropy contribution (needed for
MSST simulations with a quantum code).
In this example, the callback function is set to run the
semi-empirical quantum code DFTB+ in serial and then read in the total
energy, forces, and stress tensor from file. In this case, nlocal =
the total number of atoms in the system, so particle positions can be
read from the pos array directly, and DFTB+ forces can simply be
included via the fext array. The user should take care in the case of
a parallel calculation, where LAMMPS can assign different particules
to each processor. For example, the user should use functions such as
lammps_gather_atoms() and lammps_scatter_atoms() in the case where the
fortran force calculating code requires the positions of all atoms,
etc.
A few more important notes:
-Calling the subroutine lammps_set_callback() is required in order to set
a pointer to the callback function in LAMMPS.
-The subroutine lammps_set_user_energy() passes in the potential energy
from DFTB+ to LAMMPS. Similarly, lammps_set_user_virial passes the stress tensor.
-The electronic entropy contribution is set via lammps_set_external_vector(). Their needs
to be a call to lammps_set_external_vector_length() before this value can be
passed to LAMMPS.
This example was created by Nir Goldman, whom you can contact with
questions:
Nir Goldman, LLNL
ngoldman@llnl.gov

View File

@ -1,148 +0,0 @@
# Position data file
64 atoms
1 atom types
0 7.134 xlo xhi
0 7.134 ylo yhi
0 7.134 zlo zhi
0.00000000 0.00000000 0.00000000 xy xz yz
Masses
1 12.010000
Atoms
1 1 0 0 0 0
2 1 0 0.89175 0.89175 0.89175
3 1 0 1.7835 1.7835 0
4 1 0 2.67525 2.67525 0.89175
5 1 0 0 1.7835 1.7835
6 1 0 0.89175 2.67525 2.67525
7 1 0 1.7835 0 1.7835
8 1 0 2.67525 0.89175 2.67525
9 1 0 0 0 3.567
10 1 0 0.89175 0.89175 4.45875
11 1 0 1.7835 1.7835 3.567
12 1 0 2.67525 2.67525 4.45875
13 1 0 0 1.7835 5.3505
14 1 0 0.89175 2.67525 6.24225
15 1 0 1.7835 0 5.3505
16 1 0 2.67525 0.89175 6.24225
17 1 0 0 3.567 0
18 1 0 0.89175 4.45875 0.89175
19 1 0 1.7835 5.3505 0
20 1 0 2.67525 6.24225 0.89175
21 1 0 0 5.3505 1.7835
22 1 0 0.89175 6.24225 2.67525
23 1 0 1.7835 3.567 1.7835
24 1 0 2.67525 4.45875 2.67525
25 1 0 0 3.567 3.567
26 1 0 0.89175 4.45875 4.45875
27 1 0 1.7835 5.3505 3.567
28 1 0 2.67525 6.24225 4.45875
29 1 0 0 5.3505 5.3505
30 1 0 0.89175 6.24225 6.24225
31 1 0 1.7835 3.567 5.3505
32 1 0 2.67525 4.45875 6.24225
33 1 0 3.567 0 0
34 1 0 4.45875 0.89175 0.89175
35 1 0 5.3505 1.7835 0
36 1 0 6.24225 2.67525 0.89175
37 1 0 3.567 1.7835 1.7835
38 1 0 4.45875 2.67525 2.67525
39 1 0 5.3505 0 1.7835
40 1 0 6.24225 0.89175 2.67525
41 1 0 3.567 0 3.567
42 1 0 4.45875 0.89175 4.45875
43 1 0 5.3505 1.7835 3.567
44 1 0 6.24225 2.67525 4.45875
45 1 0 3.567 1.7835 5.3505
46 1 0 4.45875 2.67525 6.24225
47 1 0 5.3505 0 5.3505
48 1 0 6.24225 0.89175 6.24225
49 1 0 3.567 3.567 0
50 1 0 4.45875 4.45875 0.89175
51 1 0 5.3505 5.3505 0
52 1 0 6.24225 6.24225 0.89175
53 1 0 3.567 5.3505 1.7835
54 1 0 4.45875 6.24225 2.67525
55 1 0 5.3505 3.567 1.7835
56 1 0 6.24225 4.45875 2.67525
57 1 0 3.567 3.567 3.567
58 1 0 4.45875 4.45875 4.45875
59 1 0 5.3505 5.3505 3.567
60 1 0 6.24225 6.24225 4.45875
61 1 0 3.567 5.3505 5.3505
62 1 0 4.45875 6.24225 6.24225
63 1 0 5.3505 3.567 5.3505
64 1 0 6.24225 4.45875 6.24225
Velocities
1 -0.00733742 -0.0040297 -0.00315229
2 -0.00788609 -0.00567535 -0.00199152
3 -0.00239042 0.00710139 -0.00335049
4 0.00678551 0.0019976 0.00219289
5 0.00413717 0.00275709 0.000937637
6 -0.00126313 0.00485636 0.00727862
7 0.00337547 -0.00234623 -0.000922223
8 -0.00792183 -0.00509186 -0.00104168
9 0.00414091 0.00390285 0.000845961
10 -0.000284543 0.0010771 -0.00458404
11 -0.00394968 -0.00446363 -0.00361688
12 0.00067088 -0.00655175 -0.00752464
13 0.00306632 -0.00245545 -0.00183867
14 -0.0082145 -0.00564127 0.000281191
15 0.00504454 0.0045835 0.000495763
16 0.0035767 0.00320441 -0.00486426
17 0.00420597 0.00262005 -0.0049459
18 0.00440579 -1.76783e-05 0.00449311
19 -0.00406463 0.00613304 0.00285599
20 0.00171215 -0.00517887 0.00124326
21 0.0011118 0.00334129 -0.0015222
22 -0.00838394 -0.00112906 -0.00353379
23 -0.00578527 -0.00415501 0.00297043
24 -0.00211466 0.000964108 -0.00716523
25 -0.000204107 -0.00380986 0.00681648
26 0.00677838 0.00540935 0.0044354
27 -0.00266809 -0.00358382 -0.00241889
28 -0.0003973 0.00236566 0.00558871
29 0.000754103 0.00457797 0.000105531
30 -0.00246049 0.00110428 0.00511088
31 0.00248891 0.00623314 0.00461597
32 -0.00509423 0.000570503 0.00720856
33 -0.00244427 -0.00374384 0.00618767
34 -0.000360752 -8.10558e-05 0.00314052
35 0.00435313 -0.00630587 -0.0070309
36 0.00651087 -0.00389833 3.72525e-05
37 0.00631828 -0.00316064 0.00231522
38 -0.00579624 -0.00345068 -0.000277486
39 0.00483974 0.000715028 0.000206355
40 -0.00388164 -0.00189242 -0.00554862
41 0.00398115 0.00152915 0.00756919
42 -0.000552263 0.00352025 -0.000246143
43 -0.00800284 0.00555703 0.00425716
44 -0.00734405 -0.00752512 0.00667173
45 -0.00545636 0.00421035 0.00399552
46 0.00480246 0.00621147 -0.00492715
47 -0.00424168 0.00621818 -9.37733e-05
48 -0.00649561 0.00612908 -0.0020753
49 -0.0075007 -0.00384737 -0.00687913
50 -0.00203903 -0.00764372 0.0023883
51 0.00442642 0.00744072 -0.0049344
52 -0.00280486 -0.00509128 -0.00678045
53 0.00679491 0.00583493 0.00333875
54 0.00574665 -0.00521074 0.00523475
55 0.00305618 -0.00320094 0.00341297
56 0.004304 0.000615544 -0.00668787
57 0.00564532 0.00327373 0.00388611
58 0.000676899 0.00210326 0.00495295
59 0.000160781 -0.00744313 -0.00279828
60 0.00623521 0.00371301 0.00178015
61 0.00520759 0.000642669 0.00207913
62 0.00398042 0.0046438 -0.00359978
63 -0.00478071 -0.00304932 -0.00765125
64 0.00282671 -0.00548392 -0.00692691

View File

@ -1,40 +0,0 @@
#sample DFTB+ script to run this test code
Geometry = GenFormat {
<<< "lammps.gen"
}
Driver = {
}
Hamiltonian = DFTB {
LAMMPS = Yes # keyword to print energy, forces, and stress tensor to file(results.out)
SCC = No
MaxAngularMomentum = {
C = "p"
}
Charge = 0.0
Eigensolver = Standard {}
Filling = Fermi {
Temperature [Kelvin] = 298.0
}
SlaterKosterFiles = Type2FileNames {
Prefix = "~/slako/mio-1-1/" # the user must define the location of the skf files
Separator = "-"
Suffix = ".skf"
LowerCaseTypeName = No
}
KPointsAndWeights = {
0.0000000000000 0.0000000000000 0.0000000000000 1.00000000000000
}
}
Options = {
CalculateForces = Yes
WriteDetailedOut = No
WriteBandOut = No
RandomSeed = 12345
}
ParserOptions = {
ParserVersion = 3
}

View File

@ -1,129 +0,0 @@
Geometry = GenFormat {
64 S
C
1 1 7.099007 7.117657 7.119139
2 1 0.858709 0.867233 0.882294
3 1 1.772527 1.811776 7.120239
4 1 2.702145 2.681271 0.901362
5 1 0.017539 1.794455 1.788454
6 1 0.885593 2.694118 2.707994
7 1 1.795055 7.120787 1.777896
8 1 2.642849 0.868278 2.670699
9 1 0.016060 0.017156 3.568644
10 1 0.891891 0.896406 4.439286
11 1 1.766086 1.764402 3.550134
12 1 2.677349 2.648926 4.427174
13 1 0.010133 1.771283 5.342173
14 1 0.858153 2.653565 6.241596
15 1 1.804087 0.020636 5.353268
16 1 2.689680 0.907188 6.224575
17 1 0.017845 3.577563 7.113016
18 1 0.910027 4.459286 0.910286
19 1 1.766394 5.376046 0.015526
20 1 2.683727 6.220728 0.898553
21 1 0.003357 5.363423 1.774139
22 1 0.856735 6.238324 2.660213
23 1 1.761079 3.549776 1.797054
24 1 2.667227 4.463441 2.646074
25 1 7.132499 3.551558 3.599764
26 1 0.920387 4.482191 4.479257
27 1 1.772194 5.337132 3.555569
28 1 2.675010 6.251629 4.483124
29 1 0.005702 5.371095 5.351147
30 1 0.880807 6.249819 6.264231
31 1 1.793177 3.592396 5.369939
32 1 2.653179 4.463595 6.274044
33 1 3.557243 7.118913 0.026006
34 1 4.458971 0.889331 0.904950
35 1 5.367903 1.759757 7.104941
36 1 6.271565 2.658454 0.890168
37 1 3.591915 1.768681 1.793880
38 1 4.435612 2.662184 2.676722
39 1 5.371040 0.000196 1.783464
40 1 6.226453 0.886640 2.653384
41 1 3.583339 0.005449 3.600177
42 1 4.453692 0.909417 4.459713
43 1 5.314554 1.805409 3.584215
44 1 6.210181 2.642660 4.486206
45 1 3.545704 1.802745 5.365369
46 1 4.476660 2.701226 6.220451
47 1 5.332820 0.029557 5.347965
48 1 6.215725 0.915081 6.230289
49 1 3.536446 3.551469 7.106600
50 1 4.451181 4.426439 0.900180
51 1 5.368735 5.377996 7.109524
52 1 6.230666 6.220985 0.862175
53 1 3.596626 5.372822 1.797613
54 1 4.485613 6.221252 2.699652
55 1 5.364421 3.549838 1.796281
56 1 6.261739 4.459046 2.648152
57 1 3.588752 3.581054 3.581755
58 1 4.462342 4.467270 4.478800
59 1 5.355202 5.318323 3.556531
60 1 6.268570 6.259831 4.465795
61 1 3.588636 5.354278 5.362327
62 1 4.475747 6.263866 6.227803
63 1 5.331158 3.554349 5.318368
64 1 6.254581 4.436344 6.209681
0.0 0.0 0.0
7.13400000000000 0 0
0 7.13400000000000 0
0 0 7.13400000000000
}
Driver = {}
Hamiltonian = DFTB {
LAMMPS = Yes
SCC = No
MaxAngularMomentum = {
C = "p"
}
Charge = 0.0
Eigensolver = Standard {}
Filling = Fermi {
Temperature [Kelvin] = 298.0
IndependentKFilling = No
}
SlaterKosterFiles = Type2FileNames {
Prefix = "~/slako/mio-1-1/"
Separator = "-"
Suffix = ".skf"
LowerCaseTypeName = No
}
KPointsAndWeights = {
0.0000000000000 0.0000000000000 0.0000000000000 1.00000000000000
}
PolynomialRepulsive = {}
OldRepulsiveSum = No
OrbitalResolvedSCC = No
OldSKInterpolation = No
NoErep = No
Dispersion = {}
ThirdOrder = No
ThirdOrderFull = No
}
Options = {
CalculateForces = Yes
WriteDetailedOut = No
WriteBandOut = No
RandomSeed = 12345
MullikenAnalysis = No
WriteEigenvectors = No
WriteAutotestTag = No
WriteDetailedXML = No
WriteResultsTag = No
AtomResolvedEnergies = No
WriteHS = No
WriteRealHS = No
MinimiseMemoryUsage = No
ShowFoldedCoords = No
}
ParserOptions = {
ParserVersion = 3
WriteHSDInput = Yes
WriteXMLInput = No
StopAfterParsing = No
IgnoreUnprocessedNodes = No
}
Analysis = {
ProjectStates = {}
}

View File

@ -1,16 +0,0 @@
units real
atom_style charge
atom_modify map array
atom_modify sort 0 0.0
read_data data.diamond
neighbor 1.0 bin
neigh_modify delay 0 every 5 check no
fix 1 all nve
fix 2 all external pf/callback 1 1
fix_modify 2 energy yes
thermo_style custom step temp etotal ke pe lx ly lz pxx pyy pzz press
thermo 1
timestep 0.5

View File

@ -1,71 +0,0 @@
LAMMPS (6 Jul 2017)
units real
atom_style charge
atom_modify map array
atom_modify sort 0 0.0
read_data data.diamond
triclinic box = (0 0 0) to (7.134 7.134 7.134) with tilt (0 0 0)
1 by 1 by 1 MPI processor grid
reading atoms ...
64 atoms
reading velocities ...
64 velocities
neighbor 1.0 bin
neigh_modify delay 0 every 5 check no
fix 1 all nve
fix 2 all external pf/callback 1 1
fix_modify 2 energy yes
thermo_style custom step temp etotal ke pe lx ly lz pxx pyy pzz press
thermo 1
timestep 0.5
run 10
Neighbor list info ...
update every 5 steps, delay 0 steps, check no
max neighbors/atom: 2000, page size: 100000
master list distance cutoff = 0
ghost atom cutoff = 0
binsize = 7.134, bins = 1 1 1
0 neighbor lists, perpetual/occasional/extra = 0 0 0
Per MPI rank memory allocation (min/avg/max) = 2.3 | 2.3 | 2.3 Mbytes
Step Temp TotEng KinEng PotEng Lx Ly Lz Pxx Pyy Pzz Press
0 298.24835 -69593.587 56.008365 -69649.595 7.134 7.134 7.134 -19980.19 -21024.038 -21097.458 -20700.562
1 295.24358 -69593.585 55.444098 -69649.029 7.134 7.134 7.134 -19778.833 -20799.657 -20854.156 -20477.549
2 286.37211 -69593.58 53.778115 -69647.358 7.134 7.134 7.134 -19227.52 -20177.28 -20176.12 -19860.306
3 272.062 -69593.572 51.090804 -69644.663 7.134 7.134 7.134 -18360.869 -19189.684 -19100.021 -18883.525
4 253.01834 -69593.561 47.514575 -69641.075 7.134 7.134 7.134 -17198.143 -17855.03 -17652.036 -17568.403
5 230.19242 -69593.547 43.228073 -69636.775 7.134 7.134 7.134 -15750.247 -16183.764 -15854.145 -15929.386
6 204.71787 -69593.533 38.44418 -69631.977 7.134 7.134 7.134 -14083.498 -14247.434 -13789.835 -14040.256
7 177.82397 -69593.518 33.393748 -69626.911 7.134 7.134 7.134 -12340.963 -12202.878 -11623.171 -12055.671
8 150.76736 -69593.503 28.312758 -69621.816 7.134 7.134 7.134 -10637.824 -10180.827 -9495.0496 -10104.567
9 124.7737 -69593.49 23.431383 -69616.921 7.134 7.134 7.134 -9113.3842 -8339.0492 -7572.8076 -8341.747
10 100.98183 -69593.478 18.963481 -69612.442 7.134 7.134 7.134 -7833.9349 -6756.9749 -5945.8968 -6845.6022
Loop time of 2.20497 on 1 procs for 10 steps with 64 atoms
Performance: 0.196 ns/day, 122.499 hours/ns, 4.535 timesteps/s
0.2% CPU use with 1 MPI tasks x no OpenMP threads
MPI task timing breakdown:
Section | min time | avg time | max time |%varavg| %total
---------------------------------------------------------------
Pair | 0 | 0 | 0 | 0.0 | 0.00
Neigh | 1.4305e-06 | 1.4305e-06 | 1.4305e-06 | 0.0 | 0.00
Comm | 4.22e-05 | 4.22e-05 | 4.22e-05 | 0.0 | 0.00
Output | 0.00067687 | 0.00067687 | 0.00067687 | 0.0 | 0.03
Modify | 2.2042 | 2.2042 | 2.2042 | 0.0 | 99.96
Other | | 6.533e-05 | | | 0.00
Nlocal: 64 ave 64 max 64 min
Histogram: 1 0 0 0 0 0 0 0 0 0
Nghost: 0 ave 0 max 0 min
Histogram: 1 0 0 0 0 0 0 0 0 0
Neighs: 0 ave 0 max 0 min
Histogram: 1 0 0 0 0 0 0 0 0 0
Total # of neighbors = 0
Ave neighs/atom = 0
Neighbor list builds = 2
Dangerous builds not checked
Total wall time: 0:00:02

View File

@ -1,45 +0,0 @@
SHELL = /bin/sh
# Path to LAMMPS extraction directory
LAMMPS_ROOT = ../../..
LAMMPS_SRC = $(LAMMPS_ROOT)/src
# Uncomment the line below if using the MPI stubs library
MPI_STUBS = #-I$(LAMMPS_SRC)/STUBS
FC = mpif90 # replace with your Fortran compiler
CXX = mpicc # replace with your C++ compiler
# Flags for Fortran compiler, C++ compiler, and C preprocessor, respectively
FFLAGS = -O2 -fPIC
CXXFLAGS = -O2 -fPIC
CPPFLAGS = -DOMPI_SKIP_MPICXX=1 -DMPICH_SKIP_MPICXX
all : liblammps_fortran.a liblammps_fortran.so simpleF.x
liblammps_fortran.so : LAMMPS.o LAMMPS-wrapper.o LAMMPS-wrapper2.o
$(FC) $(FFLAGS) -shared -o $@ $^
simpleF.x: simple.o LAMMPS.o LAMMPS-wrapper.o LAMMPS-wrapper2.o
$(FC) $(FFLAGS) simple.o -o simpleF.x liblammps_fortran.a $(LAMMPS_SRC)/liblammps_mvapich.a -lstdc++ /usr/lib64/libfftw3.a
liblammps_fortran.a : LAMMPS.o LAMMPS-wrapper.o LAMMPS-wrapper2.o
$(AR) rs $@ $^
LAMMPS.o lammps.mod : LAMMPS.F90
$(FC) $(CPPFLAGS) $(FFLAGS) -c $<
simple.o : simple.f90
$(FC) $(FFLAGS) -c $<
LAMMPS-wrapper.o : LAMMPS-wrapper.cpp LAMMPS-wrapper.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -I$(LAMMPS_SRC) $(MPI_STUBS)
LAMMPS-wrapper2.o : LAMMPS-wrapper2.cpp LAMMPS-wrapper2.h
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -I$(LAMMPS_SRC) $(MPI_STUBS)
clean :
$(RM) *.o *.mod liblammps_fortran.a liblammps_fortran.so
dist :
tar -czvf fortran-interface-callback.tar.gz LAMMPS-wrapper.h LAMMPS-wrapper.cpp LAMMPS-wrapper2.h LAMMPS-wrapper2.cpp LAMMPS.F90 makefile README simple.f90

View File

@ -1,110 +0,0 @@
module callback
implicit none
contains
subroutine fortran_callback(lmp, timestep, nlocal, ids, c_pos, c_fext) &
& bind(C, name='f_callback')
use, intrinsic :: ISO_C_binding
use LAMMPS
implicit none
type (C_ptr), value :: lmp
integer(C_int64_t), intent(in), value :: timestep
integer(C_int), intent(in), value :: nlocal
real (C_double), dimension(:,:), pointer :: x
type(c_ptr) :: c_pos, c_fext, c_ids
double precision, pointer :: fext(:,:), pos(:,:)
integer, intent(in) :: ids(nlocal)
real(C_double) :: virial(6)
real (C_double) :: etot
real(C_double), pointer :: ts_lmp
double precision :: stress(3,3), ts_dftb
integer :: natom , i
real (C_double), parameter :: econv = 627.4947284155114 ! converts from Ha to
double precision, parameter :: fconv = 1185.793095983065 ! converts from Ha/bohr to
double precision, parameter :: autoatm = 2.9037166638E8
double precision lx, ly, lz
real (C_double), pointer :: boxxlo, boxxhi
real (C_double), pointer :: boxylo, boxyhi
real (C_double), pointer :: boxzlo, boxzhi
double precision, parameter :: nktv2p = 68568.4149999999935972
double precision :: volume
type (C_ptr) :: Cptr
type (C_ptr), pointer, dimension(:) :: Catom
call c_f_pointer(c_pos, pos, [3,nlocal])
call c_f_pointer(c_fext, fext, [3,nlocal])
call lammps_extract_global(boxxlo, lmp, 'boxxlo')
call lammps_extract_global(boxxhi, lmp, 'boxxhi')
call lammps_extract_global(boxylo, lmp, 'boxylo')
call lammps_extract_global(boxyhi, lmp, 'boxyhi')
call lammps_extract_global(boxzlo, lmp, 'boxzlo')
call lammps_extract_global(boxzhi, lmp, 'boxzhi')
lx = boxxhi - boxxlo
ly = boxyhi - boxylo
lz = boxzhi - boxzlo
volume = lx*ly*lz
open (unit = 10, status = 'replace', action = 'write', file='lammps.gen')
write(10,*)nlocal,"S"
write(10,*) "C"
do i = 1, nlocal
write(10,'(2I,3F15.6)')i,1,pos(:,ids(i))
enddo
write(10,*)"0.0 0.0 0.0"
write(10,*)lx,0,0
write(10,*)0,ly,0
write(10,*)0,0,lz
close(10)
call system("./dftb+ > dftb.out")
open (unit = 10, status = 'old', file = 'results.out')
read(10,*)etot
read(10,*)ts_dftb
do i = 1, 3
read(10,*)stress(i,:)
enddo
stress (:,:) = stress(:,:)*autoatm
virial(1) = stress(1,1)/(nktv2p/volume)
virial(2) = stress(2,2)/(nktv2p/volume)
virial(3) = stress(3,3)/(nktv2p/volume)
virial(4) = stress(1,2)/(nktv2p/volume)
virial(5) = stress(1,3)/(nktv2p/volume)
virial(6) = stress(2,3)/(nktv2p/volume)
etot = etot*econv
call lammps_set_external_vector(lmp,1,ts_dftb*econv)
do i = 1, nlocal
read(10,*)fext(:,ids(i))
fext(:,ids(i)) = fext(:,ids(i))*fconv
enddo
close(10)
call lammps_set_user_energy (lmp, etot)
call lammps_set_user_virial (lmp, virial)
end subroutine
end module callback
program simple_fortran_callback
use MPI
use LAMMPS
use callback
use, intrinsic :: ISO_C_binding, only : C_double, C_ptr, C_int, C_FUNPTR
implicit none
type (C_ptr) :: lmp
integer :: error, narg, me, nprocs
call MPI_Init (error)
call MPI_Comm_rank (MPI_COMM_WORLD, me, error)
call MPI_Comm_size (MPI_COMM_WORLD, nprocs, error)
call lammps_open_no_mpi ('lmp -log log.simple', lmp)
call lammps_file (lmp, 'in.simple')
call lammps_set_callback(lmp)
call lammps_set_external_vector_length(lmp,2)
call lammps_command (lmp, 'run 10')
call lammps_close (lmp)
call MPI_Finalize (error)
end program simple_fortran_callback

View File

@ -90,6 +90,7 @@ liblammpsplugin_t *liblammpsplugin_load(const char *lib)
ADDSYM(get_natoms);
ADDSYM(get_thermo);
ADDSYM(last_thermo);
ADDSYM(extract_box);
ADDSYM(reset_box);

View File

@ -37,12 +37,13 @@
#endif
/* The following enums must be kept in sync with the equivalent enums
* or constants in python/lammps/constants.py, fortran/lammps.f90,
* tools/swig/lammps.i, and examples/COUPLE/plugin/liblammpsplugin.h */
* or constants in src/library.h, src/lmptype.h, python/lammps/constants.py,
* fortran/lammps.f90, and tools/swig/lammps.i */
/* Data type constants for extracting data from atoms, computes and fixes */
enum _LMP_DATATYPE_CONST {
LAMMPS_NONE = -1, /*!< no data type assigned (yet) */
LAMMPS_INT = 0, /*!< 32-bit integer (array) */
LAMMPS_INT_2D = 1, /*!< two-dimensional 32-bit integer array */
LAMMPS_DOUBLE = 2, /*!< 64-bit double (array) */
@ -133,6 +134,7 @@ struct _liblammpsplugin {
double (*get_natoms)(void *);
double (*get_thermo)(void *, const char *);
void *(*last_thermo)(void *, const char *, int);
void (*extract_box)(void *, double *, double *,
double *, double *, double *, int *, int *);