Merge remote-tracking branch 'github/develop' into collected-small-fixes

# Conflicts:
#	doc/src/Tools.rst
This commit is contained in:
Axel Kohlmeyer
2024-07-23 17:04:36 -04:00
28 changed files with 32 additions and 1460 deletions

View File

@ -214,7 +214,6 @@ set(LAMMPS_BINARY lmp${LAMMPS_MACHINE})
option(BUILD_SHARED_LIBS "Build shared library" OFF)
option(CMAKE_POSITION_INDEPENDENT_CODE "Create object compatible with shared libraries" ON)
option(BUILD_TOOLS "Build and install LAMMPS tools (msi2lmp, binary2txt, chain)" OFF)
option(BUILD_LAMMPS_SHELL "Build and install the LAMMPS shell" OFF)
option(BUILD_LAMMPS_GUI "Build and install the LAMMPS GUI" OFF)
# Support using clang-tidy for C++ files with selected options
@ -1065,9 +1064,6 @@ endif()
if(BUILD_TOOLS)
message(STATUS "<<< Building Tools >>>")
endif()
if(BUILD_LAMMPS_SHELL)
message(STATUS "<<< Building LAMMPS Shell >>>")
endif()
if(BUILD_LAMMPS_GUI)
message(STATUS "<<< Building LAMMPS GUI >>>")
if(LAMMPS_GUI_USE_PLUGIN)

View File

@ -37,37 +37,6 @@ if(BUILD_TOOLS)
add_subdirectory(${LAMMPS_TOOLS_DIR}/phonon ${CMAKE_BINARY_DIR}/phana_build)
endif()
find_package(PkgConfig QUIET)
if(BUILD_LAMMPS_SHELL)
if(NOT PkgConfig_FOUND)
message(FATAL_ERROR "Must have pkg-config installed for building LAMMPS shell")
endif()
find_package(PkgConfig REQUIRED)
pkg_check_modules(READLINE IMPORTED_TARGET REQUIRED readline)
# include resource compiler to embed icons into the executable on Windows
if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
enable_language(RC)
set(ICON_RC_FILE ${LAMMPS_TOOLS_DIR}/lammps-shell/lmpicons.rc)
endif()
add_executable(lammps-shell ${LAMMPS_TOOLS_DIR}/lammps-shell/lammps-shell.cpp ${ICON_RC_FILE})
target_include_directories(lammps-shell PRIVATE ${LAMMPS_TOOLS_DIR}/lammps-shell)
target_link_libraries(lammps-shell PRIVATE lammps PkgConfig::READLINE)
# workaround for broken readline pkg-config file on FreeBSD
if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD")
target_include_directories(lammps-shell PRIVATE /usr/local/include)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "LinuxMUSL")
pkg_check_modules(TERMCAP IMPORTED_TARGET REQUIRED termcap)
target_link_libraries(lammps-shell PRIVATE lammps PkgConfig::TERMCAP)
endif()
install(TARGETS lammps-shell EXPORT LAMMPS_Targets DESTINATION ${CMAKE_INSTALL_BINDIR})
install(DIRECTORY ${LAMMPS_TOOLS_DIR}/lammps-shell/icons DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/)
install(FILES ${LAMMPS_TOOLS_DIR}/lammps-shell/lammps-shell.desktop DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/applications/)
endif()
if(BUILD_LAMMPS_GUI)
get_filename_component(LAMMPS_GUI_DIR ${LAMMPS_SOURCE_DIR}/../tools/lammps-gui ABSOLUTE)
get_filename_component(LAMMPS_GUI_BIN ${CMAKE_BINARY_DIR}/lammps-gui-build ABSOLUTE)

View File

@ -489,8 +489,7 @@ using CMake or Make.
.. code-block:: bash
-D BUILD_TOOLS=value # yes or no (default). Build binary2txt, chain.x, micelle2d.x, msi2lmp, phana, stl_bin2txt
-D BUILD_LAMMPS_SHELL=value # yes or no (default). Build lammps-shell
-D BUILD_LAMMPS_GUI=value # yes or no (default). Build lammps-gui
-D BUILD_LAMMPS_GUI=value # yes or no (default). Build LAMMPS-GUI
The generated binaries will also become part of the LAMMPS installation
(see below).
@ -505,8 +504,9 @@ using CMake or Make.
make chain # build only chain tool
make micelle2d # build only micelle2d tool
cd lammps/tools/lammps-shell
make # build LAMMPS shell
.. note::
Building the LAMMPS-GUI *requires* building LAMMPS with CMake.
----------

