Merge branch 'master' into progguide-axel
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@ -37,6 +37,7 @@ vgcore.*
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
.clang-format
|
||||
.lammps_history
|
||||
|
||||
#cmake
|
||||
/build*
|
||||
|
||||
@ -90,6 +90,7 @@ if(BUILD_SHARED_LIBS) # for all pkg libs, mpi_stubs and linalg
|
||||
endif()
|
||||
|
||||
option(BUILD_TOOLS "Build and install LAMMPS tools (msi2lmp, binary2txt, chain)" OFF)
|
||||
option(BUILD_LAMMPS_SHELL "Build and install the LAMMPS shell" OFF)
|
||||
|
||||
include(GNUInstallDirs)
|
||||
file(GLOB ALL_SOURCES ${LAMMPS_SOURCE_DIR}/[^.]*.cpp)
|
||||
@ -642,6 +643,18 @@ if(BUILD_TOOLS)
|
||||
install(FILES ${LAMMPS_DOC_DIR}/msi2lmp.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
|
||||
endif()
|
||||
|
||||
if(BUILD_LAMMPS_SHELL)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(READLINE IMPORTED_TARGET REQUIRED readline)
|
||||
if(NOT LAMMPS_EXCEPTIONS)
|
||||
message(WARNING "The LAMMPS shell needs LAMMPS_EXCEPTIONS enabled for full functionality")
|
||||
endif()
|
||||
add_executable(lammps-shell ${LAMMPS_TOOLS_DIR}/lammps-shell/lammps-shell.cpp)
|
||||
target_compile_definitions(lammps-shell PRIVATE -DLAMMPS_LIB_NO_MPI)
|
||||
target_link_libraries(lammps-shell PRIVATE lammps PkgConfig::READLINE)
|
||||
install(TARGETS lammps-shell EXPORT LAMMPS_Targets DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
endif()
|
||||
|
||||
include(Documentation)
|
||||
|
||||
###############################################################################
|
||||
|
||||
@ -542,7 +542,8 @@ using CMake or Make.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
-D BUILD_TOOLS=value # yes or no (default)
|
||||
-D BUILD_TOOLS=value # yes or no (default)
|
||||
-D BUILD_LAMMPS_SHELL=value # yes or no (default)
|
||||
|
||||
The generated binaries will also become part of the LAMMPS installation
|
||||
(see below).
|
||||
@ -558,6 +559,9 @@ using CMake or Make.
|
||||
make micelle2d # build only micelle2d tool
|
||||
make thermo_extract # build only thermo_extract tool
|
||||
|
||||
cd lammps/tools/lammps-shell
|
||||
make # build LAMMPS shell
|
||||
|
||||
----------
|
||||
|
||||
.. _install:
|
||||
|
||||
@ -328,6 +328,8 @@ Some common LAMMPS specific variables
|
||||
- build LAMMPS with OpenMP support (default: ``on`` if compiler supports OpenMP fully, else ``off``)
|
||||
* - ``BUILD_TOOLS``
|
||||
- compile some additional executables from the ``tools`` folder (default: ``off``)
|
||||
* - ``BUILD_LAMMPS_SHELL``
|
||||
- compile the LAMMPS shell from the ``tools/lammps-shell`` folder (default: ``off``)
|
||||
* - ``BUILD_DOC``
|
||||
- include building the HTML format documentation for packaging/installing (default: ``off``)
|
||||
* - ``CMAKE_TUNE_FLAGS``
|
||||
|
||||
@ -15,6 +15,9 @@ This section documents the following functions:
|
||||
- :cpp:func:`lammps_has_style`
|
||||
- :cpp:func:`lammps_style_count`
|
||||
- :cpp:func:`lammps_style_name`
|
||||
- :cpp:func:`lammps_has_id`
|
||||
- :cpp:func:`lammps_id_count`
|
||||
- :cpp:func:`lammps_id_name`
|
||||
|
||||
--------------------
|
||||
|
||||
@ -124,3 +127,18 @@ approach.
|
||||
.. doxygenfunction:: lammps_style_name
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_has_id
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_id_count
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_id_name
|
||||
:project: progguide
|
||||
|
||||
|
||||
@ -9,6 +9,8 @@ functions. They do not directly call the LAMMPS library.
|
||||
- :cpp:func:`lammps_set_fix_external_callback`
|
||||
- :cpp:func:`lammps_fix_external_set_energy_global`
|
||||
- :cpp:func:`lammps_fix_external_set_virial_global`
|
||||
- :cpp:func:`lammps_is_running`
|
||||
- :cpp:func:`lammps_force_timeout`
|
||||
- :cpp:func:`lammps_has_error`
|
||||
- :cpp:func:`lammps_get_last_error_message`
|
||||
|
||||
@ -39,6 +41,16 @@ functions. They do not directly call the LAMMPS library.
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_is_running
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_force_timeout
|
||||
:project: progguide
|
||||
|
||||
-----------------------
|
||||
|
||||
.. doxygenfunction:: lammps_has_error
|
||||
:project: progguide
|
||||
|
||||
|
||||
@ -92,6 +92,7 @@ Miscellaneous tools
|
||||
* :ref:`emacs <emacs>`
|
||||
* :ref:`i-pi <ipi>`
|
||||
* :ref:`kate <kate>`
|
||||
* :ref:`LAMMPS shell <lammps_shell>`
|
||||
* :ref:`singularity <singularity_tool>`
|
||||
* :ref:`vim <vim>`
|
||||
|
||||
@ -397,10 +398,131 @@ The file was provided by Alessandro Luigi Sellerio
|
||||
|
||||
----------
|
||||
|
||||
.. _lammps_shell:
|
||||
|
||||
LAMMPS shell
|
||||
------------
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
The LAMMPS Shell, ``lammps-shell`` is a program that functions very
|
||||
similar to the regular LAMMPS executable but has several modifications
|
||||
and additions that make it more powerful for interactive sessions,
|
||||
i.e. where you type LAMMPS commands from the prompt instead of reading
|
||||
them from a file.
|
||||
|
||||
- It uses the readline and history libraries to provide command line
|
||||
editing and context aware TAB-expansion (details on that below).
|
||||
|
||||
- When processing an input file with the '-in' or '-i' flag from the
|
||||
command line, it does not exit at the end of that input file but
|
||||
stops at a prompt, so that additional commands can be issued
|
||||
|
||||
- Errors will not abort the shell but return to the prompt.
|
||||
|
||||
- It has additional commands aimed at interactive use (details below).
|
||||
|
||||
- Interrupting a calculation with CTRL-C will not terminate the
|
||||
session but rather enforce a timeout to cleanly stop an ongoing
|
||||
run (more info on timeouts is in the timer command documentation).
|
||||
|
||||
These enhancements makes the LAMMPS shell an attractive choice for
|
||||
interactive LAMMPS sessions in graphical user interfaces.
|
||||
|
||||
TAB-expansion
|
||||
=============
|
||||
|
||||
When writing commands interactively at the shell prompt, you can hit
|
||||
the TAB key at any time to try and complete the text. This completion
|
||||
is context aware and will expand any first word only to commands
|
||||
available in that executable.
|
||||
|
||||
- For style commands it will expand to available styles of the
|
||||
corresponding category (e.g. pair styles after a
|
||||
:doc:`pair_style <pair_style>` command).
|
||||
|
||||
- For :doc:`compute <compute>`, :doc:`fix <fix>`, or :doc:`dump <dump>`
|
||||
it will also expand only to already defined groups for the group-ID
|
||||
keyword.
|
||||
|
||||
- For commands like :doc:`compute_modify <compute_modify>`,
|
||||
:doc:`fix_modify <fix_modify>`, or :doc:`dump_modify <dump_modify>`
|
||||
it will expand to known compute/fix/dump IDs only.
|
||||
|
||||
- When typing references to computes, fixes, or variables with a
|
||||
"c\_", "f\_", or "v\_" prefix, respectively, then the expansion will
|
||||
to known compute/fix IDs and variable names. Variable name expansion
|
||||
is also available for the ${name} variable syntax.
|
||||
|
||||
- In all other cases, expansion will be performed on filenames.
|
||||
|
||||
|
||||
Command line editing and history
|
||||
================================
|
||||
|
||||
When typing commands, command line editing similar to what BASH
|
||||
provides is available. Thus it is possible to move around the
|
||||
currently line and perform various cut and insert and edit operations.
|
||||
Previous commands can be retrieved by scrolling up (and down)
|
||||
or searching (e.g. with CTRL-r).
|
||||
|
||||
Also history expansion through using the exclamation mark '!'
|
||||
can be performed. Examples: '!!' will be replaced with the previous
|
||||
command, '!-2' will repeat the command before that, '!30' will be
|
||||
replaced with event number 30 in the command history list, and
|
||||
'!run' with the last command line that started with "run". Adding
|
||||
a ":p" to such a history expansion will result that the expansion is
|
||||
printed and added to the history list, but NOT executed.
|
||||
On exit the LAMMPS shell will write the history list to a file
|
||||
".lammps_history" in the current working directory. If such a
|
||||
file exists when the LAMMPS shell is launched it will be read to
|
||||
populate the history list.
|
||||
|
||||
This is realized via the readline library and can thus be customized
|
||||
with an ``.inputrc`` file in the home directory. For application
|
||||
specific customization, the LAMMPS shell uses the name "lammps-shell".
|
||||
For more information about using and customizing an application using
|
||||
readline, please see the available documentation at:
|
||||
`http://www.gnu.org/s/readline/#Documentation
|
||||
<http://www.gnu.org/s/readline/#Documentation>`_
|
||||
|
||||
Additional commands
|
||||
===================
|
||||
|
||||
The following commands are added to the LAMMPS shell on top of the
|
||||
regular LAMMPS commands:
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
help (or ?) print a brief help message
|
||||
history display the current command history list
|
||||
clear_history wipe out the current command history list
|
||||
\|<command> execute <command> as a shell command and return to the command prompt
|
||||
exit exit the LAMMPS shell cleanly (unlike the "quit" command)
|
||||
|
||||
Compilation
|
||||
===========
|
||||
|
||||
Compilation of the LAMMPS shell can be enabled by setting the CMake
|
||||
variable ``BUILD_LAMMPS_SHELL`` to "on" or using the makefile in the
|
||||
``tools/lammps-shell`` folder to compile after building LAMMPS using
|
||||
the conventional make procedure. The makefile will likely need
|
||||
customization depending on the features and settings used for
|
||||
compiling LAMMPS.
|
||||
|
||||
Limitations
|
||||
===========
|
||||
|
||||
The LAMMPS shell was not designed for use with MPI parallelization
|
||||
via ``mpirun`` or ``mpiexec`` or ``srun``.
|
||||
|
||||
----------
|
||||
|
||||
.. _arc:
|
||||
|
||||
lmp2arc tool
|
||||
----------------------
|
||||
------------
|
||||
|
||||
The lmp2arc sub-directory contains a tool for converting LAMMPS output
|
||||
files to the format for Accelrys' Insight MD code (formerly
|
||||
|
||||
@ -205,11 +205,11 @@ the following table:
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| 4 | Force :math:`f_z` exerted on the wall | force units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| 5 | :math:`\Delta x` between wall surface and particle | distance units |
|
||||
| 5 | :math:`x`-coordinate of contact point on wall | distance units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| 6 | :math:`\Delta y` between wall surface and particle | distance units |
|
||||
| 6 | :math:`y`-coordinate of contact point on wall | distance units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| 7 | :math:`\Delta z` between wall surface and particle | distance units |
|
||||
| 7 | :math:`z`-coordinate of contact point on wall | distance units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| 8 | Radius :math:`r` of atom | distance units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
|
||||
@ -246,11 +246,11 @@ the following table:
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| 4 | Force :math:`f_z` exerted on the wall | force units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| 5 | :math:`\Delta x` between wall surface and particle | distance units |
|
||||
| 5 | :math:`x`-coordinate of contact point on wall | distance units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| 6 | :math:`\Delta y` between wall surface and particle | distance units |
|
||||
| 6 | :math:`y`-coordinate of contact point on wall | distance units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| 7 | :math:`\Delta z` between wall surface and particle | distance units |
|
||||
| 7 | :math:`z`-coordinate of contact point on wall | distance units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
| 8 | Radius :math:`r` of atom | distance units |
|
||||
+-------+----------------------------------------------------+----------------+
|
||||
|
||||
@ -250,7 +250,7 @@ void FixWallGranRegion::post_force(int /*vflag*/)
|
||||
|
||||
// store contact info
|
||||
if (peratom_flag) {
|
||||
array_atom[i][0] = (double)atom->tag[i];
|
||||
array_atom[i][0] = 1.0;
|
||||
array_atom[i][4] = x[i][0] - dx;
|
||||
array_atom[i][5] = x[i][1] - dy;
|
||||
array_atom[i][6] = x[i][2] - dz;
|
||||
|
||||
@ -145,8 +145,6 @@ FixSAEDVTK::FixSAEDVTK(LAMMPS *lmp, int narg, char **arg) :
|
||||
memory->create(vector,nrows,"saed/vtk:vector");
|
||||
memory->create(vector_total,nrows,"saed/vtk:vector_total");
|
||||
|
||||
extlist = nullptr;
|
||||
|
||||
vector_flag = 1;
|
||||
size_vector = nrows;
|
||||
|
||||
@ -282,7 +280,6 @@ FixSAEDVTK::FixSAEDVTK(LAMMPS *lmp, int narg, char **arg) :
|
||||
|
||||
FixSAEDVTK::~FixSAEDVTK()
|
||||
{
|
||||
delete [] extlist;
|
||||
delete [] filename;
|
||||
delete [] ids;
|
||||
memory->destroy(vector);
|
||||
|
||||
@ -53,8 +53,10 @@ ComputeViscosityCos::ComputeViscosityCos(LAMMPS *lmp, int narg, char **arg) :
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
ComputeViscosityCos::~ComputeViscosityCos() {
|
||||
if (!copymode)
|
||||
if (!copymode) {
|
||||
delete[] vector;
|
||||
delete[] extlist;
|
||||
}
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
@ -1863,6 +1863,8 @@ int FixBondReact::check_constraints()
|
||||
if (prrhob < rrhandom[(int) constraints[i][2]]->uniform()) return 0;
|
||||
} else if (constraints[i][1] == RMSD) {
|
||||
// call superpose
|
||||
int iatom;
|
||||
int iref = -1; // choose first atom as reference
|
||||
int n2superpose = 0;
|
||||
double **xfrozen; // coordinates for the "frozen" target molecule
|
||||
double **xmobile; // coordinates for the "mobile" molecule
|
||||
@ -1875,20 +1877,28 @@ int FixBondReact::check_constraints()
|
||||
int myincr = 0;
|
||||
for (int j = 0; j < onemol->natoms; j++) {
|
||||
if (onemol->fragmentmask[ifragment][j]) {
|
||||
iatom = atom->map(glove[j][1]);
|
||||
if (iref == -1) iref = iatom;
|
||||
iatom = domain->closest_image(iref,iatom);
|
||||
for (int k = 0; k < 3; k++) {
|
||||
xfrozen[myincr][k] = x[atom->map(glove[j][1])][k];
|
||||
xfrozen[myincr][k] = x[iatom][k];
|
||||
xmobile[myincr][k] = onemol->x[j][k];
|
||||
}
|
||||
myincr++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int iatom;
|
||||
int iref = -1; // choose first atom as reference
|
||||
n2superpose = onemol->natoms;
|
||||
memory->create(xfrozen,n2superpose,3,"bond/react:xfrozen");
|
||||
memory->create(xmobile,n2superpose,3,"bond/react:xmobile");
|
||||
for (int j = 0; j < n2superpose; j++) {
|
||||
iatom = atom->map(glove[j][1]);
|
||||
if (iref == -1) iref = iatom;
|
||||
iatom = domain->closest_image(iref,iatom);
|
||||
for (int k = 0; k < 3; k++) {
|
||||
xfrozen[j][k] = x[atom->map(glove[j][1])][k];
|
||||
xfrozen[j][k] = x[iatom][k];
|
||||
xmobile[j][k] = onemol->x[j][k];
|
||||
}
|
||||
}
|
||||
|
||||
@ -224,6 +224,7 @@ ComputeSlice::~ComputeSlice()
|
||||
for (int m = 0; m < nvalues; m++) delete [] ids[m];
|
||||
delete [] ids;
|
||||
delete [] value2index;
|
||||
delete [] extlist;
|
||||
|
||||
memory->destroy(vector);
|
||||
memory->destroy(array);
|
||||
|
||||
@ -234,7 +234,7 @@ DumpCustom::~DumpCustom()
|
||||
|
||||
for (int i = 0; i < ncustom; i++) delete [] id_custom[i];
|
||||
memory->sfree(id_custom);
|
||||
delete [] flag_custom;
|
||||
memory->sfree(flag_custom);
|
||||
|
||||
memory->destroy(choose);
|
||||
memory->destroy(dchoose);
|
||||
|
||||
@ -760,7 +760,7 @@ void FixAveHisto::end_of_step()
|
||||
}
|
||||
|
||||
irepeat = 0;
|
||||
nvalid = ntimestep + nfreq - (nrepeat-1)*nevery;
|
||||
nvalid = ntimestep + nfreq - static_cast<bigint>(nrepeat-1)*nevery;
|
||||
modify->addstep_compute(nvalid);
|
||||
|
||||
// merge histogram stats across procs if necessary
|
||||
@ -1046,7 +1046,7 @@ bigint FixAveHisto::nextvalid()
|
||||
if (nvalid-nfreq == update->ntimestep && nrepeat == 1)
|
||||
nvalid = update->ntimestep;
|
||||
else
|
||||
nvalid -= (nrepeat-1)*nevery;
|
||||
nvalid -= static_cast<bigint>(nrepeat-1)*nevery;
|
||||
if (nvalid < update->ntimestep) nvalid += nfreq;
|
||||
return nvalid;
|
||||
}
|
||||
|
||||
@ -403,7 +403,7 @@ void FixAveHistoWeight::end_of_step()
|
||||
}
|
||||
|
||||
irepeat = 0;
|
||||
nvalid = ntimestep + nfreq - (nrepeat-1)*nevery;
|
||||
nvalid = ntimestep + nfreq - static_cast<bigint>(nrepeat-1)*nevery;
|
||||
modify->addstep_compute(nvalid);
|
||||
|
||||
// merge histogram stats across procs if necessary
|
||||
|
||||
@ -640,7 +640,7 @@ void FixAveTime::invoke_scalar(bigint ntimestep)
|
||||
}
|
||||
|
||||
irepeat = 0;
|
||||
nvalid = ntimestep + nfreq - (nrepeat-1)*nevery;
|
||||
nvalid = ntimestep + nfreq - static_cast<bigint>(nrepeat-1)*nevery;
|
||||
modify->addstep_compute(nvalid);
|
||||
|
||||
// average the final result for the Nfreq timestep
|
||||
@ -743,7 +743,7 @@ void FixAveTime::invoke_vector(bigint ntimestep)
|
||||
if (!varlen[i] || which[i] != COMPUTE) continue;
|
||||
if (nrepeat > 1 && ave == ONE) {
|
||||
Compute *compute = modify->compute[value2index[i]];
|
||||
compute->lock(this,ntimestep,ntimestep+(nrepeat-1)*nevery);
|
||||
compute->lock(this,ntimestep,ntimestep+static_cast<bigint>(nrepeat-1)*nevery);
|
||||
} else if ((ave == RUNNING || ave == WINDOW) && !lockforever) {
|
||||
Compute *compute = modify->compute[value2index[i]];
|
||||
compute->lock(this,update->ntimestep,-1);
|
||||
@ -838,7 +838,7 @@ void FixAveTime::invoke_vector(bigint ntimestep)
|
||||
}
|
||||
|
||||
irepeat = 0;
|
||||
nvalid = ntimestep+nfreq - (nrepeat-1)*nevery;
|
||||
nvalid = ntimestep+nfreq - static_cast<bigint>(nrepeat-1)*nevery;
|
||||
modify->addstep_compute(nvalid);
|
||||
|
||||
// unlock any variable length computes at end of Nfreq epoch
|
||||
@ -1146,7 +1146,7 @@ bigint FixAveTime::nextvalid()
|
||||
if (nvalid-nfreq == update->ntimestep && nrepeat == 1)
|
||||
nvalid = update->ntimestep;
|
||||
else
|
||||
nvalid -= (nrepeat-1)*nevery;
|
||||
nvalid -= static_cast<bigint>(nrepeat-1)*nevery;
|
||||
if (nvalid < update->ntimestep) nvalid += nfreq;
|
||||
return nvalid;
|
||||
}
|
||||
|
||||
209
src/library.cpp
209
src/library.cpp
@ -22,6 +22,7 @@
|
||||
#include "comm.h"
|
||||
#include "compute.h"
|
||||
#include "domain.h"
|
||||
#include "dump.h"
|
||||
#include "error.h"
|
||||
#include "fix.h"
|
||||
#include "fix_external.h"
|
||||
@ -31,10 +32,13 @@
|
||||
#include "input.h"
|
||||
#include "memory.h"
|
||||
#include "modify.h"
|
||||
#include "molecule.h"
|
||||
#include "neigh_list.h"
|
||||
#include "neighbor.h"
|
||||
#include "region.h"
|
||||
#include "output.h"
|
||||
#include "thermo.h"
|
||||
#include "timer.h"
|
||||
#include "universe.h"
|
||||
#include "update.h"
|
||||
#include "variable.h"
|
||||
@ -4013,18 +4017,17 @@ int lammps_style_count(void *handle, const char *category) {
|
||||
|
||||
/** Look up the name of a style by index in the list of style of a given category in the LAMMPS library.
|
||||
*
|
||||
\verbatim embed:rst
|
||||
This function copies the name of the package with the index *idx* into the
|
||||
provided C-style string buffer. The length of the buffer must be provided
|
||||
as *buf_size* argument. If the name of the package exceeds the length of the
|
||||
buffer, it will be truncated accordingly. If the index is out of range,
|
||||
the function returns 0 and *buffer* is set to an empty string, otherwise 1.
|
||||
Please see :cpp:func:`lammps_has_style` for a list of valid categories.
|
||||
\endverbatim
|
||||
*
|
||||
* This function copies the name of the *category* style with the index
|
||||
* *idx* into the provided C-style string buffer. The length of the buffer
|
||||
* must be provided as *buf_size* argument. If the name of the style
|
||||
* exceeds the length of the buffer, it will be truncated accordingly.
|
||||
* If the index is out of range, the function returns 0 and *buffer* is
|
||||
* set to an empty string, otherwise 1.
|
||||
*
|
||||
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
|
||||
* \param category category of styles
|
||||
* \param idx index of the package in the list of included packages (0 <= idx < style count)
|
||||
* \param idx index of the style in the list of *category* styles (0 <= idx < style count)
|
||||
* \param buffer string buffer to copy the name of the style to
|
||||
* \param buf_size size of the provided string buffer
|
||||
* \return 1 if successful, otherwise 0
|
||||
@ -4046,6 +4049,167 @@ int lammps_style_name(void *handle, const char *category, int idx,
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/** Check if a specific ID exists in the current LAMMPS instance
|
||||
*
|
||||
\verbatim embed:rst
|
||||
This function checks if the current LAMMPS instance a *category* ID of
|
||||
the given *name* exists. Valid categories are: *compute*\ , *dump*\ ,
|
||||
*fix*\ , *group*\ , *molecule*\ , *region*\ , and *variable*\ .
|
||||
\endverbatim
|
||||
*
|
||||
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
|
||||
* \param category category of the id
|
||||
* \param name name of the id
|
||||
* \return 1 if included, 0 if not.
|
||||
*/
|
||||
int lammps_has_id(void *handle, const char *category, const char *name) {
|
||||
LAMMPS *lmp = (LAMMPS *) handle;
|
||||
|
||||
if (strcmp(category,"compute") == 0) {
|
||||
int ncompute = lmp->modify->ncompute;
|
||||
Compute **compute = lmp->modify->compute;
|
||||
for (int i=0; i < ncompute; ++i) {
|
||||
if (strcmp(name,compute[i]->id) == 0) return 1;
|
||||
}
|
||||
} else if (strcmp(category,"dump") == 0) {
|
||||
int ndump = lmp->output->ndump;
|
||||
Dump **dump = lmp->output->dump;
|
||||
for (int i=0; i < ndump; ++i) {
|
||||
if (strcmp(name,dump[i]->id) == 0) return 1;
|
||||
}
|
||||
} else if (strcmp(category,"fix") == 0) {
|
||||
int nfix = lmp->modify->nfix;
|
||||
Fix **fix = lmp->modify->fix;
|
||||
for (int i=0; i < nfix; ++i) {
|
||||
if (strcmp(name,fix[i]->id) == 0) return 1;
|
||||
}
|
||||
} else if (strcmp(category,"group") == 0) {
|
||||
int ngroup = lmp->group->ngroup;
|
||||
char **groups = lmp->group->names;
|
||||
for (int i=0; i < ngroup; ++i) {
|
||||
if (strcmp(groups[i],name) == 0) return 1;
|
||||
}
|
||||
} else if (strcmp(category,"molecule") == 0) {
|
||||
int nmolecule = lmp->atom->nmolecule;
|
||||
Molecule **molecule = lmp->atom->molecules;
|
||||
for (int i=0; i < nmolecule; ++i) {
|
||||
if (strcmp(name,molecule[i]->id) == 0) return 1;
|
||||
}
|
||||
} else if (strcmp(category,"region") == 0) {
|
||||
int nregion = lmp->domain->nregion;
|
||||
Region **region = lmp->domain->regions;
|
||||
for (int i=0; i < nregion; ++i) {
|
||||
if (strcmp(name,region[i]->id) == 0) return 1;
|
||||
}
|
||||
} else if (strcmp(category,"variable") == 0) {
|
||||
int nvariable = lmp->input->variable->nvar;
|
||||
char **varnames = lmp->input->variable->names;
|
||||
for (int i=0; i < nvariable; ++i) {
|
||||
if (strcmp(name,varnames[i]) == 0) return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/** Count the number of IDs of a category.
|
||||
*
|
||||
\verbatim embed:rst
|
||||
This function counts how many IDs in the provided *category*
|
||||
are defined in the current LAMMPS instance.
|
||||
Please see :cpp:func:`lammps_has_id` for a list of valid
|
||||
categories.
|
||||
\endverbatim
|
||||
*
|
||||
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
|
||||
* \param category category of IDs
|
||||
* \return number of IDs in category
|
||||
*/
|
||||
int lammps_id_count(void *handle, const char *category) {
|
||||
LAMMPS *lmp = (LAMMPS *) handle;
|
||||
if (strcmp(category,"compute") == 0) {
|
||||
return lmp->modify->ncompute;
|
||||
} else if (strcmp(category,"dump") == 0) {
|
||||
return lmp->output->ndump;
|
||||
} else if (strcmp(category,"fix") == 0) {
|
||||
return lmp->modify->nfix;
|
||||
} else if (strcmp(category,"group") == 0) {
|
||||
return lmp->group->ngroup;
|
||||
} else if (strcmp(category,"molecule") == 0) {
|
||||
return lmp->atom->nmolecule;
|
||||
} else if (strcmp(category,"region") == 0) {
|
||||
return lmp->domain->nregion;
|
||||
} else if (strcmp(category,"variable") == 0) {
|
||||
return lmp->input->variable->nvar;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/** Look up the name of an ID by index in the list of IDs of a given category.
|
||||
*
|
||||
* This function copies the name of the *category* ID with the index
|
||||
* *idx* into the provided C-style string buffer. The length of the buffer
|
||||
* must be provided as *buf_size* argument. If the name of the style
|
||||
* exceeds the length of the buffer, it will be truncated accordingly.
|
||||
* If the index is out of range, the function returns 0 and *buffer* is
|
||||
* set to an empty string, otherwise 1.
|
||||
*
|
||||
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
|
||||
* \param category category of IDs
|
||||
* \param idx index of the ID in the list of *category* styles (0 <= idx < count)
|
||||
* \param buffer string buffer to copy the name of the style to
|
||||
* \param buf_size size of the provided string buffer
|
||||
* \return 1 if successful, otherwise 0
|
||||
*/
|
||||
int lammps_id_name(void *handle, const char *category, int idx,
|
||||
char *buffer, int buf_size) {
|
||||
LAMMPS *lmp = (LAMMPS *) handle;
|
||||
|
||||
if (strcmp(category,"compute") == 0) {
|
||||
if ((idx >=0) && (idx < lmp->modify->ncompute)) {
|
||||
strncpy(buffer, lmp->modify->compute[idx]->id, buf_size);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(category,"dump") == 0) {
|
||||
if ((idx >=0) && (idx < lmp->output->ndump)) {
|
||||
strncpy(buffer, lmp->output->dump[idx]->id, buf_size);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(category,"fix") == 0) {
|
||||
if ((idx >=0) && (idx < lmp->modify->nfix)) {
|
||||
strncpy(buffer, lmp->modify->fix[idx]->id, buf_size);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(category,"group") == 0) {
|
||||
if ((idx >=0) && (idx < lmp->group->ngroup)) {
|
||||
strncpy(buffer, lmp->group->names[idx], buf_size);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(category,"molecule") == 0) {
|
||||
if ((idx >=0) && (idx < lmp->atom->nmolecule)) {
|
||||
strncpy(buffer, lmp->atom->molecules[idx]->id, buf_size);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(category,"region") == 0) {
|
||||
if ((idx >=0) && (idx < lmp->domain->nregion)) {
|
||||
strncpy(buffer, lmp->domain->regions[idx]->id, buf_size);
|
||||
return 1;
|
||||
}
|
||||
} else if (strcmp(category,"variable") == 0) {
|
||||
if ((idx >=0) && (idx < lmp->input->variable->nvar)) {
|
||||
strncpy(buffer, lmp->input->variable->names[idx], buf_size);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
buffer[0] = '\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------- */
|
||||
|
||||
/** This function is used to query whether LAMMPS was compiled with
|
||||
* a real MPI library or in serial.
|
||||
*
|
||||
@ -4395,6 +4559,33 @@ void lammps_decode_image_flags(imageint image, int *flags)
|
||||
flags[2] = (image >> IMG2BITS) - IMGMAX;
|
||||
}
|
||||
|
||||
/** Check if LAMMPS is currently inside a run or minimization
|
||||
*
|
||||
* This function can be used from signal handlers or multi-threaded
|
||||
* applications to determine if the LAMMPS instance is currently active.
|
||||
*
|
||||
* \param handle pointer to a previously created LAMMPS instance cast to ``void *``.
|
||||
* \return 0 if idle or >0 if active */
|
||||
|
||||
int lammps_is_running(void *handle)
|
||||
{
|
||||
LAMMPS * lmp = (LAMMPS *) handle;
|
||||
return lmp->update->whichflag;
|
||||
}
|
||||
|
||||
/** Force a timeout to cleanly stop an ongoing run
|
||||
*
|
||||
* This function can be used from signal handlers or multi-threaded
|
||||
* applications to cleanly terminate an ongoing run.
|
||||
*
|
||||
* \param handle pointer to a previously created LAMMPS instance cast to ``void *`` */
|
||||
|
||||
void lammps_force_timeout(void *handle)
|
||||
{
|
||||
LAMMPS * lmp = (LAMMPS *) handle;
|
||||
return lmp->timer->force_timeout();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Library functions for error handling with exceptions enabled
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
@ -183,6 +183,10 @@ int lammps_has_style(void *, const char *, const char *);
|
||||
int lammps_style_count(void *, const char *);
|
||||
int lammps_style_name(void *, const char *, int, char *, int);
|
||||
|
||||
int lammps_has_id(void *, const char *, const char *);
|
||||
int lammps_id_count(void *, const char *);
|
||||
int lammps_id_name(void *, const char *, int, char *, int);
|
||||
|
||||
/* ----------------------------------------------------------------------
|
||||
* Library functions for accessing neighbor lists
|
||||
* ---------------------------------------------------------------------- */
|
||||
@ -218,6 +222,9 @@ void lammps_set_fix_external_callback(void *, char *, FixExternalFnPtr, void*);
|
||||
void lammps_fix_external_set_energy_global(void *, char *, double);
|
||||
void lammps_fix_external_set_virial_global(void *, char *, double *);
|
||||
|
||||
int lammps_is_running(void *handle);
|
||||
void lammps_force_timeout(void *handle);
|
||||
|
||||
int lammps_has_error(void *handle);
|
||||
int lammps_get_last_error_message(void *handle, char *buffer, int buf_size);
|
||||
|
||||
|
||||
@ -935,7 +935,7 @@ run(real_t<T>& eigvalue, std::vector<T>& eigvec) const
|
||||
//assert(matrix_size > 0);
|
||||
//assert(0 < this->tridiag_eps_ratio && this->tridiag_eps_ratio < 1);
|
||||
|
||||
std::vector<std::vector<T>> u; // Lanczos vectors
|
||||
std::vector<std::vector<T>> u; // Lanczos vectors
|
||||
std::vector<real_t<T>> alpha; // Diagonal elements of an approximated tridiagonal matrix
|
||||
std::vector<real_t<T>> beta; // Subdiagonal elements of an approximated tridiagonal matrix
|
||||
|
||||
|
||||
@ -244,7 +244,7 @@ void Min::setup(int flag)
|
||||
|
||||
bigint ndofme = 3 * static_cast<bigint>(atom->nlocal);
|
||||
for (int m = 0; m < nextra_atom; m++)
|
||||
ndofme += extra_peratom[m]*atom->nlocal;
|
||||
ndofme += extra_peratom[m]*static_cast<bigint>(atom->nlocal);
|
||||
MPI_Allreduce(&ndofme,&ndoftotal,1,MPI_LMP_BIGINT,MPI_SUM,world);
|
||||
ndoftotal += nextra_global;
|
||||
|
||||
|
||||
@ -51,6 +51,7 @@ Update::Update(LAMMPS *lmp) : Pointers(lmp)
|
||||
multireplica = 0;
|
||||
|
||||
eflag_global = vflag_global = -1;
|
||||
eflag_atom = vflag_atom = 0;
|
||||
|
||||
dt_default = 1;
|
||||
unit_style = nullptr;
|
||||
|
||||
@ -2687,23 +2687,23 @@ double Variable::collapse_tree(Tree *tree)
|
||||
}
|
||||
|
||||
if (tree->type == STAGGER) {
|
||||
int ivalue1 = static_cast<int> (collapse_tree(tree->first));
|
||||
int ivalue2 = static_cast<int> (collapse_tree(tree->second));
|
||||
bigint ivalue1 = static_cast<bigint> (collapse_tree(tree->first));
|
||||
bigint ivalue2 = static_cast<bigint> (collapse_tree(tree->second));
|
||||
if (tree->first->type != VALUE || tree->second->type != VALUE) return 0.0;
|
||||
tree->type = VALUE;
|
||||
if (ivalue1 <= 0 || ivalue2 <= 0 || ivalue1 <= ivalue2)
|
||||
error->one(FLERR,"Invalid math function in variable formula");
|
||||
int lower = update->ntimestep/ivalue1 * ivalue1;
|
||||
int delta = update->ntimestep - lower;
|
||||
bigint lower = update->ntimestep/ivalue1 * ivalue1;
|
||||
bigint delta = update->ntimestep - lower;
|
||||
if (delta < ivalue2) tree->value = lower+ivalue2;
|
||||
else tree->value = lower+ivalue1;
|
||||
return tree->value;
|
||||
}
|
||||
|
||||
if (tree->type == LOGFREQ) {
|
||||
int ivalue1 = static_cast<int> (collapse_tree(tree->first));
|
||||
int ivalue2 = static_cast<int> (collapse_tree(tree->second));
|
||||
int ivalue3 = static_cast<int> (collapse_tree(tree->extra[0]));
|
||||
bigint ivalue1 = static_cast<bigint> (collapse_tree(tree->first));
|
||||
bigint ivalue2 = static_cast<bigint> (collapse_tree(tree->second));
|
||||
bigint ivalue3 = static_cast<bigint> (collapse_tree(tree->extra[0]));
|
||||
if (tree->first->type != VALUE || tree->second->type != VALUE ||
|
||||
tree->extra[0]->type != VALUE) return 0.0;
|
||||
tree->type = VALUE;
|
||||
@ -2711,9 +2711,9 @@ double Variable::collapse_tree(Tree *tree)
|
||||
error->one(FLERR,"Invalid math function in variable formula");
|
||||
if (update->ntimestep < ivalue1) tree->value = ivalue1;
|
||||
else {
|
||||
int lower = ivalue1;
|
||||
bigint lower = ivalue1;
|
||||
while (update->ntimestep >= ivalue3*lower) lower *= ivalue3;
|
||||
int multiple = update->ntimestep/lower;
|
||||
bigint multiple = update->ntimestep/lower;
|
||||
if (multiple < ivalue2) tree->value = (multiple+1)*lower;
|
||||
else tree->value = lower*ivalue3;
|
||||
}
|
||||
@ -2721,9 +2721,9 @@ double Variable::collapse_tree(Tree *tree)
|
||||
}
|
||||
|
||||
if (tree->type == LOGFREQ2) {
|
||||
int ivalue1 = static_cast<int> (collapse_tree(tree->first));
|
||||
int ivalue2 = static_cast<int> (collapse_tree(tree->second));
|
||||
int ivalue3 = static_cast<int> (collapse_tree(tree->extra[0]));
|
||||
bigint ivalue1 = static_cast<bigint> (collapse_tree(tree->first));
|
||||
bigint ivalue2 = static_cast<bigint> (collapse_tree(tree->second));
|
||||
bigint ivalue3 = static_cast<bigint> (collapse_tree(tree->extra[0]));
|
||||
if (tree->first->type != VALUE || tree->second->type != VALUE ||
|
||||
tree->extra[0]->type != VALUE) return 0.0;
|
||||
tree->type = VALUE;
|
||||
@ -2733,7 +2733,7 @@ double Variable::collapse_tree(Tree *tree)
|
||||
else {
|
||||
tree->value = ivalue1;
|
||||
double delta = ivalue1*(ivalue3-1.0)/ivalue2;
|
||||
int count = 0;
|
||||
bigint count = 0;
|
||||
while (update->ntimestep >= tree->value) {
|
||||
tree->value += delta;
|
||||
count++;
|
||||
@ -2745,9 +2745,9 @@ double Variable::collapse_tree(Tree *tree)
|
||||
}
|
||||
|
||||
if (tree->type == LOGFREQ3) {
|
||||
int ivalue1 = static_cast<int> (collapse_tree(tree->first));
|
||||
int ivalue2 = static_cast<int> (collapse_tree(tree->second));
|
||||
int ivalue3 = static_cast<int> (collapse_tree(tree->extra[0]));
|
||||
bigint ivalue1 = static_cast<bigint> (collapse_tree(tree->first));
|
||||
bigint ivalue2 = static_cast<bigint> (collapse_tree(tree->second));
|
||||
bigint ivalue3 = static_cast<bigint> (collapse_tree(tree->extra[0]));
|
||||
if (tree->first->type != VALUE || tree->second->type != VALUE ||
|
||||
tree->extra[0]->type != VALUE) return 0.0;
|
||||
tree->type = VALUE;
|
||||
@ -2760,7 +2760,7 @@ double Variable::collapse_tree(Tree *tree)
|
||||
tree->value = ivalue1;
|
||||
double logsp = ivalue1;
|
||||
double factor = pow(((double)ivalue3)/ivalue1, 1.0/(ivalue2-1));
|
||||
int linsp = ivalue1;
|
||||
bigint linsp = ivalue1;
|
||||
while (update->ntimestep >= (tree->value)) {
|
||||
logsp *= factor;
|
||||
linsp++;
|
||||
@ -2774,9 +2774,9 @@ double Variable::collapse_tree(Tree *tree)
|
||||
}
|
||||
|
||||
if (tree->type == STRIDE) {
|
||||
int ivalue1 = static_cast<int> (collapse_tree(tree->first));
|
||||
int ivalue2 = static_cast<int> (collapse_tree(tree->second));
|
||||
int ivalue3 = static_cast<int> (collapse_tree(tree->extra[0]));
|
||||
bigint ivalue1 = static_cast<bigint> (collapse_tree(tree->first));
|
||||
bigint ivalue2 = static_cast<bigint> (collapse_tree(tree->second));
|
||||
bigint ivalue3 = static_cast<bigint> (collapse_tree(tree->extra[0]));
|
||||
if (tree->first->type != VALUE || tree->second->type != VALUE ||
|
||||
tree->extra[0]->type != VALUE) return 0.0;
|
||||
tree->type = VALUE;
|
||||
@ -2784,7 +2784,7 @@ double Variable::collapse_tree(Tree *tree)
|
||||
error->one(FLERR,"Invalid math function in variable formula");
|
||||
if (update->ntimestep < ivalue1) tree->value = ivalue1;
|
||||
else if (update->ntimestep < ivalue2) {
|
||||
int offset = update->ntimestep - ivalue1;
|
||||
bigint offset = update->ntimestep - ivalue1;
|
||||
tree->value = ivalue1 + (offset/ivalue3)*ivalue3 + ivalue3;
|
||||
if (tree->value > ivalue2) tree->value = (double) MAXBIGINT;
|
||||
} else tree->value = (double) MAXBIGINT;
|
||||
@ -2792,12 +2792,12 @@ double Variable::collapse_tree(Tree *tree)
|
||||
}
|
||||
|
||||
if (tree->type == STRIDE2) {
|
||||
int ivalue1 = static_cast<int> (collapse_tree(tree->first));
|
||||
int ivalue2 = static_cast<int> (collapse_tree(tree->second));
|
||||
int ivalue3 = static_cast<int> (collapse_tree(tree->extra[0]));
|
||||
int ivalue4 = static_cast<int> (collapse_tree(tree->extra[1]));
|
||||
int ivalue5 = static_cast<int> (collapse_tree(tree->extra[2]));
|
||||
int ivalue6 = static_cast<int> (collapse_tree(tree->extra[3]));
|
||||
bigint ivalue1 = static_cast<bigint> (collapse_tree(tree->first));
|
||||
bigint ivalue2 = static_cast<bigint> (collapse_tree(tree->second));
|
||||
bigint ivalue3 = static_cast<bigint> (collapse_tree(tree->extra[0]));
|
||||
bigint ivalue4 = static_cast<bigint> (collapse_tree(tree->extra[1]));
|
||||
bigint ivalue5 = static_cast<bigint> (collapse_tree(tree->extra[2]));
|
||||
bigint ivalue6 = static_cast<bigint> (collapse_tree(tree->extra[3]));
|
||||
if (tree->first->type != VALUE || tree->second->type != VALUE ||
|
||||
tree->extra[0]->type != VALUE || tree->extra[1]->type != VALUE ||
|
||||
tree->extra[2]->type != VALUE || tree->extra[3]->type != VALUE)
|
||||
@ -2813,15 +2813,15 @@ double Variable::collapse_tree(Tree *tree)
|
||||
if (update->ntimestep < ivalue1) istep = ivalue1;
|
||||
else if (update->ntimestep < ivalue2) {
|
||||
if (update->ntimestep < ivalue4 || update->ntimestep > ivalue5) {
|
||||
int offset = update->ntimestep - ivalue1;
|
||||
bigint offset = update->ntimestep - ivalue1;
|
||||
istep = ivalue1 + (offset/ivalue3)*ivalue3 + ivalue3;
|
||||
if (update->ntimestep < ivalue2 && istep > ivalue4)
|
||||
tree->value = ivalue4;
|
||||
} else {
|
||||
int offset = update->ntimestep - ivalue4;
|
||||
bigint offset = update->ntimestep - ivalue4;
|
||||
istep = ivalue4 + (offset/ivalue6)*ivalue6 + ivalue6;
|
||||
if (istep > ivalue5) {
|
||||
int offset = ivalue5 - ivalue1;
|
||||
bigint offset = ivalue5 - ivalue1;
|
||||
istep = ivalue1 + (offset/ivalue3)*ivalue3 + ivalue3;
|
||||
if (istep > ivalue2) istep = MAXBIGINT;
|
||||
}
|
||||
|
||||
@ -49,11 +49,13 @@ class Variable : protected Pointers {
|
||||
tagint int_between_brackets(char *&, int);
|
||||
double evaluate_boolean(char *);
|
||||
|
||||
public:
|
||||
int nvar; // # of defined variables
|
||||
char **names; // name of each variable
|
||||
|
||||
private:
|
||||
int me;
|
||||
int nvar; // # of defined variables
|
||||
int maxvar; // max # of variables following lists can hold
|
||||
char **names; // name of each variable
|
||||
int *style; // style of each variable
|
||||
int *num; // # of values for each variable
|
||||
int *which; // next available value for each variable
|
||||
|
||||
@ -29,6 +29,7 @@ fep scripts for free-energy perturbation with USER-FEP pkg
|
||||
i-pi Python wrapper for performing path-integral MD (PIMD)
|
||||
ipp input pre-processor Perl tool for creating input scripts
|
||||
kate add-ons to Kate editor for editing LAMMPS input scripts
|
||||
lammps-shell LAMMPS executable enhanced for interactive use
|
||||
lmp2arc convert LAMMPS output to Accelrys Insight format
|
||||
lmp2cfg convert LAMMPS output to CFG files for AtomEye viz
|
||||
matlab MatLab scripts for post-processing LAMMPS output
|
||||
|
||||
1
tools/lammps-shell/.gitignore
vendored
Normal file
1
tools/lammps-shell/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/lammps-shell
|
||||
14
tools/lammps-shell/Makefile
Normal file
14
tools/lammps-shell/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
SHELL=/bin/sh
|
||||
|
||||
CXX=g++
|
||||
CXXFLAGS=-O -g -Wall -I../../src -DLAMMPS_LIB_NO_MPI
|
||||
LDFLAGS= -L../../src -llammps -lreadline
|
||||
|
||||
lammps-shell: lammps-shell.o
|
||||
$(CXX) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
lammps-shell.o: lammps-shell.cpp
|
||||
$(CXX) -c $(CXXFLAGS) -o $@ $<
|
||||
|
||||
clean:
|
||||
@rm -f lammps-shell lammps-shell.o core *~ .lammps-history
|
||||
107
tools/lammps-shell/README
Normal file
107
tools/lammps-shell/README
Normal file
@ -0,0 +1,107 @@
|
||||
The LAMMPS Shell. An enhanced LAMMPS executable for interactive sessions.
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
This is a program that functions very similar to the regular LAMMPS
|
||||
executable but has several modifications and additions that make it
|
||||
more powerful for interactive sessions, i.e. where you type LAMMPS
|
||||
commands from the prompt instead of reading them from a file.
|
||||
|
||||
- It uses the readline and history libraries to provide command line
|
||||
editing and context aware TAB-expansion (details on that below).
|
||||
|
||||
- When processing an input file with the '-in' or '-i' flag from the
|
||||
command line, it does not exit at the end of that input file but
|
||||
stops at a prompt, so that additional commands can be issued
|
||||
|
||||
- Errors will not abort the shell but return to the prompt.
|
||||
|
||||
- It has additional commands aimed at interactive use (details below).
|
||||
|
||||
- Interrupting a calculation with CTRL-C will not terminate the
|
||||
session but rather enforce a timeout to cleanly stop an ongoing
|
||||
run (more info on timeouts is in the timer command documentation).
|
||||
|
||||
These enhancements makes the LAMMPS shell an attractive choice for
|
||||
interactive LAMMPS sessions in graphical user interfaces.
|
||||
|
||||
TAB-expansion
|
||||
=============
|
||||
|
||||
When writing commands interactively at the shell prompt, you can hit
|
||||
the TAB key at any time to try and complete the text. This completion
|
||||
is context aware and will expand any first word only to commands
|
||||
available in that executable.
|
||||
|
||||
- For style commands it will expand to available styles of the
|
||||
corresponding category (e.g. pair styles after a pair_style command).
|
||||
|
||||
- For "compute", "fix", or "dump" it will also expand only to already
|
||||
defined groups for the group-ID keyword.
|
||||
|
||||
- For commands like "compute_modify", "fix_modify", or "dump_modify"
|
||||
it will expand to known compute/fix/dump IDs only.
|
||||
|
||||
- When typing references to computes, fixes, or variables with a
|
||||
"c_", "f_", or "v_" prefix, respectively, then the expansion will
|
||||
to known compute/fix IDs and variable names. Variable name expansion
|
||||
is also available for the ${name} variable syntax.
|
||||
|
||||
- In all other cases, expansion will be performed on filenames.
|
||||
|
||||
Command line editing and history
|
||||
================================
|
||||
|
||||
When typing commands, command line editing similar to what BASH
|
||||
provides is available. Thus it is possible to move around the
|
||||
currently line and perform various cut and insert and edit operations.
|
||||
Previous commands can be retrieved by scrolling up (and down)
|
||||
or searching (e.g. with CTRL-r).
|
||||
|
||||
Also history expansion through using the exclamation mark '!'
|
||||
can be performed. Examples: '!!' will be replaced with the previous
|
||||
command, '!-2' will repeat the command before that, '!30' will be
|
||||
replaced with event number 30 in the command history list, and
|
||||
'!run' with the last command line that started with "run". Adding
|
||||
a ":p" to such a history expansion will result that the expansion is
|
||||
printed and added to the history list, but NOT executed.
|
||||
On exit the LAMMPS shell will write the history list to a file
|
||||
".lammps_history" in the current working directory. If such a
|
||||
file exists when the LAMMPS shell is launched it will be read to
|
||||
populate the history list.
|
||||
|
||||
This is realized via the readline library and can thus be customized
|
||||
with an ".inputrc" file in the home directory. For application specific
|
||||
customization, the LAMMPS shell uses the name "lammps-shell".
|
||||
For more information about using and customizing an application using
|
||||
readline, please see the available documentation at:
|
||||
http://www.gnu.org/s/readline/#Documentation
|
||||
|
||||
Additional commands
|
||||
===================
|
||||
|
||||
The followind commands are added to the LAMMPS shell on top of the
|
||||
regular LAMMPS commands:
|
||||
|
||||
- help (or ?) print a brief help message
|
||||
- history display the current command history list
|
||||
- clear_history wipe out the current command history list
|
||||
- |<command> execute <command> as a shell command and return to the command prompt
|
||||
- exit exit the LAMMPS shell cleanly (unlike the "quit" command)
|
||||
|
||||
Compilation
|
||||
===========
|
||||
|
||||
Compilation of the LAMMPS shell can be enabled by setting the CMake
|
||||
variable BUILD_LAMMPS_SHELL to "on" or using the makefile in the
|
||||
tools/lammps-shell folder to compile after building LAMMPS using
|
||||
the conventional make procedure. The makefile will likely need
|
||||
customization depending on the features and settings used for
|
||||
compiling LAMMPS.
|
||||
|
||||
Limitations
|
||||
===========
|
||||
|
||||
The LAMMPS shell was not designed for use with MPI parallelization
|
||||
via "mpirun" or "mpiexec" or "srun".
|
||||
604
tools/lammps-shell/lammps-shell.cpp
Normal file
604
tools/lammps-shell/lammps-shell.cpp
Normal file
@ -0,0 +1,604 @@
|
||||
// LAMMPS Shell. An improved interactive LAMMPS session with
|
||||
// command line editing, history, TAB expansion and shell escapes
|
||||
|
||||
// Copyright (c) 2020 Axel Kohlmeyer <akohlmey@gmail.com>
|
||||
|
||||
// This software is distributed under the GNU General Public License.
|
||||
|
||||
#include "library.h"
|
||||
#include "utils.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#if !defined(WIN32_LEAN_AND_MEAN)
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
#include <io.h>
|
||||
#include <windows.h>
|
||||
#define isatty(x) _isatty(x)
|
||||
#endif
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#include <readline/history.h>
|
||||
#include <readline/readline.h>
|
||||
|
||||
using namespace LAMMPS_NS;
|
||||
|
||||
const int buflen = 512;
|
||||
char buf[buflen];
|
||||
void *lmp = nullptr;
|
||||
enum {
|
||||
ATOM_STYLE,
|
||||
INTEGRATE_STYLE,
|
||||
MINIMIZE_STYLE,
|
||||
PAIR_STYLE,
|
||||
BOND_STYLE,
|
||||
ANGLE_STYLE,
|
||||
DIHEDRAL_STYLE,
|
||||
IMPROPER_STYLE,
|
||||
KSPACE_STYLE,
|
||||
FIX_STYLE,
|
||||
COMPUTE_STYLE,
|
||||
REGION_STYLE,
|
||||
DUMP_STYLE
|
||||
};
|
||||
const char *lmp_style[] = {"atom", "integrate", "minimize", "pair", "bond",
|
||||
"angle", "dihedral", "improper", "kspace", "fix",
|
||||
"compute", "region", "dump"};
|
||||
|
||||
enum { COMPUTE_ID, DUMP_ID, FIX_ID, MOLECULE_ID, REGION_ID, VARIABLE_ID };
|
||||
const char *lmp_id[] = {"compute", "dump", "fix", "molecule", "region", "variable"};
|
||||
|
||||
std::vector<std::string> commands;
|
||||
|
||||
// this list of commands is generated by:
|
||||
// grep '!strcmp(command,' ../../src/input.cpp | sed -e 's/^.*!strcmp(command,"\(.*\)".*$/"\1",/'
|
||||
|
||||
const char *cmdlist[] = {"clear",
|
||||
"echo",
|
||||
"if",
|
||||
"include",
|
||||
"jump",
|
||||
"label",
|
||||
"log",
|
||||
"next",
|
||||
"partition",
|
||||
"print",
|
||||
"python",
|
||||
"quit",
|
||||
"shell",
|
||||
"variable",
|
||||
"angle_coeff",
|
||||
"angle_style",
|
||||
"atom_modify",
|
||||
"atom_style",
|
||||
"bond_coeff",
|
||||
"bond_style",
|
||||
"bond_write",
|
||||
"boundary",
|
||||
"box",
|
||||
"comm_modify",
|
||||
"comm_style",
|
||||
"compute",
|
||||
"compute_modify",
|
||||
"dielectric",
|
||||
"dihedral_coeff",
|
||||
"dihedral_style",
|
||||
"dimension",
|
||||
"dump",
|
||||
"dump_modify",
|
||||
"fix",
|
||||
"fix_modify",
|
||||
"group",
|
||||
"improper_coeff",
|
||||
"improper_style",
|
||||
"kspace_modify",
|
||||
"kspace_style",
|
||||
"lattice",
|
||||
"mass",
|
||||
"min_modify",
|
||||
"min_style",
|
||||
"molecule",
|
||||
"neigh_modify",
|
||||
"neighbor",
|
||||
"newton",
|
||||
"package",
|
||||
"pair_coeff",
|
||||
"pair_modify",
|
||||
"pair_style",
|
||||
"pair_write",
|
||||
"processors",
|
||||
"region",
|
||||
"reset_timestep",
|
||||
"restart",
|
||||
"run_style",
|
||||
"special_bonds",
|
||||
"suffix",
|
||||
"thermo",
|
||||
"thermo_modify",
|
||||
"thermo_style",
|
||||
"timestep",
|
||||
"timer",
|
||||
"uncompute",
|
||||
"undump",
|
||||
"unfix",
|
||||
"units"};
|
||||
|
||||
static char *dupstring(const std::string &text)
|
||||
{
|
||||
int len = text.size() + 1;
|
||||
char *copy = (char *)malloc(len);
|
||||
strcpy(copy, text.c_str());
|
||||
return copy;
|
||||
}
|
||||
|
||||
template <int STYLE> char *style_generator(const char *text, int state)
|
||||
{
|
||||
static int idx, num, len;
|
||||
if (!state) {
|
||||
idx = 0;
|
||||
num = lammps_style_count(lmp, lmp_style[STYLE]);
|
||||
len = strlen(text);
|
||||
}
|
||||
|
||||
while (idx < num) {
|
||||
lammps_style_name(lmp, lmp_style[STYLE], idx, buf, buflen);
|
||||
++idx;
|
||||
if ((len == 0) || (strncmp(text, buf, len) == 0)) return dupstring(buf);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <int ID> char *id_generator(const char *text, int state)
|
||||
{
|
||||
static int idx, num, len;
|
||||
if (!state) {
|
||||
idx = 0;
|
||||
num = lammps_id_count(lmp, lmp_id[ID]);
|
||||
len = strlen(text);
|
||||
}
|
||||
|
||||
while (idx < num) {
|
||||
lammps_id_name(lmp, lmp_id[ID], idx, buf, buflen);
|
||||
++idx;
|
||||
if ((len == 0) || (strncmp(text, buf, len) == 0)) return dupstring(buf);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template <int ID, char PREFIX> char *ref_generator(const char *text, int state)
|
||||
{
|
||||
char prefix[] = "X_";
|
||||
prefix[0] = PREFIX;
|
||||
|
||||
if (strncmp(text, prefix, 2) == 0) {
|
||||
char *id = id_generator<ID>(text + 2, state);
|
||||
char *ref = nullptr;
|
||||
if (id) {
|
||||
ref = (char *)malloc(strlen(id) + 3);
|
||||
if (ref) {
|
||||
ref[0] = PREFIX;
|
||||
ref[1] = '_';
|
||||
ref[2] = 0;
|
||||
strcat(ref, id);
|
||||
}
|
||||
free(id);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
#if !defined(_WIN32)
|
||||
static void ctrl_c_handler(int)
|
||||
#else
|
||||
static BOOL WINAPI ctrl_c_handler(DWORD event)
|
||||
#endif
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
if (event == CTRL_C_EVENT) {
|
||||
#endif
|
||||
if (lmp)
|
||||
if (lammps_is_running(lmp)) lammps_force_timeout(lmp);
|
||||
#if defined(_WIN32)
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
static char *cmd_generator(const char *text, int state)
|
||||
{
|
||||
static std::size_t idx, len;
|
||||
if (!state) idx = 0;
|
||||
len = strlen(text);
|
||||
|
||||
do {
|
||||
if ((len == 0) || (commands[idx].substr(0, len) == text))
|
||||
return dupstring(commands[idx++]);
|
||||
else
|
||||
++idx;
|
||||
} while (idx < commands.size());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static char *compute_id_generator(const char *text, int state)
|
||||
{
|
||||
return id_generator<COMPUTE_ID>(text, state);
|
||||
}
|
||||
|
||||
static char *compute_ref_generator(const char *text, int state)
|
||||
{
|
||||
return ref_generator<COMPUTE_ID, 'c'>(text, state);
|
||||
}
|
||||
|
||||
static char *dump_id_generator(const char *text, int state)
|
||||
{
|
||||
return id_generator<DUMP_ID>(text, state);
|
||||
}
|
||||
|
||||
static char *fix_id_generator(const char *text, int state)
|
||||
{
|
||||
return id_generator<FIX_ID>(text, state);
|
||||
}
|
||||
|
||||
static char *fix_ref_generator(const char *text, int state)
|
||||
{
|
||||
return ref_generator<FIX_ID, 'f'>(text, state);
|
||||
}
|
||||
|
||||
static char *variable_ref_generator(const char *text, int state)
|
||||
{
|
||||
return ref_generator<VARIABLE_ID, 'v'>(text, state);
|
||||
}
|
||||
|
||||
static char *variable_expand_generator(const char *text, int state)
|
||||
{
|
||||
if (strncmp(text, "${", 2) == 0) {
|
||||
char *id = id_generator<VARIABLE_ID>(text + 2, state);
|
||||
char *ref = nullptr;
|
||||
if (id) {
|
||||
ref = (char *)malloc(strlen(id) + 4);
|
||||
if (ref) {
|
||||
ref[0] = '$';
|
||||
ref[1] = '{';
|
||||
ref[2] = 0;
|
||||
strcat(ref, id);
|
||||
strcat(ref, "}");
|
||||
}
|
||||
free(id);
|
||||
}
|
||||
return ref;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static char *atom_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<ATOM_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *integrate_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<INTEGRATE_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *minimize_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<MINIMIZE_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *pair_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<PAIR_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *bond_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<BOND_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *angle_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<ANGLE_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *dihedral_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<DIHEDRAL_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *improper_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<IMPROPER_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *kspace_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<KSPACE_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *fix_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<FIX_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *compute_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<COMPUTE_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *region_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<REGION_STYLE>(text, state);
|
||||
}
|
||||
|
||||
static char *dump_generator(const char *text, int state)
|
||||
{
|
||||
return style_generator<DUMP_STYLE>(text, state);
|
||||
}
|
||||
|
||||
char *group_generator(const char *text, int state)
|
||||
{
|
||||
static int idx, num, len;
|
||||
if (!state) {
|
||||
idx = 0;
|
||||
num = lammps_id_count(lmp, "group");
|
||||
len = strlen(text);
|
||||
}
|
||||
|
||||
while (idx < num) {
|
||||
lammps_id_name(lmp, "group", idx, buf, buflen);
|
||||
++idx;
|
||||
if ((len == 0) || (strncmp(text, buf, len) == 0)) return dupstring(buf);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static char **cmd_completion(const char *text, int start, int)
|
||||
{
|
||||
char **matches = nullptr;
|
||||
|
||||
// avoid segfaults
|
||||
if (strlen(text) == 0) return matches;
|
||||
|
||||
if (start == 0) {
|
||||
// match command names from the beginning of a line
|
||||
matches = rl_completion_matches(text, cmd_generator);
|
||||
} else {
|
||||
// try to provide context specific matches
|
||||
// first split the already completed text into words for position specific expansion
|
||||
auto words = utils::split_words(std::string(rl_line_buffer).substr(0, start));
|
||||
|
||||
if (strncmp(text, "c_", 2) == 0) { // expand references to computes or fixes
|
||||
matches = rl_completion_matches(text, compute_ref_generator);
|
||||
} else if (strncmp(text, "f_", 2) == 0) {
|
||||
matches = rl_completion_matches(text, fix_ref_generator);
|
||||
} else if (strncmp(text, "v_", 2) == 0) {
|
||||
matches = rl_completion_matches(text, variable_ref_generator);
|
||||
} else if (strncmp(text, "${", 2) == 0) {
|
||||
matches = rl_completion_matches(text, variable_expand_generator);
|
||||
} else if (words.size() == 1) { // expand second word
|
||||
if (words[0] == "atom_style") {
|
||||
matches = rl_completion_matches(text, atom_generator);
|
||||
} else if (words[0] == "pair_style") {
|
||||
matches = rl_completion_matches(text, pair_generator);
|
||||
} else if (words[0] == "bond_style") {
|
||||
matches = rl_completion_matches(text, bond_generator);
|
||||
} else if (words[0] == "angle_style") {
|
||||
matches = rl_completion_matches(text, angle_generator);
|
||||
} else if (words[0] == "dihedral_style") {
|
||||
matches = rl_completion_matches(text, dihedral_generator);
|
||||
} else if (words[0] == "improper_style") {
|
||||
matches = rl_completion_matches(text, improper_generator);
|
||||
} else if (words[0] == "kspace_style") {
|
||||
matches = rl_completion_matches(text, kspace_generator);
|
||||
} else if (words[0] == "run_style") {
|
||||
matches = rl_completion_matches(text, integrate_generator);
|
||||
} else if (words[0] == "min_style") {
|
||||
matches = rl_completion_matches(text, minimize_generator);
|
||||
} else if (words[0] == "compute_modify") {
|
||||
matches = rl_completion_matches(text, compute_id_generator);
|
||||
} else if (words[0] == "dump_modify") {
|
||||
matches = rl_completion_matches(text, dump_id_generator);
|
||||
} else if (words[0] == "fix_modify") {
|
||||
matches = rl_completion_matches(text, fix_id_generator);
|
||||
}
|
||||
} else if (words.size() == 2) { // expand third word
|
||||
|
||||
// these commands have a group name as 3rd word
|
||||
if ((words[0] == "fix") || (words[0] == "compute") || (words[0] == "dump")) {
|
||||
matches = rl_completion_matches(text, group_generator);
|
||||
} else if (words[0] == "region") {
|
||||
matches = rl_completion_matches(text, region_generator);
|
||||
}
|
||||
} else if (words.size() == 3) { // expand fourth word
|
||||
|
||||
// style name is the fourth word
|
||||
if (words[0] == "fix") {
|
||||
matches = rl_completion_matches(text, fix_generator);
|
||||
} else if (words[0] == "compute") {
|
||||
matches = rl_completion_matches(text, compute_generator);
|
||||
} else if (words[0] == "dump") {
|
||||
matches = rl_completion_matches(text, dump_generator);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
} // end of extern "C"
|
||||
|
||||
static void init_commands()
|
||||
{
|
||||
// store internal commands
|
||||
int ncmds = sizeof(cmdlist) / sizeof(const char *);
|
||||
for (int i = 0; i < ncmds; ++i)
|
||||
commands.push_back(cmdlist[i]);
|
||||
|
||||
// store optional commands from command styles
|
||||
ncmds = lammps_style_count(lmp, "command");
|
||||
for (int i = 0; i < ncmds; ++i) {
|
||||
if (lammps_style_name(lmp, "command", i, buf, buflen)) commands.push_back(buf);
|
||||
}
|
||||
|
||||
// store LAMMPS shell specific command names
|
||||
commands.push_back("help");
|
||||
commands.push_back("exit");
|
||||
commands.push_back("history");
|
||||
commands.push_back("clear_history");
|
||||
|
||||
// set name so there can be specific entries in ~/.inputrc
|
||||
rl_readline_name = "lammps-shell";
|
||||
rl_basic_word_break_characters = " \t\n\"\\'`@><=;|&(";
|
||||
|
||||
// attempt completions only if we are connected to a tty,
|
||||
// otherwise any tabs in redirected input will cause havoc.
|
||||
if (isatty(fileno(stdin))) {
|
||||
rl_attempted_completion_function = cmd_completion;
|
||||
} else {
|
||||
rl_bind_key('\t', rl_insert);
|
||||
}
|
||||
|
||||
// read old history
|
||||
read_history(".lammps_history");
|
||||
|
||||
#if !defined(_WIN32)
|
||||
signal(SIGINT, ctrl_c_handler);
|
||||
#else
|
||||
SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static int help_cmd()
|
||||
{
|
||||
std::cout << "\nThis is the LAMMPS Shell. An interactive LAMMPS session with command \n"
|
||||
"line editing, context aware command expansion, and history.\n\n"
|
||||
"- Hit the TAB key any time to try to expand the current word\n"
|
||||
"- Issue shell commands by prefixing them with '|' (Example: '|ls -la')\n"
|
||||
"- Use the '!' character for bash-like history epansion. (Example: '!run)\n\n"
|
||||
"A history of the session will be written to the a file '.lammps_history'\n"
|
||||
"in the current working directory and - if present - this file will be\n"
|
||||
"read at the beginning of the next session of the LAMMPS shell.\n\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_end()
|
||||
{
|
||||
write_history(".lammps_history");
|
||||
if (lmp) lammps_close(lmp);
|
||||
lammps_mpi_finalize();
|
||||
lmp = nullptr;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int shell_cmd(const std::string &cmd)
|
||||
{
|
||||
char *expansion;
|
||||
char *text = dupstring(cmd);
|
||||
int retval = history_expand(text, &expansion);
|
||||
|
||||
// history expansion error
|
||||
if (retval < 0) {
|
||||
free(text);
|
||||
free(expansion);
|
||||
std::cout << "History error: " << utils::getsyserror() << "\n";
|
||||
return 1;
|
||||
}
|
||||
|
||||
// use expanded or original text and add to history
|
||||
if (retval > 0) {
|
||||
free(text);
|
||||
text = expansion;
|
||||
} else
|
||||
free(expansion);
|
||||
|
||||
add_history(text);
|
||||
|
||||
// only print, don't execute.
|
||||
if (retval == 2) {
|
||||
std::cout << text << "\n";
|
||||
free(text);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// check for commands particular to lammps-shell
|
||||
auto words = utils::split_words(text);
|
||||
if (words[0][0] == '|') {
|
||||
int rv = system(text + 1);
|
||||
free(text);
|
||||
return rv;
|
||||
} else if ((words[0] == "help") || (words[0] == "?")) {
|
||||
free(text);
|
||||
return help_cmd();
|
||||
} else if (words[0] == "exit") {
|
||||
free(text);
|
||||
return shell_end();
|
||||
} else if (words[0] == "history") {
|
||||
free(text);
|
||||
HIST_ENTRY **list = history_list();
|
||||
for (int i = 0; i < history_length; ++i) {
|
||||
std::cout << i + history_base << ": " << list[i]->line << "\n";
|
||||
}
|
||||
return 0;
|
||||
} else if (words[0] == "clear_history") {
|
||||
free(text);
|
||||
clear_history();
|
||||
return 0;
|
||||
}
|
||||
|
||||
lammps_command(lmp, text);
|
||||
free(text);
|
||||
return lammps_has_error(lmp);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char *line;
|
||||
std::string trimmed;
|
||||
|
||||
std::cout << "LAMMPS Shell version 1.0\n";
|
||||
if (!lammps_config_has_exceptions())
|
||||
std::cout << "WARNING: LAMMPS was compiled without exceptions\n"
|
||||
"WARNING: The shell will terminate on errors.\n";
|
||||
|
||||
lmp = lammps_open_no_mpi(argc, argv, nullptr);
|
||||
if (lmp == nullptr) return 1;
|
||||
|
||||
using_history();
|
||||
init_commands();
|
||||
|
||||
// pre-load an input file that was provided on the command line
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if ((strcmp(argv[i], "-in") == 0) || (strcmp(argv[i], "-i") == 0)) {
|
||||
lammps_file(lmp, argv[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
while (lmp != nullptr) {
|
||||
line = readline("LAMMPS Shell> ");
|
||||
if (!line) break;
|
||||
trimmed = utils::trim(line);
|
||||
if (trimmed.size() > 0) {
|
||||
shell_cmd(trimmed);
|
||||
}
|
||||
free(line);
|
||||
}
|
||||
|
||||
return shell_end();
|
||||
}
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "lammps.h"
|
||||
#include "library.h"
|
||||
#include "timer.h"
|
||||
#include <string>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
@ -34,7 +35,11 @@ protected:
|
||||
int argc = sizeof(args) / sizeof(char *);
|
||||
|
||||
::testing::internal::CaptureStdout();
|
||||
lmp = lammps_open_no_mpi(argc, argv, NULL);
|
||||
lmp = lammps_open_no_mpi(argc, argv, NULL);
|
||||
lammps_command(lmp, "fix charge all property/atom q ghost yes");
|
||||
lammps_command(lmp, "region box block 0 1 0 1 0 1");
|
||||
lammps_command(lmp, "create_box 1 box");
|
||||
lammps_command(lmp, "group none empty");
|
||||
std::string output = ::testing::internal::GetCapturedStdout();
|
||||
if (verbose) std::cout << output;
|
||||
EXPECT_THAT(output, StartsWith("LAMMPS ("));
|
||||
@ -118,6 +123,76 @@ TEST_F(LibraryConfig, style_name)
|
||||
EXPECT_THAT(buf, StrEq(""));
|
||||
};
|
||||
|
||||
TEST_F(LibraryConfig, has_id)
|
||||
{
|
||||
EXPECT_EQ(lammps_has_id(lmp, "compute", "thermo_temp"), 1);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "compute", "thermo_press"), 1);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "compute", "thermo_pe"), 1);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "dump", "xxx"), 0);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "fix", "charge"), 1);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "fix", "xxx"), 0);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "group", "all"), 1);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "group", "none"), 1);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "group", "xxx"), 0);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "molecule", "xxx"), 0);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "region", "box"), 1);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "region", "xxx"), 0);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "variable", "input_dir"), 1);
|
||||
EXPECT_EQ(lammps_has_id(lmp, "variable", "xxx"), 0);
|
||||
};
|
||||
|
||||
TEST_F(LibraryConfig, id_count)
|
||||
{
|
||||
EXPECT_EQ(lammps_id_count(lmp, "compute"), 3);
|
||||
EXPECT_EQ(lammps_id_count(lmp, "dump"), 0);
|
||||
EXPECT_EQ(lammps_id_count(lmp, "fix"), 1);
|
||||
EXPECT_EQ(lammps_id_count(lmp, "group"), 2);
|
||||
EXPECT_EQ(lammps_id_count(lmp, "molecule"), 0);
|
||||
EXPECT_EQ(lammps_id_count(lmp, "region"), 1);
|
||||
EXPECT_EQ(lammps_id_count(lmp, "variable"), 1);
|
||||
};
|
||||
|
||||
TEST_F(LibraryConfig, id_name)
|
||||
{
|
||||
const int bufsize = 128;
|
||||
char buf[bufsize];
|
||||
EXPECT_EQ(lammps_id_name(lmp, "compute", 2, buf, bufsize), 1);
|
||||
EXPECT_THAT(buf, StrEq("thermo_pe"));
|
||||
EXPECT_EQ(lammps_id_name(lmp, "compute", 10, buf, bufsize), 0);
|
||||
EXPECT_THAT(buf, StrEq(""));
|
||||
EXPECT_EQ(lammps_id_name(lmp, "fix", 0, buf, bufsize), 1);
|
||||
EXPECT_THAT(buf, StrEq("charge"));
|
||||
EXPECT_EQ(lammps_id_name(lmp, "fix", 10, buf, bufsize), 0);
|
||||
EXPECT_THAT(buf, StrEq(""));
|
||||
EXPECT_EQ(lammps_id_name(lmp, "group", 0, buf, bufsize), 1);
|
||||
EXPECT_THAT(buf, StrEq("all"));
|
||||
EXPECT_EQ(lammps_id_name(lmp, "group", 1, buf, bufsize), 1);
|
||||
EXPECT_THAT(buf, StrEq("none"));
|
||||
EXPECT_EQ(lammps_id_name(lmp, "group", 10, buf, bufsize), 0);
|
||||
EXPECT_THAT(buf, StrEq(""));
|
||||
EXPECT_EQ(lammps_id_name(lmp, "region", 0, buf, bufsize), 1);
|
||||
EXPECT_THAT(buf, StrEq("box"));
|
||||
EXPECT_EQ(lammps_id_name(lmp, "region", 10, buf, bufsize), 0);
|
||||
EXPECT_THAT(buf, StrEq(""));
|
||||
EXPECT_EQ(lammps_id_name(lmp, "variable", 0, buf, bufsize), 1);
|
||||
EXPECT_THAT(buf, StrEq("input_dir"));
|
||||
EXPECT_EQ(lammps_id_name(lmp, "variable", 10, buf, bufsize), 0);
|
||||
EXPECT_THAT(buf, StrEq(""));
|
||||
};
|
||||
|
||||
TEST_F(LibraryConfig, is_running)
|
||||
{
|
||||
EXPECT_EQ(lammps_is_running(lmp), 0);
|
||||
}
|
||||
|
||||
TEST_F(LibraryConfig, force_timeout)
|
||||
{
|
||||
LAMMPS_NS::Timer *timer = ((LAMMPS_NS::LAMMPS *)lmp)->timer;
|
||||
EXPECT_EQ(timer->is_timeout(), false);
|
||||
lammps_force_timeout(lmp);
|
||||
EXPECT_EQ(timer->is_timeout(), true);
|
||||
}
|
||||
|
||||
TEST(LAMMPSConfig, exceptions)
|
||||
{
|
||||
EXPECT_EQ(lammps_config_has_exceptions(), LAMMPS_HAS_EXCEPTIONS);
|
||||
|
||||
Reference in New Issue
Block a user