Remove lammps-shell tool as it has been superseded by LAMMPS-GUI
@ -198,7 +198,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
|
||||
@ -1049,9 +1048,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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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.
|
||||
|
||||
----------
|
||||
|
||||
|
||||
@ -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>`
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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``
|
||||
|
||||
@ -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
|
||||
|
||||
@ -92,7 +92,6 @@ Miscellaneous tools
|
||||
* :ref:`emacs <emacs>`
|
||||
* :ref:`i-PI <ipi>`
|
||||
* :ref:`kate <kate>`
|
||||
* :ref:`LAMMPS shell <lammps_shell>`
|
||||
* :ref:`LAMMPS GUI <lammps_gui>`
|
||||
* :ref:`LAMMPS magic patterns for file(1) <magic>`
|
||||
* :ref:`Offline build tool <offline>`
|
||||
@ -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
|
||||
|
||||
@ -5783,7 +5783,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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -1 +0,0 @@
|
||||
../../unittest/.clang-format
|
||||
1
tools/lammps-shell/.gitignore
vendored
@ -1 +0,0 @@
|
||||
/lammps-shell
|
||||
@ -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
|
||||
@ -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.
|
||||
|
||||
|
Before Width: | Height: | Size: 39 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 204 KiB |
|
Before Width: | Height: | Size: 186 KiB |
@ -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();
|
||||
}
|
||||
@ -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
|
||||
@ -1,2 +0,0 @@
|
||||
id1 ICON icons/lammps.ico
|
||||
id2 ICON icons/lmpfile.ico
|
||||
@ -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
|
||||
|
||||
@ -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()
|
||||
@ -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()
|
||||