View File

@ -8,6 +8,18 @@ stop LAMMPS and print a suitable error message in most cases, when a
style/command is used that has been removed or will replace the command
with the direct alternative (if available) and print a warning.
restart2data tool
-----------------
.. versionchanged:: 23Nov2013
The functionality of the restart2data tool has been folded into the
LAMMPS executable directly instead of having a separate tool. A
combination of the commands :doc:`read_restart <read_restart>` and
:doc:`write_data <write_data>` can be used to the same effect. For
added convenience this conversion can also be triggered by
:doc:`command line flags <Run_options>`
Fix ave/spatial and fix ave/spatial/sphere
------------------------------------------
@ -151,17 +163,16 @@ and allow running LAMMPS with GPU acceleration.
i-PI tool
---------
.. versionchanged:: 27June2024
.. versionchanged:: 27Jun2024
The i-PI tool has been removed from the LAMMPS distribution. Instead,
instructions to install i-PI from PyPI via pip are provided.
restart2data tool
-----------------
LAMMPS shell
------------
.. versionchanged:: TBD
The LAMMPS shell has been removed from the LAMMPS distribution. Users
are encouraged to use the :ref:`LAMMPS-GUI <lammps_gui>` tool instead.
The functionality of the restart2data tool has been folded into the
LAMMPS executable directly instead of having a separate tool. A
combination of the commands :doc:`read_restart <read_restart>` and
:doc:`write_data <write_data>` can be used to the same effect. For
added convenience this conversion can also be triggered by
:doc:`command line flags <Run_options>`

View File

@ -2327,7 +2327,7 @@ Procedures Bound to the :f:type:`lammps` Derived Type
retrieved via :f:func:`get_last_error_message`. This allows to
restart a calculation or delete and recreate the LAMMPS instance when
a C++ exception occurs. One application of using exceptions this way
is the :ref:`lammps_shell`.
is the :ref:`lammps_gui`.
:to: :cpp:func:`lammps_config_has_exceptions`
:r has_exceptions:

View File

@ -339,8 +339,6 @@ 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``

View File

@ -35,11 +35,11 @@ packages listed below), they do not depend on any installed software and
thus should run on *any* 64-bit x86 machine with *any* Linux version.
These executable include most of the available packages and multi-thread
parallelization (via INTEL, KOKKOS, or OPENMP package). They are **not**
compatible with MPI. Several of the LAMMPS tools executables (e.g. ``msi2lmp``)
and the ``lammps-shell`` program are included as well. Because of the
static linkage, there is no ``liblammps.so`` library file and thus also the
LAMMPS python module, which depends on it, is not included.
parallelization (via INTEL, KOKKOS, or OPENMP package). They are
**not** compatible with MPI. Several of the LAMMPS tools executables
(e.g. ``msi2lmp``) are included as well. Because of the static linkage,
there is no ``liblammps.so`` library file and thus also the LAMMPS
python module, which depends on it, is not included.
The compressed tar archives available for download have names following
the pattern ``lammps-linux-x86_64-<version>.tar.gz`` and will all unpack

View File

