forked from lijiext/lammps
Merge remote-tracking branch 'github/master' into move-convenience-functions
This commit is contained in:
commit
dd03c7232a
|
@ -75,7 +75,7 @@ if(GPU_API STREQUAL "CUDA")
|
|||
endif()
|
||||
# Kepler (GPU Arch 3.5) is supported by CUDA 5 to CUDA 11
|
||||
if((CUDA_VERSION VERSION_GREATER_EQUAL "5.0") AND (CUDA_VERSION VERSION_LESS "12.0"))
|
||||
string(APPEND GPU_CUDA_GENCODE " -gencode arch=compute_30,code=[sm_30,compute_30] -gencode arch=compute_35,code=[sm_35,compute_35]")
|
||||
string(APPEND GPU_CUDA_GENCODE " -gencode arch=compute_35,code=[sm_35,compute_35]")
|
||||
endif()
|
||||
# Maxwell (GPU Arch 5.x) is supported by CUDA 6 and later
|
||||
if(CUDA_VERSION VERSION_GREATER_EQUAL "6.0")
|
||||
|
|
|
@ -422,6 +422,12 @@ INPUT = @LAMMPS_SOURCE_DIR@/utils.cpp \
|
|||
@LAMMPS_SOURCE_DIR@/atom.h \
|
||||
@LAMMPS_SOURCE_DIR@/input.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/input.h \
|
||||
@LAMMPS_SOURCE_DIR@/tokenizer.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/tokenizer.h \
|
||||
@LAMMPS_SOURCE_DIR@/text_file_reader.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/text_file_reader.h \
|
||||
@LAMMPS_SOURCE_DIR@/potential_file_reader.cpp \
|
||||
@LAMMPS_SOURCE_DIR@/potential_file_reader.h \
|
||||
|
||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
Using the C++ API directly
|
||||
**************************
|
||||
|
||||
Using the C++ classes of the LAMMPS library is lacking some of the
|
||||
convenience of the C library API, but it allows a more direct access to
|
||||
simulation data and thus more low-level manipulations and tighter
|
||||
integration of LAMMPS into another code. While for the complete C
|
||||
library API is provided in the ``library.h`` header file, for using
|
||||
the C++ API it is required to include the individual header files
|
||||
defining the individual classes in use. Typically the name of the
|
||||
class and the name of the header follow some simple rule. Examples
|
||||
are given below.
|
||||
|
||||
|
||||
Creating or deleting a LAMMPS object
|
||||
*************************************
|
||||
|
||||
When using the LAMMPS library interfaces, the core task is to create an
|
||||
instance of the :cpp:class:`LAMMPS_NS::LAMMPS` class. In C++ this can
|
||||
be done directly through the ``new`` operator. All further operations
|
||||
are then initiated through calling member functions of some of the
|
||||
components of the LAMMPS class or accessing their data members. The
|
||||
destruction of the LAMMPS instance is correspondingly initiated by using
|
||||
the ``delete`` operator. Here is a simple example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
#include "lammps.h"
|
||||
#include "universe.h"
|
||||
|
||||
#include <mpi.h>
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
LAMMPS_NS::LAMMPS *lmp;
|
||||
// custom argument vector for LAMMPS library
|
||||
const char *lmpargv[] {"liblammps", "-log", "none"};
|
||||
int lmpargc = sizeof(lmpargv)/sizeof(const char *);
|
||||
|
||||
// explicitly initialize MPI
|
||||
MPI_Init(&argc, &argv);
|
||||
|
||||
// create LAMMPS instance
|
||||
lmp = new LAMMPS_NS::LAMMPS(lmpargc, (char **)lmpargv, MPI_COMM_WORLD);
|
||||
// output numerical version string
|
||||
std::cout << "LAMMPS version: " << lmp->universe->num_ver << std::endl;
|
||||
// delete LAMMPS instance
|
||||
delete lmp;
|
||||
|
||||
// stop MPI environment
|
||||
MPI_Finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
Please note that this requires to include the ``lammps.h`` header for accessing
|
||||
the members of the LAMMPS class and then the ``universe.h`` header for accessing the ``num_ver`` member of the :cpp:class:`Universe` class.
|
||||
|
||||
|
||||
Executing LAMMPS commands
|
||||
*************************
|
||||
|
||||
Once a LAMMPS instance is created by your C++ code, you need to set up a
|
||||
simulation and that is most conveniently done by "driving" it through
|
||||
issuing commands like you would do when running a LAMMPS simulation from
|
||||
an input script. Processing of input in LAMMPS is handled by the
|
||||
:cpp:class:`Input <LAMMPS_NS::Input>` class an instance of which is a
|
||||
member of the :cpp:class:`LAMMPS <LAMMPS_NS::LAMMPS>` class. You have
|
||||
two options: reading commands from a file, or executing a single
|
||||
command from a string. See below for a small example:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
#include "lammps.h"
|
||||
#include "input.h"
|
||||
#include <mpi.h>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
const char *lmpargv[] {"liblammps", "-log", "none"};
|
||||
int lmpargc = sizeof(lmpargv)/sizeof(const char *);
|
||||
|
||||
MPI_Init(&argc, &argv);
|
||||
LAMMPS *lmp = new LAMMPS(lmpargc, (char **)lmpargv, MPI_COMM_WORLD);
|
||||
lmp->input->file("in.melt");
|
||||
lmp->input->one("run 100 post no");
|
||||
delete lmp;
|
||||
return 0;
|
||||
}
|
|
@ -762,6 +762,8 @@ on reading or an unexpected end-of-file state was reached. In that
|
|||
case, the functions will stop the calculation with an error message,
|
||||
indicating the name of the problematic file, if possible.
|
||||
|
||||
----------
|
||||
|
||||
.. doxygenfunction:: sfgets
|
||||
:project: progguide
|
||||
|
||||
|
@ -787,6 +789,8 @@ and avoids a "hanging" calculation when run in parallel.
|
|||
Please also see :cpp:func:`is_integer` and :cpp:func:`is_double` for
|
||||
testing strings for compliance without conversion.
|
||||
|
||||
----------
|
||||
|
||||
.. doxygenfunction:: numeric
|
||||
:project: progguide
|
||||
|
||||
|
@ -806,6 +810,8 @@ String processing
|
|||
The following are functions to help with processing strings
|
||||
and parsing files or arguments.
|
||||
|
||||
----------
|
||||
|
||||
.. doxygenfunction:: trim
|
||||
:project: progguide
|
||||
|
||||
|
@ -895,3 +901,188 @@ Convenience functions
|
|||
|
||||
.. doxygenfunction:: timespec2seconds
|
||||
:project: progguide
|
||||
|
||||
---------------------------
|
||||
|
||||
Tokenizer classes
|
||||
=================
|
||||
|
||||
The purpose of the tokenizer classes is to simplify the recurring task
|
||||
of breaking lines of text down into words and/or numbers.
|
||||
Traditionally, LAMMPS code would be using the ``strtok()`` function from
|
||||
the C library for that purpose, but that function has two significant
|
||||
disadvantages: 1) it cannot be used concurrently from different LAMMPS
|
||||
instances since it stores its status in a global variable and 2) it
|
||||
modifies the string that it is processing. These classes were
|
||||
implemented to avoid both of these issues and also to reduce the amount
|
||||
of code that needs to be written.
|
||||
|
||||
The basic procedure is to create an instance of the tokenizer class with
|
||||
the string to be processed as an argument and then do a loop until all
|
||||
available tokens are read. The constructor has a default set of
|
||||
separator characters, but that can be overridden. The default separators
|
||||
are all "whitespace" characters, i.e. the space character, the tabulator
|
||||
character, the carriage return character, the linefeed character, and
|
||||
the form feed character.
|
||||
|
||||
.. code-block:: C++
|
||||
:caption: Tokenizer class example listing entries of the PATH environment variable
|
||||
|
||||
#include "tokenizer.h"
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
const char *path = getenv("PATH");
|
||||
|
||||
if (path != nullptr) {
|
||||
Tokenizer p(path,":");
|
||||
while (p.has_next())
|
||||
std::cout << "Entry: " << p.next() << "\n";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Most tokenizer operations cannot fail except for
|
||||
:cpp:func:`LAMMPS_NS::Tokenizer::next` (when used without first
|
||||
checking with :cpp:func:`LAMMPS_NS::Tokenizer::has_next`) and
|
||||
:cpp:func:`LAMMPS_NS::Tokenizer::skip`. In case of failure, the class
|
||||
will throw an exception, so you may need to wrap the code using the
|
||||
tokenizer into a ``try`` / ``catch`` block to handle errors. The
|
||||
:cpp:class:`LAMMPS_NS::ValueTokenizer` class may also throw an exception
|
||||
when a (type of) number is requested as next token that is not
|
||||
compatible with the string representing the next word.
|
||||
|
||||
.. code-block:: C++
|
||||
:caption: ValueTokenizer class example with exception handling
|
||||
|
||||
#include "tokenizer.h"
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
int main(int, char **)
|
||||
{
|
||||
const char *text = "1 2 3 4 5 20.0 21 twentytwo 2.3";
|
||||
double num1(0),num2(0),num3(0),num4(0);
|
||||
|
||||
ValueTokenizer t(text);
|
||||
// read 4 doubles after skipping over 5 numbers
|
||||
try {
|
||||
t.skip(5);
|
||||
num1 = t.next_double();
|
||||
num2 = t.next_double();
|
||||
num3 = t.next_double();
|
||||
num4 = t.next_double();
|
||||
} catch (TokenizerException &e) {
|
||||
std::cout << "Reading numbers failed: " << e.what() << "\n";
|
||||
}
|
||||
std::cout << "Values: " << num1 << " " << num2 << " " << num3 << " " << num4 << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
This code example should produce the following output:
|
||||
|
||||
.. code-block::
|
||||
|
||||
Reading numbers failed: Not a valid floating-point number: 'twentytwo'
|
||||
Values: 20 21 0 0
|
||||
|
||||
----------
|
||||
|
||||
.. doxygenclass:: LAMMPS_NS::Tokenizer
|
||||
:project: progguide
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: LAMMPS_NS::TokenizerException
|
||||
:project: progguide
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: LAMMPS_NS::ValueTokenizer
|
||||
:project: progguide
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: LAMMPS_NS::InvalidIntegerException
|
||||
:project: progguide
|
||||
:members: what
|
||||
|
||||
.. doxygenclass:: LAMMPS_NS::InvalidFloatException
|
||||
:project: progguide
|
||||
:members: what
|
||||
|
||||
File reader classes
|
||||
====================
|
||||
|
||||
The purpose of the file reader classes is to simplify the recurring task
|
||||
of reading and parsing files. They can use the
|
||||
:cpp:class:`LAMMPS_NS::ValueTokenizer` class to process the read in
|
||||
text. The :cpp:class:`LAMMPS_NS::TextFileReader` is a more general
|
||||
version while :cpp:class:`LAMMPS_NS::PotentialFileReader` is specialized
|
||||
to implement the behavior expected for looking up and reading/parsing
|
||||
files with potential parameters in LAMMPS. The potential file reader
|
||||
class requires a LAMMPS instance, requires to be run on MPI rank 0 only,
|
||||
will use the :cpp:func:`LAMMPS_NS::utils::get_potential_file_path`
|
||||
function to look up and open the file, and will call the
|
||||
:cpp:class:`LAMMPS_NS::Error` class in case of failures to read or to
|
||||
convert numbers, so that LAMMPS will be aborted.
|
||||
|
||||
.. code-block:: C++
|
||||
:caption: Use of PotentialFileReader class in pair style coul/streitz
|
||||
|
||||
PotentialFileReader reader(lmp, file, "coul/streitz");
|
||||
char * line;
|
||||
|
||||
while((line = reader.next_line(NPARAMS_PER_LINE))) {
|
||||
try {
|
||||
ValueTokenizer values(line);
|
||||
std::string iname = values.next_string();
|
||||
|
||||
int ielement;
|
||||
for (ielement = 0; ielement < nelements; ielement++)
|
||||
if (iname == elements[ielement]) break;
|
||||
|
||||
if (nparams == maxparam) {
|
||||
maxparam += DELTA;
|
||||
params = (Param *) memory->srealloc(params,maxparam*sizeof(Param),
|
||||
"pair:params");
|
||||
}
|
||||
|
||||
params[nparams].ielement = ielement;
|
||||
params[nparams].chi = values.next_double();
|
||||
params[nparams].eta = values.next_double();
|
||||
params[nparams].gamma = values.next_double();
|
||||
params[nparams].zeta = values.next_double();
|
||||
params[nparams].zcore = values.next_double();
|
||||
|
||||
} catch (TokenizerException & e) {
|
||||
error->one(FLERR, e.what());
|
||||
}
|
||||
nparams++;
|
||||
}
|
||||
|
||||
A file that would be parsed by the reader code fragment looks like this:
|
||||
|
||||
# DATE: 2015-02-19 UNITS: metal CONTRIBUTOR: Ray Shan CITATION: Streitz and Mintmire, Phys Rev B, 50, 11996-12003 (1994)
|
||||
#
|
||||
# X (eV) J (eV) gamma (1/\AA) zeta (1/\AA) Z (e)
|
||||
|
||||
Al 0.000000 10.328655 0.000000 0.968438 0.763905
|
||||
O 5.484763 14.035715 0.000000 2.143957 0.000000
|
||||
|
||||
|
||||
----------
|
||||
|
||||
.. doxygenclass:: LAMMPS_NS::TextFileReader
|
||||
:project: progguide
|
||||
:members:
|
||||
|
||||
.. doxygenclass:: LAMMPS_NS::PotentialFileReader
|
||||
:project: progguide
|
||||
:members:
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ used from multiple compiler versions from different vendors for as long
|
|||
as they are compatible with the hosting operating system, the same is
|
||||
not true for Fortran codes. Thus the LAMMPS Fortran module needs to be
|
||||
compiled alongside the code using it from the source code in
|
||||
``examples/COUPLE/fortran/lammps.f90``. When linking, you also need to
|
||||
``fortran/lammps.f90``. When linking, you also need to
|
||||
:doc:`link to the LAMMPS library <Build_link>`. A typical command line
|
||||
for a simple program using the Fortran interface would be:
|
||||
|
||||
|
@ -19,5 +19,184 @@ for a simple program using the Fortran interface would be:
|
|||
mpifort -o testlib.x lammps.f90 testlib.f90 -L. -llammps
|
||||
|
||||
Please note, that the MPI compiler wrapper is only required when the
|
||||
calling the library from an MPI parallel code.
|
||||
calling the library from an MPI parallel code. Please also note the order
|
||||
of the source files: the lammps.f90 file needs to be compiled first,
|
||||
since it provides the ``LIBLAMMPS`` module that is imported by the
|
||||
Fortran code using the interface.
|
||||
|
||||
.. versionadded:: 30Sep2020
|
||||
|
||||
.. admonition:: Work in Progress
|
||||
|
||||
This Fortran module is work in progress and only the documented
|
||||
functionality is currently available. The final implementation should
|
||||
cover the entire range of functionality available in the C and
|
||||
Python library interfaces.
|
||||
|
||||
----------
|
||||
|
||||
Creating or deleting a LAMMPS object
|
||||
************************************
|
||||
|
||||
With the Fortran interface the creation of a :cpp:class:`LAMMPS
|
||||
<LAMMPS_NS::LAMMPS>` instance is included in the constructor for
|
||||
creating the :f:func:`lammps` derived type. To import the definition of
|
||||
that type and its type bound procedures you need to add a ``USE
|
||||
LIBLAMMPS`` statement. Internally it will call either
|
||||
:cpp:func:`lammps_open_fortran` or :cpp:func:`lammps_open_no_mpi` from
|
||||
the C library API to create the class instance. All arguments are
|
||||
optional and :cpp:func:`lammps_mpi_init` will be called automatically,
|
||||
if it is needed. Similarly, a possible call to :cpp:func:`lammps_finalize`
|
||||
is integrated into the :f:func:`close` function and triggered with
|
||||
the optional logical argument set to ``.true.``. Here is a simple example:
|
||||
|
||||
.. code-block:: fortran
|
||||
|
||||
PROGRAM testlib
|
||||
USE LIBLAMMPS ! include the LAMMPS library interface
|
||||
TYPE(lammps) :: lmp ! derived type to hold LAMMPS instance
|
||||
CHARACTER(len=*), DIMENSION(*), PARAMETER :: args = &
|
||||
[ CHARACTER(len=12) :: 'liblammps', '-log', 'none' ]
|
||||
|
||||
! create a LAMMPS instance (and initialize MPI)
|
||||
lmp = lammps(args)
|
||||
! get and print numerical version code
|
||||
PRINT*, 'LAMMPS Version: ', lmp%version()
|
||||
! delete LAMMPS instance (and shuts down MPI)
|
||||
CALL lmp%close(.true.)
|
||||
|
||||
END PROGRAM testlib
|
||||
|
||||
--------------------
|
||||
|
||||
Executing LAMMPS commands
|
||||
=========================
|
||||
|
||||
Once a LAMMPS instance is created, it is possible to "drive" the LAMMPS
|
||||
simulation by telling LAMMPS to read commands from a file, or pass
|
||||
individual or multiple commands from strings or lists of strings. This
|
||||
is done similar to how it is implemented in the `C-library
|
||||
<pg_lib_execute>` interface. Before handing off the calls to the
|
||||
C-library interface, the corresponding Fortran versions of the calls
|
||||
(:f:func:`file`, :f:func:`command`, :f:func:`commands_list`, and
|
||||
:f:func:`commands_string`) have to make a copy of the strings passed as
|
||||
arguments so that they can be modified to be compatible with the
|
||||
requirements of strings in C without affecting the original strings.
|
||||
Those copies are automatically deleted after the functions return.
|
||||
Below is a small demonstration of the uses of the different functions:
|
||||
|
||||
.. code-block:: fortran
|
||||
|
||||
PROGRAM testcmd
|
||||
USE LIBLAMMPS
|
||||
TYPE(lammps) :: lmp
|
||||
CHARACTER(len=512) :: cmds
|
||||
CHARACTER(len=40),ALLOCATABLE :: cmdlist(:)
|
||||
CHARACTER(len=10) :: trimmed
|
||||
INTEGER :: i
|
||||
|
||||
lmp = lammps()
|
||||
CALL lmp%file('in.melt')
|
||||
CALL lmp%command('variable zpos index 1.0')
|
||||
! define 10 groups of 10 atoms each
|
||||
ALLOCATE(cmdlist(10))
|
||||
DO i=1,10
|
||||
WRITE(trimmed,'(I10)') 10*i
|
||||
WRITE(cmdlist(i),'(A,I1,A,I10,A,A)') &
|
||||
'group g',i-1,' id ',10*(i-1)+1,':',ADJUSTL(trimmed)
|
||||
END DO
|
||||
CALL lmp%commands_list(cmdlist)
|
||||
! run multiple commands from multi-line string
|
||||
cmds = 'clear' // NEW_LINE('A') // &
|
||||
'region box block 0 2 0 2 0 2' // NEW_LINE('A') // &
|
||||
'create_box 1 box' // NEW_LINE('A') // &
|
||||
'create_atoms 1 single 1.0 1.0 ${zpos}'
|
||||
CALL lmp%commands_string(cmds)
|
||||
CALL lmp%close()
|
||||
|
||||
END PROGRAM testcmd
|
||||
|
||||
---------------
|
||||
|
||||
The ``LIBLAMMPS`` module API
|
||||
****************************
|
||||
|
||||
Below are the detailed descriptions of definitions and interfaces
|
||||
of the contents of the ``LIBLAMMPS`` Fortran interface to LAMMPS.
|
||||
|
||||
.. f:type:: lammps
|
||||
|
||||
Derived type that is the general class of the Fortran interface.
|
||||
It holds a reference to the :cpp:class:`LAMMPS <LAMMPS_NS::LAMMPS>` class instance
|
||||
that any of the included calls are forwarded to.
|
||||
|
||||
:f c_ptr handle: reference to the LAMMPS class
|
||||
:f close: :f:func:`close`
|
||||
:f version: :f:func:`version`
|
||||
:f file: :f:func:`file`
|
||||
:f command: :f:func:`command`
|
||||
:f commands_list: :f:func:`commands_list`
|
||||
:f commands_string: :f:func:`commands_string`
|
||||
|
||||
.. f:function:: lammps(args[,comm])
|
||||
|
||||
This is the constructor for the Fortran class and will forward
|
||||
the arguments to a call to either :cpp:func:`lammps_open_fortran`
|
||||
or :cpp:func:`lammps_open_no_mpi`. If the LAMMPS library has been
|
||||
compiled with MPI support, it will also initialize MPI, if it has
|
||||
not already been initialized before.
|
||||
|
||||
The *args* argument with the list of command line parameters is
|
||||
optional and so it the *comm* argument with the MPI communicator.
|
||||
If *comm* is not provided, ``MPI_COMM_WORLD`` is assumed. For
|
||||
more details please see the documentation of :cpp:func:`lammps_open`.
|
||||
|
||||
:p character(len=*) args(*) [optional]: arguments as list of strings
|
||||
:o integer comm [optional]: MPI communicator
|
||||
:r lammps: an instance of the :f:type:`lammps` derived type
|
||||
|
||||
.. f:subroutine:: close([finalize])
|
||||
|
||||
This method will close down the LAMMPS instance through calling
|
||||
:cpp:func:`lammps_close`. If the *finalize* argument is present and
|
||||
has a value of ``.true.``, then this subroutine also calls
|
||||
:cpp:func:`lammps_mpi_finalize`.
|
||||
|
||||
:o logical finalize [optional]: shut down the MPI environment of the LAMMPS library if true.
|
||||
|
||||
.. f:function:: version()
|
||||
|
||||
This method returns the numeric LAMMPS version like :cpp:func:`lammps_version`
|
||||
|
||||
:r integer: LAMMPS version
|
||||
|
||||
--------
|
||||
|
||||
.. f:subroutine:: file(filename)
|
||||
|
||||
This method will call :cpp:func:`lammps_file` to have LAMMPS read
|
||||
and process commands from a file.
|
||||
|
||||
:p character(len=*) filename: name of file with LAMMPS commands
|
||||
|
||||
.. f:subroutine:: command(cmd)
|
||||
|
||||
This method will call :cpp:func:`lammps_command` to have LAMMPS
|
||||
execute a single command.
|
||||
|
||||
:p character(len=*) cmd: single LAMMPS command
|
||||
|
||||
.. f:subroutine:: commands_list(cmds)
|
||||
|
||||
This method will call :cpp:func:`lammps_commands_list` to have LAMMPS
|
||||
execute a list of input lines.
|
||||
|
||||
:p character(len=*) cmd(*): list of LAMMPS input lines
|
||||
|
||||
.. f:subroutine:: commands_string(str)
|
||||
|
||||
This method will call :cpp:func:`lammps_commands_string` to have LAMMPS
|
||||
execute a block of commands from a string.
|
||||
|
||||
:p character(len=*) str: LAMMPS input in string
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
Adding code to the Library interface
|
||||
====================================
|
||||
|
||||
The functionality of the LAMMPS library interface has historically
|
||||
always been motivated by the needs of its users and functions were
|
||||
added or expanded as they were needed and used. Contributions to
|
||||
the interface are always welcome. However with a refactoring of
|
||||
the library interface and its documentation that started in 2020,
|
||||
there are now a few requirements for inclusion of changes.
|
||||
|
||||
- New functions should be orthogonal to existing ones and not
|
||||
implement functionality that can already be achieved with the
|
||||
existing APIs.
|
||||
- All changes and additions should be documented with
|
||||
`Doxygen <https://doxgygen.org>`_ style comments and references
|
||||
to those functions added to the corresponding files in the
|
||||
``doc/src`` folder.
|
||||
- If possible, new unit tests to test those new features should
|
||||
be added.
|
||||
- The new feature should also be implemented and documented for
|
||||
the Python and Fortran modules.
|
||||
- All additions should work and be compatible with ``-DLAMMPS_BIGBIG``,
|
||||
``-DLAMMPS_SMALLBIG``, ``-DLAMMPS_SMALLSMALL`` and compiling
|
||||
with and without MPI support.
|
||||
- The ``library.h`` file should be kept compatible to C code at
|
||||
a level similar to C89. Its interfaces may not reference any
|
||||
custom data types (e.g. ``bigint``, ``tagint``, and so on) only
|
||||
known inside of LAMMPS.
|
||||
- only C style comments, not C++ style
|
||||
|
||||
Please note, that these are *not* *strict* requirements, but the
|
||||
LAMMPS developers appreciate if they are followed closely and will
|
||||
assist with implementing what is missing.
|
|
@ -0,0 +1,67 @@
|
|||
Retrieving LAMMPS configuration information
|
||||
===========================================
|
||||
|
||||
The following library functions can be used to query the
|
||||
LAMMPS library about compile time settings and included
|
||||
packages and styles.
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_config_has_mpi_support
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_config_has_gzip_support
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_config_has_png_support
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_config_has_jpeg_support
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_config_has_ffmpeg_support
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_config_has_exceptions
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_config_has_package
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_config_package_count
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_config_package_name
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_has_style
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_style_count
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_style_name
|
||||
:project: progguide
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
Creating or deleting a LAMMPS object
|
||||
====================================
|
||||
|
||||
The :cpp:func:`lammps_open` and :cpp:func:`lammps_open_no_mpi`
|
||||
functions are used to create and initialize a
|
||||
:cpp:func:`LAMMPS` instance. The calling program has to
|
||||
provide a handle where a reference to this instance can be stored and
|
||||
which has to be used in all subsequent function calls until that
|
||||
instance is destroyed by calling :cpp:func:`lammps_close`.
|
||||
Here is a simple example demonstrating its use:
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
#include "library.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *handle;
|
||||
int version;
|
||||
const char *lmpargv[] = { "liblammps", "-log", "none"};
|
||||
int lmpargc = sizeof(lmpargv)/sizeof(const char *);
|
||||
|
||||
/* create LAMMPS instance */
|
||||
handle = lammps_open_no_mpi(lmpargc, lmpargv, NULL);
|
||||
if (handle == NULL) {
|
||||
printf("LAMMPS initialization failed");
|
||||
lammps_mpi_finalize();
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* get and print numerical version code */
|
||||
version = lammps_version(handle);
|
||||
printf("LAMMPS Version: %d\n",version);
|
||||
|
||||
/* delete LAMMPS instance and shut down MPI */
|
||||
lammps_close(handle);
|
||||
lammps_mpi_finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
The LAMMPS library will be using the MPI library it was compiled with
|
||||
and will either run on all processors in the ``MPI_COMM_WORLD``
|
||||
communicator or on the set of processors in the communicator given in
|
||||
the ``comm`` argument of :cpp:func:`lammps_open`. This means
|
||||
the calling code can run LAMMPS on all or a subset of processors. For
|
||||
example, a wrapper code might decide to alternate between LAMMPS and
|
||||
another code, allowing them both to run on all the processors. Or it
|
||||
might allocate part of the processors to LAMMPS and the rest to the
|
||||
other code by creating a custom communicator with ``MPI_Comm_split()``
|
||||
and running both codes concurrently before syncing them up periodically.
|
||||
Or it might instantiate multiple instances of LAMMPS to perform
|
||||
different calculations and either alternate between them, run them
|
||||
concurrently on split communicators, or run them one after the other.
|
||||
The :cpp:func:`lammps_open` function may be called multiple
|
||||
times for this latter purpose.
|
||||
|
||||
The :cpp:func:`lammps_close` function is used to shut down
|
||||
the :cpp:class:`LAMMPS <LAMMPS_NS::LAMMPS>` class pointed to by the handle
|
||||
passed as an argument and free all its memory. This has to be called for
|
||||
every instance created with any of the :cpp:func:`lammps_open` functions. It will, however, **not** call
|
||||
``MPI_Finalize()``, since that may only be called once. See
|
||||
:cpp:func:`lammps_mpi_finalize` for an alternative to calling
|
||||
``MPI_Finalize()`` explicitly in the calling program.
|
||||
|
||||
The :cpp:func:`lammps_free` function is a clean-up
|
||||
function to free memory that the library allocated previously
|
||||
via other function calls. See below for notes in the descriptions
|
||||
of the individual commands where such memory buffers were allocated.
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_open
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_open_no_mpi
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_open_fortran
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_close
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_mpi_init
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_mpi_finalize
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_free
|
||||
:project: progguide
|
|
@ -0,0 +1,69 @@
|
|||
Executing LAMMPS commands
|
||||
=========================
|
||||
|
||||
Once a LAMMPS instance is created, there are multiple ways to "drive" a
|
||||
simulation. In most cases it is easiest to process single or multiple
|
||||
LAMMPS commands like in an input file. This can be done through reading
|
||||
a file or passing single commands or lists of commands or blocks of
|
||||
commands with the following functions.
|
||||
|
||||
Via these functions, the calling code can have the LAMMPS instance act
|
||||
on a series of :doc:`input file commands <Commands_all>` that are either
|
||||
read from a file or passed as strings. This for, for example, allows to
|
||||
setup a problem from a template file and then run it in stages while
|
||||
performing other operations in between or concurrently. The caller can
|
||||
interleave the LAMMPS function calls with operations it performs, calls
|
||||
to extract information from or set information within LAMMPS, or calls
|
||||
to another code's library.
|
||||
|
||||
Also equivalent to regular :doc:`input script parsing <Commands_parse>`
|
||||
is the handling of comments and expansion of variables with ``${name}``
|
||||
or ``$(expression)`` syntax before the commands are parsed and
|
||||
executed. Below is a short example using some of these functions.
|
||||
|
||||
.. code-block:: C
|
||||
|
||||
#include "library.h"
|
||||
#include <mpi.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
void *handle;
|
||||
int i;
|
||||
|
||||
MPI_Init(&argc, &argv);
|
||||
handle = lammps_open(0, NULL, MPI_COMM_WORLD, NULL);
|
||||
lammps_file(handle,"in.sysinit");
|
||||
lammps_command(handle,"run 1000 post no");
|
||||
|
||||
for (i=0; i < 100; ++i) {
|
||||
lammps_commands_string(handle,"run 100 pre no post no\n"
|
||||
"print 'PE = $(pe)'\n"
|
||||
"print 'KE = $(ke)'\n");
|
||||
}
|
||||
lammps_close(handle);
|
||||
MPI_Finalize();
|
||||
return 0;
|
||||
}
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_file
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_command
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_commands_list
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_commands_string
|
||||
:project: progguide
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
Accessing LAMMPS Neighbor lists
|
||||
===============================
|
||||
|
||||
The following functions allow to access neighbor lists
|
||||
generated by LAMMPS or query their properties.
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_find_compute_neighlist
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_find_fix_neighlist
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_find_pair_neighlist
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_neighlist_num_elements
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_neighlist_element_neighbors
|
||||
:project: progguide
|
|
@ -0,0 +1,31 @@
|
|||
Retrieving or setting properties of LAMMPS objects
|
||||
==================================================
|
||||
|
||||
This section documents accessing or modifying data from objects like
|
||||
computes, fixes, or variables in LAMMPS.
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_extract_compute
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_extract_fix
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_extract_variable
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_set_variable
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenenum:: _LMP_STYLE_CONST
|
||||
|
||||
.. doxygenenum:: _LMP_TYPE_CONST
|
|
@ -0,0 +1,62 @@
|
|||
Retrieving or setting LAMMPS system properties
|
||||
==============================================
|
||||
|
||||
The library interface allows to extract different kinds of information
|
||||
about the active simulation instance and also to modify some of them.
|
||||
This allows to combine MD simulation steps with other processing and
|
||||
simulation methods computed in the calling code or another code that is
|
||||
coupled to LAMMPS via the library interface. In some cases the data
|
||||
returned is direct reference to the original data inside LAMMPS cast
|
||||
to a void pointer. In that case the data needs to be cast to a suitable
|
||||
pointer to be able to access it, and you need to know the correct dimensions
|
||||
and lengths. When accessing per-atom data, please note that this data
|
||||
is the per-processor **local** data and indexed accordingly. These arrays
|
||||
can change sizes and order at every neighbor list rebuild and atom sort
|
||||
event as atoms are migrating between sub-domains.
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_version
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_get_natoms
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_get_thermo
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_extract_box
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_reset_box
|
||||
:project: progguide
|
||||
|
||||
-------------------
|
||||
|
||||
.. doxygenfunction:: lammps_extract_setting
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_extract_global
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_extract_atom
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_create_atoms(void *handle, int n, int *id, int *type, double *x, double *v, int *image, int bexpand)
|
||||
:project: progguide
|
||||
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
Library functions for scatter/gather operations
|
||||
================================================
|
||||
|
||||
.. TODO add description
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_gather_atoms
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_gather_atoms_concat
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_gather_atoms_subset
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_scatter_atoms
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_scatter_atoms_subset
|
||||
:project: progguide
|
|
@ -0,0 +1,30 @@
|
|||
Library interface utility functions
|
||||
===================================
|
||||
|
||||
To simplify some of the tasks, the library interface contains
|
||||
some utility functions that are not directly calling LAMMPS.
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_encode_image_flags
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_decode_image_flags(int image, int *flags)
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_set_fix_external_callback(void *, char *, FixExternalFnPtr, void*)
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_has_error
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_get_last_error_message
|
||||
:project: progguide
|
|
@ -91,15 +91,15 @@ and consequently the function :cpp:func:`lammps_open` may not be used.
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
.. pg_lib_create
|
||||
.. pg_lib_execute
|
||||
.. pg_lib_properties
|
||||
.. pg_lib_objects
|
||||
.. pg_lib_scatter
|
||||
.. pg_lib_neighbor
|
||||
.. pg_lib_config
|
||||
.. pg_lib_utility
|
||||
.. pg_lib_add
|
||||
pg_lib_create
|
||||
pg_lib_execute
|
||||
pg_lib_properties
|
||||
pg_lib_objects
|
||||
pg_lib_scatter
|
||||
pg_lib_neighbor
|
||||
pg_lib_config
|
||||
pg_lib_utility
|
||||
pg_lib_add
|
||||
|
||||
--------------------
|
||||
|
||||
|
@ -111,7 +111,7 @@ LAMMPS Python APIs
|
|||
The LAMMPS Python module enables calling the LAMMPS C library API from
|
||||
Python by dynamically loading functions in the LAMMPS shared library through
|
||||
the `Python ctypes module <https://docs.python.org/3/library/ctypes.html>`_.
|
||||
Because of the dynamics loading, it is **required** that LAMMPS is compiled
|
||||
Because of the dynamic loading, it is **required** that LAMMPS is compiled
|
||||
in :ref:`"shared" mode <exe>`. The Python interface is object oriented, but
|
||||
otherwise trying to be very similar to the C library API. Three different
|
||||
Python classes to run LAMMPS are available and they build on each other.
|
||||
|
@ -153,6 +153,6 @@ The following links provide some examples and references to the C++ API.
|
|||
.. toctree::
|
||||
:maxdepth: 1
|
||||
|
||||
.. pg_cplusplus
|
||||
pg_cplusplus
|
||||
|
||||
|
||||
|
|
|
@ -26,4 +26,163 @@ There are multiple Python interface classes in the :py:mod:`lammps` module:
|
|||
|
||||
.. _mpi4py_url: https://mpi4py.readthedocs.io
|
||||
|
||||
----------
|
||||
|
||||
Creating or deleting a LAMMPS object
|
||||
************************************
|
||||
|
||||
With the Python interface the creation of a :cpp:class:`LAMMPS
|
||||
<LAMMPS_NS::LAMMPS>` instance is included in the constructor for the
|
||||
:py:func:`lammps <lammps.lammps>` class. Internally it will call either
|
||||
:cpp:func:`lammps_open` or :cpp:func:`lammps_open_no_mpi` from the C
|
||||
library API to create the class instance.
|
||||
|
||||
All arguments are optional. The *name* argument is to allow loading a
|
||||
LAMMPS shared library that is named ``liblammps_machine.so`` instead of
|
||||
the default name of ``liblammps.so``. In most cases the latter will be
|
||||
installed or used. The *ptr* argument is for use of the
|
||||
:py:mod:`lammps` module from inside a LAMMPS instance, e.g. with the
|
||||
:doc:`python <python>` command, where a pointer to the already existing
|
||||
:cpp:class:`LAMMPS <LAMMPS_NS::LAMMPS>` class instance can be passed
|
||||
to the Python class and used instead of creating a new instance. The
|
||||
*comm* argument may be used in combination with the `mpi4py <mpi4py_url_>`_
|
||||
module to pass an MPI communicator to LAMMPS and thus it is possible
|
||||
to run the Python module like the library interface on a subset of the
|
||||
MPI ranks after splitting the communicator. Here is a simple example:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from lammps import lammps
|
||||
|
||||
# NOTE: argv[0] is set by the Python module
|
||||
args = ["-log", "none"]
|
||||
# create LAMMPS instance
|
||||
lmp = lammps(cmdargs=args)
|
||||
# get and print numerical version code
|
||||
print("LAMMPS Version: ", lmp.version())
|
||||
# explicitly close and delete LAMMPS instance (optional)
|
||||
lmp.close()
|
||||
|
||||
Same as with the :doc:`C library API <pg_lib_create>` this will use the
|
||||
``MPI_COMM_WORLD`` communicator for the MPI library that LAMMPS was
|
||||
compiled with. The :py:func:`lmp.close() <lammps.lammps.close>` call is
|
||||
optional since the LAMMPS class instance will also be deleted
|
||||
automatically during the :py:class:`lammps <lammps.lammps>` class
|
||||
destructor.
|
||||
|
||||
Executing LAMMPS commands
|
||||
*************************
|
||||
|
||||
Once an instance of the :py:class:`lammps <lammps.lammps>` class is
|
||||
created, there are multiple ways to "feed" it commands. In a way that is
|
||||
not very different from running a LAMMPS input script, except that
|
||||
Python has many more facilities for structured programming than the
|
||||
LAMMPS input script syntax. Furthermore it is possible to "compute"
|
||||
what the next LAMMPS command should be. Same as in the equivalent `C
|
||||
library functions <pg_lib_execute>`, commands can be read from a file, a
|
||||
single string, a list of strings and a block of commands in a single
|
||||
multi-line string. They are processed under the same boundary conditions
|
||||
as the C library counterparts. The example below demonstrates the use
|
||||
of :py:func:`lammps.file`, :py:func:`lammps.command`,
|
||||
:py:func:`lammps.commands_list`, and :py:func:`lammps.commands_string`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from lammps import lammps
|
||||
|
||||
lmp = lammps()
|
||||
# read commands from file 'in.melt'
|
||||
lmp.file('in.melt')
|
||||
# issue a single command
|
||||
lmp.command('variable zpos index 1.0')
|
||||
# create 10 groups with 10 atoms each
|
||||
cmds = ["group g{} id {}:{}".format(i,10*i+1,10*(i+1)) for i in range(10)]
|
||||
lmp.commands_list(cmds)
|
||||
# run commands from a multi-line string
|
||||
block = """
|
||||
clear
|
||||
region box block 0 2 0 2 0 2
|
||||
create_box 1 box
|
||||
create_atoms 1 single 1.0 1.0 ${zpos}
|
||||
"""
|
||||
lmp.commands_string(block)
|
||||
|
||||
----------
|
||||
|
||||
The ``lammps`` class API
|
||||
************************
|
||||
|
||||
The :py:class:`lammps <lammps.lammps>` class is the core of the LAMMPS
|
||||
Python interfaces. It is a wrapper around the :doc:`LAMMPS C library
|
||||
API <pg_library>` using the `Python ctypes module
|
||||
<https://docs.python.org/3/library/ctypes.html>`_ and a shared library
|
||||
compiled from the LAMMPS sources code. The individual methods in this
|
||||
class try to closely follow the corresponding C functions. The handle
|
||||
argument that needs to be passed to the C functions is stored internally
|
||||
in the class and automatically added when calling the C library
|
||||
functions. Below is a detailed documentation of the API.
|
||||
|
||||
.. autoclass:: lammps.lammps
|
||||
:members:
|
||||
|
||||
----------
|
||||
|
||||
The ``PyLammps`` class API
|
||||
**************************
|
||||
|
||||
.. autoclass:: lammps.PyLammps
|
||||
:members:
|
||||
|
||||
----------
|
||||
|
||||
The ``IPyLammps`` class API
|
||||
***************************
|
||||
|
||||
.. autoclass:: lammps.IPyLammps
|
||||
:members:
|
||||
|
||||
----------
|
||||
|
||||
Additional components of the ``lammps`` module
|
||||
**********************************************
|
||||
|
||||
The :py:mod:`lammps` module additionally contains several constants
|
||||
and the :py:class:`NeighList <lammps.NeighList>` class:
|
||||
|
||||
.. _py_data_constants:
|
||||
.. py:data:: LAMMPS_INT, LAMMPS_DOUBLE, LAMMPS_BIGINT, LAMMPS_TAGINT, LAMMPS_STRING
|
||||
:type: int
|
||||
|
||||
Constants in the :py:mod:`lammps` module to indicate how to
|
||||
cast data when the C library function returns a void pointer.
|
||||
Used in :py:func:`lammps.extract_global`.
|
||||
|
||||
.. _py_style_constants:
|
||||
.. py:data:: LMP_STYLE_GLOBAL, LMP_STYLE_ATOM, LMP_STYLE_LOCAL
|
||||
:type: int
|
||||
|
||||
Constants in the :py:mod:`lammps` module to select what style of data
|
||||
to request from computes or fixes. See :cpp:enum:`_LMP_STYLE_CONST`
|
||||
for the equivalent constants in the C library interface. Used in
|
||||
:py:func:`lammps.extract_compute` and :py:func:`lammps.extract_fix`.
|
||||
|
||||
.. _py_type_constants:
|
||||
.. py:data:: LMP_TYPE_SCALAR, LMP_TYLE_VECTOR, LMP_TYPE_ARRAY, LMP_SIZE_VECTOR, LMP_SIZE_ROWS, LMP_SIZE_COLS
|
||||
:type: int
|
||||
|
||||
Constants in the :py:mod:`lammps` module to select what type of data
|
||||
to request from computes or fixes. See :cpp:enum:`_LMP_TYPE_CONST`
|
||||
for the equivalent constants in the C library interface. Used in
|
||||
:py:func:`lammps.extract_compute` and :py:func:`lammps.extract_fix`.
|
||||
|
||||
.. _py_var_constants:
|
||||
.. py:data:: LMP_VAR_EQUAL, LMP_VAR_ATOM
|
||||
:type: int
|
||||
|
||||
Constants in the :py:mod:`lammps` module to select what style of
|
||||
variable to query when calling :py:func:`lammps.extract_variable`.
|
||||
|
||||
.. autoclass:: lammps.NeighList
|
||||
:members:
|
||||
:no-undoc-members:
|
||||
|
||||
|
|
|
@ -115,6 +115,7 @@ Archlinux
|
|||
arcsin
|
||||
arg
|
||||
args
|
||||
argv
|
||||
arrhenius
|
||||
Arun
|
||||
arXiv
|
||||
|
@ -138,6 +139,8 @@ atc
|
|||
AtC
|
||||
ATC
|
||||
athermal
|
||||
atime
|
||||
atimestep
|
||||
athomps
|
||||
atm
|
||||
atomeye
|
||||
|
@ -207,7 +210,6 @@ bcolor
|
|||
bdiam
|
||||
bdw
|
||||
Beckman
|
||||
behaviour
|
||||
Belak
|
||||
Bellott
|
||||
benchmarking
|
||||
|
@ -267,6 +269,7 @@ bodystyle
|
|||
Bogaerts
|
||||
Bogusz
|
||||
Bohrs
|
||||
boltz
|
||||
Boltzman
|
||||
BondAngle
|
||||
BondBond
|
||||
|
@ -285,6 +288,14 @@ Botu
|
|||
Bouguet
|
||||
Bourne
|
||||
boxcolor
|
||||
boxlo
|
||||
boxhi
|
||||
boxxlo
|
||||
boxxhi
|
||||
boxylo
|
||||
boxyhi
|
||||
boxzlo
|
||||
boxzhi
|
||||
bp
|
||||
bpclermont
|
||||
bpls
|
||||
|
@ -411,6 +422,7 @@ cmap
|
|||
Cmax
|
||||
cmd
|
||||
cmdlist
|
||||
cmds
|
||||
Cmin
|
||||
cmm
|
||||
CMM
|
||||
|
@ -675,6 +687,8 @@ Donadio
|
|||
dotc
|
||||
Doty
|
||||
doxygen
|
||||
doxygenclass
|
||||
doxygenfunction
|
||||
downarrow
|
||||
Doye
|
||||
dpd
|
||||
|
@ -983,6 +997,7 @@ Fock
|
|||
Fogarty
|
||||
Foiles
|
||||
fopenmp
|
||||
forceclear
|
||||
forestgreen
|
||||
formatarg
|
||||
formulae
|
||||
|
@ -1007,6 +1022,7 @@ fs
|
|||
fsh
|
||||
fstyle
|
||||
fsw
|
||||
ftm
|
||||
ftol
|
||||
fugacity
|
||||
Fumi
|
||||
|
@ -1177,6 +1193,7 @@ hexorder
|
|||
Heyes
|
||||
HfO
|
||||
hgrid
|
||||
hhmrr
|
||||
Hibbs
|
||||
Higdon
|
||||
Hijazi
|
||||
|
@ -1186,6 +1203,7 @@ histogrammed
|
|||
histogramming
|
||||
hma
|
||||
hmaktulga
|
||||
hplanck
|
||||
hoc
|
||||
Hochbruck
|
||||
Hofling
|
||||
|
@ -1228,6 +1246,7 @@ hyperspherical
|
|||
hysteretic
|
||||
hz
|
||||
Ibanez
|
||||
iatom
|
||||
ibar
|
||||
ibm
|
||||
icc
|
||||
|
@ -1270,6 +1289,7 @@ indices
|
|||
inertiax
|
||||
inertiay
|
||||
inertiaz
|
||||
infile
|
||||
infty
|
||||
inhomogeneities
|
||||
inhomogeneous
|
||||
|
@ -1310,6 +1330,7 @@ ipp
|
|||
Ippolito
|
||||
IPv
|
||||
IPython
|
||||
ipython
|
||||
Isele
|
||||
isenthalpic
|
||||
ish
|
||||
|
@ -1458,6 +1479,7 @@ Kloza
|
|||
kmax
|
||||
Kmax
|
||||
KMP
|
||||
kmu
|
||||
Knizhnik
|
||||
knl
|
||||
Kofke
|
||||
|
@ -1944,6 +1966,7 @@ muz
|
|||
mv
|
||||
mV
|
||||
Mvapich
|
||||
mvh
|
||||
mvv
|
||||
MxN
|
||||
myCompute
|
||||
|
@ -1956,11 +1979,13 @@ na
|
|||
nabla
|
||||
Nagaosa
|
||||
Nakano
|
||||
nall
|
||||
namespace
|
||||
namespaces
|
||||
nan
|
||||
NaN
|
||||
Nandor
|
||||
nangles
|
||||
Nangletype
|
||||
nangletypes
|
||||
Nangletypes
|
||||
|
@ -1989,6 +2014,7 @@ Nbin
|
|||
Nbins
|
||||
nbody
|
||||
Nbody
|
||||
nbonds
|
||||
nbondtype
|
||||
Nbondtype
|
||||
nbondtypes
|
||||
|
@ -2001,9 +2027,11 @@ Nc
|
|||
nchunk
|
||||
Nchunk
|
||||
ncoeff
|
||||
ncol
|
||||
ncorr
|
||||
ncount
|
||||
nd
|
||||
ndihedrals
|
||||
Ndihedraltype
|
||||
Ndirango
|
||||
ndof
|
||||
|
@ -2050,6 +2078,7 @@ NiAlH
|
|||
Nicklas
|
||||
Niklasson
|
||||
Nikolskiy
|
||||
nimpropers
|
||||
Nimpropertype
|
||||
Ninteger
|
||||
Nissila
|
||||
|
@ -2058,6 +2087,7 @@ nitride
|
|||
nitrides
|
||||
niu
|
||||
Nk
|
||||
nktv
|
||||
nl
|
||||
nlen
|
||||
Nlines
|
||||
|
@ -2124,6 +2154,7 @@ Nrepeat
|
|||
nreset
|
||||
Nrho
|
||||
Nroff
|
||||
nrow
|
||||
nrun
|
||||
Ns
|
||||
Nsample
|
||||
|
@ -2142,6 +2173,7 @@ Nt
|
|||
Ntable
|
||||
ntheta
|
||||
nthreads
|
||||
ntimestep
|
||||
Ntptask
|
||||
Ntriples
|
||||
Ntype
|
||||
|
@ -2371,6 +2403,7 @@ polydisperse
|
|||
polydispersity
|
||||
polyelectrolyte
|
||||
polyhedra
|
||||
polymorphism
|
||||
popen
|
||||
Popov
|
||||
popstore
|
||||
|
@ -2404,6 +2437,7 @@ proc
|
|||
Proc
|
||||
procs
|
||||
Prony
|
||||
progguide
|
||||
ps
|
||||
Ps
|
||||
pscreen
|
||||
|
@ -2450,7 +2484,9 @@ qbmsst
|
|||
qcore
|
||||
qdist
|
||||
qE
|
||||
qe
|
||||
qeff
|
||||
qelectron
|
||||
qeq
|
||||
QeQ
|
||||
QEq
|
||||
|
@ -2468,6 +2504,8 @@ qmol
|
|||
qoffload
|
||||
qopenmp
|
||||
qoverride
|
||||
qqr
|
||||
qqrd
|
||||
qtb
|
||||
quadratically
|
||||
quadrupolar
|
||||
|
@ -2523,6 +2561,7 @@ rebo
|
|||
recursing
|
||||
Ree
|
||||
refactored
|
||||
refactoring
|
||||
reflectionstyle
|
||||
regoin
|
||||
Reinders
|
||||
|
@ -2608,6 +2647,7 @@ Rkouter
|
|||
RkouterN
|
||||
rmask
|
||||
Rmask
|
||||
rmass
|
||||
rmax
|
||||
Rmax
|
||||
rmdir
|
||||
|
@ -2742,6 +2782,7 @@ shlib
|
|||
SHM
|
||||
shm
|
||||
shockvel
|
||||
shrinkexceed
|
||||
Shugaev
|
||||
si
|
||||
SiC
|
||||
|
@ -2879,6 +2920,7 @@ strstr
|
|||
Stukowski
|
||||
Su
|
||||
subbox
|
||||
Subclassed
|
||||
subcutoff
|
||||
subcycle
|
||||
subcycling
|
||||
|
@ -3249,6 +3291,7 @@ vv
|
|||
vx
|
||||
Vx
|
||||
vxcm
|
||||
vxmu
|
||||
vy
|
||||
Vy
|
||||
vycm
|
||||
|
@ -3325,6 +3368,7 @@ Xmax
|
|||
xmgrace
|
||||
xMIC
|
||||
xmin
|
||||
xml
|
||||
xmovie
|
||||
Xmovie
|
||||
xmu
|
||||
|
@ -3339,6 +3383,7 @@ xsu
|
|||
xtc
|
||||
xu
|
||||
Xu
|
||||
xxt
|
||||
xxxxx
|
||||
xy
|
||||
xyz
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
This directory contains Fortran code which interface LAMMPS as a library
|
||||
and allows the LAMMPS library interface to be invoked from Fortran codes.
|
||||
It requires a Fortran compiler that supports the Fortran 2003 standard.
|
||||
|
||||
This interface is based on and supersedes the previous Fortran interfaces
|
||||
in the examples/COUPLE/fortran* folders. But is fully supported by the
|
||||
LAMMPS developers and included in the documentation and unit testing.
|
||||
|
||||
Details on this Fortran interface and how to build programs using it
|
||||
are in the manual in the doc/html/pg_fortran.html file.
|
||||
|
|
@ -0,0 +1,281 @@
|
|||
! -------------------------------------------------------------------------
|
||||
! LAMMPS - Large-scale Atomic/Molecular Massively Parallel Simulator
|
||||
! http://lammps.sandia.gov, Sandia National Laboratories
|
||||
! Steve Plimpton, sjplimp@sandia.gov
|
||||
!
|
||||
! 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.
|
||||
! -------------------------------------------------------------------------
|
||||
!
|
||||
! Fortran interface to the LAMMPS library implemented as a Fortran 2003
|
||||
! style module that wraps the C-style library interface in library.cpp
|
||||
! and library.h using the ISO_C_BINDING module of the Fortran compiler.
|
||||
!
|
||||
! Based on the LAMMPS Fortran 2003 module contributed by:
|
||||
! Karl D. Hammond <karlh@ugcs.caltech.edu>
|
||||
! University of Tennessee, Knoxville (USA), 2012
|
||||
!
|
||||
! The Fortran module tries to follow the API of the C-library interface
|
||||
! closely, but like the Python wrapper it employs an object oriented
|
||||
! approach. To accommodate the object oriented approach, all exported
|
||||
! subroutine and functions have to be implemented in Fortran to then
|
||||
! call the interfaced C style functions with adapted calling conventions
|
||||
! as needed. The C-library interfaced functions retain their names
|
||||
! starting with "lammps_" while the Fortran versions start with "lmp_".
|
||||
!
|
||||
MODULE LIBLAMMPS
|
||||
|
||||
USE, INTRINSIC :: ISO_C_BINDING, ONLY: c_ptr, c_null_ptr, c_loc, &
|
||||
c_int, c_char, c_null_char, c_double
|
||||
|
||||
IMPLICIT NONE
|
||||
PRIVATE
|
||||
PUBLIC :: lammps
|
||||
|
||||
TYPE lammps
|
||||
TYPE(c_ptr) :: handle
|
||||
CONTAINS
|
||||
PROCEDURE :: close => lmp_close
|
||||
PROCEDURE :: file => lmp_file
|
||||
PROCEDURE :: command => lmp_command
|
||||
PROCEDURE :: commands_list => lmp_commands_list
|
||||
PROCEDURE :: commands_string => lmp_commands_string
|
||||
PROCEDURE :: version => lmp_version
|
||||
PROCEDURE :: get_natoms => lmp_get_natoms
|
||||
END TYPE lammps
|
||||
|
||||
INTERFACE lammps
|
||||
MODULE PROCEDURE lmp_open
|
||||
END INTERFACE lammps
|
||||
|
||||
! interface definitions for calling functions in library.cpp
|
||||
INTERFACE
|
||||
FUNCTION lammps_open(argc,argv,comm,handle) &
|
||||
BIND(C, name='lammps_open_fortran')
|
||||
IMPORT :: c_ptr, c_int
|
||||
INTEGER(c_int), VALUE, INTENT(in) :: argc, comm
|
||||
TYPE(c_ptr), DIMENSION(*), INTENT(in) :: argv
|
||||
TYPE(c_ptr), INTENT(out) :: handle
|
||||
TYPE(c_ptr) :: lammps_open
|
||||
END FUNCTION lammps_open
|
||||
|
||||
FUNCTION lammps_open_no_mpi(argc,argv,handle) &
|
||||
BIND(C, name='lammps_open_no_mpi')
|
||||
IMPORT :: c_ptr, c_int
|
||||
INTEGER(c_int), VALUE, INTENT(in) :: argc
|
||||
TYPE(c_ptr), DIMENSION(*), INTENT(in) :: argv
|
||||
TYPE(c_ptr), INTENT(out) :: handle
|
||||
TYPE(c_ptr) :: lammps_open_no_mpi
|
||||
END FUNCTION lammps_open_no_mpi
|
||||
|
||||
SUBROUTINE lammps_close(handle) BIND(C, name='lammps_close')
|
||||
IMPORT :: c_ptr
|
||||
TYPE(c_ptr), VALUE :: handle
|
||||
END SUBROUTINE lammps_close
|
||||
|
||||
SUBROUTINE lammps_mpi_init(handle) BIND(C, name='lammps_mpi_init')
|
||||
IMPORT :: c_ptr
|
||||
TYPE(c_ptr), VALUE :: handle
|
||||
END SUBROUTINE lammps_mpi_init
|
||||
|
||||
SUBROUTINE lammps_mpi_finalize(handle) &
|
||||
BIND(C, name='lammps_mpi_finalize')
|
||||
IMPORT :: c_ptr
|
||||
TYPE(c_ptr), VALUE :: handle
|
||||
END SUBROUTINE lammps_mpi_finalize
|
||||
|
||||
SUBROUTINE lammps_file(handle,filename) BIND(C, name='lammps_file')
|
||||
IMPORT :: c_ptr
|
||||
TYPE(c_ptr), VALUE :: handle
|
||||
TYPE(c_ptr), VALUE :: filename
|
||||
END SUBROUTINE lammps_file
|
||||
|
||||
SUBROUTINE lammps_command(handle,cmd) BIND(C, name='lammps_command')
|
||||
IMPORT :: c_ptr
|
||||
TYPE(c_ptr), VALUE :: handle
|
||||
TYPE(c_ptr), VALUE :: cmd
|
||||
END SUBROUTINE lammps_command
|
||||
|
||||
SUBROUTINE lammps_commands_list(handle,ncmd,cmds) &
|
||||
BIND(C, name='lammps_commands_list')
|
||||
IMPORT :: c_ptr, c_int
|
||||
TYPE(c_ptr), VALUE :: handle
|
||||
INTEGER(c_int), VALUE, INTENT(in) :: ncmd
|
||||
TYPE(c_ptr), DIMENSION(*), INTENT(in) :: cmds
|
||||
END SUBROUTINE lammps_commands_list
|
||||
|
||||
SUBROUTINE lammps_commands_string(handle,str) &
|
||||
BIND(C, name='lammps_commands_string')
|
||||
IMPORT :: c_ptr
|
||||
TYPE(c_ptr), VALUE :: handle
|
||||
TYPE(c_ptr), VALUE :: str
|
||||
END SUBROUTINE lammps_commands_string
|
||||
|
||||
SUBROUTINE lammps_free(ptr) BIND(C, name='lammps_free')
|
||||
IMPORT :: c_ptr
|
||||
TYPE(c_ptr), VALUE :: ptr
|
||||
END SUBROUTINE lammps_free
|
||||
|
||||
FUNCTION lammps_version(handle) BIND(C, name='lammps_version')
|
||||
IMPORT :: c_ptr, c_int
|
||||
TYPE(c_ptr), VALUE :: handle
|
||||
INTEGER(c_int) :: lammps_version
|
||||
END FUNCTION lammps_version
|
||||
|
||||
FUNCTION lammps_get_natoms(handle) BIND(C, name='lammps_get_natoms')
|
||||
IMPORT :: c_ptr, c_double
|
||||
TYPE(c_ptr), VALUE :: handle
|
||||
REAL(c_double) :: lammps_get_natoms
|
||||
END FUNCTION lammps_get_natoms
|
||||
END INTERFACE
|
||||
|
||||
CONTAINS
|
||||
|
||||
! Fortran wrappers and helper functions.
|
||||
|
||||
! Constructor for the LAMMPS class.
|
||||
! Combined wrapper around lammps_open_fortran() and lammps_open_no_mpi()
|
||||
TYPE(lammps) FUNCTION lmp_open(args,comm)
|
||||
IMPLICIT NONE
|
||||
INTEGER,INTENT(in), OPTIONAL :: comm
|
||||
CHARACTER(len=*), INTENT(in), OPTIONAL :: args(:)
|
||||
TYPE(c_ptr), ALLOCATABLE :: argv(:)
|
||||
TYPE(c_ptr) :: dummy=c_null_ptr
|
||||
INTEGER :: i,argc
|
||||
|
||||
IF (PRESENT(args)) THEN
|
||||
! convert argument list to c style
|
||||
argc = SIZE(args)
|
||||
ALLOCATE(argv(argc))
|
||||
DO i=1,argc
|
||||
argv(i) = f2c_string(args(i))
|
||||
END DO
|
||||
ELSE
|
||||
argc = 1
|
||||
ALLOCATE(argv(1))
|
||||
argv(1) = f2c_string("liblammps")
|
||||
ENDIF
|
||||
|
||||
IF (PRESENT(comm)) THEN
|
||||
lmp_open%handle = lammps_open(argc,argv,comm,dummy)
|
||||
ELSE
|
||||
lmp_open%handle = lammps_open_no_mpi(argc,argv,dummy)
|
||||
END IF
|
||||
|
||||
! Clean up allocated memory
|
||||
DO i=1,argc
|
||||
CALL lammps_free(argv(i))
|
||||
END DO
|
||||
DEALLOCATE(argv)
|
||||
END FUNCTION lmp_open
|
||||
|
||||
! Combined Fortran wrapper around lammps_close() and lammps_mpi_finalize()
|
||||
SUBROUTINE lmp_close(self,finalize)
|
||||
IMPLICIT NONE
|
||||
CLASS(lammps) :: self
|
||||
LOGICAL,INTENT(in),OPTIONAL :: finalize
|
||||
|
||||
CALL lammps_close(self%handle)
|
||||
|
||||
IF (PRESENT(finalize)) THEN
|
||||
IF (finalize) THEN
|
||||
CALL lammps_mpi_finalize(self%handle)
|
||||
END IF
|
||||
END IF
|
||||
END SUBROUTINE lmp_close
|
||||
|
||||
INTEGER FUNCTION lmp_version(self)
|
||||
IMPLICIT NONE
|
||||
CLASS(lammps) :: self
|
||||
|
||||
lmp_version = lammps_version(self%handle)
|
||||
END FUNCTION lmp_version
|
||||
|
||||
DOUBLE PRECISION FUNCTION lmp_get_natoms(self)
|
||||
IMPLICIT NONE
|
||||
CLASS(lammps) :: self
|
||||
|
||||
lmp_get_natoms = lammps_get_natoms(self%handle)
|
||||
END FUNCTION lmp_get_natoms
|
||||
|
||||
SUBROUTINE lmp_file(self,filename)
|
||||
IMPLICIT NONE
|
||||
CLASS(lammps) :: self
|
||||
CHARACTER(len=*) :: filename
|
||||
TYPE(c_ptr) :: str
|
||||
|
||||
str = f2c_string(filename)
|
||||
CALL lammps_file(self%handle,str)
|
||||
CALL lammps_free(str)
|
||||
END SUBROUTINE lmp_file
|
||||
|
||||
! equivalent function to lammps_command()
|
||||
SUBROUTINE lmp_command(self,cmd)
|
||||
IMPLICIT NONE
|
||||
CLASS(lammps) :: self
|
||||
CHARACTER(len=*) :: cmd
|
||||
TYPE(c_ptr) :: str
|
||||
|
||||
str = f2c_string(cmd)
|
||||
CALL lammps_command(self%handle,str)
|
||||
CALL lammps_free(str)
|
||||
END SUBROUTINE lmp_command
|
||||
|
||||
! equivalent function to lammps_commands_list()
|
||||
SUBROUTINE lmp_commands_list(self,cmds)
|
||||
IMPLICIT NONE
|
||||
CLASS(lammps) :: self
|
||||
CHARACTER(len=*), INTENT(in), OPTIONAL :: cmds(:)
|
||||
TYPE(c_ptr), ALLOCATABLE :: cmdv(:)
|
||||
INTEGER :: i,ncmd
|
||||
|
||||
! convert command list to c style
|
||||
ncmd = SIZE(cmds)
|
||||
ALLOCATE(cmdv(ncmd))
|
||||
DO i=1,ncmd
|
||||
cmdv(i) = f2c_string(cmds(i))
|
||||
END DO
|
||||
|
||||
CALL lammps_commands_list(self%handle,ncmd,cmdv)
|
||||
|
||||
! Clean up allocated memory
|
||||
DO i=1,ncmd
|
||||
CALL lammps_free(cmdv(i))
|
||||
END DO
|
||||
DEALLOCATE(cmdv)
|
||||
END SUBROUTINE lmp_commands_list
|
||||
|
||||
! equivalent function to lammps_commands_string()
|
||||
SUBROUTINE lmp_commands_string(self,str)
|
||||
IMPLICIT NONE
|
||||
CLASS(lammps) :: self
|
||||
CHARACTER(len=*) :: str
|
||||
TYPE(c_ptr) :: tmp
|
||||
|
||||
tmp = f2c_string(str)
|
||||
CALL lammps_commands_string(self%handle,tmp)
|
||||
CALL lammps_free(tmp)
|
||||
END SUBROUTINE lmp_commands_string
|
||||
|
||||
! ----------------------------------------------------------------------
|
||||
! local helper functions
|
||||
! copy fortran string to zero terminated c string
|
||||
FUNCTION f2c_string(f_string) RESULT(ptr)
|
||||
CHARACTER (len=*), INTENT(in) :: f_string
|
||||
CHARACTER (len=1, kind=c_char), POINTER :: c_string(:)
|
||||
TYPE(c_ptr) :: ptr
|
||||
INTEGER :: i, n
|
||||
|
||||
n = LEN_TRIM(f_string)
|
||||
ALLOCATE(c_string(n+1))
|
||||
DO i=1,n
|
||||
c_string(i) = f_string(i:i)
|
||||
END DO
|
||||
c_string(n+1) = c_null_char
|
||||
ptr = c_loc(c_string(1))
|
||||
END FUNCTION f2c_string
|
||||
END MODULE LIBLAMMPS
|
|
@ -85,8 +85,8 @@ PACKUSERUC = $(call uppercase,$(PACKUSER))
|
|||
|
||||
YESDIR = $(call uppercase,$(@:yes-%=%))
|
||||
NODIR = $(call uppercase,$(@:no-%=%))
|
||||
LIBDIR = $($(@:lib-%=%))
|
||||
LIBUSERDIR = $($(@:lib-user-%=%))
|
||||
LIBDIR = $(@:lib-%=%)
|
||||
LIBUSERDIR = $(@:lib-user-%=%)
|
||||
|
||||
# List of all targets
|
||||
|
||||
|
|
|
@ -169,7 +169,7 @@ FixBondReact::FixBondReact(LAMMPS *lmp, int narg, char **arg) :
|
|||
} else if (strcmp(arg[iarg],"reset_mol_ids") == 0) {
|
||||
if (iarg+2 > narg) error->all(FLERR,"Illegal fix bond/react command: "
|
||||
"'reset_mol_ids' keyword has too few arguments");
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) ; // default
|
||||
if (strcmp(arg[iarg+1],"yes") == 0) reset_mol_ids_flag = 1; // default
|
||||
if (strcmp(arg[iarg+1],"no") == 0) reset_mol_ids_flag = 0;
|
||||
iarg += 2;
|
||||
} else if (strcmp(arg[iarg],"react") == 0) {
|
||||
|
|
|
@ -752,29 +752,29 @@ recognized, the function returns -1. Please also see :cpp:func:`lammps_extract_
|
|||
* \param keyword string with the name of the thermo keyword
|
||||
* \return value of the queried setting or -1 if unknown */
|
||||
|
||||
int lammps_extract_setting(void * handle, char *name)
|
||||
int lammps_extract_setting(void * handle, char *keyword)
|
||||
{
|
||||
LAMMPS *lmp = (LAMMPS *) handle;
|
||||
|
||||
// This can be customized by adding keywords and documenting them in the section above.
|
||||
if (strcmp(name,"bigint") == 0) return sizeof(bigint);
|
||||
if (strcmp(name,"tagint") == 0) return sizeof(tagint);
|
||||
if (strcmp(name,"imageint") == 0) return sizeof(imageint);
|
||||
if (strcmp(keyword,"bigint") == 0) return sizeof(bigint);
|
||||
if (strcmp(keyword,"tagint") == 0) return sizeof(tagint);
|
||||
if (strcmp(keyword,"imageint") == 0) return sizeof(imageint);
|
||||
|
||||
if (strcmp(name,"dimension") == 0) return lmp->domain->dimension;
|
||||
if (strcmp(name,"box_exist") == 0) return lmp->domain->box_exist;
|
||||
if (strcmp(name,"triclinic") == 0) return lmp->domain->triclinic;
|
||||
if (strcmp(keyword,"dimension") == 0) return lmp->domain->dimension;
|
||||
if (strcmp(keyword,"box_exist") == 0) return lmp->domain->box_exist;
|
||||
if (strcmp(keyword,"triclinic") == 0) return lmp->domain->triclinic;
|
||||
|
||||
if (strcmp(name,"nlocal") == 0) return lmp->atom->nlocal;
|
||||
if (strcmp(name,"nghost") == 0) return lmp->atom->nghost;
|
||||
if (strcmp(name,"nall") == 0) return lmp->atom->nlocal+lmp->atom->nghost;
|
||||
if (strcmp(name,"nmax") == 0) return lmp->atom->nmax;
|
||||
if (strcmp(name,"ntypes") == 0) return lmp->atom->ntypes;
|
||||
if (strcmp(keyword,"nlocal") == 0) return lmp->atom->nlocal;
|
||||
if (strcmp(keyword,"nghost") == 0) return lmp->atom->nghost;
|
||||
if (strcmp(keyword,"nall") == 0) return lmp->atom->nlocal+lmp->atom->nghost;
|
||||
if (strcmp(keyword,"nmax") == 0) return lmp->atom->nmax;
|
||||
if (strcmp(keyword,"ntypes") == 0) return lmp->atom->ntypes;
|
||||
|
||||
if (strcmp(name,"molecule_flag") == 0) return lmp->atom->molecule_flag;
|
||||
if (strcmp(name,"q_flag") == 0) return lmp->atom->q_flag;
|
||||
if (strcmp(name,"mu_flag") == 0) return lmp->atom->mu_flag;
|
||||
if (strcmp(name,"rmass_flag") == 0) return lmp->atom->rmass_flag;
|
||||
if (strcmp(keyword,"molecule_flag") == 0) return lmp->atom->molecule_flag;
|
||||
if (strcmp(keyword,"q_flag") == 0) return lmp->atom->q_flag;
|
||||
if (strcmp(keyword,"mu_flag") == 0) return lmp->atom->mu_flag;
|
||||
if (strcmp(keyword,"rmass_flag") == 0) return lmp->atom->rmass_flag;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -250,17 +250,23 @@ The typecast prevents compiler warnings about possible truncations.
|
|||
// functions and avoid compiler warnings about variable tracking.
|
||||
// Disable for broken -D_FORTIFY_SOURCE feature.
|
||||
|
||||
#if defined(_FORTIFY_SOURCE) && (_FORTIFY_SOURCE > 0)
|
||||
#define _noopt
|
||||
#elif defined(__clang__)
|
||||
#if defined(__clang__)
|
||||
# define _noopt __attribute__((optnone))
|
||||
#elif defined(__INTEL_COMPILER)
|
||||
# define _noopt
|
||||
#elif defined(__GNUC__)
|
||||
# if (__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9))
|
||||
# define _noopt __attribute__((optimize("O0","no-var-tracking-assignments")))
|
||||
# if defined(_FORTIFY_SOURCE) && (_FORTIFY_SOURCE > 0)
|
||||
# define _noopt __attribute__((optimize("no-var-tracking-assignments")))
|
||||
# else
|
||||
# define _noopt __attribute__((optimize("O0","no-var-tracking-assignments")))
|
||||
# endif
|
||||
# else
|
||||
# define _noopt __attribute__((optimize("O0")))
|
||||
# if defined(_FORTIFY_SOURCE) && (_FORTIFY_SOURCE > 0)
|
||||
# define _noopt
|
||||
# else
|
||||
# define _noopt __attribute__((optimize("O0")))
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
# define _noopt
|
||||
|
|
|
@ -29,6 +29,19 @@
|
|||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/** Class for reading and parsing LAMMPS potential files
|
||||
*
|
||||
* The value of the class member variable *ignore_comments* controls
|
||||
* whether any text following the pound sign (#) should be ignored (true)
|
||||
* or not (false). Default: true, i.e. ignore.
|
||||
*
|
||||
* \param lmp Pointer to LAMMPS instance
|
||||
* \param filename Name of file to be read
|
||||
* \param potential_name Name of potential style for error messages
|
||||
* \param auto_convert Bitmask of supported unit conversions
|
||||
*
|
||||
* \sa TextFileReader */
|
||||
|
||||
PotentialFileReader::PotentialFileReader(LAMMPS *lmp,
|
||||
const std::string &filename,
|
||||
const std::string &potential_name,
|
||||
|
@ -53,14 +66,21 @@ PotentialFileReader::PotentialFileReader(LAMMPS *lmp,
|
|||
}
|
||||
}
|
||||
|
||||
/** Closes the file */
|
||||
|
||||
PotentialFileReader::~PotentialFileReader() {
|
||||
delete reader;
|
||||
}
|
||||
|
||||
/** Set comment (= text after '#') handling preference for the file to be read
|
||||
*
|
||||
* \param value Comment text is ignored if true, or not if false */
|
||||
void PotentialFileReader::ignore_comments(bool value) {
|
||||
reader->ignore_comments = value;
|
||||
}
|
||||
|
||||
/** Read a line but ignore its content */
|
||||
|
||||
void PotentialFileReader::skip_line() {
|
||||
try {
|
||||
reader->skip_line();
|
||||
|
@ -69,6 +89,17 @@ void PotentialFileReader::skip_line() {
|
|||
}
|
||||
}
|
||||
|
||||
/** Read the next line(s) until *nparams* words have been read.
|
||||
*
|
||||
* This reads a line and counts the words in it, if the number
|
||||
* is less than the requested number, it will read the next
|
||||
* line, as well. Output will be a string with all read lines
|
||||
* combined. The purpose is to somewhat replicate the reading
|
||||
* behavior of formatted files in Fortran.
|
||||
*
|
||||
* \param nparams Number of words that must be read. Default: 0
|
||||
* \return String with the concatenated text */
|
||||
|
||||
char *PotentialFileReader::next_line(int nparams) {
|
||||
try {
|
||||
return reader->next_line(nparams);
|
||||
|
@ -78,6 +109,15 @@ char *PotentialFileReader::next_line(int nparams) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
/** Read lines until *n* doubles have been read and stored in array *list*
|
||||
*
|
||||
* This reads lines from the file using the next_line() function,
|
||||
* and splits them into floating-point numbers using the
|
||||
* ValueTokenizer class and stores the number is the provided list.
|
||||
*
|
||||
* \param list Pointer to array with suitable storage for *n* doubles
|
||||
* \param n Number of doubles to be read */
|
||||
|
||||
void PotentialFileReader::next_dvector(double * list, int n) {
|
||||
try {
|
||||
return reader->next_dvector(list, n);
|
||||
|
@ -86,6 +126,16 @@ void PotentialFileReader::next_dvector(double * list, int n) {
|
|||
}
|
||||
}
|
||||
|
||||
/** Read text until *nparams* words are read and passed to a tokenizer object for custom parsing.
|
||||
*
|
||||
* This reads lines from the file using the next_line() function,
|
||||
* and splits them into floating-point numbers using the
|
||||
* ValueTokenizer class and stores the number is the provided list.
|
||||
*
|
||||
* \param nparams Number of words to be read
|
||||
* \param separators String with list of separators.
|
||||
* \return ValueTokenizer object for read in text */
|
||||
|
||||
ValueTokenizer PotentialFileReader::next_values(int nparams, const std::string & separators) {
|
||||
try {
|
||||
return reader->next_values(nparams, separators);
|
||||
|
@ -95,6 +145,10 @@ ValueTokenizer PotentialFileReader::next_values(int nparams, const std::string &
|
|||
return ValueTokenizer("");
|
||||
}
|
||||
|
||||
/** Read next line and convert first word to a double
|
||||
*
|
||||
* \return Value of first word in line as double */
|
||||
|
||||
double PotentialFileReader::next_double() {
|
||||
try {
|
||||
char * line = reader->next_line(1);
|
||||
|
@ -105,6 +159,10 @@ double PotentialFileReader::next_double() {
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
/** Read next line and convert first word to an int
|
||||
*
|
||||
* \return Value of first word in line as int */
|
||||
|
||||
int PotentialFileReader::next_int() {
|
||||
try {
|
||||
char * line = reader->next_line(1);
|
||||
|
@ -115,6 +173,10 @@ int PotentialFileReader::next_int() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** Read next line and convert first word to a tagint
|
||||
*
|
||||
* \return Value of first word in line as tagint */
|
||||
|
||||
tagint PotentialFileReader::next_tagint() {
|
||||
try {
|
||||
char * line = reader->next_line(1);
|
||||
|
@ -125,6 +187,10 @@ tagint PotentialFileReader::next_tagint() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** Read next line and convert first word to a bigint
|
||||
*
|
||||
* \return Value of first word in line as bigint */
|
||||
|
||||
bigint PotentialFileReader::next_bigint() {
|
||||
try {
|
||||
char * line = reader->next_line(1);
|
||||
|
@ -135,6 +201,10 @@ bigint PotentialFileReader::next_bigint() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/** Read next line and return first word
|
||||
*
|
||||
* \return First word of read in line */
|
||||
|
||||
std::string PotentialFileReader::next_string() {
|
||||
try {
|
||||
char * line = reader->next_line(1);
|
||||
|
@ -145,6 +215,12 @@ std::string PotentialFileReader::next_string() {
|
|||
return "";
|
||||
}
|
||||
|
||||
/** Look up and open the potential file
|
||||
*
|
||||
* \param path Path of the potential file to open
|
||||
* \return Pointer to TextFileReader object created
|
||||
* \sa TextFileReader */
|
||||
|
||||
TextFileReader *PotentialFileReader::open_potential(const std::string &path) {
|
||||
std::string filepath = utils::get_potential_file_path(path);
|
||||
|
||||
|
|
|
@ -28,6 +28,17 @@
|
|||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
/** Class for reading and parsing text files
|
||||
*
|
||||
* The value of the class member variable *ignore_comments* controls
|
||||
* whether any text following the pound sign (#) should be ignored (true)
|
||||
* or not (false). Default: true, i.e. ignore.
|
||||
*
|
||||
* \param filename Name of file to be read
|
||||
* \param filetype Description of file type for error messages
|
||||
*
|
||||
* \sa PotentialFileReader */
|
||||
|
||||
TextFileReader::TextFileReader(const std::string &filename, const std::string &filetype)
|
||||
: filename(filename), filetype(filetype), ignore_comments(true)
|
||||
{
|
||||
|
@ -38,10 +49,14 @@ TextFileReader::TextFileReader(const std::string &filename, const std::string &f
|
|||
}
|
||||
}
|
||||
|
||||
/** Closes the file */
|
||||
|
||||
TextFileReader::~TextFileReader() {
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
/** Read the next line and ignore it */
|
||||
|
||||
void TextFileReader::skip_line() {
|
||||
char *ptr = fgets(line, MAXLINE, fp);
|
||||
if (ptr == nullptr) {
|
||||
|
@ -50,6 +65,20 @@ void TextFileReader::skip_line() {
|
|||
}
|
||||
}
|
||||
|
||||
/** Read the next line(s) until *nparams* words have been read.
|
||||
*
|
||||
* This reads a line and counts the words in it, if the number
|
||||
* is less than the requested number, it will read the next
|
||||
* line, as well. Output will be a string with all read lines
|
||||
* combined. The purpose is to somewhat replicate the reading
|
||||
* behavior of formatted files in Fortran.
|
||||
*
|
||||
* If the *ignore_comments* class member has the value *true*,
|
||||
* then any text read in is truncated at the first '#' character.
|
||||
*
|
||||
* \param nparams Number of words that must be read. Default: 0
|
||||
* \return String with the concatenated text */
|
||||
|
||||
char *TextFileReader::next_line(int nparams) {
|
||||
// concatenate lines until have nparams words
|
||||
int n = 0;
|
||||
|
@ -82,7 +111,6 @@ char *TextFileReader::next_line(int nparams) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
// strip comment
|
||||
if (ignore_comments && (ptr = strchr(line, '#'))) *ptr = '\0';
|
||||
|
||||
|
@ -97,6 +125,15 @@ char *TextFileReader::next_line(int nparams) {
|
|||
return line;
|
||||
}
|
||||
|
||||
/** Read lines until *n* doubles have been read and stored in array *list*
|
||||
*
|
||||
* This reads lines from the file using the next_line() function,
|
||||
* and splits them into floating-point numbers using the
|
||||
* ValueTokenizer class and stores the number is the provided list.
|
||||
*
|
||||
* \param list Pointer to array with suitable storage for *n* doubles
|
||||
* \param n Number of doubles to be read */
|
||||
|
||||
void TextFileReader::next_dvector(double * list, int n) {
|
||||
int i = 0;
|
||||
while (i < n) {
|
||||
|
@ -116,6 +153,16 @@ void TextFileReader::next_dvector(double * list, int n) {
|
|||
}
|
||||
}
|
||||
|
||||
/** Read text until *nparams* words are read and passed to a tokenizer object for custom parsing.
|
||||
*
|
||||
* This reads lines from the file using the next_line() function,
|
||||
* and splits them into floating-point numbers using the
|
||||
* ValueTokenizer class and stores the number is the provided list.
|
||||
*
|
||||
* \param nparams Number of words to be read
|
||||
* \param separators String with list of separators.
|
||||
* \return ValueTokenizer object for read in text */
|
||||
|
||||
ValueTokenizer TextFileReader::next_values(int nparams, const std::string & separators) {
|
||||
return ValueTokenizer(next_line(nparams), separators);
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@ namespace LAMMPS_NS
|
|||
FILE *fp;
|
||||
|
||||
public:
|
||||
bool ignore_comments;
|
||||
bool ignore_comments; //!< Controls whether comments are ignored
|
||||
|
||||
TextFileReader(const std::string &filename, const std::string &filetype);
|
||||
~TextFileReader();
|
||||
|
|
|
@ -30,6 +30,16 @@ TokenizerException::TokenizerException(const std::string & msg, const std::strin
|
|||
}
|
||||
}
|
||||
|
||||
/** Class for splitting text into words
|
||||
*
|
||||
* This tokenizer will break down a string into sub-strings (i.e words)
|
||||
* separated by the given separator characters.
|
||||
*
|
||||
* \param str string to be processed
|
||||
* \param separators string with separator characters (default: " \t\r\n\f")
|
||||
*
|
||||
* \sa ValueTokenizer TokenizerException */
|
||||
|
||||
Tokenizer::Tokenizer(const std::string & str, const std::string & separators) :
|
||||
text(str), separators(separators), start(0), ntokens(std::string::npos)
|
||||
{
|
||||
|
@ -48,14 +58,23 @@ Tokenizer::Tokenizer(Tokenizer && rhs) :
|
|||
reset();
|
||||
}
|
||||
|
||||
/*! Re-position the tokenizer state to the first word,
|
||||
* i.e. the first non-separator character */
|
||||
void Tokenizer::reset() {
|
||||
start = text.find_first_not_of(separators);
|
||||
}
|
||||
|
||||
/*! Search the text to be processed for a sub-string.
|
||||
*
|
||||
* \param str string to be searched for
|
||||
* \return true if string was found, false if not */
|
||||
bool Tokenizer::contains(const std::string & str) const {
|
||||
return text.find(str) != std::string::npos;
|
||||
}
|
||||
|
||||
/*! Skip over a given number of tokens
|
||||
*
|
||||
* \param n number of tokens to skip over */
|
||||
void Tokenizer::skip(int n) {
|
||||
for(int i = 0; i < n; ++i) {
|
||||
if(!has_next()) throw TokenizerException("No more tokens", "");
|
||||
|
@ -70,10 +89,16 @@ void Tokenizer::skip(int n) {
|
|||
}
|
||||
}
|
||||
|
||||
/*! Indicate whether more tokens are available
|
||||
*
|
||||
* \return true if there are more tokens, false if not */
|
||||
bool Tokenizer::has_next() const {
|
||||
return start != std::string::npos;
|
||||
}
|
||||
|
||||
/*! Retrieve next token.
|
||||
*
|
||||
* \return string with the next token */
|
||||
std::string Tokenizer::next() {
|
||||
if(!has_next()) throw TokenizerException("No more tokens", "");
|
||||
|
||||
|
@ -90,6 +115,9 @@ std::string Tokenizer::next() {
|
|||
return token;
|
||||
}
|
||||
|
||||
/*! Count number of tokens in text.
|
||||
*
|
||||
* \return number of counted tokens */
|
||||
size_t Tokenizer::count() {
|
||||
// lazy evaluation
|
||||
if (ntokens == std::string::npos) {
|
||||
|
@ -98,6 +126,9 @@ size_t Tokenizer::count() {
|
|||
return ntokens;
|
||||
}
|
||||
|
||||
/*! Retrieve the entire text converted to an STL vector of tokens.
|
||||
*
|
||||
* \return The STL vector */
|
||||
std::vector<std::string> Tokenizer::as_vector() {
|
||||
// store current state
|
||||
size_t current = start;
|
||||
|
@ -117,6 +148,12 @@ std::vector<std::string> Tokenizer::as_vector() {
|
|||
return tokens;
|
||||
}
|
||||
|
||||
/*! Class for reading text with numbers
|
||||
*
|
||||
* \param str String to be processed
|
||||
* \param separators String with separator characters (default: " \t\r\n\f")
|
||||
*
|
||||
* \sa Tokenizer InvalidIntegerException InvalidFloatException */
|
||||
|
||||
ValueTokenizer::ValueTokenizer(const std::string & str, const std::string & separators) : tokens(str, separators) {
|
||||
}
|
||||
|
@ -127,14 +164,24 @@ ValueTokenizer::ValueTokenizer(const ValueTokenizer & rhs) : tokens(rhs.tokens)
|
|||
ValueTokenizer::ValueTokenizer(ValueTokenizer && rhs) : tokens(std::move(rhs.tokens)) {
|
||||
}
|
||||
|
||||
/*! Indicate whether more tokens are available
|
||||
*
|
||||
* \return true if there are more tokens, false if not */
|
||||
bool ValueTokenizer::has_next() const {
|
||||
return tokens.has_next();
|
||||
}
|
||||
|
||||
/*! Search the text to be processed for a sub-string.
|
||||
*
|
||||
* \param value string with value to be searched for
|
||||
* \return true if string was found, false if not */
|
||||
bool ValueTokenizer::contains(const std::string & value) const {
|
||||
return tokens.contains(value);
|
||||
}
|
||||
|
||||
/*! Retrieve next token
|
||||
*
|
||||
* \return string with next token */
|
||||
std::string ValueTokenizer::next_string() {
|
||||
if (has_next()) {
|
||||
std::string value = tokens.next();
|
||||
|
@ -143,6 +190,9 @@ std::string ValueTokenizer::next_string() {
|
|||
return "";
|
||||
}
|
||||
|
||||
/*! Retrieve next token and convert to int
|
||||
*
|
||||
* \return value of next token */
|
||||
int ValueTokenizer::next_int() {
|
||||
if (has_next()) {
|
||||
std::string current = tokens.next();
|
||||
|
@ -155,6 +205,9 @@ int ValueTokenizer::next_int() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Retrieve next token and convert to bigint
|
||||
*
|
||||
* \return value of next token */
|
||||
bigint ValueTokenizer::next_bigint() {
|
||||
if (has_next()) {
|
||||
std::string current = tokens.next();
|
||||
|
@ -167,6 +220,9 @@ bigint ValueTokenizer::next_bigint() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Retrieve next token and convert to tagint
|
||||
*
|
||||
* \return value of next token */
|
||||
tagint ValueTokenizer::next_tagint() {
|
||||
if (has_next()) {
|
||||
std::string current = tokens.next();
|
||||
|
@ -179,6 +235,9 @@ tagint ValueTokenizer::next_tagint() {
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*! Retrieve next token and convert to double
|
||||
*
|
||||
* \return value of next token */
|
||||
double ValueTokenizer::next_double() {
|
||||
if (has_next()) {
|
||||
std::string current = tokens.next();
|
||||
|
@ -191,10 +250,16 @@ double ValueTokenizer::next_double() {
|
|||
return 0.0;
|
||||
}
|
||||
|
||||
/*! Skip over a given number of tokens
|
||||
*
|
||||
* \param n number of tokens to skip over */
|
||||
void ValueTokenizer::skip(int n) {
|
||||
tokens.skip(n);
|
||||
}
|
||||
|
||||
/*! Count number of tokens in text.
|
||||
*
|
||||
* \return number of counted tokens */
|
||||
size_t ValueTokenizer::count() {
|
||||
return tokens.count();
|
||||
}
|
||||
|
|
|
@ -52,11 +52,17 @@ public:
|
|||
class TokenizerException : public std::exception {
|
||||
std::string message;
|
||||
public:
|
||||
/** Thrown during retrieving or skipping tokens
|
||||
*
|
||||
* \param msg String with error message
|
||||
* \param token String of the token/word that caused the error */
|
||||
TokenizerException(const std::string &msg, const std::string &token);
|
||||
|
||||
~TokenizerException() throw() {
|
||||
}
|
||||
|
||||
/** Retrieve message describing the thrown exception
|
||||
* \return string with error message */
|
||||
virtual const char * what() const throw() {
|
||||
return message.c_str();
|
||||
}
|
||||
|
@ -64,14 +70,20 @@ public:
|
|||
|
||||
class InvalidIntegerException : public TokenizerException {
|
||||
public:
|
||||
InvalidIntegerException(const std::string &token) : TokenizerException("Not a valid integer number", token) {
|
||||
}
|
||||
/** Thrown during converting string to integer number
|
||||
*
|
||||
* \param token String of the token/word that caused the error */
|
||||
InvalidIntegerException(const std::string &token)
|
||||
: TokenizerException("Not a valid integer number", token) {}
|
||||
};
|
||||
|
||||
class InvalidFloatException : public TokenizerException {
|
||||
public:
|
||||
InvalidFloatException(const std::string &token) : TokenizerException("Not a valid floating-point number", token) {
|
||||
}
|
||||
/** Thrown during converting string to floating point number
|
||||
*
|
||||
* \param token String of the token/word that caused the error */
|
||||
InvalidFloatException(const std::string &token)
|
||||
: TokenizerException("Not a valid floating-point number", token) {}
|
||||
};
|
||||
|
||||
class ValueTokenizer {
|
||||
|
|
|
@ -870,14 +870,10 @@ std::string utils::get_potential_date(const std::string &path, const std::string
|
|||
reader.ignore_comments = false;
|
||||
|
||||
char *line = reader.next_line();
|
||||
ValueTokenizer values(line);
|
||||
while (values.has_next()) {
|
||||
std::string word = values.next_string();
|
||||
if (word == "DATE:") {
|
||||
if (values.has_next()) {
|
||||
std::string date = values.next_string();
|
||||
return date;
|
||||
}
|
||||
Tokenizer words(line);
|
||||
while (words.has_next()) {
|
||||
if (words.next() == "DATE:") {
|
||||
if (words.has_next()) return words.next();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
|
@ -893,14 +889,10 @@ std::string utils::get_potential_units(const std::string &path, const std::strin
|
|||
reader.ignore_comments = false;
|
||||
|
||||
char *line = reader.next_line();
|
||||
ValueTokenizer values(line);
|
||||
while (values.has_next()) {
|
||||
std::string word = values.next_string();
|
||||
if (word == "UNITS:") {
|
||||
if (values.has_next()) {
|
||||
std::string units = values.next_string();
|
||||
return units;
|
||||
}
|
||||
Tokenizer words(line);
|
||||
while (words.has_next()) {
|
||||
if (words.next() == "UNITS:") {
|
||||
if (words.has_next()) return words.next();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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()
|
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
|
@ -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);
|
||||
};
|
|
@ -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:");
|
||||
}
|
Loading…
Reference in New Issue