@ -92,8 +92,7 @@ Miscellaneous tools
* :ref:`emacs <emacs>`
* :ref:`i-PI <ipi>`
* :ref:`kate <kate>`
* :ref:`LAMMPS shell <lammps_shell>`
* :ref:`LAMMPS-GUI <lammps_gui>`
* :ref:`LAMMPS GUI <lammps_gui>`
* :ref:`LAMMPS magic patterns for file(1) <magic>`
* :ref:`Offline build tool <offline>`
* :ref:`singularity/apptainer <singularity_tool>`
@ -444,216 +443,6 @@ The file was provided by Alessandro Luigi Sellerio
----------
.. _lammps_shell:
LAMMPS shell
------------
.. versionadded:: 9Oct2020
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 :doc:`timer command <timer>`
documentation).
These enhancements make the LAMMPS shell an attractive choice for
interactive LAMMPS sessions in graphical desktop environments
(e.g. Gnome, KDE, Cinnamon, XFCE, Windows).
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
be to known compute/fix IDs and variable names. Variable name
expansion is also available for the ${name} variable syntax.
- In all other cases TAB expansion will complete to names of files
and directories.
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:
https://www.gnu.org/software/readline/
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
save_history <range> <file>
write commands from the history to file.
The range is given as <from>-<to>, where <from> and <to>
may be empty. Example: save_history 100- in.recent
source <file> read commands from file (same as "include")
pwd print current working directory
cd <directory> change current working directory (same as pwd if no directory)
mem print current and maximum memory usage
\|<command> execute <command> as a shell command and return to the command prompt
exit exit the LAMMPS shell cleanly (unlike the "quit" command)
Please note that some known shell operations are implemented in the
LAMMPS :doc:`shell command <shell>` in a platform neutral fashion,
while using the '\|' character will always pass the following text
to the operating system's shell 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``.
Readline customization
^^^^^^^^^^^^^^^^^^^^^^
The behavior of the readline functionality can be customized in the
``${HOME}/.inputrc`` file. This can be used to alter the default
settings or change the key-bindings. The LAMMPS Shell sets the
application name ``lammps-shell``, so settings can be either applied
globally or only for the LAMMPS shell by bracketing them between
``$if lammps-shell`` and ``$endif`` like in the following example:
.. code-block:: bash
$if lammps-shell
# disable "beep" or "screen flash"
set bell-style none
# bind the "Insert" key to toggle overwrite mode
"\e[2~": overwrite-mode
$endif
More details about this are in the `readline documentation <https://tiswww.cwru.edu/php/chet/readline/rluserman.html#SEC9>`_.
LAMMPS Shell tips and tricks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Below are some suggestions for how to use and customize the LAMMPS shell.
Enable tilde expansion
""""""""""""""""""""""
Adding ``set expand-tilde on`` to ``${HOME}/.inputrc`` is recommended as
this will change the filename expansion behavior to replace any text
starting with "~" by the full path to the corresponding user's home
directory. While the expansion of filenames **will** happen on all
arguments where the context is not known (e.g. ``~/compile/lamm<TAB>``
will expand to ``~/compile/lammps/``), it will not replace the tilde by
default. But since LAMMPS does not do tilde expansion itself (unlike a
shell), this will result in errors. Instead the tilde-expression should
be expanded into a valid path, where the plain "~/" stands for the
current user's home directory and "~someuser/" stands for
"/home/someuser" or whatever the full path to that user's home directory
is.
File extension association
""""""""""""""""""""""""""
Since the LAMMPS shell (unlike the regular LAMMPS executable) does not
exit when an input file is passed on the command line with the "-in" or
"-i" flag (the behavior is like for ``python -i <filename>``), it makes
the LAMMPS shell suitable for associating it with input files based on
their filename extension (e.g. ".lmp"). Since ``lammps-shell`` is a
console application, you have to run it inside a terminal program with a
command line like this:
.. code-block:: bash
xterm -title "LAMMPS Shell" -e /path/to/lammps-shell -i in.file.lmp
Use history to create an input file
"""""""""""""""""""""""""""""""""""
When experimenting with commands to interactively to figure out a
suitable choice of settings or simply the correct syntax, you may want
to record part of your commands to a file for later use. This can be
done with the ``save_history`` commands, which allows to selectively
write a section of the command history to a file (Example:
``save_history 25-30 in.run``). This file can be further edited
(Example: ``|vim in.run``) and then the file read back in and tried out
(Example: ``source in.run``). If the input also creates a system box,
you first need to use the :doc:`clear` command.
----------
.. _lammps_gui:
LAMMPS-GUI

View File

@ -5847,7 +5847,7 @@ error status can then be checked by calling
can be retrieved via :cpp:func:`lammps_get_last_error_message`.
This can allow to restart a calculation or delete and recreate
the LAMMPS instance when C++ exceptions are enabled. One application
of using exceptions this way is the :ref:`lammps_shell`. If C++
of using exceptions this way is the :ref:`lammps_gui`. If C++
exceptions are disabled and an error happens during a call to
LAMMPS, the application will terminate.
\endverbatim

View File

@ -28,7 +28,6 @@ fep scripts for free-energy perturbation with 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
magic patterns to detect LAMMPS files with the file(1) command

View File

@ -1 +0,0 @@
../../unittest/.clang-format

View File

@ -1 +0,0 @@
/lammps-shell

View File

@ -1,17 +0,0 @@
SHELL=/bin/sh
CXX=g++ -std=c++11
#CXX=g++
CXXFLAGS=-O -g -Wall -I../../src $(shell pkg-config --cflags readline)
#CXXFLAGS=-O -g -Wall -I../../src
LDFLAGS= -L../../src -Wl,-rpath,../../src -llammps $(shell pkg-config --libs readline)
#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 log.lammps log.cite

View File

@ -1,175 +0,0 @@
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 TAB expansion will complete to names of files
and directories.
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
- save_history <range> <file>
write commands from the history to file.
The range is given as <from>-<to>, where <from> and <to>
may be empty. Example: save_history 100- in.recent
- source <file> read commands from file (same as "include")
- pwd print current working directory
- cd <directory> change current working directory (same as pwd if no directory)
- mem print current and maximum memory usage
- |<command> execute <command> as a shell command and return to the command prompt
- exit exit the LAMMPS shell cleanly (unlike the "quit" command)
Please note that some known shell operations are implemented in the
LAMMPS "shell" command in a platform neutral fashion, while using
the '\|' character will always pass the following text to the
operating system's shell 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".
Readline customization
^^^^^^^^^^^^^^^^^^^^^^
The behavior of the readline functionality can be customized in the
"${HOME}/.inputrc" file. This can be used to alter the default
settings or change the key-bindings. The LAMMPS Shell sets the
application name "lammps-shell", so customizations can be either
global or specific for the LAMMPS shell by bracketing them between
"$if lammps-shell" and "$endif" like in the following example:
$if lammps-shell
# disable "beep" or "screen flash"
set bell-style none
# bind the "Insert" key to toggle overwrite mode
"\e[2~": overwrite-mode
$endif
More details about this are in the readline documentation https://tiswww.cwru.edu/php/chet/readline/rluserman.html#SEC9
LAMMPS Shell tips and tricks
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Enable tilde expansion
""""""""""""""""""""""
Adding "set expand-tilde on" to "${HOME}/.inputrc" is recommended as
this will change the filename expansion behavior to replace any text
starting with "~" by the full path to the corresponding user's home
directory. While the expansion of filenames **will** happen on all
arguments where the context is not known (e.g. "~/compile/lamm<TAB>"
will expand to "~/compile/lammps/"), it will not replace the tilde by
default. But since LAMMPS does not do tilde expansion itself (unlike a
shell), this will result in errors. Instead the tilde-expression should
be expanded into a valid path, where the plain "~/" stands for the
current user's home directory and "~someuser/" stands for
"/home/someuser" or whatever the full path to that user's home directory
is.
File extension association
""""""""""""""""""""""""""
The LAMMPS shell (unlike the regular LAMMPS executable) does not
exit when an input file is passed on the command line, which can be
either with the "-in" or "-i" flag (the behavior is like for
"python -i <filename>") or as the first argument without a flag.
Thus the LAMMPS shell is suitable for associating it with input files
based on their filename extension (e.g. ".lmp"). Since "lammps-shell"
is a console application, you have to run it inside a terminal program.
A "lammps-shell.desktop" and suitable icon files are provided, so that
it can be integrated into compatible desktop environments.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 186 KiB

View File

@ -1,811 +0,0 @@
// LAMMPS Shell. An improved interactive LAMMPS session with
// command line editing, history, TAB expansion and shell escapes
// Copyright (c) 2020, 2021 Axel Kohlmeyer <akohlmey@gmail.com>
// This software is distributed under the GNU General Public License.
#include "library.h"
#include "platform.h"
#include "utils.h"
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#if defined(_WIN32)
#if !defined(WIN32_LEAN_AND_MEAN)
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#else
#include <csignal>
#endif
#if defined(_OPENMP)
#include <omp.h>
#endif
#include <readline/history.h>
#include <readline/readline.h>
using namespace LAMMPS_NS;
void *lmp = nullptr;
char *omp_threads = nullptr;
constexpr int BUFLEN = 512;
char buf[BUFLEN];
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 'mycmd ==' src/input.cpp | sed -e 's/^.*mycmd == \(".*"\).*$/\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",
"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",
"labelmap",
"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",
"reset_atoms"};
static char *dupstring(const std::string &text)
{
int len = text.size() + 1;
char *copy = (char *)malloc(len);
strcpy(copy, text.c_str());
return copy;
}
static int save_history(const std::string &range, const std::string &file)
{
int from = history_base;
int to = from + history_length - 1;
if (!range.empty()) {
std::size_t found = range.find_first_of("-");
if (found == std::string::npos) { // only a single number
int num = strtol(range.c_str(), nullptr, 10);
if ((num >= from) && (num <= to)) {
from = to = num;
} else
return 1;
} else { // range of numbers
if (found > 0) { // get number before '-'
int num = strtol(range.substr(0, found).c_str(), nullptr, 10);
if ((num >= from) && (num <= to)) {
from = num;
} else
return 1;
}
if (range.size() > found + 1) { // get number after '-'
int num = strtol(range.substr(found + 1).c_str(), nullptr, 10);
if ((num >= from) && (num <= to)) {
to = num;
} else
return 1;
}
}
std::ofstream out(file, std::ios::out | std::ios::trunc);
if (out.fail()) {
std::cerr << "'" << utils::getsyserror() << "' error when "
<< "trying to open file '" << file << "' for writing.\n";
return 0;
}
out << "# saved LAMMPS Shell history\n";
for (int i = from; i <= to; ++i) {
HIST_ENTRY *item = history_get(i);
if (item == nullptr) {
out.close();
return 1;
}
out << item->line << "\n";
}
out.close();
}
return 0;
}
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 ((idx < commands.size()) && ((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 *plugin_generator(const char *text, int state)
{
const char *subcmd[] = {"load", "unload", "list", "clear", nullptr};
const char *sub;
static std::size_t idx = 0, len;
if (!state) idx = 0;
len = strlen(text);
while ((sub = subcmd[idx]) != nullptr) {
++idx;
if (strncmp(text, sub, len) == 0) return dupstring(sub);
}
return nullptr;
}
static char *plugin_style_generator(const char *text, int state)
{
const char *styles[] = {"pair",
"bond",
"angle",
"dihedral"
"improper",
"kspace",
"compute",
"fix",
"region",
"command",
nullptr};
const char *s;
static std::size_t idx = 0, len;
if (!state) idx = 0;
len = strlen(text);
while ((s = styles[idx]) != nullptr) {
++idx;
if (strncmp(text, s, len) == 0) return dupstring(s);
}
return nullptr;
}
static char *plugin_name_generator(const char *text, int state)
{
auto words = utils::split_words(text);
if (words.size() < 4) return nullptr;
static std::size_t idx, len, nmax;
if (!state) idx = 0;
len = words[3].size();
nmax = lammps_plugin_count();
while (idx < nmax) {
char style[BUFLEN], name[BUFLEN];
lammps_plugin_name(idx, style, name, BUFLEN);
++idx;
if (words[2] == style) {
if (strncmp(name, words[3].c_str(), len) == 0) return dupstring(name);
}
}
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[0] == "plugin") {
matches = rl_completion_matches(text, plugin_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);
// plugin style is the third word
} else if ((words[0] == "plugin") && (words[1] == "unload")) {
matches = rl_completion_matches(text, plugin_style_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);
// plugin name is the fourth word
} else if ((words[0] == "plugin") && (words[1] == "unload")) {
matches = rl_completion_matches(rl_line_buffer, plugin_name_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.emplace_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.emplace_back(buf);
}
// store LAMMPS shell specific command names
commands.emplace_back("help");
commands.emplace_back("exit");
commands.emplace_back("pwd");
commands.emplace_back("cd");
commands.emplace_back("mem");
commands.emplace_back("source");
commands.emplace_back("history");
commands.emplace_back("clear_history");
commands.emplace_back("save_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 or are running tests.
// otherwise any tabs in redirected input will cause havoc.
const char *test_mode = getenv("LAMMPS_SHELL_TESTING");
if (test_mode) std::cout << "*TESTING* using LAMMPS Shell in test mode *TESTING*\n";
if (platform::is_console(stdin) || test_mode) {
rl_attempted_completion_function = cmd_completion;
} else {
rl_bind_key('\t', rl_insert);
}
// read saved history, but not in test mode.
if (!test_mode) read_history(".lammps_history");
// intercept CTRL-C
#if defined(_WIN32)
SetConsoleCtrlHandler(ctrl_c_handler, TRUE);
#else
signal(SIGINT, ctrl_c_handler);
#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"
"Additional information is at https://packages.lammps.org/lammps-shell.html\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] == "source") {
lammps_file(lmp, words[1].c_str());
free(text);
return 0;
} else if ((words[0] == "pwd") || ((words[0] == "cd") && (words.size() == 1))) {
std::cout << platform::current_directory() << "\n";
free(text);
return 0;
} else if (words[0] == "cd") {
std::string shellcmd = "shell ";
shellcmd += text;
lammps_command(lmp, shellcmd.c_str());
free(text);
return 0;
} else if (words[0] == "mem") {
double meminfo[3];
lammps_memory_usage(lmp, meminfo);
std::cout << "Memory usage. Current: " << meminfo[0] << " MByte, "
<< "Maximum : " << meminfo[2] << " MByte\n";
free(text);
return 0;
} 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;
} else if (words[0] == "save_history") {
free(text);
if (words.size() == 3) {
if (save_history(words[1], words[2]) != 0) {
int from = history_base;
int to = from + history_length - 1;
std::cerr << "Range error: min = " << from << " max = " << to << "\n";
return 1;
}
} else {
std::cerr << "Usage: save_history <range> <filename>\n";
return 1;
}
return 0;
}
lammps_command(lmp, text);
free(text);
return lammps_has_error(lmp);
}
int main(int argc, char **argv)
{
char *line;
std::string trimmed;
#if defined(_WIN32)
// Special hack for Windows: if the current working directory is
// the "system folder" (because that is where cmd.exe lives)
// switch to the user's documents directory.
auto curdir = platform::current_directory();
if (utils::strmatch(curdir, "[Ss]ystem32")) {
std::string docdir = getenv("HOMEDRIVE");
docdir += getenv("HOMEPATH");
docdir += "\\Documents";
platform::chdir(docdir);
}
#endif
lammps_get_os_info(buf, BUFLEN);
std::cout << "LAMMPS Shell version 1.2 OS: " << buf;
if (!lammps_config_has_exceptions())
std::cout << "WARNING: LAMMPS was compiled without exceptions\n"
"WARNING: The shell will terminate on errors.\n";
#if defined(_OPENMP)
int nthreads = omp_get_max_threads();
#else
int nthreads = 1;
#endif
// avoid OMP_NUM_THREADS warning and change the default behavior
// to use the maximum number of threads available since this is
// not intended to be run with MPI.
omp_threads = dupstring(std::string("OMP_NUM_THREADS=" + std::to_string(nthreads)));
platform::putenv(omp_threads);
// handle the special case where the first argument is not a flag but a file
// this happens for example when using file type associations on Windows.
// in this case we save the pointer and remove it from argv.
// we also get the directory name and switch to that folder
std::string input_file;
if ((argc > 1) && (argv[1][0] != '-')) {
--argc;
input_file = platform::path_basename(argv[1]);
platform::chdir(platform::path_dirname(input_file));
for (int i = 1; i < argc; ++i)
argv[i] = argv[i + 1];
}
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
if (!input_file.empty()) {
lammps_file(lmp, input_file.c_str());
} else {
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();
}

View File

@ -1,10 +0,0 @@
[Desktop Entry]
Version=1.0
Type=Application
Categories=Science;Engineering;
Exec=/bin/sh -c "echo -e -n \"\033]0;The LAMMPS Shell\007\"; LC_ALL=C lammps-shell %f"
Name=The LAMMPS Shell
Terminal=true
GenericName=MD Simulator
Keywords=MD Simulation;LAMMPS;Molecular Dynamics;N-Body
Icon=lammps

View File

@ -1,2 +0,0 @@
id1 ICON icons/lammps.ico
id2 ICON icons/lmpfile.ico

View File

@ -99,7 +99,6 @@ add_subdirectory(c-library)
add_subdirectory(cplusplus)
add_subdirectory(fortran)
add_subdirectory(python)
add_subdirectory(tools)
add_subdirectory(force-styles)
# clang-format support for test sources

View File

@ -1,21 +0,0 @@
# -*- CMake -*- file for tests of utily functions and classes in LAMMPS
# we use python 3's subprocess module to run the tools and check the output
find_package(Python 3.6 COMPONENTS Interpreter)
get_property(BUILD_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(BUILD_IS_MULTI_CONFIG)
set(LAMMPS_SHELL_EXE_DIR ${CMAKE_BINARY_DIR}/$<CONFIG>)
else()
set(LAMMPS_SHELL_EXE_DIR ${CMAKE_BINARY_DIR})
endif()
if(Python_EXECUTABLE)
if(BUILD_LAMMPS_SHELL)
add_test(NAME LammpsShell
COMMAND ${Python_EXECUTABLE} -u ${CMAKE_CURRENT_SOURCE_DIR}/test_lammps_shell.py -v
WORKING_DIRECTORY ${LAMMPS_SHELL_EXE_DIR})
endif()
else()
message(STATUS "Skipping Tests for LAMMPS tools: no suitable Python interpreter")
endif()

View File

@ -1,151 +0,0 @@
import os, re, subprocess, unittest
# enable test mode
os.putenv('LAMMPS_SHELL_TESTING','1')
shell_prompt_re = r"([^>]*LAMMPS Shell> ([a-z0-9_]+) *([a-z0-9_\.]+)?.*\n)+"
cmd_group_re = r"([^>]*LAMMPS Shell> ([a-z0-9_]+) +([a-z0-9]+) +([a-z0-9]+)? *([a-z/0-9]+)?.*\n)+"
#
class LammpsShell(unittest.TestCase):
def setUp(self):
self.proc = subprocess.Popen('./lammps-shell',
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
def tearDown(self):
self.proc.kill()
def InputRunner(self,text):
"""Test tab expansions"""
try:
[outs,errs] = self.proc.communicate(input=text, timeout=10)
self.timeout = 0
except subprocess.TimeoutExpired:
self.proc.kill()
[outs,errs] = self.proc.communicate()
self.timeout = 1
return outs.decode('UTF-8')
def testExpandClearHistory(self):
"""Test expansion of a shell specific command"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'clear_his\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"clear_history")
def testExpandDimension(self):
"""Test expansion of a LAMMPS command"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'dimens\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"dimension")
def testExpandPairStyle(self):
"""Test expansion of a pair style"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'pair_st\t zer\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"pair_style")
self.assertEqual(matches[0][2],"zero")
def testExpandBondStyle(self):
"""Test expansion of a bond style"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'bond_st\t zer\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"bond_style")
self.assertEqual(matches[0][2],"zero")
def testExpandAngleStyle(self):
"""Test expansion of a angle style"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'angle_st\t zer\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"angle_style")
self.assertEqual(matches[0][2],"zero")
def testExpandDihedralStyle(self):
"""Test expansion of a dihedral style"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'dihedral_st\t zer\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"dihedral_style")
self.assertEqual(matches[0][2],"zero")
def testExpandImproperStyle(self):
"""Test expansion of a improper style"""
matches = re.findall(shell_prompt_re, self.InputRunner(b'improper_st\t zer\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"improper_style")
self.assertEqual(matches[0][2],"zero")
def testExpandComputeGroup(self):
"""Test expansion of a group-ID and a compute command"""
matches = re.findall(cmd_group_re, self.InputRunner(b'compute test al\tstress/at\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"compute")
self.assertEqual(matches[0][2],"test")
self.assertEqual(matches[0][3],"all")
self.assertEqual(matches[0][4],"stress/atom")
def testExpandFixGroup(self):
"""Test expansion of a group-ID and a fix command"""
matches = re.findall(cmd_group_re, self.InputRunner(b'fix test al\tpropert\t\n'), re.MULTILINE)
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"fix")
self.assertEqual(matches[0][2],"test")
self.assertEqual(matches[0][3],"all")
self.assertEqual(matches[0][4],"property/atom")
def testExpandSource(self):
"""Test expansion of a shell command and a file name"""
with open('.tmp.in.source', 'w') as out:
print('units real', file=out)
out.close()
matches = re.findall(shell_prompt_re, self.InputRunner(b'sour\t.tmp.in.sou\t\n'), re.MULTILINE)
os.remove('.tmp.in.source')
if self.timeout:
self.fail("Timeout")
else:
self.assertEqual(matches[0][1],"source")
self.assertEqual(matches[0][2],".tmp.in.source")
def testHistory(self):
"""Test history expansion"""
out = self.InputRunner(b'clear_history\nunits real\ndimension 2\n!!:p\n!-3:p\n!dim:p\n!uni:p\nprint !!:$\nprint !dim:1\n')
idx = 0
if self.timeout:
self.fail("Timeout")
else:
lines = out.splitlines()
for line in lines:
if line.startswith('LAMMPS Shell>'): break
idx += 1
self.assertEqual(lines[idx+4],"dimension 2")
self.assertEqual(lines[idx+6],"units real")
self.assertEqual(lines[idx+8],"dimension 2")
self.assertEqual(lines[idx+10],"units real")
self.assertEqual(lines[idx+12],"real")
self.assertEqual(lines[idx+14],"2")
###########################
if __name__ == "__main__":
unittest.main()