diff --git a/README.md b/README.md index 55756e5a5..f8363d368 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,9 @@ -i-PI: a Universal Force Engine -============================== +# i-PI: a Universal Force Engine A Python interface for ab initio path integral molecular dynamics simulations (and more). -i-PI is a Python server (that does not need to be compiled and only requires a relatively -recent version of Python and Numpy) that applies an algorithm to update the positions of -the nuclei. One of many compatible external codes acts as client, and computes the +i-PI is a Python server (that does not need to be compiled and only requires a relatively +recent version of Python and Numpy) that applies an algorithm to update the positions of +the nuclei. One of many compatible external codes acts as client, and computes the electronic energy and forces. This is typically a patched version of an electronic structure code, but a @@ -13,17 +12,17 @@ potentials is included for test purposes. i-PI was originally developed to simulate the quantum mechanical nature of light nuclei by performing path integral molecular dynamics simulations, -and it implements most of the state-of-the-art methods to accelerate this kind of -calculations. It has since grown to also provide all sorts of simulation -strategies, from replica exchange to geometry optimization. +and it implements most of the state-of-the-art methods to accelerate this kind of +calculations. It has since grown to also provide all sorts of simulation +strategies, from replica exchange to geometry optimization. If you use i-PI in your research, please cite the accompanying publication: -for version 3, the relevant paper is -[Litman et al., *J. Chem. Phys.* 161, 062504 (2024)](https://doi.org/10.1063/5.0215869) +for version 3, the relevant paper is +[Litman et al., _J. Chem. Phys._ 161, 062504 (2024)](https://doi.org/10.1063/5.0215869) ``` @article{litman2024ipi, -title={i-PI 3.0: a flexible and efficient framework for advanced atomistic simulations}, +title={i-PI 3.0: a flexible and efficient framework for advanced atomistic simulations}, author={Yair Litman and Venkat Kapil and Yotam M. Y. Feldman and Davide Tisi and Tomislav Begušić and Karen Fidanyan and Guillaume Fraux and Jacob Higer and Matthias Kellner and Tao E. Li and Eszter S. Pós and Elia Stocco and George Trenins and Barak Hirshberg and Mariana Rossi and Michele Ceriotti}, journal = {J. Chem. Phys.}, pages = {062505}, @@ -32,8 +31,7 @@ year = {2024} } ``` -Quick Setup ------------ +## Quick Setup To use i-PI with an existing driver, install and update using `pip`: @@ -49,8 +47,11 @@ Last Release: pip install -U ipi ``` -Source installation -------------------- +## Documentation + +You can find the online documentation at [https://docs.ipi-code.org](https://docs.ipi-code.org/). Alternatively, you can build it locally by following instructions in the `docs/README.md` file. + +## Source installation To develop i-PI or test it with the self-contained driver, follow these instructions. It is assumed that i-PI will @@ -63,11 +64,10 @@ git clone https://github.com/i-pi/i-pi.git ``` Source the environment settings file `env.sh` as `source env.sh` or `. -env.sh`. It is useful to put this in your `.bashrc` or other settings file if +env.sh`. It is useful to put this in your `.bashrc` or other settings file if you always want to have i-PI available. - -### Compile the driver code +## Compile the driver code The built-in driver requires a FORTRAN compiler, and can be built as @@ -78,14 +78,14 @@ cd ../.. ``` There is also a Python driver available in `drivers/py`, which however has limited -functionalities. +functionalities. -### Examples and demos +## Examples and demos The `examples` and `demos` folders contain inputs for many different types of calculations based on i-PI. Examples are typically minimal use-cases of specific features, while demos are more structured, tutorial-like examples that show how -to realize more complex setups, and also provide a brief discussion of the +to realize more complex setups, and also provide a brief discussion of the underlying algorithms. To run these examples, you should typically start i-PI, redirecting the output to @@ -93,7 +93,7 @@ a log file, and then run a couple of instances of the driver code. The progress of the wrapper is followed by monitoring the log file with the `tail` Linux command. Optionally, you can make a copy of the directory with the example somewhere -else if you want to keep the i-PI directory clean. For example +else if you want to keep the i-PI directory clean. For example, after sourcing the `env.sh` file, ```bash cd demos/para-h2-tutorial/tutorial-1/ @@ -105,7 +105,12 @@ tail -f log The monitoring can be interrupted with CTRL+C when the run has finished (5000 steps). -### Run the automatic test suite +## Tutorials and online resources + +The i-PI [documentation](https://docs.ipi-code.org/onlinereso.html) has a list of +available tutorials, recipes and other useful online resources. + +## Run the automatic test suite The automatic test suite can be run by calling the i-pi-tests script. You need to have the `pytest` package installed @@ -118,8 +123,7 @@ You may also need to install some dependencies, listed in `requirements.txt`. See more details in the README file inside the `ipi_tests` folder. -Contributing ------------- +## Contributing If you have new features you want to implement into i-PI, your contributions are much welcome. See `CONTRIBUTING.md` for a brief set of style guidelines and best practices. Before embarking diff --git a/bin/i-pi b/bin/i-pi index d26d8c92b..554567dd4 100755 --- a/bin/i-pi +++ b/bin/i-pi @@ -58,7 +58,7 @@ def main(fn_input, options): raise ImportError('Profiling requires the `yappi` package.') # construct simulation based on input file - simulation = Simulation.load_from_xml(fn_input, request_banner=True, custom_verbosity=options.verbosity, sockets_prefix=options.sockets_prefix) + simulation = Simulation.load_from_xml(open(fn_input), request_banner=True, custom_verbosity=options.verbosity, sockets_prefix=options.sockets_prefix) # run the simulation simulation.run() diff --git a/demos/2D-IR-Raman/noneqm-traj.py b/demos/2D-IR-Raman/noneqm-traj.py index 658c945c7..86277f1ab 100755 --- a/demos/2D-IR-Raman/noneqm-traj.py +++ b/demos/2D-IR-Raman/noneqm-traj.py @@ -175,7 +175,7 @@ def main(fn_input, options): tree.write(fn_input_noneqm) simulation = Simulation.load_from_xml( - fn_input_noneqm, request_banner=False, custom_verbosity=options.verbosity + open(fn_input_noneqm), request_banner=False, custom_verbosity=options.verbosity ) spec.run(simulation, options.tfirst, options.tlast) softexit.trigger(status="success", message=" @ SIMULATION: Exiting cleanly.") diff --git a/demos/te-pigs/1_dataset_curation/get_pigs_dataset.py b/demos/te-pigs/1_dataset_curation/get_pigs_dataset.py index be39f7274..63d72e23b 100644 --- a/demos/te-pigs/1_dataset_curation/get_pigs_dataset.py +++ b/demos/te-pigs/1_dataset_curation/get_pigs_dataset.py @@ -11,7 +11,6 @@ iread(centroid_force_filename), iread(physical_force_filename), ): - atoms = a_pos.copy() atoms.arrays["centroid_force"] = a_cforce.arrays["f_centroid"] diff --git a/docs/README b/docs/README.md similarity index 57% rename from docs/README rename to docs/README.md index f0bc71199..d130343b4 100644 --- a/docs/README +++ b/docs/README.md @@ -1,13 +1,12 @@ -i-PI documentation -================== +## i-PI documentation -This folder contains the files needed to build the documentation for i-PI. +This folder contains the files needed to locally build the documentation for i-PI. * `latex/` contains the "legacy" TeX manual, that includes also autogenerated input reference * `scripts/` contains automatic scripts to build the input reference * `src/` contains RST files that are compiled by sphynx into the HTML documentation. -To make the docs, make sure you have all the needed packages in `requirements.txt` installed, and type `make html`. The local documentation will be generated in `_build/html`. +To make the docs, make sure you have all the needed packages in `requirements.txt` installed, which can be achieved with `pip install -r requirements.txt`, and type `make html`. The local documentation will be generated in `_build/html`. To make the TeX docs follow the instructions in `latex`. diff --git a/docs/_static/custom_styles.css b/docs/_static/custom_styles.css new file mode 100644 index 000000000..13c727374 --- /dev/null +++ b/docs/_static/custom_styles.css @@ -0,0 +1,8 @@ +figcaption { + font-style: italic; /* makes text italic */ + font-size: 0.9em; /* reduces font size to 90% of the surrounding text */ +} + +img.white-background { + background-color: white; +} diff --git a/docs/_static/favicon-ipi.png b/docs/_static/favicon-ipi.png new file mode 100644 index 000000000..beaf016d9 Binary files /dev/null and b/docs/_static/favicon-ipi.png differ diff --git a/docs/latex/README b/docs/latex/README deleted file mode 100644 index 59a8b0e0c..000000000 --- a/docs/latex/README +++ /dev/null @@ -1,46 +0,0 @@ - -- Documentation directory -- - - * This gives all the documentation for the program. - - * Directories: - - figures: Holds the figures used in the manual. - - input_docs: Generated by the Makefile to hold the automatically generated - input reference sections of the manual. - - * Files: - - ../scripts/create_man.py: python script which automatically generates latex help files - for all the classes, for use in the manual. - - ../scripts/help_list.py: python script which can generate custom help files for - the output classes, for use in the manual. - - ../scripts/help.py: python script which can generate custom help files for - each of the input classes, for use in the manual. - - Makefile: The makefile for the automatically generated manual. - - manual.tex: TeX file giving the manual template. - - mybib.bib: Bibliography file for the manual. - - elsarticle-num-names.bst: Bibliography style file. - - etoolbox.sty: LaTeX package which is used by manual.tex. - - * Some of the above files are used to automatically generate sections of the - user manual, and to create an xml showing the class hierarchy. The sections - of the user manual are created in a directory input_docs. - The user manual itself is created in two files, manual.pdf and manual.xml. - These are: - - manual.pdf: The user manual file. This explains how to run the code, - the input and output file syntax, and the design paradigm for ipi. - Also contains a tutorial which goes step by step through an example - calculation. - - manual.xml: This is an xml file that contains all the input names - along with a description of their purpose and what values are - expected for each of them. - - * To make the help files use: - -$ make - - * To remove the input reference sections and LaTeX compiled files, use: - -$ make clean - - * To remove all the generated files, use: - -$ make distclean diff --git a/docs/latex/README.md b/docs/latex/README.md new file mode 100644 index 000000000..de1b68f5f --- /dev/null +++ b/docs/latex/README.md @@ -0,0 +1,45 @@ + +## Documentation Directory + +This directory contains all the documentation for the program. + +### Directories + +- **figures**: Holds the figures used in the manual. +- **input_docs**: Generated by the Makefile to hold the automatically generated input reference sections of the manual. + +### Files + +- `../scripts/create_man.py`: Python script that automatically generates LaTeX help files for all the classes, used in the manual. +- `../scripts/help_list.py`: Python script to generate custom help files for the output classes, used in the manual. +- `../scripts/help.py`: Python script to generate custom help files for each of the input classes, used in the manual. +- `Makefile`: Makefile for generating the manual automatically. +- `manual.tex`: TeX file serving as the template for the manual. +- `mybib.bib`: Bibliography file for the manual. +- `elsarticle-num-names.bst`: Bibliography style file. +- `etoolbox.sty`: LaTeX package used by `manual.tex`. + +### Notes + +Some of the files listed above are used to automatically generate sections of the user manual and to create an XML file showing the class hierarchy. The sections of the user manual are generated in the `input_docs` directory. The user manual itself is created in two files: + +- **manual.pdf**: The main user manual file, explaining how to run the code, the syntax for input and output files, and the design paradigm for i-PI. It also contains a tutorial that goes step-by-step through an example calculation. +- **manual.xml**: An XML file that contains all the input names, along with descriptions of their purpose and the expected values for each. + +### Commands + +- **Generate Help Files**: + ```bash + make + ``` + +- **Clean Up (Remove Input Reference Sections and LaTeX Compiled Files)**: + ```bash + make clean + ``` + +- **Full Clean (Remove All Generated Files)**: + ```bash + make distclean + ``` + diff --git a/docs/requirements.txt b/docs/requirements.txt index 1d4517693..a05ac6e3f 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -1,5 +1,6 @@ sphinx >= 3.2 -jinja2 < 3.1 +jinja2 sphinxcontrib-bibtex==2.1.4 numpy pathlib +furo diff --git a/docs/scripts/help.py b/docs/scripts/help.py index 541281e7e..7a6a74f80 100644 --- a/docs/scripts/help.py +++ b/docs/scripts/help.py @@ -68,6 +68,8 @@ "dynamics": motion.dynamics.InputDynamics(), "constrained_dynamics": motion.constrained_dynamics.InputConstrainedDynamics(), "driven_dynamics": motion.driven_dynamics.InputDrivenDynamics(), + "bec": motion.driven_dynamics.InputBEC(), + "efield": motion.driven_dynamics.InputElectricField(), "csolver": motion.constrained_dynamics.InputConstraintSolver(), "constraint": motion.constrained_dynamics.InputConstraint(), "t_ramp": motion.ramp.InputTemperatureRamp(), @@ -87,6 +89,7 @@ "h0": cell.InputCell(), "forcefield": forcefields.InputForceField(), "ffsocket": forcefields.InputFFSocket(), + "ffdirect": forcefields.InputFFDirect(), "fflj": forcefields.InputFFLennardJones(), "ffdebye": forcefields.InputFFDebye(), "ffplumed": forcefields.InputFFPlumed(), diff --git a/docs/src/conf.py b/docs/src/conf.py index a1bccef5c..a6ebf7cb5 100644 --- a/docs/src/conf.py +++ b/docs/src/conf.py @@ -54,11 +54,12 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # -html_theme = "agogo" +html_title = "i-PI documentation pages" +html_theme = "furo" html_theme_options = { - "rightsidebar": "false", + "top_of_page_buttons": [], } - +html_favicon = "../_static/favicon-ipi.png" html_logo = "../figures/ipi-logo.svg" html_css_files = [ diff --git a/docs/src/contributing.rst b/docs/src/contributing.rst index 7b2a9313d..32955b51c 100644 --- a/docs/src/contributing.rst +++ b/docs/src/contributing.rst @@ -1,3 +1,5 @@ +.. _contributing: + Contributing ============ @@ -89,7 +91,11 @@ If your new development in i-PI is directly related to a specific client code or We very much welcome new interfaces and we will be happy to answer your questions. If you want to enable the communication of a new client code with i-PI, it is not difficult: Please check an example of how it was done in ``fortran`` and ``python`` in the `drivers` folder in the repository. - +It is especially simple to add a new potential energy that is evaluated in Python: it is sufficient to add a file in the `ipi/pes` folder, specifying +`__DRIVER_NAME__` (a string that will be used to refer to the PES from the i-PI input or the command line) and `__DRIVER_CLASS__`, the name of the +actual class, that should provide, directly or through inheritance, a `__call__(self, cell, pos)` function and return a tuple with +`(potential, forces, virial, extras)`. See any of the existing PES files to use as templates - it is particularly simple to create a class that +piggybacs on an existing ASE-style calculator. Getting recognition for your contribution diff --git a/docs/src/distributed.rst b/docs/src/distributed.rst index 449bee7a1..f8e30a879 100644 --- a/docs/src/distributed.rst +++ b/docs/src/distributed.rst @@ -213,6 +213,7 @@ example above. .. _fig-network: .. figure:: ../figures/ipi-network.* + :class: white-background :width: 90.0% A schematic representation of the network layout one diff --git a/docs/src/getting-started.rst b/docs/src/getting-started.rst index fcc32010e..e1f6d2e06 100644 --- a/docs/src/getting-started.rst +++ b/docs/src/getting-started.rst @@ -83,9 +83,29 @@ The built-in driver requires a FORTRAN compiler, and can be built as make cd ../.. +Python driver and PES +^^^^^^^^^^^^^^^^^^^^^ + +In addition to the FORTRAN drive, the i-PI distribution contains also a Python +driver, available in `drivers/py` and through the command-line command +`i-pi-py_driver`, which evaluates potential energy surfaces evaluated by simple +driver classes, that can be found in `ipi/pes`. + +These classes are particularly suitable to perform inference with machine-learning +potentials implemented in Python, and it is reasonably simple to add your own, +if you need to (see also the :ref:`contributing` section). + +These PES files can also be used directly, without the need to go through a +client-server interface, using a :ref:`ffdirect` forcefield, including in the +XML input a block similar to + +.. code-block:: + + + harmonic + { k1: 1.0} + -There is also a Python driver available in `drivers/py`, which however has limited -functionalities. Alternative installation using the setup.py module ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -266,7 +286,7 @@ The flags do the following: -S: Optional parameter. If given, overwrite the default socket prefix used in the creation of files for the socket communication. - (default "/tmp/ipi_") + (default "/tmp/ipi\_") This code should be fairly simple to extend to other pair-wise interaction potentials, and examples of its use can be seen in the @@ -415,6 +435,7 @@ nodes, and to queue and manage computational jobs. .. _fig-running: .. figure:: ../figures/ipi-running.* + :class: white-background :width: 90.0% Different approaches to run i-PI and a number of diff --git a/docs/src/index.rst b/docs/src/index.rst index 37b4c4f72..1c2ecd10a 100644 --- a/docs/src/index.rst +++ b/docs/src/index.rst @@ -26,16 +26,17 @@ This documentation is structured as follows: :maxdepth: 2 introduction - onlinereso - features getting-started + features units input-files input-tags output-files output-tags + python distributed tutorials + onlinereso faq troubleshooting contributing diff --git a/docs/src/introduction.rst b/docs/src/introduction.rst index 21e3934b2..d198457a8 100644 --- a/docs/src/introduction.rst +++ b/docs/src/introduction.rst @@ -27,6 +27,7 @@ A schematic representation of the code structure and the server-client communica .. figure:: ../figures/ipi-structure-v3.* :width: 90.0% + :class: white-background Figure 1. Schematic representation of the i-PI code structure and the server-client communication. @@ -81,6 +82,7 @@ machinery in i-PI might appear complicated at first, and deserves a brief discussion. .. figure:: ../figures/ipi-forces.* + :class: white-background :width: 90.0% Schematic representation of the different objects that @@ -146,6 +148,7 @@ a “depend” object class, which is given the parameters on which it depends and a function used to calculate its value. .. figure:: ../figures/ipi-depend.* + :class: white-background :width: 90.0% Schematic overview of the functioning of the diff --git a/docs/src/onlinereso.rst b/docs/src/onlinereso.rst index 62f971018..8ca372b5b 100644 --- a/docs/src/onlinereso.rst +++ b/docs/src/onlinereso.rst @@ -1,7 +1,15 @@ .. _librarywebsites: -On-line resources -================= +Tutorials, recipes, and on-line resources +========================================= + +Massive Open Online Course (MOOC) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The theory behind classical and path-integral methods for structure +and dynamics along with practical exercises can be found in an online +course freely available to everyone, and accessible from this +`link `_. i-PI resources ~~~~~~~~~~~~~~ @@ -13,50 +21,59 @@ In http://gle4md.org/ one can also obtain colored-noise parameters to run Path Integral with Generalized Langevin Equation thermostat (PI+GLE/PIGLET) calculations. -Several examples of usage of i-PI to perform advanced molecular simulations -can be found among the recipes of the -`atomistic cookbook `_. +Examples and demos +~~~~~~~~~~~~~~~~~~~ +The `examples` and `demos` folders in the i-PI `source code `_ +contain inputs for many different types of +calculations based on i-PI. Examples are typically minimal use-cases of specific +features, examples of client codes, or setups for high performance computing, +while demos are more structured, tutorial-like examples that show how +to realize more complex setups, and also provide a brief discussion of the +underlying algorithms. + +To run these examples, you should typically start i-PI, redirecting the output to +a log file, and then run a couple of instances of the driver code. The progress +of the wrapper is followed by monitoring the log file with the `tail` Linux command. + +Optionally, you can make a copy of the directory with the example somewhere +else if you want to keep the i-PI directory clean. For example:: + + bash + cd demos/para-h2-tutorial/tutorial-1/ + i-pi tutorial-1.xml > log & + i-pi-driver -a localhost -p 31415 -m sg -o 15 & + i-pi-driver -a localhost -p 31415 -m sg -o 15 & + tail -f log + +Tutorials +~~~~~~~~~ +A simple tutorial on how to run i-PI can be found in the documentation: +`a simple tutorial `_. -Python resources -~~~~~~~~~~~~~~~~ - -For help with Python programming, see -`www.python.org `__. For information about the NumPy -mathematical library, see `www.numpy.org `__, and for -worked examples of its capabilities see -`www.scipy.org/Tentative_NumPy_Tutorial `__. -Finally, see http://hgomersall.github.io/pyFFTW/ for documentation on -the Python FFTW library that is currently implemented with i-PI. - - -Client code resources -~~~~~~~~~~~~~~~~~~~~~ - -Several codes provide out-of-the-box an i-PI interface, including -ASE, -CASTEP, -CP2K, -DFTB+, -elphmod, -ffsGDML, -FHI-aims, -LAMMPS, -librascal, -Quantum ESPRESSO, -Siesta, -Yaff. - -If you are interested in interfacing your code to i-PI please get in -touch, we are always glad to help! - -There are several Fortran and C libraries that most client codes will -probably need to run, such as FFTW, BLAS and LAPACK. These can be found -at `www.fftw.org `__, -`www.netlib.org/blas `__ and -`www.netlib.org/lapack `__ respectively. - -These codes do not come as part of the i-PI package, and must be -downloaded separately. - -.. See chapter :ref:`clientinstall` for more details of how to do this. +You can try a set of guided examples that demonstrate some more +advanced features of i-PI. These Tutorials, from the 2021 CECAM +Flagship school, are available here: +`i-PI 2021 tutorials `_. + +Tutorials from the 2023 CECAM Flagship school are available here: +`i-PI 2023 tutorials `_. + +Tutorial from one of our developers on using machine learning interatomic potentials with i-PI are available here: +`MLIPs-with-i-PI `_. + +Note that these examples use some features +(such as qTIP4P/F water and the Zundel cation potentials in the driver code, +and optionally also CP2K). Instructions on how to install and run these codes +with i-PI are contained in the tutorial. + +Atomistic recipes +~~~~~~~~~~~~~~~~~ + +Several examples of usage of i-PI to perform advanced molecular +simulations can be found among the recipes of the +`atomistic cookbook `_. +These include an +`introduction to path integral simulations `_, +a discussion of `how to compute quantum heat capacities `_, +and an example of `path integral metadynamics `_. diff --git a/docs/src/python.rst b/docs/src/python.rst new file mode 100644 index 000000000..422bb2185 --- /dev/null +++ b/docs/src/python.rst @@ -0,0 +1,71 @@ +Tools and python utilities +========================== + +Post-processing tools +~~~~~~~~~~~~~~~~~~~~~ +Some observables (such as autocorrelation functions, isotope fractionation ratios, particle +momentum distributions) require post-processing the raw outputs of a simulation. +The folder ``tools`` contains several post-processing scripts, that can +be used to this end - each (tersely) self-documented with a help string and in +the code. +Some of these tools are also accessible as python functions, so that they can +be invoked from custom post-processing workflows. They can be found in +the ``ipi/utils/tools`` folder, and accessed by importing the module, e.g. + +.. code-block:: python + + from ipi.utils.tools import isra_deconvolute + +is a routine to correct the correlation spectrum computed from a thermostatted simulation, +see this `example `_. + +Parsing +~~~~~~~ + +i-PI trajectories can be output in +`extended xyz format `_, +and can be read by `ASE `_, while the property +outputs can be simply read with ``np.loadtxt``. However, more reliable parsing can be +achieved using the ``ipi.read_output`` and ``ipi.read_trajectory`` functions, that +can also read the native i-PI trajectory formats, and that parse the header of the +output file to provide metadata on the type and units of the properties it contains. + +Scripting i-PI +~~~~~~~~~~~~~~ + +If one wants to run an i-PI simulation within a Python script, it is also possible +to use a (somewhat primitive) scripting API, defined in the ``ipi.utils.scripting`` +module. The core component is the ``InteractiveSimulation`` class, that can be +initialized from an *XML* input, advanced for a given number of steps using the +``run`` method. The calculation requires also the use of a driver, that can +communicate through sockets (in which case it must be launched after +initialization, and before running) or directly using a Python API +using an :ref:`ffdirect` block. + +Properties can be accessed using the ``properties`` method, and a snapshot +of the configuration by calling ``get_structures``. +It is also possible to call ``set_structures`` to change positions, cell +and (if available) velocities to those that can be found in an Atoms structure +(or a list of structures in case there are multiple systems and/or multiple +beads). +Several utility functions, also available within the module, facilitate +building on the fly an *XML* string to initialize the simulation. +An example of usage of this interface goes as follows: + +.. code-block:: python + + from ipi.utils.scripting import InteractiveSimulation, simulation_xml, motion_nvt_xml, forcefield_xml + + data = ase.io.read("init.xyz") + input_xml = simulation_xml( + structures=data, + forcefield=forcefield_xml(name="dummy", mode="direct"), + motion=motion_nvt_xml(timestep=2.0 * ase.units.fs), + temperature=300, + prefix="example", + ) + + sim = InteractiveSimulation(input_xml) + sim.run(100) + potential = sim.properties("potential") + ase.io.write("final_structure.xyz", sim.get_structures()) diff --git a/drivers/f90/driver.f90 b/drivers/f90/driver.f90 index 7fa0b378b..c1554f0fd 100644 --- a/drivers/f90/driver.f90 +++ b/drivers/f90/driver.f90 @@ -1000,8 +1000,7 @@ PROGRAM DRIVER CALL writebuffer(socket,initbuffer,cbuf) IF (verbose > 1) WRITE(*,*) " !write!=> extra: ", & & initbuffer(1:cbuf) -! ELSEIF (vstyle==5 .or. vstyle==6 .or. vstyle==8 .or. vstyle==99) THEN ! returns the dipole through initbuffer - ELSEIF (vstyle==5 .or. vstyle==6 .or. vstyle==8) THEN ! returns the dipole through initbuffer + ELSEIF (vstyle==5 .or. vstyle==6 .or. vstyle==8 .or. vstyle==99) THEN ! returns the dipole through initbuffer WRITE(initbuffer, '(a,3x,f15.8,a,f15.8,a,f15.8, & & 3x,a)') '{"dipole": [',dip(1),",",dip(2),",",dip(3),"]}" cbuf = LEN_TRIM(initbuffer) diff --git a/drivers/py/driver.py b/drivers/py/driver.py index aeff7f8e4..1877613e1 100755 --- a/drivers/py/driver.py +++ b/drivers/py/driver.py @@ -3,12 +3,8 @@ import argparse import numpy as np - -try: - from pes import * -except ImportError: - # when in an installed i-PI package - from ipi._driver.pes import * +from ipi.pes import * +from ipi.utils.io.inputs import read_args_kwargs description = """ Minimal example of a Python driver connecting to i-PI and exchanging energy, forces, etc. @@ -119,8 +115,8 @@ def run_driver( nat = recv_data(sock, np.int32()) if len(pos) == 0: # shapes up the position array - pos.resize((nat, 3)) - force.resize((nat, 3)) + pos.resize((nat, 3), refcheck=False) + force.resize((nat, 3), refcheck=False) else: if len(pos) != nat: raise RuntimeError("Atom number changed during i-PI run") @@ -205,8 +201,8 @@ def run_driver( "--mode", type=str, default="dummy", + choices=list(__drivers__.keys()), help="""Type of potential to be used to compute the potential and its derivatives. - Currently implemented: [dummy, harmonic] """, ) parser.add_argument( @@ -227,10 +223,23 @@ def run_driver( args = parser.parse_args() + driver_args, driver_kwargs = read_args_kwargs(args.param) + if args.mode in __drivers__: - d_f = __drivers__[args.mode](args.param, args.verbose) + try: + d_f = __drivers__[args.mode]( + *driver_args, verbose=args.verbose, **driver_kwargs + ) + except ImportError: + # specific errors have already been triggered + raise + except Exception as err: + print(f"Error setting up PES mode {args.mode}") + print(__drivers__[args.mode].__doc__) + print("Error trace: ") + raise err elif args.mode == "dummy": - d_f = Dummy_driver(args.param, args.verbose) + d_f = Dummy_driver(verbose=args.verbose) else: raise ValueError("Unsupported driver mode ", args.mode) diff --git a/drivers/py/pes/elphmod.py b/drivers/py/pes/elphmod.py deleted file mode 100644 index efa863131..000000000 --- a/drivers/py/pes/elphmod.py +++ /dev/null @@ -1,32 +0,0 @@ -"""Interface with [elphmod](https://github.com/janberges/elphmod) MD driver.""" - -import sys -from .dummy import Dummy_driver - -__DRIVER_NAME__ = "elphmod" -__DRIVER_CLASS__ = "ModelIIIDriver" - -ERROR_MSG = """ -A pickled driver instance is required (see elphmod.md.Driver.save). - -Example: python3 driver.py -u -m elphmod -o driver.pickle -""" - - -class ModelIIIDriver(Dummy_driver): - """Wrapper around elphmod MD driver.""" - - def check_arguments(self): - """Check arguments and load driver instance.""" - - import elphmod - - if len(self.args) != 1: - sys.exit(ERROR_MSG) - - self.driver = elphmod.md.Driver.load(self.args[0]) - - def __call__(self, cell, pos): - """Calculate energy and forces for given structure.""" - - return self.driver(cell, pos) diff --git a/drivers/py/pes/mace.py b/drivers/py/pes/mace.py deleted file mode 100644 index 881f9e5cd..000000000 --- a/drivers/py/pes/mace.py +++ /dev/null @@ -1,40 +0,0 @@ -""" An interface for the [MACE](https://github.com/ACEsuit/mace) calculator """ - -import sys -from .ase import ASEDriver - -try: - from mace.calculators import MACECalculator -except: - MACECalculator = None - -__DRIVER_NAME__ = "mace" -__DRIVER_CLASS__ = "MACE_driver" - -ERROR_MSG = """ -MACE driver requires specification of a .json model, -and a template file that describes the chemical makeup of the structure. - -Example: python driver.py -m mace -u -o model.json,template.xyz -""" - - -class MACE_driver(ASEDriver): - def __init__(self, args=None, verbose=False): - if MACECalculator is None: - raise ImportError("Couldn't load mace bindings") - - super().__init__(args, verbose, ERROR_MSG) - - def check_arguments(self): - """Check the arguments requuired to run the driver - - This loads the potential and atoms template in MACE - """ - - super().check_arguments() - - if len(self.args) < 2: - sys.exit(self.error_msg) - - self.ase_calculator = MACECalculator(model_paths=self.args[1], device="cpu") diff --git a/drivers/py/pes/metatensor.py b/drivers/py/pes/metatensor.py deleted file mode 100644 index 271a0c04e..000000000 --- a/drivers/py/pes/metatensor.py +++ /dev/null @@ -1,94 +0,0 @@ -""" -Interface with metatensor -(https://lab-cosmo.github.io/metatensor/latest/atomistic/index.html), that can -be used to perform calculations based on different types of machine learning -potentials -""" - -import sys - -from ipi.utils.messages import warning - -from .ase import ASEDriver - -try: - import metatensor.torch - from metatensor.torch.atomistic.ase_calculator import MetatensorCalculator -except ImportError as e: - warning(f"Could not find or import metatensor.torch: {e}") - MetatensorCalculator = None - -__DRIVER_NAME__ = "metatensor" -__DRIVER_CLASS__ = "MetatensorDriver" - -ERROR_MSG = """ -The metatensor driver requires specification of a .pt TorchScript model and an -ASE-readable template file that describes the chemical makeup of the structure. - -Example: python driver.py -m metatensor -u -o template.xyz,model.pt,device=cpu,\ -extensions=path/to/extensions,check_consistency=False -""" - - -class MetatensorDriver(ASEDriver): - def __init__(self, args=None, verbose=False, error_msg=ERROR_MSG): - super().__init__(args, verbose, error_msg) - - def check_arguments(self): - """Check the arguments required to run the driver - - This loads the potential and atoms template in metatensor - """ - - if MetatensorCalculator is None: - raise ImportError("could not import metatensor.torch, is it installed?") - - metatensor_major, metatensor_minor, *_ = metatensor.torch.__version__.split(".") - metatensor_major = int(metatensor_major) - metatensor_minor = int(metatensor_minor) - - if metatensor_major != 0 or metatensor_minor != 5: - raise ImportError( - "this code is only compatible with metatensor-torch v0.5.x, " - f"found version v{metatensor.torch.__version__} " - f"at '{metatensor.torch.__file__}'" - ) - - super().check_arguments() - - if len(self.args) < 2: - sys.exit(self.error_msg) - self.model_path = self.args[1] - - device = None - extensions_directory = None - check_consistency = False - for arg in self.args[2:]: - if arg.startswith("device="): - device = arg[7:] - elif arg.startswith("extensions="): - extensions_directory = arg[11:] - elif arg.startswith("check_consistency="): - arg = arg[18:] - if arg == "True": - check_consistency = True - elif arg == "False": - check_consistency = False - else: - raise ValueError( - "invalid value for check_consistency, expected True or False, " - f"got {arg}" - ) - - else: - sys.exit(self.error_msg) - - self.ase_calculator = MetatensorCalculator( - self.model_path, - device=device, - extensions_directory=extensions_directory, - check_consistency=check_consistency, - ) - - # Show the model metadata to the users - print(self.ase_calculator.metadata()) diff --git a/drivers/py/pes/xtb.py b/drivers/py/pes/xtb.py deleted file mode 100644 index c2b7947fd..000000000 --- a/drivers/py/pes/xtb.py +++ /dev/null @@ -1,83 +0,0 @@ -""" -Interface with tblite to provide GFN1-xTB and GFN2-xTB calculators. - -Example:: - - python driver.py -m xtb -u -o '{"method": "GFN2-xTB", "numbers": [8,1,1], "periodic": false}' -""" - -import numpy as np -import json - -from ipi.utils.units import unit_to_internal, unit_to_user - -try: - import tblite.interface as tb -except ImportError as e: - raise ModuleNotFoundError( - "Could not find tblite for xtb driver. Please install tblite-python with mamba" - ) from e - -__DRIVER_NAME__ = "xtb" -__DRIVER_CLASS__ = "TBLiteDriver" - - -class TBLiteDriver(object): - """Base class providing the structure of a PES for the python driver.""" - - def __init__( - self, - args="", - verbose=False, - ): - """Initialized dummy drivers""" - config = json.loads(args) - try: - self.method = config["method"] - self.numbers = np.asarray(config["numbers"]) - except KeyError as e: - raise ValueError(f"Required key {str(e)} not found.") - self.charge = config.get("charge") - self.uhf = config.get("uhf") - self.periodic = config.get("periodic") - self.verbosity = 1 if verbose else 0 - - def __call__(self, cell, pos): - """ - Get energies, forces, and stresses from the tblite library - This routine assumes that the client will take positions - in bohr, and return energies in hartree, and forces - in hartree/abohr. - """ - - pos = unit_to_user("length", "atomic_unit", pos) - cell = unit_to_user("length", "atomic_unit", cell.T) - - calc = tb.Calculator( - self.method, - self.numbers, - np.asarray(pos), - self.charge, - self.uhf, # unpaired electrons - np.asarray(cell) if self.periodic else None, - np.repeat(self.periodic, 3) if self.periodic else None, - ) - calc.set("verbosity", self.verbosity) - - # Do the actual calculation - results = calc.singlepoint() - pot = results.get("energy") - grad = results.get("gradient") - vir = results.get("virial") - - # converts to internal quantities - pot_ipi = np.asarray(unit_to_internal("energy", "atomic_unit", pot), np.float64) - force_ipi = np.asarray( - unit_to_internal("force", "atomic_unit", -grad), np.float64 - ) - vir_ipi = np.array( - unit_to_internal("energy", "atomic_unit", -vir.T), np.float64 - ) - extras = "" - - return pot_ipi, force_ipi, vir_ipi, extras diff --git a/examples/clients/elphmod/Makefile b/examples/clients/elphmod/Makefile index 1561650d4..60e3ecf40 100644 --- a/examples/clients/elphmod/Makefile +++ b/examples/clients/elphmod/Makefile @@ -22,7 +22,7 @@ driver $(DRIVER): driver.py $(MODEL) run $(RUN): input.xml $(DRIVER) $(IPI) $< & sleep 5 - i-pi-driver-py -u -m elphmod -o $(word 2,$^) + i-pi-driver-py -u -m elphmod -o driver=driver.pickle wait run2: input.xml run.py $(DRIVER) diff --git a/examples/clients/mace/README.md b/examples/clients/mace/README.md new file mode 100644 index 000000000..3b8f24ef3 --- /dev/null +++ b/examples/clients/mace/README.md @@ -0,0 +1,28 @@ +# MACE Example + +Runs an example of the pretrained [MACE model](https://github.com/ACEsuit/mace-mp/releases/download/mace_mp_0c/mace-small-density-agnesi-stress.model) for simple molecular dynamics of liquid water at 300 K. + +## Installation + +To be able to run MACE, check out the installation instructions at [https://github.com/ACEsuit/mace/tree/main?tab=readme-ov-file#installation](https://github.com/ACEsuit/mace/tree/main?tab=readme-ov-file#installation). + +## Running the Example + +To download the pretrained [MACE model](https://github.com/ACEsuit/mace-mp/releases/download/mace_mp_0c/mace-small-density-agnesi-stress.model): + +```bash +bash getmodel.sh +``` + +Then, run the following to start the i-PI simulation: + +```bash +i-pi input.xml & sleep 10 +i-pi-py_driver -a driver -u -m mace -o init.xyz,mace.model +``` + +### Options (after `-o`) + +- Path to a template file, used to retrieve the types for all atoms in the system. +- Path to the model file. + diff --git a/examples/clients/mace/getmodel.sh b/examples/clients/mace/getmodel.sh new file mode 100644 index 000000000..31ee1ca0d --- /dev/null +++ b/examples/clients/mace/getmodel.sh @@ -0,0 +1,3 @@ +wget wget https://github.com/ACEsuit/mace-mp/releases/download/mace_mp_0c/mace-small-density-agnesi-stress.model +mv mace-small-density-agnesi-stress.model mace.model + diff --git a/examples/clients/mace/init.xyz b/examples/clients/mace/init.xyz new file mode 120000 index 000000000..0db27c06d --- /dev/null +++ b/examples/clients/mace/init.xyz @@ -0,0 +1 @@ +../../init_files/water_64mols.extxyz \ No newline at end of file diff --git a/examples/clients/mace/input.xml b/examples/clients/mace/input.xml new file mode 100644 index 000000000..72103e52f --- /dev/null +++ b/examples/clients/mace/input.xml @@ -0,0 +1,37 @@ + + + + [ step, time{picosecond}, conserved{electronvolt}, temperature{kelvin}, kinetic_md{electronvolt}, potential{electronvolt}, pressure_md{megapascal} ] + positions + + + 20000 + + 31415 + + +
driver
+
+ + + init.xyz + 300 + + + + + + + + + 100 + + + 0.50 + + + + 300 + + +
diff --git a/examples/clients/metatensor/README.md b/examples/clients/metatensor/README.md index a5b0f23c2..b85f96bdf 100644 --- a/examples/clients/metatensor/README.md +++ b/examples/clients/metatensor/README.md @@ -10,14 +10,14 @@ machine learning potentials. ## Installation -The code is compatible with metatensor-torch v0.5, which you can install with +The code is compatible with metatensor-torch v0.6, which you can install with ```bash # install all metatensor packages simultaneously pip install "metatensor[torch]" # install packages individually, with explicit control over the installed versions -pip install "metatensor-torch ==0.5.*" "metatensor-operations ==0.2.*" +pip install "metatensor-torch ==0.6.*" "metatensor-operations ==0.2.*" ``` ## Running the example @@ -42,3 +42,22 @@ The options (after `-o`) are as follow: - `check_consistency` controls whether we should run some extra internal consistency checks about data given to the model and data returned by the model. + +## Running with FFDirect + +It is also possible to run the metatensor PES directly, without the need for an external +driver. To do so, you need to use a `` clause in the input, and specify +the appropriate options as a dictionary. Then, you can simply run + +```bash +i-pi input-direct.xml +``` + +## Running with a scripting interface + +To see how to run the metatensor calculator through the interactive Python interface, +check the `run.py` script + +```bash +python run.py +``` diff --git a/examples/clients/metatensor/create-model.py b/examples/clients/metatensor/create-model.py index f821b73b2..b93ad10d6 100644 --- a/examples/clients/metatensor/create-model.py +++ b/examples/clients/metatensor/create-model.py @@ -1,4 +1,4 @@ -# Use https://github.com/Luthaf/metatensor-lj-test/ to define a basic LJ model, +# Use https://github.com/metatensor/lj-test/ to define a basic LJ model, # with and without a custom TorchScript extension import metatensor_lj_test @@ -13,7 +13,7 @@ with_extension=False, ) -model.export("nickel-lj.pt") +model.save("nickel-lj.pt") model = metatensor_lj_test.lennard_jones_model( @@ -25,4 +25,4 @@ energy_unit="kcal/mol", with_extension=True, ) -model.export("nickel-lj-extensions.pt", collect_extensions="collected-extensions/") +model.save("nickel-lj-extensions.pt", collect_extensions="collected-extensions/") diff --git a/examples/clients/metatensor/input-direct.xml b/examples/clients/metatensor/input-direct.xml new file mode 100644 index 000000000..9422cd787 --- /dev/null +++ b/examples/clients/metatensor/input-direct.xml @@ -0,0 +1,47 @@ + + + + [step, time{picosecond}, conserved{electronvolt}, temperature{kelvin}, + kinetic_md{electronvolt}, potential{electronvolt}, pressure_md{bar}, + volume{angstrom3}, ensemble_temperature{kelvin}, cell_abcABC] + + x_centroid{angstrom} + + + 1000 +12345 + + + metatensor + {template:nickel.xyz,model:nickel-lj.pt,device:cpu } + + + + + nickel.xyz + 250.0 + + + + + + + + 0.5 + + [ + 4.49e-3, 6.59e-6, 2.79e-4, -8.81e-4, 5.61e-3, + -6.73e-6, 2.08e-9, 1.75e-5, -4.80e-6, 1.03e-5, + -3.59e-4, -1.75e-5, 3.29e-5, 1.24e-4, -2.42e-4, + -2.51e-4, 4.80e-6, -1.24e-4, 6.45e-4, 2.78e-4, + 5.27e-3, -1.03e-5, 2.42e-4, -2.78e-4, 7.49e-3 + ] + + + + + + 250.0 + + + diff --git a/examples/clients/metatensor/input.xml b/examples/clients/metatensor/input.xml index ad58b0a8c..0af3796b7 100644 --- a/examples/clients/metatensor/input.xml +++ b/examples/clients/metatensor/input.xml @@ -27,7 +27,7 @@ - 0.5 + 2 [ 4.49e-3, 6.59e-6, 2.79e-4, -8.81e-4, 5.61e-3, diff --git a/examples/clients/metatensor/nickel-lj.pt b/examples/clients/metatensor/nickel-lj.pt index 9491841ca..17b7ccea5 100644 Binary files a/examples/clients/metatensor/nickel-lj.pt and b/examples/clients/metatensor/nickel-lj.pt differ diff --git a/examples/clients/metatensor/run.py b/examples/clients/metatensor/run.py new file mode 100644 index 000000000..8943415f5 --- /dev/null +++ b/examples/clients/metatensor/run.py @@ -0,0 +1,47 @@ +#!/usr/bin/python +from ipi.utils.scripting import ( + simulation_xml, + forcefield_xml, + motion_nvt_xml, + InteractiveSimulation, +) +import ase, ase.io + +# There are utilities to quickly set up XML inputs for commonly-used simulations +data = ase.io.read("nickel.xyz") +input_xml = simulation_xml( + structures=data, + forcefield=forcefield_xml( + name="lj-mtt", + mode="direct", + pes="metatensor", + parameters={"model": "nickel-lj.pt", "template": "nickel.xyz"}, + ), + motion=motion_nvt_xml(timestep=2 * ase.units.fs), + temperature=250, + prefix="script", +) + +print("Running with XML input:\n\n", input_xml) + +# The main object for scripting is `InteractiveSimulation`, that is initialized from +# and XML input and acts as a wrapper around an i-PI simulation object +sim = InteractiveSimulation(input_xml) + +# `properties` accesses the (well) properties of the simulation object +print( + sim.properties("time") / ase.units.fs, + sim.properties("potential"), + sim.properties("temperature"), +) +# `run` advances the interactive simulation by one (or the prescribed number) of steps +sim.run(100) +print( + sim.properties("time") / ase.units.fs, + sim.properties("potential"), + sim.properties("temperature"), +) + +# `get_structures` dumps the state of the system as ASE Atoms objects, possibly listing +# all systems and beads +ase.io.write("final_positions.xyz", sim.get_structures()) diff --git a/examples/clients/pes/README.md b/examples/clients/pes/README.md new file mode 100644 index 000000000..0356afea1 --- /dev/null +++ b/examples/clients/pes/README.md @@ -0,0 +1,8 @@ +Examples for the PES modules +============================ + +These examples show how to run a simulation using one of the PES defined in +`ipi.pes`. + +harmonic/ shows how to run using the Python driver `i-pi-py_driver` +harmonic-direct/ shows how to run using a `` clause in the input diff --git a/examples/clients/pes/harmonic-direct/Makefile b/examples/clients/pes/harmonic-direct/Makefile new file mode 100644 index 000000000..7bc94106b --- /dev/null +++ b/examples/clients/pes/harmonic-direct/Makefile @@ -0,0 +1,17 @@ +# Makefile for the "direct" harmonic oscillator example +# +# This file is part of i-PI. +# i-PI Copyright (C) 2014-2015 i-PI developers +# See the "licenses" directory for full license information. + +.PHONY: all clean harmonic +all: harmonic + +IPI:=i-pi + + +harmonic: + $(IPI) input.xml + +clean: + rm -f *simulation.* RESTART EXIT diff --git a/examples/clients/pes/harmonic-direct/init.xyz b/examples/clients/pes/harmonic-direct/init.xyz new file mode 100644 index 000000000..8efa9e7ef --- /dev/null +++ b/examples/clients/pes/harmonic-direct/init.xyz @@ -0,0 +1,3 @@ +1 + +H 0.108 0.000 0.000 diff --git a/examples/clients/pes/harmonic-direct/input.xml b/examples/clients/pes/harmonic-direct/input.xml new file mode 100644 index 000000000..b3b5ba4b6 --- /dev/null +++ b/examples/clients/pes/harmonic-direct/input.xml @@ -0,0 +1,38 @@ + + + [ step, time{picosecond}, conserved{kelvin}, temperature{kelvin}, kinetic_cv{kelvin}, potential{kelvin}, pressure_cv{megapascal}] + positions{angstrom} + forces{piconewton} + + 100 + + 3348 + + + harmonic + { k1:1.0 } + + + + + [ 15., 15.0, 15.0 ] + + init.xyz + 3683.412077 + + + + + + 3683.412077 + + + + + 25 + + 0.003 + + + + diff --git a/examples/clients/pes/harmonic-direct/test_settings.dat b/examples/clients/pes/harmonic-direct/test_settings.dat new file mode 100644 index 000000000..e69de29bb diff --git a/examples/clients/xtb/README.md b/examples/clients/xtb/README.md index c3b2b0c57..ccb6475e6 100644 --- a/examples/clients/xtb/README.md +++ b/examples/clients/xtb/README.md @@ -15,5 +15,5 @@ the example can be run as usual ```bash i-pi input.xml &> log.ipi & -i-pi-py_driver -m xtb -o '{"method": "GFN2-xTB", "numbers": [6,1,1,1,1], "periodic": false}' -u -a xtb &> log.xtb & +i-pi-py_driver -m xtb -o template=ch4.xyz,method=GFN2-xTB -u -a xtb &> log.xtb ``` diff --git a/examples/clients/xtb/run.sh b/examples/clients/xtb/run.sh old mode 100644 new mode 100755 index 3726ce141..a93bebf5c --- a/examples/clients/xtb/run.sh +++ b/examples/clients/xtb/run.sh @@ -3,5 +3,5 @@ echo "Running i-PI" i-pi input.xml &> log.ipi & sleep 1 echo "Running driver" -i-pi-py_driver -m xtb -o '{"method": "GFN2-xTB", "numbers": [6,1,1,1,1], "periodic": false}' -u -a xtb &> log.xtb +i-pi-py_driver -m xtb -o template=ch4.xyz,method=GFN2-xTB -u -a xtb &> log.xtb diff --git a/examples/features/geometry_optimization/SD_pswater_with_fixatoms/init.xyz b/examples/features/geometry_optimization/SD_pswater_with_fixatoms/init.xyz new file mode 100644 index 000000000..3b64742f2 --- /dev/null +++ b/examples/features/geometry_optimization/SD_pswater_with_fixatoms/init.xyz @@ -0,0 +1,5 @@ +3 +# CELL(abcABC): 35.23300 35.23300 35.23300 90.00000 90.00000 90.00000 Traj: positions{angstrom} Step: 11 Bead: 0 + O 0.00000e+00 -2.00000e-02 0.00000e+00 + H 7.50000e-01 5.00000e-01 0.00000e+00 + H -7.50000e-01 5.00000e-01 0.00000e+00 diff --git a/examples/features/geometry_optimization/SD_pswater_with_fixatoms/input.xml b/examples/features/geometry_optimization/SD_pswater_with_fixatoms/input.xml new file mode 100644 index 000000000..bfca87a2e --- /dev/null +++ b/examples/features/geometry_optimization/SD_pswater_with_fixatoms/input.xml @@ -0,0 +1,31 @@ + + + [ step, potential ] + positions + + 1000 + + 32342 + + +
h2o-geop
+
+ + + init.xyz + + + + + + [0] + + + 1e-5 + 1e-5 + 1e-5 + + + + +
diff --git a/examples/features/geometry_optimization/SD_pswater_with_fixatoms/run.sh b/examples/features/geometry_optimization/SD_pswater_with_fixatoms/run.sh new file mode 100644 index 000000000..c3c631499 --- /dev/null +++ b/examples/features/geometry_optimization/SD_pswater_with_fixatoms/run.sh @@ -0,0 +1,16 @@ +ipi=i-pi +driver="i-pi-driver -m pswater -u -a h2o-geop" +sleep_time=4 + +${ipi} input.xml > log.i-pi & +echo "# i-PI is running" + +echo "# Waiting for ${sleep_time} (s) before executing driver" +sleep ${sleep_time} + +${driver} > /dev/null & +echo "# Driver is running" + +wait + +echo "# Simulation complete" diff --git a/examples/features/geometry_optimization/SD_pswater_with_fixdofs/init.xyz b/examples/features/geometry_optimization/SD_pswater_with_fixdofs/init.xyz new file mode 100644 index 000000000..3b64742f2 --- /dev/null +++ b/examples/features/geometry_optimization/SD_pswater_with_fixdofs/init.xyz @@ -0,0 +1,5 @@ +3 +# CELL(abcABC): 35.23300 35.23300 35.23300 90.00000 90.00000 90.00000 Traj: positions{angstrom} Step: 11 Bead: 0 + O 0.00000e+00 -2.00000e-02 0.00000e+00 + H 7.50000e-01 5.00000e-01 0.00000e+00 + H -7.50000e-01 5.00000e-01 0.00000e+00 diff --git a/examples/features/geometry_optimization/SD_pswater_with_fixdofs/input.xml b/examples/features/geometry_optimization/SD_pswater_with_fixdofs/input.xml new file mode 100644 index 000000000..72665cc3d --- /dev/null +++ b/examples/features/geometry_optimization/SD_pswater_with_fixdofs/input.xml @@ -0,0 +1,31 @@ + + + [ step, potential ] + positions + + 1000 + + 32342 + + +
h2o-geop
+
+ + + init.xyz + + + + + + [0,1,2] + + + 1e-5 + 1e-5 + 1e-5 + + + + +
diff --git a/examples/features/geometry_optimization/SD_pswater_with_fixdofs/run.sh b/examples/features/geometry_optimization/SD_pswater_with_fixdofs/run.sh new file mode 100755 index 000000000..c3c631499 --- /dev/null +++ b/examples/features/geometry_optimization/SD_pswater_with_fixdofs/run.sh @@ -0,0 +1,16 @@ +ipi=i-pi +driver="i-pi-driver -m pswater -u -a h2o-geop" +sleep_time=4 + +${ipi} input.xml > log.i-pi & +echo "# i-PI is running" + +echo "# Waiting for ${sleep_time} (s) before executing driver" +sleep ${sleep_time} + +${driver} > /dev/null & +echo "# Driver is running" + +wait + +echo "# Simulation complete" diff --git a/examples/features/ring_polymer_instanton/rates_1D_double_well_with_friction/implicit_bath_pos-dependent/run.sh b/examples/features/ring_polymer_instanton/rates_1D_double_well_with_friction/implicit_bath_pos-dependent/run.sh index 8bc25bc1e..3ee1793d9 100755 --- a/examples/features/ring_polymer_instanton/rates_1D_double_well_with_friction/implicit_bath_pos-dependent/run.sh +++ b/examples/features/ring_polymer_instanton/rates_1D_double_well_with_friction/implicit_bath_pos-dependent/run.sh @@ -5,9 +5,9 @@ wc=500 V0=2085 mass=1837.36223469 - x0=0 epsilon=-1.0 delta=0 + epsilon2=0 deltaQ=1 address=localhost @@ -19,4 +19,9 @@ sleep 3 #Launch driver - i-pi-driver-py -m ${model} -o ${wb},${V0},${mass},${x0},${eta},${epsilon},${delta},${deltaQ} -u -a ${address} + #i-pi-driver-py -m ${model} -o ${wb},${V0},${mass},${x0},${eta},${epsilon},${delta},${deltaQ} -u -a ${address} + arg="w_b=${wb},v0=${V0},m=${mass},delta=${delta},eta0=${eta},eps1=${epsilon},eps2=${epsilon2},deltaQ=${deltaQ}" + + echo ${arg} +# def __init__(self,w_b=None,v0=None,m=None,eta0=None,eps1=None,eps2=None,delta=None,deltaQ=None, *args, **kwargs): + i-pi-driver-py -m ${model} -o ${arg} -u -a ${address} diff --git a/examples/features/scripting-api/run.py b/examples/features/scripting-api/run.py new file mode 100644 index 000000000..869b40dca --- /dev/null +++ b/examples/features/scripting-api/run.py @@ -0,0 +1,63 @@ +#!/usr/bin/python +from ipi.utils.scripting import ( + simulation_xml, + forcefield_xml, + motion_nvt_xml, + InteractiveSimulation, +) +import ase, ase.io + +# There are utilities to quickly set up XML inputs for commonly-used simulations +data = ase.io.read("water-64.xyz") +input_xml = simulation_xml( + structures=data, + forcefield=forcefield_xml( + name="harmonic", mode="direct", pes="harmonic", parameters="{k1:1e-3}" + ), + motion=motion_nvt_xml(timestep=0.5 * ase.units.fs), + temperature=400, + prefix="script", +) + +print("Running with XML input:\n\n", input_xml) + +# The main object for scripting is `InteractiveSimulation`, that is initialized from +# and XML input and acts as a wrapper around an i-PI simulation object +sim = InteractiveSimulation(input_xml) + +# `properties` accesses the (well) properties of the simulation object +print( + sim.properties("time") / ase.units.fs, + sim.properties("potential"), + sim.properties("temperature"), +) +# `run` advances the interactive simulation by one (or the prescribed number) of steps +sim.run(10) +print( + sim.properties("time") / ase.units.fs, + sim.properties("potential"), + sim.properties("temperature"), +) +sim.run(10, write_outputs=False) # we can suppress the outputs +print( + sim.properties("time") / ase.units.fs, + sim.properties("potential"), + sim.properties("temperature"), +) +sim.run(10) +print( + sim.properties("time") / ase.units.fs, + sim.properties("potential"), + sim.properties("temperature"), +) + +# `get_structures` dumps the state of the system as ASE Atoms objects, possibly listing +# all systems and beads +ase.io.write("final_positions.xyz", sim.get_structures()) + +# we can also set the simulation state +structure = sim.get_structures() +structure.positions[:] = data.positions +structure.arrays["ipi_velocities"][:] = 0 +sim.set_structures(structure) +print(sim.properties("potential"), sim.properties("kinetic_md")) diff --git a/examples/features/scripting-api/water-64.xyz b/examples/features/scripting-api/water-64.xyz new file mode 100644 index 000000000..c6d078e3f --- /dev/null +++ b/examples/features/scripting-api/water-64.xyz @@ -0,0 +1,194 @@ +192 +Lattice="12.4244 0.0 0.0 0.0 12.4244 0.0 0.0 0.0 12.4244" Properties=species:S:1:pos:R:3 ipi_comment="Step: 1900 Bead: 0 positions{ase} cell{ase}" pbc="T T T" +O 2.21387327 12.40725068 2.23031948 +H 2.06694404 11.67860309 1.64454197 +H 1.31318334 12.80514770 2.28237999 +O -0.75321508 -0.59448153 -1.04435843 +H -0.43690708 0.32900852 -1.04657525 +H -0.57971040 -0.98114653 -1.94412965 +O 5.74154040 -0.87984718 0.72588630 +H 6.39142623 -1.27091020 0.15466910 +H 4.95746147 -0.84286870 0.17858963 +O 11.99198992 13.45036196 2.41825677 +H 11.37275732 12.74729899 2.49935612 +H 11.89932759 14.00247471 1.54806628 +O 11.93044048 1.05488399 -3.73314299 +H 11.32455922 0.93150585 -4.46539255 +H 12.65005178 0.53170032 -3.90569743 +O 14.73647355 5.99191632 -7.05710376 +H 14.64143925 5.03360348 -7.27737786 +H 14.06733122 6.17072192 -6.37654095 +O -2.73217835 10.36158893 0.16191577 +H -2.06962320 10.93427055 -0.33139183 +H -2.51616800 9.45621753 -0.12184826 +O 6.23846578 1.75374492 0.35639039 +H 5.96089981 0.77730520 0.46453180 +H 5.39628380 2.29054891 0.26418202 +O 8.80269662 8.43566538 5.05023611 +H 9.72832216 8.80499254 4.93842353 +H 8.41177392 8.34800960 4.16677335 +O 5.89328910 5.88414156 -1.14225059 +H 6.07707839 5.68838338 -2.06445181 +H 5.43934590 6.71987929 -1.04508996 +O 7.84016011 2.70671541 2.39204316 +H 7.20788308 3.26556062 2.89380271 +H 7.32436176 2.27545437 1.68427297 +O 11.00517380 5.32928124 3.72557263 +H 10.29738407 5.10122268 2.99805211 +H 10.47093006 5.51304477 4.52225686 +O 2.68516096 2.41177930 -0.66463660 +H 3.12947415 1.66826602 -1.03006854 +H 3.27709683 2.85722501 -0.03548707 +O 0.86065791 8.02193473 -3.37520070 +H 1.11321946 7.81534106 -2.41395316 +H 0.22218987 8.78231178 -3.28348522 +O 5.85747567 0.46065763 -7.43414667 +H 5.53128874 0.87653800 -6.61624733 +H 6.70168137 0.85902635 -7.62984359 +O 0.35921371 7.78272581 0.92779636 +H 0.33955254 7.65595272 1.95023127 +H -0.57003051 7.61892999 0.59896908 +O 9.66377080 4.68256823 1.55730430 +H 8.94312649 3.99347302 1.59425106 +H 9.12089025 5.41769479 1.22888925 +O 7.65457008 9.64069496 -5.18343076 +H 6.71889770 10.06399282 -5.36783785 +H 7.86674566 9.22701576 -6.04725986 +O 7.19321761 7.29823464 -3.80100596 +H 6.56015700 6.73992439 -4.20133887 +H 7.11414012 8.15417328 -4.27363292 +O 3.83577940 1.78813133 -9.06883411 +H 4.53247690 1.32915811 -8.51485276 +H 3.49007109 1.14218766 -9.67998028 +O 5.41832971 4.07076363 -9.29354261 +H 5.48908171 4.86701095 -8.71798047 +H 4.68397254 3.57778432 -8.93660697 +O 5.43789885 9.40228872 -2.55111439 +H 5.53478981 8.57938118 -3.03901209 +H 6.35730989 9.67858848 -2.30146709 +O -0.45742934 2.92384837 4.23795020 +H -0.65542588 3.78038584 3.80834483 +H -0.37808374 2.22326659 3.64590428 +O 11.29795954 -2.96162904 4.75239636 +H 11.63370731 -2.27574515 5.29218659 +H 11.98621823 -3.65051989 4.71422796 +O 4.99707156 -1.79914799 -5.28772929 +H 4.51880831 -2.52931828 -4.83665169 +H 4.55020604 -1.70717848 -6.16555670 +O 2.45689908 4.45686228 -2.67399317 +H 1.51398216 4.27108297 -2.80060549 +H 2.66694593 3.70962297 -2.01741030 +O 3.73283820 -4.15860576 2.96998886 +H 4.08732955 -3.25525927 3.11614931 +H 3.82660862 -4.19314289 2.00934888 +O 3.79953928 3.53561128 -5.00221400 +H 3.17434628 3.25755097 -5.65336138 +H 3.29406548 3.75250667 -4.22005070 +O 2.15476289 2.61062944 -7.02913464 +H 2.47557818 2.36463061 -7.99045139 +H 1.25468277 2.75698642 -7.25518955 +O 4.88286219 6.36826713 -5.16303301 +H 4.34394281 7.02331963 -4.75813168 +H 4.30506585 5.73206177 -5.44919722 +O 7.54258972 -1.74845549 -1.20128842 +H 7.58173346 -0.96340903 -1.81213879 +H 8.41599553 -1.70098336 -0.75529423 +O 8.66587253 3.99443202 -4.83379584 +H 9.05848307 4.73782323 -5.32398176 +H 9.08641306 3.24755764 -5.24853036 +O 15.39832523 -0.98662008 -7.24558405 +H 14.81412921 -0.61721460 -7.92182780 +H 14.88249533 -0.75285373 -6.45380899 +O 8.73211726 0.85742774 4.18921288 +H 8.71727739 1.55957315 3.54206134 +H 8.81252752 0.01593544 3.72986823 +O 3.32413086 8.59329072 -4.72268559 +H 2.51972443 8.61143412 -4.19067201 +H 3.00530797 8.60420808 -5.62979986 +O 9.88683349 6.02693741 5.99064857 +H 10.66843185 6.47446641 6.38238368 +H 9.45847853 6.79275119 5.61687708 +O 5.48734339 -1.80547540 3.21362128 +H 5.37614757 -1.28745938 4.05714107 +H 5.55205282 -1.14821437 2.49504858 +O -0.17451136 1.95380021 -0.42983176 +H 0.74756628 2.13576872 -0.57275419 +H -0.83764648 2.59865739 -0.79248245 +O 12.26425852 4.05272251 -3.21409599 +H 12.35662902 3.10992710 -3.53322869 +H 11.49147736 4.13940388 -2.66280329 +O -0.98576882 10.01726713 -3.28890861 +H -1.54050933 9.23169822 -3.08255339 +H -1.55693518 10.58711799 -3.82222753 +O 10.32526061 7.73843560 -0.33229257 +H 10.23281998 7.39655498 -1.22803525 +H 9.60467759 7.22752309 0.25198323 +O 0.09191373 6.28553276 -5.26909244 +H 0.30345729 5.42888899 -4.86584086 +H 0.24416340 6.99184601 -4.61102483 +O -2.18445141 11.11099414 2.66233241 +H -1.77931618 10.42404589 3.27279560 +H -2.45449419 10.70582712 1.83155514 +O 11.83691986 11.62521338 6.29252911 +H 10.90703270 11.66245027 6.65664727 +H 11.98152631 12.58003326 6.01283684 +O 9.76700302 7.21345169 -3.05782750 +H 8.81888709 7.11975811 -3.43799470 +H 10.29610713 6.47686190 -3.37256470 +O 2.22433993 8.82465394 5.46407496 +H 2.53017747 9.68322136 5.08696224 +H 2.62159591 8.18963464 4.84191210 +O 2.58549224 10.22788385 -2.23574588 +H 3.28576690 9.54599998 -2.29861530 +H 2.05697668 10.04802514 -1.46372318 +O 1.28564872 10.23409319 0.08375371 +H 0.51315024 10.65646336 -0.17658479 +H 0.89435872 9.38464929 0.35596781 +O 6.46338348 4.56083691 -3.42884523 +H 7.25243635 4.40444161 -3.91165357 +H 5.65045951 4.36919349 -3.97438205 +O 5.12851460 6.42128330 4.49193755 +H 5.20109935 6.63813806 5.44949628 +H 4.39732180 7.02007805 4.19101922 +O 0.31002319 7.34990480 3.60793458 +H 1.09376589 7.03127626 4.00071569 +H -0.23051772 6.49087082 3.49320068 +O 7.85467960 2.94434063 -1.52839549 +H 7.18762033 3.47881011 -2.01180042 +H 7.32398761 2.43871845 -0.89548889 +O 7.99176053 6.67379648 0.76234189 +H 7.36968188 6.48516030 0.02147414 +H 7.39906311 7.03701090 1.43547078 +O 10.45810792 4.19159838 -1.06465671 +H 9.71439511 3.54579561 -1.27241836 +H 10.25866575 4.52896421 -0.14439244 +O 2.16580171 7.02507248 -1.05936971 +H 1.56300413 7.11891493 -0.25941855 +H 2.07623629 6.16423927 -1.48299475 +O 4.68508075 3.85099647 0.53238242 +H 5.13098521 4.42762464 -0.12485212 +H 5.02723072 4.13401269 1.40990289 +O 7.41492214 0.57564648 -2.89288637 +H 7.63746561 1.40778149 -2.49914757 +H 6.59782147 0.64798185 -3.36395253 +O 1.71626830 11.66007035 -4.47546514 +H 0.99756996 11.32581387 -5.05282264 +H 2.00055363 10.90357627 -3.92540839 +O 4.85017126 1.03969846 -4.52787580 +H 4.08444178 1.63223795 -4.64862906 +H 4.50350826 0.17230808 -4.81974036 +O 9.41760438 -0.98890426 7.68151902 +H 8.76346603 -1.69362425 7.48031621 +H 9.01846782 -0.30634124 8.18571242 +O 10.17759636 1.75304672 6.41252838 +H 10.73383750 2.36059625 5.95314219 +H 9.67149853 1.27545072 5.73203121 +O 4.28513592 8.22630015 0.13948157 +H 4.92185001 8.72436720 -0.37998991 +H 3.61827294 8.05475284 -0.47628170 +O 3.86459479 0.29107940 -1.75734214 +H 3.35482860 -0.52822670 -1.97160082 +H 4.17943753 0.58968815 -2.64543229 +O 6.90060092 8.00151268 3.01115132 +H 6.30143375 7.46163097 3.57494518 +H 6.55125677 8.87622169 3.02492108 diff --git a/examples/init_files/water_64mols.extxyz b/examples/init_files/water_64mols.extxyz new file mode 100644 index 000000000..7e35fe97f --- /dev/null +++ b/examples/init_files/water_64mols.extxyz @@ -0,0 +1,194 @@ +192 +Lattice="10.4119090601988 0 0 0 10.4119090601988 0 0 0 10.4119090601988" +O 11.18136 -7.24116 6.42199 +H 11.31672 -7.89411 5.71998 +H 11.94205 -7.06097 7.01033 +O 2.78582 1.60883 1.56485 +H 2.45814 1.98676 2.52844 +H 3.72449 1.60021 1.79886 +O 4.06425 1.21834 6.13650 +H 4.52259 0.84151 5.38020 +H 3.73582 0.62974 6.86168 +O -5.85212 -1.78980 -1.47238 +H -5.90795 -2.64483 -2.11048 +H -6.81342 -1.58626 -1.68821 +O -0.69190 1.48298 4.64653 +H -0.57700 1.71944 5.58467 +H -1.16810 2.29631 4.29351 +O 9.78623 -1.22461 5.88911 +H 9.05533 -0.91721 5.33231 +H 10.59603 -1.00085 5.39957 +O 1.78731 -5.40285 -2.77723 +H 2.33162 -5.12910 -2.00467 +H 0.89681 -5.12748 -2.70535 +O -2.75590 -8.62956 -0.10520 +H -2.53979 -8.69428 -1.07891 +H -2.75324 -7.69016 0.12631 +O 9.87767 -4.00367 7.00969 +H 9.30537 -3.91345 7.71858 +H 9.86640 -3.07612 6.67277 +O 1.36270 2.71836 3.60327 +H 0.90987 3.43987 3.16458 +H 0.69390 2.17126 4.04330 +O 7.35720 -5.27057 -1.72224 +H 8.03476 -6.10104 -1.79227 +H 6.40744 -5.61367 -2.01308 +O 7.59285 -3.91299 1.89032 +H 6.71605 -4.09193 1.42394 +H 7.44293 -4.07392 2.84248 +O -0.53502 -7.32429 -1.57639 +H 0.08940 -6.74166 -2.03905 +H -0.92479 -7.79351 -2.35343 +O 6.33684 6.38743 -5.76835 +H 5.27875 6.21603 -5.54541 +H 6.28403 7.30291 -6.28440 +O 4.69882 -1.31516 6.09464 +H 4.31123 -1.15051 5.12558 +H 4.03848 -1.19721 6.76146 +O 3.70821 -4.04859 4.85959 +H 3.88830 -4.26209 3.90588 +H 3.41156 -4.85543 5.33543 +O 4.25159 -7.25513 3.40025 +H 3.80863 -6.84649 4.18355 +H 4.58665 -8.16468 3.69969 +O 2.85185 -0.22288 -0.08384 +H 2.30198 0.32795 0.57462 +H 3.49964 0.50183 -0.31096 +O 0.71578 0.75467 -1.03772 +H 0.48930 1.73621 -0.79676 +H -0.11147 0.47379 -1.50236 +O 3.86173 -5.86884 0.83708 +H 3.02686 -6.20624 0.38164 +H 3.60762 -6.18672 1.72461 +O -2.65909 1.61105 2.65709 +H -2.81796 1.41394 1.66795 +H -2.90099 2.59787 2.79689 +O 8.58320 -0.93140 3.69116 +H 8.51457 -1.71811 3.08024 +H 9.40919 -0.52395 3.22850 +O 2.00819 -1.77043 1.77406 +H 1.71599 -2.29317 2.51221 +H 2.88786 -2.15737 1.53734 +O -1.21196 4.38114 0.57505 +H -1.88725 5.08448 0.43844 +H -1.31330 3.95262 -0.28572 +O 6.62006 -6.28562 3.52156 +H 6.70557 -5.37221 4.07543 +H 5.67024 -6.53243 3.51712 +O 4.55162 -4.02218 2.45618 +H 4.78639 -3.09848 2.15965 +H 3.76492 -4.29938 1.84435 +O -1.58811 -3.45511 4.54425 +H -2.07874 -3.09246 5.28050 +H -0.94080 -4.03592 4.85498 +O 0.63844 5.84407 -0.58258 +H 0.33058 6.12957 0.29606 +H 1.44170 6.38939 -0.65771 +O 13.89937 3.85311 -4.62853 +H 13.58234 2.94223 -4.24959 +H 14.94280 3.89592 -4.43418 +O 1.45155 -9.85714 -4.86694 +H 2.35131 -9.93790 -5.24325 +H 1.00248 -10.03331 -5.77904 +O 2.10425 -2.89321 -3.62158 +H 1.47224 -2.48362 -2.86866 +H 2.18045 -2.09609 -4.16680 +O 5.30876 -9.33887 2.23872 +H 6.09707 -9.59732 2.71391 +H 5.36099 -10.01325 1.53512 +O 9.39110 -6.28070 3.25110 +H 8.98146 -6.14406 4.06255 +H 8.78207 -5.97081 2.67205 +O 6.25165 -8.48610 -5.29389 +H 6.81062 -9.32378 -5.41835 +H 6.47210 -7.92782 -5.96594 +O -3.15468 -3.34260 7.11828 +H -2.83364 -4.08200 7.65508 +H -3.63428 -3.76480 6.37405 +O 5.85238 -8.41894 -2.66855 +H 5.35988 -8.45234 -1.87962 +H 5.37565 -8.88515 -3.35133 +O -4.47590 -1.40335 3.66515 +H -3.56824 -1.01032 3.81598 +H -4.73962 -1.16543 2.71828 +O -0.20781 -8.30570 1.23188 +H -0.68347 -8.80535 0.48392 +H -0.61830 -7.73467 1.86794 +O 4.95749 4.52203 -1.53048 +H 4.64077 5.16432 -2.29082 +H 4.44398 3.75315 -1.76902 +O -1.18170 -0.41798 -12.61310 +H -0.94931 -0.26291 -13.63669 +H -1.43151 -1.36626 -12.50848 +O 4.37654 -3.87984 -3.11203 +H 3.36699 -3.74856 -3.32174 +H 4.73860 -3.44669 -3.96314 +O 1.47263 -5.10769 2.05248 +H 1.54376 -5.28591 3.06801 +H 0.73852 -4.40355 2.11733 +O 0.57171 0.08269 2.96703 +H 1.33511 -0.28899 2.60400 +H 0.39918 0.95384 2.48030 +O 4.82014 1.75266 -0.26475 +H 4.07740 2.26716 -0.04860 +H 5.55096 2.23000 0.36991 +O 1.26659 -4.90102 -5.18088 +H 0.71571 -5.68172 -5.03880 +H 1.78228 -4.86123 -4.40607 +O -7.57618 -3.41768 -0.23405 +H -7.16860 -4.28058 0.15792 +H -6.80151 -2.90991 -0.56491 +O 6.24921 -6.16862 -4.16104 +H 7.07600 -6.28218 -4.74638 +H 6.36108 -6.98816 -3.57694 +O -1.82911 1.56633 -3.40176 +H -2.45012 2.25119 -3.81374 +H -2.40852 0.75307 -3.27997 +O 1.71669 3.71840 -0.28443 +H 1.27373 4.74944 -0.21805 +H 1.17547 3.28611 0.29122 +O 8.46853 -3.09340 9.86116 +H 7.80954 -2.56880 10.22497 +H 9.34209 -2.47122 9.85476 +O 3.21682 -7.79589 -1.99707 +H 2.52837 -7.35831 -1.41162 +H 2.92784 -8.70634 -2.22468 +O -3.96971 -0.48422 -0.87321 +H -4.71266 -0.93801 -1.27585 +H -3.40046 0.07288 -1.44726 +O 2.58880 0.07464 -2.64410 +H 1.88211 0.38311 -3.18472 +H 1.99881 -0.03955 -1.64188 +O -3.19736 -0.62180 -3.87710 +H -2.95370 -1.51924 -3.42177 +H -4.00833 -0.93762 -4.45389 +O 4.86152 -1.55101 1.42393 +H 5.64113 -1.93118 0.83995 +H 4.42948 -1.03684 0.61612 +O 0.96100 -1.84820 -1.40869 +H 0.12950 -1.31463 -1.51719 +H 1.27479 -1.83709 -0.53915 +O -1.55890 -6.13475 5.77682 +H -0.95828 -6.74283 6.34991 +H -1.41913 -5.28777 6.20053 +O 6.38516 3.66860 0.78566 +H 6.58667 4.01604 1.64321 +H 5.42592 3.87325 0.63911 +O 7.59422 -0.83492 1.07614 +H 7.07118 -1.52087 1.49718 +H 7.19591 -0.75122 0.17345 +O 3.47168 -0.43168 3.60482 +H 3.09120 -1.22210 3.21392 +H 3.70663 0.14389 2.92538 +O -0.36322 -3.35602 1.73591 +H -1.32945 -3.51529 1.69406 +H -0.17779 -2.37533 1.36604 +O 5.81550 6.35896 10.60725 +H 5.04874 5.77496 10.58989 +H 6.38013 6.03712 9.91339 +O 1.14085 -12.62231 4.16390 +H 1.78212 -13.35146 4.36508 +H 0.23752 -13.05745 4.08631 +O -0.35190 -11.38652 0.43131 +H -1.00022 -11.03186 1.01782 +H 0.38267 -10.78230 0.46692 diff --git a/ipi/__init__.py b/ipi/__init__.py index 1b337369a..b611ab7a1 100644 --- a/ipi/__init__.py +++ b/ipi/__init__.py @@ -12,6 +12,7 @@ "inputs", "interfaces", "utils", + "pes", "ipi_global_settings", "install_driver", "read_output", @@ -19,3 +20,10 @@ ] ipi_global_settings = {"floatformat": "%16.8e"} + +from ipi.engine.simulation import Simulation + + +class IPI: + def __init__(self, xml_data): + self._simulation = Simulation.load_from_xml(xml_data) diff --git a/ipi/engine/forcefields.py b/ipi/engine/forcefields.py index 0b994d1b4..fae7fafba 100644 --- a/ipi/engine/forcefields.py +++ b/ipi/engine/forcefields.py @@ -23,11 +23,9 @@ from ipi.utils.io import read_file from ipi.utils.units import unit_to_internal from ipi.utils.distance import vector_separation +from ipi.pes import __drivers__ -try: - import plumed -except ImportError: - plumed = None +plumed = None class ForceRequest(dict): @@ -391,6 +389,58 @@ def evaluate(self, request): request["status"] = "Done" +class FFDirect(FFEval): + def __init__( + self, + latency=1.0, + offset=0.0, + name="", + pars=None, + dopbc=False, + active=np.array([-1]), + threaded=False, + pes="dummy", + ): + """Initialises FFDirect. + + Args: + latency: The number of seconds the socket will wait before updating + the client list. + offset: A constant offset subtracted from the energy value given by the + client. + name: The name of the forcefield. + pars: A dictionary used to initialize the forcefield, if required. + Of the form {'name1': value1, 'name2': value2, ... }. + dopbc: Decides whether or not to apply the periodic boundary conditions + before sending the positions to the client code. + active: Indexes of active atoms in this forcefield + + """ + + super().__init__(latency, offset, name, pars, dopbc, active, threaded) + + self.pes = pes + try: + self.driver = __drivers__[self.pes](verbose=verbosity.high, **pars) + except ImportError: + # specific errors have already been triggered + raise + except Exception as err: + print(f"Error setting up PES mode {self.pes}") + print(__drivers__[self.pes].__doc__) + print("Error trace: ") + raise err + + def evaluate(self, request): + results = list(self.driver(request["cell"][0], request["pos"].reshape(-1, 3))) + + # ensure forces and virial have the correct shape to fit the results + results[1] = results[1].reshape(-1) + results[2] = results[2].reshape(3, 3) + request["result"] = results + request["status"] = "Done" + + class FFLennardJones(FFEval): """Basic fully pythonic force provider. @@ -409,12 +459,14 @@ class FFLennardJones(FFEval): def __init__( self, - latency=1.0e-3, + latency=1.0, offset=0.0, name="", pars=None, - dopbc=False, - threaded=False, + dopbc=True, + active=np.array([-1]), + threaded=True, + interface=None, ): """Initialises FFLennardJones. @@ -430,7 +482,7 @@ def __init__( # a socket to the communication library is created or linked super(FFLennardJones, self).__init__( - latency, offset, name, pars, dopbc=dopbc, threaded=threaded + latency, offset, name, pars, dopbc=dopbc, threaded=threaded, active=active ) self.epsfour = float(self.pars["eps"]) * 4 self.sixepsfour = 6 * self.epsfour @@ -678,8 +730,11 @@ def __init__( pars: Optional dictionary, giving the parameters needed by the driver. """ + global plumed # a socket to the communication library is created or linked - if plumed is None: + try: + import plumed + except ImportError: raise ImportError( "Cannot find plumed libraries to link to a FFPlumed object/" ) @@ -869,6 +924,14 @@ def __init__( """ + warning( + """ + is deprecated and might be removed in a future release of i-PI. + If you are interested in using it, please help port it to the PES + infrastructure. + """ + ) + from yaff import System, ForceField, log import codecs import locale @@ -961,6 +1024,14 @@ def __init__( """ + warning( + """ + is deprecated and might be removed in a future release of i-PI. + If you are interested in using it, please help port it to the PES + infrastructure. + """ + ) + # a socket to the communication library is created or linked super(FFsGDML, self).__init__( latency, offset, name, pars, dopbc, threaded=threaded diff --git a/ipi/engine/initializer.py b/ipi/engine/initializer.py index 03ee134ad..e609502b7 100644 --- a/ipi/engine/initializer.py +++ b/ipi/engine/initializer.py @@ -123,7 +123,7 @@ def init_file( ratoms = [] info( - " # Initializing from file %s. Dimension: %s, units: %s, cell_units: %s" + " @init_file: Initializing from file %s. Dimension: %s, units: %s, cell_units: %s" % (filename, dimension, units, cell_units), verbosity.low, ) @@ -283,7 +283,7 @@ def set_vector(iif, dq, rq): res = nm_rescale(nbeads, dbeads) # path rescaler if nbeads != dbeads: info( - " # Initialize is rescaling from %5d beads to %5d beads" + " @set_vector: Initialize is rescaling from %5d beads to %5d beads" % (nbeads, dbeads), verbosity.low, ) @@ -368,7 +368,7 @@ def init_stage1(self, simul): for k, v in self.queue: info( - " # Initializer (stage 1) parsing " + str(k) + " object.", + " @initializer: Initializer (stage 1) parsing " + str(k) + " object.", verbosity.high, ) @@ -491,7 +491,7 @@ def init_stage1(self, simul): rtemp = simul.ensemble.temp else: info( - " # Resampling velocities at temperature %s %s" + " @initializer: Resampling velocities at temperature %s %s" % (v.value, v.units), verbosity.low, ) @@ -615,7 +615,7 @@ def init_stage2(self, simul): for k, v in self.queue: info( - " # Initializer (stage 2) parsing " + str(k) + " object.", + " @initializer: Initializer (stage 2) parsing " + str(k) + " object.", verbosity.high, ) diff --git a/ipi/engine/motion/al6xxx_kmc.py b/ipi/engine/motion/al6xxx_kmc.py index 34f73dbf2..e4908d420 100755 --- a/ipi/engine/motion/al6xxx_kmc.py +++ b/ipi/engine/motion/al6xxx_kmc.py @@ -68,7 +68,7 @@ def __init__( thermostat=None, barostat=None, fixcom=False, - fixatoms=None, + fixatoms_dof=None, nmts=None, max_cache_len=1000, ): @@ -165,7 +165,7 @@ def __init__( # the KMC step is variable and so it cannot be stored as proper timing self._dt = depend_value(name="dt", value=0.0) - self.fixatoms = np.asarray([]) + self.fixatoms_dof = np.asarray([]) self.fixcom = True self.optimizer = [None] * self.neval # geop should not trigger exit if there is early convergence, but just carry on. @@ -174,7 +174,7 @@ def __init__( for i in range(self.neval): # geometry optimizer should not have *any* hystory dependence self.optimizer[i] = GeopMotion( - fixcom=fixcom, fixatoms=fixatoms, **optimizer + fixcom=fixcom, fixatoms_dof=fixatoms_dof, **optimizer ) # mode="cg", ls_options={"tolerance": 1, "iter": 20, "step": 1e-3, "adaptive": 0.0}, tolerances={"energy": 1e-7, "force": 1e-2, "position": 1e-4}, ) #!TODO: set the geop parameters properly # dictionary of previous energy evaluations - kind of tricky to use this with the omaker thingie diff --git a/ipi/engine/motion/alchemy.py b/ipi/engine/motion/alchemy.py index ee4448409..cc5f4bb2a 100644 --- a/ipi/engine/motion/alchemy.py +++ b/ipi/engine/motion/alchemy.py @@ -30,7 +30,7 @@ class AlchemyMC(Motion): """ def __init__( - self, fixcom=False, fixatoms=None, mode=None, names=[], nxc=1, ealc=None + self, fixcom=False, fixatoms_dof=None, mode=None, names=[], nxc=1, ealc=None ): """Initialises a "alchemical exchange" motion object. @@ -40,7 +40,7 @@ def __init__( """ - super(AlchemyMC, self).__init__(fixcom=fixcom, fixatoms=fixatoms) + super(AlchemyMC, self).__init__(fixcom=fixcom, fixatoms_dof=fixatoms_dof) self.names = names self.nxc = nxc diff --git a/ipi/engine/motion/atomswap.py b/ipi/engine/motion/atomswap.py index 99f62ab82..98570e4cf 100644 --- a/ipi/engine/motion/atomswap.py +++ b/ipi/engine/motion/atomswap.py @@ -25,7 +25,7 @@ class AtomSwap(Motion): """ def __init__( - self, fixcom=False, fixatoms=None, mode=None, names=[], nxc=1, ealc=None + self, fixcom=False, fixatoms_dof=None, mode=None, names=[], nxc=1, ealc=None ): """Initialises a "alchemical exchange" motion object. @@ -35,7 +35,7 @@ def __init__( """ - super(AtomSwap, self).__init__(fixcom=fixcom, fixatoms=fixatoms) + super(AtomSwap, self).__init__(fixcom=fixcom, fixatoms_dof=fixatoms_dof) self.names = names self.nxc = nxc diff --git a/ipi/engine/motion/dynamics.py b/ipi/engine/motion/dynamics.py index 9e3f1f8c2..e0ffd2a19 100644 --- a/ipi/engine/motion/dynamics.py +++ b/ipi/engine/motion/dynamics.py @@ -53,7 +53,7 @@ def __init__( thermostat=None, barostat=None, fixcom=False, - fixatoms=None, + fixatoms_dof=None, nmts=None, efield=None, bec=None, @@ -66,7 +66,7 @@ def __init__( motion will be constrained or not. Defaults to False. """ - super(Dynamics, self).__init__(fixcom=fixcom, fixatoms=fixatoms) + super(Dynamics, self).__init__(fixcom=fixcom, fixatoms_dof=fixatoms_dof) # initialize time step. this is the main time step that covers a full time step self._dt = depend_value(name="dt", value=timestep) @@ -76,7 +76,7 @@ def __init__( else: if ( thermostat.__class__.__name__ is ("ThermoPILE_G" or "ThermoNMGLEG ") - ) and (len(fixatoms) > 0): + ) and (len(fixatoms_dof) > 0): softexit.trigger( status="bad", message="!! Sorry, fixed atoms and global thermostat on the centroid not supported. Use a local thermostat. !!", @@ -115,21 +115,17 @@ def __init__( # constraints self.fixcom = fixcom - if fixatoms is None: - self.fixatoms = np.zeros(0, int) - self.fixatoms3 = np.zeros(0, int) + if fixatoms_dof is None: + self.fixatoms_dof = np.zeros(0, int) else: - self.fixatoms = fixatoms - self.fixatoms3 = np.array( - [[3 * i, 3 * i + 1, 3 * i + 2] for i in self.fixatoms] - ).flatten() + self.fixatoms_dof = fixatoms_dof def get_fixdof(self): """Calculate the number of fixed degrees of freedom, required for temperature and pressure calculations. """ - fixdof = len(self.fixatoms) * 3 * self.beads.nbeads + fixdof = len(self.fixatoms_dof) * self.beads.nbeads if self.fixcom: fixdof += 3 return fixdof @@ -279,8 +275,7 @@ def bind(self, motion): self.thermostat = motion.thermostat self.barostat = motion.barostat self.fixcom = motion.fixcom - self.fixatoms = motion.fixatoms - self.fixatoms3 = motion.fixatoms3 + self.fixatoms_dof = motion.fixatoms_dof self.enstype = motion.enstype # no need to dpipe these are really just references @@ -368,13 +363,14 @@ def pconstraints(self): self.ensemble.eens += np.sum(vcom**2) * 0.5 * Mnb # COM kinetic energy - if len(self.fixatoms) > 0: + if len(self.fixatoms_dof) > 0: m3 = dstrip(beads.m3) p = dstrip(beads.p) - fixatoms3 = self.fixatoms3 - self.ensemble.eens += 0.5 * np.sum(p[:, fixatoms3] ** 2 / m3[:, fixatoms3]) - beads.p[:, fixatoms3] = 0.0 + self.ensemble.eens += 0.5 * np.sum( + p[:, self.fixatoms_dof] ** 2 / m3[:, self.fixatoms_dof] + ) + beads.p[:, self.fixatoms_dof] = 0.0 dproperties( diff --git a/ipi/engine/motion/geop.py b/ipi/engine/motion/geop.py index 9847b868e..ca924c8fb 100755 --- a/ipi/engine/motion/geop.py +++ b/ipi/engine/motion/geop.py @@ -53,7 +53,7 @@ class GeopMotion(Motion): def __init__( self, fixcom=False, - fixatoms=None, + fixatoms_dof=None, mode="lbfgs", exit_on_convergence=True, biggest_step=100.0, @@ -81,7 +81,7 @@ def __init__( # raise ValueError("The optimization algorithm with fixatoms is not implemented. " # "We stop here. Comment this line and continue only if you know what you are doing") - super(GeopMotion, self).__init__(fixcom=fixcom, fixatoms=fixatoms) + super(GeopMotion, self).__init__(fixcom=fixcom, fixatoms_dof=fixatoms_dof) # Optimization Options @@ -158,7 +158,7 @@ def bind(self, ens, beads, nm, cell, bforce, prng, omaker): # Binds optimizer self.optimizer.bind(self) - if len(self.fixatoms) == len(self.beads[0]): + if len(self.fixatoms_dof) == 3 * len(self.beads[0]): softexit.trigger( status="bad", message="WARNING: all atoms are fixed, geometry won't change. Exiting simulation", @@ -202,10 +202,8 @@ def bind(self, dumop): self.fixatoms_mask = np.ones( 3 * dumop.beads.natoms, dtype=bool ) # Mask to exclude fixed atoms from 3N-arrays - if len(dumop.fixatoms) > 0: - self.fixatoms_mask[3 * dumop.fixatoms] = 0 - self.fixatoms_mask[3 * dumop.fixatoms + 1] = 0 - self.fixatoms_mask[3 * dumop.fixatoms + 2] = 0 + if len(dumop.fixatoms_dof) > 0: + self.fixatoms_mask[dumop.fixatoms_dof] = 0 def set_dir(self, x0, mdir): self.x0 = x0.copy() @@ -256,10 +254,8 @@ def bind(self, dumop): self.fixatoms_mask = np.ones( 3 * dumop.beads.natoms, dtype=bool ) # Mask to exclude fixed atoms from 3N-arrays - if len(dumop.fixatoms) > 0: - self.fixatoms_mask[3 * dumop.fixatoms] = 0 - self.fixatoms_mask[3 * dumop.fixatoms + 1] = 0 - self.fixatoms_mask[3 * dumop.fixatoms + 2] = 0 + if len(dumop.fixatoms_dof) > 0: + self.fixatoms_mask[dumop.fixatoms_dof] = 0 def __call__(self, x): """computes energy and gradient for optimization step""" @@ -298,7 +294,7 @@ def bind(self, geop): self.cell = geop.cell self.forces = geop.forces self.fixcom = geop.fixcom - self.fixatoms = geop.fixatoms + self.fixatoms_dof = geop.fixatoms_dof self.mode = geop.mode self.tolerances = geop.tolerances @@ -360,12 +356,10 @@ def exitstep(self, fx, u0, x): info(" @GEOP: Updating bead positions", verbosity.debug) self.qtime += time.time() - if len(self.fixatoms) > 0: + if len(self.fixatoms_dof) > 0: ftmp = self.forces.f.copy() for dqb in ftmp: - dqb[self.fixatoms * 3] = 0.0 - dqb[self.fixatoms * 3 + 1] = 0.0 - dqb[self.fixatoms * 3 + 2] = 0.0 + dqb[self.fixatoms_dof] = 0.0 fmax = np.amax(np.absolute(ftmp)) else: fmax = np.amax(np.absolute(self.forces.f)) @@ -440,21 +434,17 @@ def step(self, step=None): np.dot(self.forces.f.flatten(), self.forces.f.flatten()) ) - if len(self.fixatoms) > 0: + if len(self.fixatoms_dof) > 0: for dqb in self.d: - dqb[self.fixatoms * 3] = 0.0 - dqb[self.fixatoms * 3 + 1] = 0.0 - dqb[self.fixatoms * 3 + 2] = 0.0 + dqb[self.fixatoms_dof] = 0.0 self.old_x[:] = self.beads.q self.old_u[:] = self.forces.pot self.old_f[:] = self.forces.f - if len(self.fixatoms) > 0: + if len(self.fixatoms_dof) > 0: for dqb in self.old_f: - dqb[self.fixatoms * 3] = 0.0 - dqb[self.fixatoms * 3 + 1] = 0.0 - dqb[self.fixatoms * 3 + 2] = 0.0 + dqb[self.fixatoms_dof] = 0.0 fdf0 = (self.old_u, -self.old_f[:, self.gm.fixatoms_mask]) @@ -551,11 +541,9 @@ def step(self, step=None): self.old_u[:] = self.forces.pot self.old_f[:] = self.forces.f - if len(self.fixatoms) > 0: + if len(self.fixatoms_dof) > 0: for dqb in self.old_f: - dqb[self.fixatoms * 3] = 0.0 - dqb[self.fixatoms * 3 + 1] = 0.0 - dqb[self.fixatoms * 3 + 2] = 0.0 + dqb[self.fixatoms_dof] = 0.0 # Reduce dimensionality masked_old_x = self.old_x[:, self.gm.fixatoms_mask] @@ -659,11 +647,9 @@ def step(self, step=None): self.old_u[:] = self.forces.pot self.old_f[:] = self.forces.f - if len(self.fixatoms) > 0: + if len(self.fixatoms_dof) > 0: for dqb in self.old_f: - dqb[self.fixatoms * 3] = 0.0 - dqb[self.fixatoms * 3 + 1] = 0.0 - dqb[self.fixatoms * 3 + 2] = 0.0 + dqb[self.fixatoms_dof] = 0.0 # Reduce the dimensionality masked_old_x = self.old_x[:, self.gm.fixatoms_mask] @@ -768,11 +754,9 @@ def step(self, step=None): self.old_u[:] = self.forces.pot self.old_f[:] = self.forces.f - if len(self.fixatoms) > 0: + if len(self.fixatoms_dof) > 0: for dqb in self.old_f: - dqb[self.fixatoms * 3] = 0.0 - dqb[self.fixatoms * 3 + 1] = 0.0 - dqb[self.fixatoms * 3 + 2] = 0.0 + dqb[self.fixatoms_dof] = 0.0 fdf0 = (self.old_u, -self.old_f[:, self.gm.fixatoms_mask]) @@ -849,11 +833,9 @@ def step(self, step=None): self.old_f[:] = self.forces.f # Check for fixatoms - if len(self.fixatoms) > 0: + if len(self.fixatoms_dof) > 0: for dqb in self.old_f: - dqb[self.fixatoms * 3] = 0.0 - dqb[self.fixatoms * 3 + 1] = 0.0 - dqb[self.fixatoms * 3 + 2] = 0.0 + dqb[self.fixatoms_dof] = 0.0 dq1 = dstrip(self.old_f) @@ -956,11 +938,9 @@ def step(self, step=None): self.d[:] = dq1 self.old_f[:] = gradf1 - if len(self.fixatoms) > 0: + if len(self.fixatoms_dof) > 0: for dqb in dq1_unit: - dqb[self.fixatoms * 3] = 0.0 - dqb[self.fixatoms * 3 + 1] = 0.0 - dqb[self.fixatoms * 3 + 2] = 0.0 + dqb[self.fixatoms_dof] = 0.0 self.lm.set_dir(dstrip(self.beads.q), dq1_unit) diff --git a/ipi/engine/motion/instanton.py b/ipi/engine/motion/instanton.py index d7eb2e935..bffb6edd2 100644 --- a/ipi/engine/motion/instanton.py +++ b/ipi/engine/motion/instanton.py @@ -83,7 +83,7 @@ class InstantonMotion(Motion): def __init__( self, fixcom=False, - fixatoms=None, + fixatoms_dof=None, mode="None", tolerances={"energy": 1e-5, "force": 1e-4, "position": 1e-3}, biggest_step=0.3, @@ -118,7 +118,7 @@ def __init__( ): """Initialises InstantonMotion.""" - super(InstantonMotion, self).__init__(fixcom=fixcom, fixatoms=fixatoms) + super(InstantonMotion, self).__init__(fixcom=fixcom, fixatoms_dof=fixatoms_dof) self.options = {} # Optimization options @@ -862,7 +862,7 @@ def spring_hessian(natoms, nbeads, m3, omega2, mode="half", coef=None): class Mapper(object): """Creation of the multi-dimensional function that is the proxy between all the energy and force components and the optimization algorithm. - It also handles fixatoms""" + It also handles fixatoms_dof""" def __init__(self): """Initializes object for Mapper. @@ -894,7 +894,7 @@ def bind(self, dumop): self.nm = dumop.nm self.rp_factor = dumop.rp_factor - self.fixatoms = dumop.fixatoms + self.fixatoms_dof = dumop.fixatoms_dof self.fix = dumop.fix self.fixbeads = self.fix.fixbeads @@ -969,9 +969,9 @@ def bind(self, geop): self.cell = geop.cell self.forces = geop.forces self.fixcom = geop.fixcom - self.fixatoms = geop.fixatoms + self.fixatoms_dof = geop.fixatoms_dof - self.fix = Fix(self.fixatoms, self.beads, self.beads.nbeads) + self.fix = Fix(self.fixatoms_dof, self.beads, self.beads.nbeads) self.nm = geop.nm self.rp_factor = geop.rp_factor @@ -1055,7 +1055,7 @@ def initial_geo(self): verbosity.low, ) - fix_onebead = Fix(self.fixatoms, self.beads, 1) + fix_onebead = Fix(self.fixatoms_dof, self.beads, 1) active_hessian = fix_onebead.get_active_vector( self.optarrays["initial_hessian"], 2 ) @@ -1140,7 +1140,7 @@ def exitstep(self, d_x_max, step): x0=self.beads.q.copy(), natoms=self.beads.natoms, nbeads=self.beads.nbeads, - fixatoms=self.fixatoms, + fixatoms_dof=self.fixatoms_dof, friction=self.options["frictionSD"], ) @@ -1272,7 +1272,7 @@ def bind(self, geop): self.options["hessian_update"] = geop.options["hessian_update"] self.options["hessian_asr"] = geop.options["hessian_asr"] - if len(self.fixatoms) > 0: + if len(self.fixatoms_dof) > 0: info(" 'fixatoms' is enabled. Setting asr to None", verbosity.low) self.options["hessian_asr"] = "none" # self.output_maker = geop.output_maker @@ -1380,7 +1380,7 @@ def initialize(self, step): x0=self.beads.q.copy(), natoms=self.beads.natoms, nbeads=self.beads.nbeads, - fixatoms=self.fixatoms, + fixatoms_dof=self.fixatoms_dof, friction=self.options["frictionSD"], ) if self.options["friction"] and self.options["frictionSD"]: @@ -1422,7 +1422,7 @@ def update_hessian(self, update, active_hessian, new_x, d_x, d_g): x0=new_x, natoms=self.beads.natoms, nbeads=self.beads.nbeads, - fixatoms=self.fixatoms, + fixatoms_dof=self.fixatoms_dof, friction=self.options["frictionSD"], ) diff --git a/ipi/engine/motion/motion.py b/ipi/engine/motion/motion.py index abc484892..a1cb6e483 100644 --- a/ipi/engine/motion/motion.py +++ b/ipi/engine/motion/motion.py @@ -23,29 +23,29 @@ class Motion: each bead. fixcom: A boolean which decides whether the centre of mass motion will be constrained or not. - fixatoms: A list of atoms that should be held fixed to their + fixatoms_dof: A list of degrees of freedom that should be held fixed to their initial positions. Depend objects: none """ - def __init__(self, fixcom=False, fixatoms=None): + def __init__(self, fixcom=False, fixatoms_dof=None): """Initialises Motion object. Args: fixcom: An optional boolean which decides whether the centre of mass motion will be constrained or not. Defaults to False. - fixatoms: A list of atoms that should be held fixed to their - initial positions. + fixatoms_dof: A list of degrees of freedom that should be held fixed to their + initial positions. """ self._dt = depend_value(name="dt", value=0.0) self.fixcom = fixcom - if fixatoms is None: - self.fixatoms = np.zeros(0, int) + if fixatoms_dof is None: + self.fixatoms_dof = np.zeros(0, int) else: - self.fixatoms = fixatoms + self.fixatoms_dof = fixatoms_dof self.beads = self.cell = self.forces = self.prng = self.nm = self.enstype = None diff --git a/ipi/engine/motion/multi.py b/ipi/engine/motion/multi.py index 3e078e35d..3debd22d7 100644 --- a/ipi/engine/motion/multi.py +++ b/ipi/engine/motion/multi.py @@ -28,10 +28,10 @@ def __init__(self, motionlist=None): self.dt ) # DON'T ASK WHY BUT IF YOU DON'T DO THAT WEAKREFS TO SELF.DT WILL BE INVALIDATED - self.fixatoms = set(self.mlist[0].fixatoms) + self.fixatoms_dof = set(self.mlist[0].fixatoms_dof) for m in self.mlist: - self.fixatoms = self.fixatoms.intersection(m.fixatoms) - self.fixatoms = list(self.fixatoms) + self.fixatoms_dof = self.fixatoms_dof.intersection(m.fixatoms_dof) + self.fixatoms_dof = list(self.fixatoms_dof) self.fixcom = True # fixcom is true only if all movers are fixed for m in self.mlist: diff --git a/ipi/engine/motion/neb.py b/ipi/engine/motion/neb.py index 4b1c5068e..e72f17953 100644 --- a/ipi/engine/motion/neb.py +++ b/ipi/engine/motion/neb.py @@ -54,14 +54,11 @@ def bind(self, ens): self.dbeads = ens.beads.clone() self.dcell = ens.cell.clone() self.dforces = ens.forces.clone(self.dbeads, self.dcell) - self.fixatoms = ens.fixatoms.copy() + self.fixatoms_dof = ens.fixatoms_dof.copy() # Mask to exclude fixed atoms from 3N-arrays self.fixatoms_mask = np.ones(3 * ens.beads.natoms, dtype=bool) - if len(ens.fixatoms) > 0: - self.fixatoms_mask[3 * ens.fixatoms] = 0 - self.fixatoms_mask[3 * ens.fixatoms + 1] = 0 - self.fixatoms_mask[3 * ens.fixatoms + 2] = 0 + self.fixatoms_mask[ens.fixatoms_dof] = 0 # Create reduced bead and force object self.rbeads = Beads(ens.beads.natoms, ens.beads.nbeads - 2) @@ -111,12 +108,12 @@ def __call__(self, x): nimg = self.dbeads.nbeads # Number of atoms - nat = self.dbeads.natoms - len(self.fixatoms) + nactive_dof = 3 * self.dbeads.natoms - len(self.fixatoms_dof) # Array for spring constants kappa = np.zeros(nimg) - btau = np.zeros((nimg, 3 * nat), float) + btau = np.zeros((nimg, nactive_dof), float) for ii in range(1, nimg - 1): d1 = bq[ii] - bq[ii - 1] # tau minus d2 = bq[ii + 1] - bq[ii] # tau plus @@ -238,20 +235,18 @@ def bind(self, ens): """Creates reduced Beads object in order to calculate forces only for the climbing bead, and binds it to beads """ - self.fixatoms = ens.fixatoms.copy() + self.fixatoms_dof = ens.fixatoms_dof.copy() # A mask to exclude fixed atoms from 3N-arrays self.fixatoms_mask = np.ones(3 * ens.beads.natoms, dtype=bool) - if len(ens.fixatoms) > 0: - self.fixatoms_mask[3 * ens.fixatoms] = 0 - self.fixatoms_mask[3 * ens.fixatoms + 1] = 0 - self.fixatoms_mask[3 * ens.fixatoms + 2] = 0 + if len(ens.fixatoms_dof) > 0: + self.fixatoms_mask[self.fixatoms_dof] = 0 # Reduced Beads object is needed to calculate only required beads. self.rbeads = Beads(ens.beads.natoms, 1) self.rcell = ens.cell.clone() # Coords of the bead before and after the climbing one. - self.q_prev = np.zeros(3 * (ens.beads.natoms - len(ens.fixatoms))) - self.q_next = np.zeros(3 * (ens.beads.natoms - len(ens.fixatoms))) + self.q_prev = np.zeros(3 * ens.beads.natoms - len(ens.fixatoms_dof)) + self.q_next = np.zeros(3 * ens.beads.natoms - len(ens.fixatoms_dof)) # Make reduced forces dependent on reduced beads self.rforces = ens.forces.clone(self.rbeads, self.rcell) @@ -336,7 +331,7 @@ class NEBMover(Motion): def __init__( self, fixcom=False, - fixatoms=None, + fixatoms_dof=None, mode="damped_bfgs", biggest_step=0.5, old_coord=np.zeros(0, float), @@ -371,7 +366,7 @@ def __init__( motion will be constrained or not. Defaults to False. """ - super(NEBMover, self).__init__(fixcom=fixcom, fixatoms=fixatoms) + super(NEBMover, self).__init__(fixcom=fixcom, fixatoms_dof=fixatoms_dof) # Optimization options self.tolerances = tolerances @@ -420,7 +415,7 @@ def bind(self, ens, beads, nm, cell, bforce, prng, omaker): # and reduce it if needed, because someone may want to provide # existing hessian of the full system. if self.mode == "damped_bfgs": - n_activedim = beads.q[0].size - len(self.fixatoms) * 3 + n_activedim = beads.q[0].size - len(self.fixatoms_dof) if self.stage == "neb": if self.hessian.size == (n_activedim * (beads.nbeads - 2)) ** 2: # Desired dimension @@ -486,7 +481,7 @@ def bind(self, ens, beads, nm, cell, bforce, prng, omaker): else: raise ValueError("Hessian size does not match system size.") - if len(self.fixatoms) == len(self.beads[0]): + if len(self.fixatoms_dof) == 3 * len(self.beads[0]): softexit.trigger( status="bad", message="WARNING: all atoms are fixed, geometry won't change. Exiting simulation.", @@ -518,7 +513,7 @@ def init_climb(self): % (str(self.climbgm.q_prev.shape), str(self.climbgm.q_next.shape)), verbosity.debug, ) - n_activedim = self.beads.q[0].size - len(self.fixatoms) * 3 + n_activedim = self.beads.q[0].size - len(self.fixatoms_dof) if self.hessian.shape != (n_activedim, n_activedim): self.hessian = np.eye(n_activedim) @@ -591,7 +586,7 @@ def step(self, step=None): info(" @NEB STEP %d, stage: %s" % (step, self.stage), verbosity.debug) - n_activedim = self.beads.q[0].size - len(self.fixatoms) * 3 + n_activedim = self.beads.q[0].size - len(self.fixatoms_dof) # Check if we restarted a converged calculation (by mistake) if self.stage == "converged": diff --git a/ipi/engine/motion/phonons.py b/ipi/engine/motion/phonons.py index 5e1cd35e6..25dc5c0d8 100644 --- a/ipi/engine/motion/phonons.py +++ b/ipi/engine/motion/phonons.py @@ -34,7 +34,7 @@ class DynMatrixMover(Motion): def __init__( self, fixcom=False, - fixatoms=None, + fixatoms_dof=None, mode="fd", energy_shift=0.0, pos_shift=0.001, @@ -52,7 +52,7 @@ def __init__( refdynmatrix : A 3Nx3N array that stores the refined dynamic matrix. """ - super(DynMatrixMover, self).__init__(fixcom=fixcom, fixatoms=fixatoms) + super(DynMatrixMover, self).__init__(fixcom=fixcom, fixatoms_dof=fixatoms_dof) # Finite difference option. self.mode = mode @@ -77,13 +77,12 @@ def __init__( if self.prefix == "": self.prefix = "phonons" - if len(fixatoms) > 0: - fixdof = np.concatenate((3 * fixatoms, 3 * fixatoms + 1, 3 * fixatoms + 2)) - self.fixdof = np.sort(fixdof) + if len(fixatoms_dof) > 0: + self.fixatoms_dof = fixatoms_dof if self.mode == "enmfd" or self.mode == "nmfd": raise ValueError("Fixatoms is not implemented for the selected mode.") else: - self.fixdof = np.array([]) + self.fixatoms_dof = np.array([]) def bind(self, ens, beads, nm, cell, bforce, prng, omaker): super(DynMatrixMover, self).bind(ens, beads, nm, cell, bforce, prng, omaker) @@ -109,13 +108,15 @@ def step(self, step=None): else: self.phcalc.transform() self.refdynmatrix = self.apply_asr(self.refdynmatrix.copy()) - self.printall(self.prefix, self.refdynmatrix.copy(), fixdof=self.fixdof) + self.printall( + self.prefix, self.refdynmatrix.copy(), fixatoms_dof=self.fixatoms_dof + ) softexit.trigger( status="success", message="Dynamic matrix is calculated. Exiting simulation", ) - def printall(self, prefix, dmatx, deltaw=0.0, fixdof=np.array([])): + def printall(self, prefix, dmatx, deltaw=0.0, fixatoms_dof=np.array([])): """Prints out diagnostics for a given dynamical matrix.""" dmatx = dmatx + np.eye(len(dmatx)) * deltaw @@ -124,17 +125,19 @@ def printall(self, prefix, dmatx, deltaw=0.0, fixdof=np.array([])): else: wstr = "" - # get active arrays: - activedof = 3 * self.beads.natoms - fixdof.size - if fixdof.size > 0: - mask = np.delete(np.arange(3 * self.beads.natoms), fixdof) + # Get active arrays: + activedof = 3 * self.beads.natoms - fixatoms_dof.size + if fixatoms_dof.size > 0: + active_atoms_mask = np.delete( + np.arange(3 * self.beads.natoms), fixatoms_dof + ) else: - mask = np.arange(3 * self.beads.natoms) + active_atoms_mask = np.arange(3 * self.beads.natoms) dmatx_full = dmatx.copy() ism_full = self.ism.copy() - dmatx = dmatx[mask][:, mask] - ism = self.ism[mask] + dmatx = dmatx[active_atoms_mask][:, active_atoms_mask] + ism = self.ism[active_atoms_mask] # prints out the dynamical matrix outfile = self.output_maker.get_output(self.prefix + ".dynmat", "w") @@ -344,7 +347,7 @@ def bind(self, dm): def step(self, step=None): """Computes one row of the dynamic matrix.""" - if step not in self.dm.fixdof: + if step not in self.dm.fixatoms_dof: # initializes the finite deviation dev = np.zeros(3 * self.dm.beads.natoms, float) dev[step] = self.dm.deltax diff --git a/ipi/engine/motion/planetary.py b/ipi/engine/motion/planetary.py index 58ad1a553..11d36afff 100644 --- a/ipi/engine/motion/planetary.py +++ b/ipi/engine/motion/planetary.py @@ -53,7 +53,7 @@ def __init__( thermostat=None, barostat=None, fixcom=False, - fixatoms=None, + fixatoms_dof=None, nmts=None, ): """Initialises a "dynamics" motion object. @@ -73,7 +73,7 @@ def __init__( # the planetary step just computes constrained-centroid properties so it # should not advance the timer self._dt = depend_value(name="dt", value=0.0) - self.fixatoms = np.asarray([]) + self.fixatoms_dof = np.asarray([]) self.fixcom = True # nvt-cc means contstant-temperature with constrained centroid @@ -85,7 +85,7 @@ def __init__( thermostat=thermostat, nmts=nmts, fixcom=fixcom, - fixatoms=fixatoms, + fixatoms_dof=fixatoms_dof, ) def bind(self, ens, beads, nm, cell, bforce, prng, omaker): diff --git a/ipi/engine/motion/ramp.py b/ipi/engine/motion/ramp.py index 77a82fcf3..df5e21119 100644 --- a/ipi/engine/motion/ramp.py +++ b/ipi/engine/motion/ramp.py @@ -24,7 +24,7 @@ class TemperatureRamp(Motion): def __init__( self, fixcom=False, - fixatoms=None, + fixatoms_dof=None, t_start=1.0, t_end=1.0, total_steps=0, @@ -75,7 +75,7 @@ class PressureRamp(Motion): def __init__( self, fixcom=False, - fixatoms=None, + fixatoms_dof=None, p_start=1.0, p_end=1.0, total_steps=0, diff --git a/ipi/engine/motion/replay.py b/ipi/engine/motion/replay.py index c2de1cf8c..3f9cee312 100644 --- a/ipi/engine/motion/replay.py +++ b/ipi/engine/motion/replay.py @@ -39,7 +39,7 @@ class Replay(Motion): None really meaningful. """ - def __init__(self, fixcom=False, fixatoms=None, intraj=None): + def __init__(self, fixcom=False, fixatoms_dof=None, intraj=None): """Initialises Replay. Args: @@ -50,7 +50,7 @@ def __init__(self, fixcom=False, fixatoms=None, intraj=None): intraj: The input trajectory file. """ - super(Replay, self).__init__(fixcom=fixcom, fixatoms=fixatoms) + super(Replay, self).__init__(fixcom=fixcom, fixatoms_dof=fixatoms_dof) if intraj is None: raise ValueError( "Must provide an initialized InitFile object to read trajectory from" diff --git a/ipi/engine/motion/scphonons.py b/ipi/engine/motion/scphonons.py index 9c6cdad00..95ee83459 100644 --- a/ipi/engine/motion/scphonons.py +++ b/ipi/engine/motion/scphonons.py @@ -45,7 +45,7 @@ class SCPhononsMover(Motion): def __init__( self, fixcom=False, - fixatoms=None, + fixatoms_dof=None, mode="sc", dynmat=np.zeros(0, float), prefix="", @@ -72,7 +72,7 @@ def __init__( delta: A 3Nx3N array that stores the dynamic matrix. """ - super(SCPhononsMover, self).__init__(fixcom=fixcom, fixatoms=fixatoms) + super(SCPhononsMover, self).__init__(fixcom=fixcom, fixatoms_dof=fixatoms_dof) # Finite difference option. self.dynmatrix = dynmat diff --git a/ipi/engine/motion/stringmep.py b/ipi/engine/motion/stringmep.py index 3a1fc9311..66420173f 100644 --- a/ipi/engine/motion/stringmep.py +++ b/ipi/engine/motion/stringmep.py @@ -64,14 +64,12 @@ def bind(self, ens): self.dbeads = ens.beads.clone() self.dcell = ens.cell.clone() self.dforces = ens.forces.clone(self.dbeads, self.dcell) - self.fixatoms = ens.fixatoms.copy() + self.fixatoms_dof = ens.fixatoms_dof.copy() # Mask to exclude fixed atoms from 3N-arrays - self.fixmask = np.ones(3 * ens.beads.natoms, dtype=bool) - if len(ens.fixatoms) > 0: - self.fixmask[3 * ens.fixatoms] = 0 - self.fixmask[3 * ens.fixatoms + 1] = 0 - self.fixmask[3 * ens.fixatoms + 2] = 0 + self.fixatoms_mask = np.ones(3 * ens.beads.natoms, dtype=bool) + if len(ens.fixatoms_dof) > 0: + self.fixatoms_mask[self.fixatoms_dof] = 0 # Create reduced bead and force object self.rbeads = Beads(ens.beads.natoms, ens.beads.nbeads - 2) @@ -84,18 +82,20 @@ def __call__(self, x): # Bead positions # Touch positions only if they have changed (to avoid triggering forces) # I need both dbeads and rbeads because of the endpoint tangents. - if (self.rbeads.q[:, self.fixmask] != x).any(): - self.rbeads.q[:, self.fixmask] = x - rbq = self.rbeads.q[:, self.fixmask] + if (self.rbeads.q[:, self.fixatoms_mask] != x).any(): + self.rbeads.q[:, self.fixatoms_mask] = x + rbq = self.rbeads.q[:, self.fixatoms_mask] # We need all beads, but only reduced number is being updated. - self.dbeads.q[1:-1, self.fixmask] = rbq + self.dbeads.q[1:-1, self.fixatoms_mask] = rbq # Forces and energies - rbf = dstrip(self.rforces.f).copy()[:, self.fixmask] + rbf = dstrip(self.rforces.f).copy()[:, self.fixatoms_mask] be = dstrip(self.rforces.pots).copy() # Calculate the force component perpendicular to the spline. - tangent = spline_derv(self.dbeads.q[:, self.fixmask], self.dbeads.nbeads)[1:-1] + tangent = spline_derv(self.dbeads.q[:, self.fixatoms_mask], self.dbeads.nbeads)[ + 1:-1 + ] rbf_perp = rbf - tangent * np.sum(rbf * tangent, axis=1)[:, np.newaxis] # Return potential energy of the whole string and minus f_perpendicular @@ -133,14 +133,12 @@ def bind(self, ens): self.dbeads = ens.beads.clone() self.dcell = ens.cell.clone() self.dforces = ens.forces.clone(self.dbeads, self.dcell) - self.fixatoms = ens.fixatoms.copy() + self.fixatoms_dof = ens.fixatoms_dof.copy() # Mask to exclude fixed atoms from 3N-arrays - self.fixmask = np.ones(3 * ens.beads.natoms, dtype=bool) - if len(ens.fixatoms) > 0: - self.fixmask[3 * ens.fixatoms] = 0 - self.fixmask[3 * ens.fixatoms + 1] = 0 - self.fixmask[3 * ens.fixatoms + 2] = 0 + self.fixatoms_mask = np.ones(3 * ens.beads.natoms, dtype=bool) + if len(ens.fixatoms_dof) > 0: + self.fixatoms_mask[self.fixatoms_dof] = 0 # Create reduced bead and force object self.rbeads = Beads(ens.beads.natoms, ens.beads.nbeads - 2) @@ -153,14 +151,14 @@ def __call__(self, x): # Bead positions # Touch positions only if they have changed (to avoid triggering forces) # I need both dbeads and rbeads because of the endpoint tangents. - if (self.rbeads.q[:, self.fixmask] != x).any(): - self.rbeads.q[:, self.fixmask] = x - rbq = self.rbeads.q[:, self.fixmask] + if (self.rbeads.q[:, self.fixatoms_mask] != x).any(): + self.rbeads.q[:, self.fixatoms_mask] = x + rbq = self.rbeads.q[:, self.fixatoms_mask] # We need all beads, but only reduced number is being updated. - self.dbeads.q[1:-1, self.fixmask] = rbq + self.dbeads.q[1:-1, self.fixatoms_mask] = rbq # Forces - rbf = dstrip(self.rforces.f).copy()[:, self.fixmask] + rbf = dstrip(self.rforces.f).copy()[:, self.fixatoms_mask] be = dstrip(self.rforces.pots).copy() # Return potential energy of the whole string and full force gradient @@ -189,20 +187,22 @@ def bind(self, ens): """Creates reduced Beads object in order to calculate forces only for the climbing bead, and binds it to beads """ - self.fixatoms = ens.fixatoms.copy() + self.fixatoms_dof = ens.fixatoms_dof.copy() # A mask to exclude fixed atoms from 3N-arrays - self.fixmask = np.ones(3 * ens.beads.natoms, dtype=bool) - if len(ens.fixatoms) > 0: - self.fixmask[3 * ens.fixatoms] = 0 - self.fixmask[3 * ens.fixatoms + 1] = 0 - self.fixmask[3 * ens.fixatoms + 2] = 0 + self.fixatoms_mask = np.ones(3 * ens.beads.natoms, dtype=bool) + if len(ens.fixatoms_dof) > 0: + self.ffixatoms_mask[ens.fixatoms_dof] = 0 # Reduced Beads object is needed to calculate only required beads. self.rbeads = Beads(ens.beads.natoms, 1) self.rcell = ens.cell.clone() # Coords of the bead before and after the climbing one. - self.q_prev = np.zeros(3 * (ens.beads.natoms - len(ens.fixatoms))) - self.q_next = np.zeros(3 * (ens.beads.natoms - len(ens.fixatoms))) + self.q_prev = np.zeros( + 3 * (ens.beads.natoms - len(ens.fixatoms)) + ) # ALBERTO HERE + self.q_next = np.zeros( + 3 * (ens.beads.natoms - len(ens.fixatoms)) + ) # ALBERTO HERE # Make reduced forces dependent on reduced beads self.rforces = ens.forces.clone(self.rbeads, self.rcell) @@ -216,15 +216,15 @@ def __call__(self, x): vrb.debug, ) # Touch positions only if they have changed (to avoid triggering forces) - if (self.rbeads.q[:, self.fixmask] != x).any(): - self.rbeads.q[:, self.fixmask] = x + if (self.rbeads.q[:, self.fixatoms_mask] != x).any(): + self.rbeads.q[:, self.fixatoms_mask] = x # Compared to stringgradientMapper, I need to flatten here, # otherwise it's (1, 3N) instead of just 3N. - rbq = self.rbeads.q[:, self.fixmask].flatten() + rbq = self.rbeads.q[:, self.fixatoms_mask].flatten() # Reduced forces # We don't need copy() because flatten() implies copying. - rbf = dstrip(self.rforces.f)[:, self.fixmask].flatten() + rbf = dstrip(self.rforces.f)[:, self.fixatoms_mask].flatten() # I think here it's better to use plain tangents. # Then we don't need energies of the neighboring beads. @@ -272,7 +272,7 @@ class StringMover(Motion): def __init__( self, fixcom=False, - fixatoms=None, + fixatoms_dof=None, mode="damped_bfgs", biggest_step=0.5, old_coord=np.zeros(0, float), @@ -306,7 +306,7 @@ def __init__( motion will be constrained or not. Defaults to False. """ - super(StringMover, self).__init__(fixcom=fixcom, fixatoms=fixatoms) + super(StringMover, self).__init__(fixcom=fixcom, fixatoms_dof=fixatoms_dof) # Optimization options self.tolerances = tolerances @@ -358,7 +358,7 @@ def bind(self, ens, beads, nm, cell, bforce, prng, omaker): # and reduce it if needed, because someone may want to provide # existing Hessian of the full system. if self.mode in ["damped_bfgs", "bfgstrm"]: - n_activedim = beads.q[0].size - len(self.fixatoms) * 3 + n_activedim = beads.q[0].size - len(self.fixatoms_dof) if self.stage == "string": if self.hessian.size == (n_activedim * (beads.nbeads - 2)) ** 2: # Desired dimension @@ -381,8 +381,8 @@ def bind(self, ens, beads, nm, cell, bforce, prng, omaker): ] )[ np.ix_( - np.tile(self.stringgm.fixmask, self.beads.nbeads - 2), - np.tile(self.stringgm.fixmask, self.beads.nbeads - 2), + np.tile(self.stringgm.fixatoms_mask, self.beads.nbeads - 2), + np.tile(self.stringgm.fixatoms_mask, self.beads.nbeads - 2), ) ] elif self.hessian.size == 0: @@ -412,7 +412,7 @@ def bind(self, ens, beads, nm, cell, bforce, prng, omaker): vrb.high, ) self.hessian = self.hessian[ - np.ix_(self.climbgm.fixmask, self.climbgm.fixmask) + np.ix_(self.climbgm.fixatoms_mask, self.climbgm.fixatoms_mask) ] if self.hessian.size == 0: info( @@ -424,7 +424,7 @@ def bind(self, ens, beads, nm, cell, bforce, prng, omaker): else: raise ValueError("Hessian size does not match system size.") - if len(self.fixatoms) == len(self.beads[0]): + if len(self.fixatoms_dof) == 3 * len(self.beads[0]): softexit.trigger( status="bad", message="WARNING: all atoms are fixed, geometry won't change. Exiting simulation.", @@ -449,8 +449,8 @@ def init_climb(self): status="bad", message="ERROR: climbing bead is the endpoint." ) self.climbgm.rbeads.q[:] = self.beads.q[cl_indx] - self.climbgm.q_prev[:] = self.beads.q[cl_indx - 1, self.climbgm.fixmask] - self.climbgm.q_next[:] = self.beads.q[cl_indx + 1, self.climbgm.fixmask] + self.climbgm.q_prev[:] = self.beads.q[cl_indx - 1, self.climbgm.fixatoms_mask] + self.climbgm.q_next[:] = self.beads.q[cl_indx + 1, self.climbgm.fixatoms_mask] info( "q_prev.shape: %s, q_next.shape: %s" % (str(self.climbgm.q_prev.shape), str(self.climbgm.q_next.shape)), @@ -459,12 +459,12 @@ def init_climb(self): info(" @STRING_CLIMB: call StringClimbGrMapper for the first time.", vrb.debug) self.stringpot, self.stringgrad = self.climbgm( - self.beads.q[cl_indx, self.climbgm.fixmask] + self.beads.q[cl_indx, self.climbgm.fixatoms_mask] ) if self.mode in ["damped_bfgs", "bfgstrm"]: # Initialize BFGS Hessian for a single bead - n_activedim = self.beads.q[0].size - len(self.fixatoms) * 3 + n_activedim = self.beads.q[0].size - len(self.fixatoms_dof) if self.hessian.shape != (n_activedim, n_activedim): self.hessian = np.eye(n_activedim) elif self.mode == "fire": @@ -475,7 +475,7 @@ def init_climb(self): self.N_up = 0 self.dt_fire = 0.1 - self.old_x = dstrip(self.beads.q[cl_indx, self.climbgm.fixmask]).copy() + self.old_x = dstrip(self.beads.q[cl_indx, self.climbgm.fixatoms_mask]).copy() self.stage = "climb" return cl_indx @@ -500,12 +500,12 @@ def path_step_textbook2002(self, step=None): # Shortcuts for prettier expresions nbeads = self.beads.nbeads natoms = self.beads.natoms - fixmask = self.stringgm.fixmask + fixatoms_mask = self.stringgm.fixatoms_mask - n_activedim = self.beads.q[0].size - len(self.fixatoms) * 3 + n_activedim = self.beads.q[0].size - len(self.fixatoms_dof) # Store 'old' resampled positions - self.old_x[:] = self.beads.q[1:-1, fixmask] + self.old_x[:] = self.beads.q[1:-1, fixatoms_mask] # 'Self' stringpot will be updated later on, # therefore we store the copy to check convergence in the end. @@ -599,7 +599,7 @@ def path_step_textbook2002(self, step=None): info(" @EULER: WARNING: hit the big_step.") dq *= self.big_step / np.amax(np.abs(dq)) info(" @EULER: maxdispl is %g" % np.amax(np.abs(dq))) - self.beads.q[1:-1, fixmask] += dq.reshape((nbeads - 2, -1)) + self.beads.q[1:-1, fixatoms_mask] += dq.reshape((nbeads - 2, -1)) # info(" @EULER: calling the mapper.", vrb.debug) self.stringgm.dbeads.q[:] = self.beads.q[:] # self.stringpot, self.stringgrad = self.stringgm(self.beads.q[1:-1, fixmask]) @@ -618,14 +618,16 @@ def path_step_textbook2002(self, step=None): # Resample the beads after an optimizer step. info(" @STRING: resampling beads uniformly.", vrb.debug) - self.beads.q[:, fixmask] = spline_resample( - self.beads.q[:, fixmask], + self.beads.q[:, fixatoms_mask] = spline_resample( + self.beads.q[:, fixatoms_mask], nbeads, ) # Here the forces are called on resampled positions. info(" @STRING: calling forces on resampled positions.", vrb.debug) - self.stringpot, self.stringgrad = self.stringgm(self.beads.q[1:-1, fixmask]) + self.stringpot, self.stringgrad = self.stringgm( + self.beads.q[1:-1, fixatoms_mask] + ) # This transfers forces from the mapper beads to the "main" beads, # so that recalculation won't be triggered after the step. # We need to keep forces up to date to be able to output @@ -645,16 +647,16 @@ def path_step_textbook2002(self, step=None): self.full_v = dstrip(self.forces.pots) # Calculate the force component perpendicular to the spline to check convergence. - tangent = spline_derv(self.beads.q[:, fixmask], nbeads)[1:-1] + tangent = spline_derv(self.beads.q[:, fixatoms_mask], nbeads)[1:-1] f_perp = ( - self.full_f[1:-1, fixmask] + self.full_f[1:-1, fixatoms_mask] - tangent - * np.sum(self.full_f[1:-1, fixmask] * tangent, axis=1)[:, np.newaxis] + * np.sum(self.full_f[1:-1, fixatoms_mask] * tangent, axis=1)[:, np.newaxis] ) # Check convergence at the resampled positions. # dx = current resampled position - previous resampled position. - dx = np.amax(np.abs(self.beads.q[1:-1, fixmask] - self.old_x)) + dx = np.amax(np.abs(self.beads.q[1:-1, fixatoms_mask] - self.old_x)) de = np.amax(np.abs(self.stringpot - old_stringpot)) / (nbeads * natoms) if ( (de <= self.tolerances["energy"]) @@ -720,7 +722,7 @@ def path_step_single_f_call(self, step=None): # natoms = self.beads.natoms # fixmask = self.stringgm.fixmask - # n_activedim = self.beads.q[0].size - len(self.fixatoms) * 3 + # n_activedim = self.beads.q[0].size - len(self.fixatoms_dof) # # Resample beads in the beginning of every step. # info(" @STRING: resampling beads uniformly.", vrb.debug) @@ -1023,17 +1025,17 @@ def climb_step(self, step=None): # Use to determine converged minimization # max displacement dx = np.amax( - np.abs(self.beads.q[self.cl_indx, self.climbgm.fixmask] - self.old_x) + np.abs(self.beads.q[self.cl_indx, self.climbgm.fixatoms_mask] - self.old_x) ) # Store old positions - self.old_x[:] = self.beads.q[self.cl_indx, self.climbgm.fixmask] + self.old_x[:] = self.beads.q[self.cl_indx, self.climbgm.fixatoms_mask] # This transfers forces from the climbing mapper to the "main" beads, # so that recalculation won't be triggered after the step. tmp_f = self.full_f.copy() tmp_v = self.full_v.copy() - tmp_f[self.cl_indx, self.climbgm.fixmask] = self.stringgrad + tmp_f[self.cl_indx, self.climbgm.fixatoms_mask] = self.stringgrad tmp_v[self.cl_indx] = self.stringpot self.forces.transfer_forces_manual( new_q=[ @@ -1119,8 +1121,8 @@ def step(self, step=None): if step == 0: # TODO add a condition when after the endpoints. # Make sure the beads are equidistant before we start info(" @STRING: resampling beads uniformly at step 0.", vrb.debug) - self.beads.q[:, self.stringgm.fixmask] = spline_resample( - self.beads.q[:, self.stringgm.fixmask], + self.beads.q[:, self.stringgm.fixatoms_mask] = spline_resample( + self.beads.q[:, self.stringgm.fixatoms_mask], self.beads.nbeads, ) @@ -1141,14 +1143,16 @@ def step(self, step=None): ) info(" @STRING: calling StringGradientMapper at step 0.", vrb.debug) self.stringpot, self.stringgrad = self.stringgm( - self.beads.q[1:-1, self.stringgm.fixmask] + self.beads.q[1:-1, self.stringgm.fixatoms_mask] ) info( " @STRING: StringGradientMapper returned stringpot and stringgrad.", vrb.debug, ) # Store old bead positions at step 0 - self.old_x = dstrip(self.beads.q[1:-1, self.stringgm.fixmask]).copy() + self.old_x = dstrip( + self.beads.q[1:-1, self.stringgm.fixatoms_mask] + ).copy() self.path_step_textbook2002(step) diff --git a/ipi/engine/motion/vscf.py b/ipi/engine/motion/vscf.py index effe76c27..4d49cd6fd 100644 --- a/ipi/engine/motion/vscf.py +++ b/ipi/engine/motion/vscf.py @@ -51,7 +51,7 @@ class NormalModeMover(Motion): def __init__( self, fixcom=False, - fixatoms=None, + fixatoms_dof=None, mode="imf", dynmat=np.zeros(0, float), prefix="", @@ -85,7 +85,7 @@ def __init__( refdynmatrix : A 3Nx3N array that stores the refined dynamic matrix. """ - super(NormalModeMover, self).__init__(fixcom=fixcom, fixatoms=fixatoms) + super(NormalModeMover, self).__init__(fixcom=fixcom, fixatoms_dof=fixatoms_dof) # Finite difference option. self.mode = mode diff --git a/ipi/engine/properties.py b/ipi/engine/properties.py index a3ab7edc7..6bc259c30 100644 --- a/ipi/engine/properties.py +++ b/ipi/engine/properties.py @@ -998,14 +998,14 @@ def __getitem__(self, key): pkey = self.property_dict[key] # pkey["func"](*arglist,**kwarglist) gives the value of the property - # in atomic units. unit_to_user() returns the value in the user + # in atomic units. use unit_to_user() to convert the value in the user # specified units. with self._threadlock: value = pkey["func"](*arglist, **kwarglist) if "dimension" in pkey: dimension = pkey["dimension"] else: - dimension = "" + dimension = "undefined" return value, dimension, unit def tensor2vec(self, tensor): @@ -1075,9 +1075,8 @@ def get_temp(self, atom="", bead="", nm=""): """ if self.ensemble.temp > 0 and ( - self.motion.fixcom or len(self.motion.fixatoms) > 0 + self.motion.fixcom or len(self.motion.fixatoms_dof) > 0 ): - dp = np.zeros_like(self.beads.p) # correction tempfactor = np.sqrt(Constants.kb * self.ensemble.temp * self.beads.nbeads) @@ -1090,10 +1089,10 @@ def get_temp(self, atom="", bead="", nm=""): dp += dstrip(self.beads.m3) * vcm - if len(self.motion.fixatoms) > 0: - for i in self.motion.fixatoms: - pi = self.beads.sm3[0, 3 * i] * tempfactor - dp[:, 3 * i : 3 * i + 3] = pi + if len(self.motion.fixatoms_dof) > 0: + for i in self.motion.fixatoms_dof: + pi = self.beads.sm3[0, i] * tempfactor + dp[:, i] = pi # we have to change p in place because the kinetic energy # can depend on nm masses diff --git a/ipi/engine/simulation.py b/ipi/engine/simulation.py index ce896971f..122b012f3 100644 --- a/ipi/engine/simulation.py +++ b/ipi/engine/simulation.py @@ -16,11 +16,12 @@ from copy import deepcopy from ipi.utils.depend import depend_value, dpipe, dproperties -from ipi.utils.io.inputs.io_xml import xml_parse_file +from ipi.utils.io.inputs.io_xml import xml_parse_file, xml_parse_string, xml_write from ipi.utils.messages import verbosity, info, warning, banner from ipi.utils.softexit import softexit import ipi.engine.outputs as eoutputs import ipi.inputs.simulation as isimulation +import threading from concurrent.futures import ThreadPoolExecutor @@ -59,7 +60,7 @@ class Simulation: @staticmethod def load_from_xml( - fn_input, + xml_input, custom_verbosity=None, sockets_prefix=None, request_banner=False, @@ -68,7 +69,7 @@ def load_from_xml( """Load an XML input file and return a `Simulation` object. Arguments: - fn_input (str): Name of the input file. + xml_input (str | file): XML-formatted string, or open file handle custom_verbosity (str): If not `None`, overrides the verbosity specified by the input file. request_banner (bool): Whether to print the i-PI banner, @@ -77,7 +78,10 @@ def load_from_xml( """ # parse the file - xmlrestart = xml_parse_file(open(fn_input)) + if type(xml_input) is str: + xmlrestart = xml_parse_string(xml_input) + else: + xmlrestart = xml_parse_file(xml_input) # prepare the simulation input object input_simulation = isimulation.InputSimulation() @@ -103,19 +107,14 @@ def load_from_xml( # create the simulation object simulation = input_simulation.fetch() - # pipe between the components of the simulation - simulation.bind(read_only) - # echo the input file if verbose enough - if verbosity.low: - print(" # i-PI loaded input file: ", fn_input) - elif verbosity.medium: + if verbosity.medium: print(" --- begin input file content ---") - ifile = open(fn_input, "r") - for line in ifile.readlines(): - print(line, end=" ") + print(xml_write(xmlrestart)) print(" --- end input file content ---") - ifile.close() + + # pipe between the components of the simulation + simulation.bind(read_only) return simulation @@ -151,7 +150,7 @@ def __init__( cumulative total. """ - info(" # Initializing simulation object ", verbosity.low) + info(" @simulation: Initializing simulation object ", verbosity.low) self.prng = prng self.mode = mode self.threading = threads @@ -161,6 +160,12 @@ def __init__( self.syslist = syslist for s in syslist: s.prng = self.prng # bind the system's prng to self prng + if threading.current_thread() == threading.main_thread(): + info( + "@ RANDOM SEED: The seed used in this calculation was " + + str(self.prng.seed), + verbosity.low, + ) s.init.init_stage1(s) # TODO - does this have any meaning now that we introduce the smotion class? @@ -258,6 +263,14 @@ def bind(self, read_only=False): if self.smotion is not None: self.smotion.bind(self.syslist, self.prng, self.output_maker) + # registers the softexit routine + softexit.register_function(self.softexit) + softexit.start(self.ttime) + + # starts tracemalloc to debug memory leaks + if verbosity.debug: + tracemalloc.start(10) + def softexit(self): """Deals with a soft exit request. @@ -268,12 +281,14 @@ def softexit(self): if self.step < self.tsteps: self.step += 1 if not self.rollback: - info("SOFTEXIT: Saving the latest status at the end of the step") + info( + " @simulation.softexit: Saving the latest status at the end of the step" + ) self.chk.store() self.chk.write(store=False) - def run(self): + def run(self, write_outputs=True): """Runs the simulation. Does all the simulation steps, and outputs data to the appropriate files @@ -281,16 +296,8 @@ def run(self): in the communication between the driver and the PIMD code. """ - # registers the softexit routine - softexit.register_function(self.softexit) - softexit.start(self.ttime) - - # starts tracemalloc to debug memory leaks - if verbosity.debug: - tracemalloc.start(10) - # prints inital configuration -- only if we are not restarting - if self.step == 0: + if self.step == 0 and write_outputs: self.step = -1 # must use multi-threading to avoid blocking in multi-system runs with WTE if self.threading: @@ -328,44 +335,25 @@ def run(self): if self.step % self.safe_stride == 0: self.chk.store() - if len(self.syslist) > 0 and self.threading: - stepthreads = [] - # steps through all the systems - for s in self.syslist: - # creates separate threads for the different systems - st = self.executor.submit(s.motion.step, step=self.step) - stepthreads.append(st) - - for st in stepthreads: - st.result() - else: - for s in self.syslist: - s.motion.step(step=self.step) - - if softexit.triggered: - # Don't continue if we are about to exit. - break - - # does the "super motion" step - if self.smotion is not None: - self.smotion.step(self.step) + self.run_step(self.step) if softexit.triggered: # Don't write if we are about to exit. break - if self.threading: - stepthreads = [] - for o in self.outputs: - if o.active(): # don't start a thread if it's not needed - st = self.executor.submit(o.write) - stepthreads.append(st) + if write_outputs: + if self.threading: + stepthreads = [] + for o in self.outputs: + if o.active(): # don't start a thread if it's not needed + st = self.executor.submit(o.write) + stepthreads.append(st) - for st in stepthreads: - st.result() - else: - for o in self.outputs: - o.write() + for st in stepthreads: + st.result() + else: + for o in self.outputs: + o.write() steptime += time.time() ttot += steptime @@ -377,7 +365,7 @@ def run(self): or (verbosity.low and self.step % 1000 == 0) ): info( - " # Average timings at MD step % 7d. t/step: %10.5e" + " @simulation.run: Average timings at MD step % 7d. t/step: %10.5e" % (self.step, ttot / cstep) ) cstep = 0 @@ -396,14 +384,43 @@ def run(self): info(line) if os.path.exists("EXIT"): - info(" # EXIT file detected! Bye bye!", verbosity.low) + info(" @simulation.run: EXIT file detected! Bye bye!", verbosity.low) break if (self.ttime > 0) and (time.time() - simtime > self.ttime): - info(" # Wall clock time expired! Bye bye!", verbosity.low) + info( + " @simulation.run: Wall clock time expired! Bye bye!", verbosity.low + ) break self.rollback = False + def run_step(self, step): + if len(self.syslist) > 0 and self.threading: + stepthreads = [] + # steps through all the systems + for s in self.syslist: + # creates separate threads for the different systems + st = self.executor.submit(s.motion.step, step=step) + stepthreads.append(st) + + for st in stepthreads: + if softexit.triggered: + return + st.result() + else: + for s in self.syslist: + s.motion.step(step=step) + if softexit.triggered: + return + + # does the "super motion" step + if self.smotion is not None: + self.smotion.step(step) + + def stop(self): + for k, f in self.fflist.items(): + f.stop() + dproperties(Simulation, ["step"]) diff --git a/ipi/engine/system.py b/ipi/engine/system.py index 7f5c2e65a..dd7c99d83 100644 --- a/ipi/engine/system.py +++ b/ipi/engine/system.py @@ -61,7 +61,7 @@ def __init__( systems. """ - info(" # Initializing system object ", verbosity.low) + info(" @system: Initializing system object ", verbosity.low) self.prefix = prefix self.init = init self.ensemble = ensemble @@ -82,7 +82,7 @@ def bind(self, simul): self.simul = simul # keeps a handle to the parent simulation object # binds important computation engines - info(" # Binding the forces ", verbosity.low) + info(" @system.bind: Binding the forces ", verbosity.low) self.forces.bind( self.beads, self.cell, diff --git a/ipi/inputs/barostats.py b/ipi/inputs/barostats.py index f832be7a8..ff8833815 100644 --- a/ipi/inputs/barostats.py +++ b/ipi/inputs/barostats.py @@ -41,7 +41,7 @@ class InputBaro(Input): { "dtype": str, "default": "dummy", - "help": """The type of barostat. 'isotropic' implements the Bussi-Zykova-Parrinello barostat [doi:10.1063/1.3073889] that isotropically scales the volume while sampling the isothermal isobaric ensemble. The implementation details are given in [doi:10.1016/j.cpc.2013.10.027]. 'sc-isotropic' implements the same for Suzuki-Chin path integral molecular dynamics [10.1021/acs.jctc.8b01297]. This barostat is suitable for simulating liquids. 'flexible' implements the path integral version of the Martyna-Tuckerman-Tobias-Klein barostat which incorporates full cell fluctuations while sampling the isothermal isobaric ensemble [doi:10.1063/1.478193]. This is suitable for anisotropic systems such as molecular solids. 'anisotropic' implements the Raiteri-Gale-Bussi barostat which enables cell fluctuations at constant external stress [10.1088/0953-8984/23/33/334213]. It is suitable for simulating solids at given external (non-diagonal) stresses and requires specifying a reference cell for estimating strain. Note that this ensemble is valid only within the elastic limit of small strains. For diagonal stresses (or external pressures) the 'flexible' and the 'anisotropic' modes should give very similar results. 'dummy' barostat does not do anything.""", + "help": """The type of barostat. 'isotropic' implements the Bussi-Zykova-Parrinello barostat [doi:10.1063/1.3073889] that isotropically scales the volume while sampling the isothermal isobaric ensemble. The implementation details are given in [doi:10.1016/j.cpc.2013.10.027]. This barostat is suitable for simulating liquids. 'sc-isotropic' implements the same for Suzuki-Chin path integral molecular dynamics [10.1021/acs.jctc.8b01297] and should only be used with the Suzuki-Chin NPT ensemble. 'flexible' implements the path integral version of the Martyna-Tuckerman-Tobias-Klein barostat which incorporates full cell fluctuations while sampling the isothermal isobaric ensemble [doi:10.1063/1.478193]. This is suitable for anisotropic systems such as molecular solids. 'anisotropic' implements the Raiteri-Gale-Bussi barostat which enables cell fluctuations at constant external stress [10.1088/0953-8984/23/33/334213]. It is suitable for simulating solids at given external (non-diagonal) stresses and requires specifying a reference cell for estimating strain. Note that this ensemble is valid only within the elastic limit of small strains. For diagonal stresses (or external pressures) the 'flexible' and the 'anisotropic' modes should give very similar results. 'dummy' barostat does not do anything.""", "options": [ "dummy", "isotropic", diff --git a/ipi/inputs/forcefields.py b/ipi/inputs/forcefields.py index a8fcd6467..5174a8c23 100644 --- a/ipi/inputs/forcefields.py +++ b/ipi/inputs/forcefields.py @@ -11,6 +11,7 @@ from ipi.engine.forcefields import ( ForceField, FFSocket, + FFDirect, FFLennardJones, FFDebye, FFPlumed, @@ -21,6 +22,7 @@ FFCavPhSocket, ) from ipi.interfaces.sockets import InterfaceSocket +from ipi.pes import __drivers__ import ipi.engine.initializer from ipi.inputs.initializer import * from ipi.utils.inputvalue import * @@ -28,6 +30,7 @@ __all__ = [ "InputFFSocket", + "InputFFDirect", "InputFFLennardJones", "InputFFDebye", "InputFFPlumed", @@ -135,6 +138,8 @@ def store(self, ff): self.activelist.store(ff.active) self.threaded.store(ff.threaded) + _FFCLASS = ForceField + def fetch(self): """Creates a ForceField object. @@ -144,7 +149,7 @@ def fetch(self): super(InputForceField, self).fetch() - return ForceField( + return self._FFCLASS( pars=self.parameters.fetch(), name=self.name.fetch(), latency=self.latency.fetch(), @@ -336,37 +341,58 @@ def check(self): raise ValueError("Negative timeout parameter specified.") -class InputFFLennardJones(InputForceField): +class InputFFDirect(InputForceField): + fields = { + "pes": ( + InputValue, + { + "dtype": str, + "default": "dummy", + "options": list(__drivers__.keys()), + "help": "Type of PES that should be used to evaluate the forcefield", + }, + ), + } + fields.update(InputForceField.fields) + attribs = {} attribs.update(InputForceField.attribs) - default_help = """Simple, internal LJ evaluator without cutoff, neighbour lists or minimal image convention. - Expects standard LJ parameters, e.g. { eps: 0.1, sigma: 1.0 }. """ - default_label = "FFLJ" + default_help = """ Direct potential that evaluates forces through a Python + call, using PES providers from a list of possible external codes. The available + PES interfaces are listed into the `ipi/pes` folder, and are the same available + for the Python driver. The `` field should contain a dictionary + of the specific option of the chosen PES. + """ + default_label = "FFDirect" def store(self, ff): - super(InputFFLennardJones, self).store(ff) + super().store(ff) + self.pes.store(ff.pes) def fetch(self): - super(InputFFLennardJones, self).fetch() + super().fetch() - return FFLennardJones( + return FFDirect( pars=self.parameters.fetch(), name=self.name.fetch(), latency=self.latency.fetch(), offset=self.offset.fetch(), dopbc=self.pbc.fetch(), threaded=self.threaded.fetch(), + pes=self.pes.fetch(), ) - if self.slots.fetch() < 1 or self.slots.fetch() > 5: - raise ValueError( - "Slot number " + str(self.slots.fetch()) + " out of acceptable range." - ) - if self.latency.fetch() < 0: - raise ValueError("Negative latency parameter specified.") - if self.timeout.fetch() < 0.0: - raise ValueError("Negative timeout parameter specified.") + +class InputFFLennardJones(InputForceField): + attribs = {} + attribs.update(InputForceField.attribs) + + default_help = """Simple, internal LJ evaluator without cutoff, neighbour lists or minimal image convention. + Expects standard LJ parameters, e.g. { eps: 0.1, sigma: 1.0 }. """ + default_label = "FFLJ" + + _FFCLASS = FFLennardJones class InputFFdmd(InputForceField): @@ -445,7 +471,7 @@ class InputFFDebye(InputForceField): "default": input_default(factory=np.zeros, args=(0,)), "help": "Specifies the Hessian of the harmonic potential. " "Default units are atomic. Units can be specified only by xml attribute. " - "Implemented options are: 'atomic_unit', 'ev/ang\^2'", + r"Implemented options are: 'atomic_unit', 'ev/ang\^2'", "dimension": "hessian", }, ), @@ -747,6 +773,7 @@ class InputFFCommittee(InputForceField): dynamic = { "ffsocket": (InputFFSocket, {"help": InputFFSocket.default_help}), + "ffdirect": (InputFFDirect, {"help": InputFFDirect.default_help}), "fflj": (InputFFLennardJones, {"help": InputFFLennardJones.default_help}), "ffdebye": (InputFFDebye, {"help": InputFFDebye.default_help}), "ffplumed": (InputFFPlumed, {"help": InputFFPlumed.default_help}), diff --git a/ipi/inputs/motion/dynamics.py b/ipi/inputs/motion/dynamics.py index 2a9ae7931..e4571c74d 100644 --- a/ipi/inputs/motion/dynamics.py +++ b/ipi/inputs/motion/dynamics.py @@ -144,5 +144,4 @@ def fetch(self): rv = super(InputDynamics, self).fetch() rv["mode"] = self.mode.fetch() rv["splitting"] = self.splitting.fetch() - print(self) return rv diff --git a/ipi/inputs/motion/motion.py b/ipi/inputs/motion/motion.py index 97bb1bfcb..1bbf81187 100755 --- a/ipi/inputs/motion/motion.py +++ b/ipi/inputs/motion/motion.py @@ -83,6 +83,8 @@ class InputMotionBase(Input): fixcom: An optional boolean which decides whether the centre of mass motion will be constrained or not. fixatoms: A list of the indices of atoms that should not be moved. + fixatoms_dof: A list of indices of degrees of freedom that should be kept fixed. + Note that fixatoms is a 'short' way for to provide the fixatoms_dof, but only the latter is stored internally and written restart files. Example: [0,2,4] means (x-coordinate atom 1, z-coordinate atom 1, y-coordinate atom 2) """ @@ -130,7 +132,15 @@ class InputMotionBase(Input): { "dtype": int, "default": np.zeros(0, int), - "help": "Indices of the atmoms that should be held fixed.", + "help": "Indices of the atoms that should be held fixed.", + }, + ), + "fixatoms_dof": ( + InputArray, + { + "dtype": int, + "default": np.zeros(0, int), + "help": "Indices of the degrees of freedom that should be held fixed.", }, ), "optimizer": ( @@ -305,9 +315,9 @@ def store(self, sc): else: raise ValueError("Cannot store Mover calculator of type " + str(type(sc))) - if (sc.fixcom is True) and (len(sc.fixatoms) > 0): + if (sc.fixcom is True) and (len(sc.fixatoms_dof) > 0): warning( - "The flag fixcom is true by default but you have chosen to fix some atoms explicitly. Because the two cannot be used together, we are overriding the fixcom setting and making it False.", + "The flag fixcom is true by default but you have chosen to fix some atoms (or degree of freedom) explicitly. Because the two cannot be used together, we are overriding the fixcom setting and making it False.", verbosity.low, ) sc.fixcom = False @@ -316,7 +326,7 @@ def store(self, sc): self.file.store(sc.intraj) elif tsc > 0: self.fixcom.store(sc.fixcom) - self.fixatoms.store(sc.fixatoms) + self.fixatoms_dof.store(sc.fixatoms_dof) def fetch(self): """Creates a motion calculator object. @@ -328,16 +338,30 @@ def fetch(self): super(InputMotionBase, self).fetch() + fixatoms = self.fixatoms.fetch() + fixatoms_dof = self.fixatoms_dof.fetch() + if len(fixatoms) > 0: + if len(fixatoms_dof > 0): + softexit.trigger( + status="bad", + message=( + "Please specify either fixatoms or fixatoms_dof in your input file" + ), + ) + else: + fixatoms_dof = fixatoms[:, np.newaxis] * 3 + np.array([0, 1, 2]) + fixatoms_dof = np.sort(fixatoms_dof.flatten()) + if self.mode.fetch() == "replay": sc = Replay( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, intraj=self.file.fetch(), ) elif self.mode.fetch() == "minimize": sc = GeopMotion( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.optimizer.fetch() ) elif self.mode.fetch() == "neb": @@ -347,7 +371,7 @@ def fetch(self): # ) sc = NEBMover( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.neb_optimizer.fetch() ) elif self.mode.fetch() == "string": @@ -361,67 +385,67 @@ def fetch(self): ) sc = StringMover( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.string_optimizer.fetch() ) elif self.mode.fetch() == "driven_dynamics": sc = DrivenDynamics( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.driven_dynamics.fetch() ) elif self.mode.fetch() == "dynamics": sc = Dynamics( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.dynamics.fetch() ) elif self.mode.fetch() == "constrained_dynamics": sc = ConstrainedDynamics( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.constrained_dynamics.fetch() ) elif self.mode.fetch() == "vibrations": sc = DynMatrixMover( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.vibrations.fetch() ) elif self.mode.fetch() == "normalmodes": sc = NormalModeMover( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.normalmodes.fetch() ) elif self.mode.fetch() == "scp": sc = SCPhononsMover( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.scp.fetch() ) elif self.mode.fetch() == "alchemy": sc = AlchemyMC( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.alchemy.fetch() ) elif self.mode.fetch() == "atomswap": sc = AtomSwap( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.atomswap.fetch() ) elif self.mode.fetch() == "instanton": sc = InstantonMotion( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.instanton.fetch() ) elif self.mode.fetch() == "planetary": sc = Planetary( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.planetary.fetch() ) elif self.mode.fetch() == "t_ramp": @@ -431,7 +455,7 @@ def fetch(self): elif self.mode.fetch() == "al-kmc": sc = AlKMC( fixcom=self.fixcom.fetch(), - fixatoms=self.fixatoms.fetch(), + fixatoms_dof=fixatoms_dof, **self.al6xxx_kmc.fetch() ) else: diff --git a/ipi/inputs/prng.py b/ipi/inputs/prng.py index 9d83ced86..78e386aae 100644 --- a/ipi/inputs/prng.py +++ b/ipi/inputs/prng.py @@ -51,8 +51,8 @@ class InputRandom(Input): InputValue, { "dtype": int, - "default": 123456, - "help": "This is the seed number used to generate the initial state of the random number generator.", + "default": -1, + "help": "This specifies the seed number used to generate the initial state of the random number generator. Previously, the default seed was fixed as 123456. Currently, the default seed is random and given by the system time (down to ms). This is done in utils/prng.py.", }, ), "state": ( diff --git a/ipi/inputs/simulation.py b/ipi/inputs/simulation.py index 56b8666a3..796316d59 100644 --- a/ipi/inputs/simulation.py +++ b/ipi/inputs/simulation.py @@ -159,6 +159,10 @@ class InputSimulation(Input): iforcefields.InputFFSocket, {"help": iforcefields.InputFFSocket.default_help}, ), + "ffdirect": ( + iforcefields.InputFFDirect, + {"help": iforcefields.InputFFDirect.default_help}, + ), "fflj": ( iforcefields.InputFFLennardJones, {"help": iforcefields.InputFFLennardJones.default_help}, @@ -246,6 +250,10 @@ def store(self, simul): _iobj = iforcefields.InputFFSocket() _iobj.store(_obj) self.extra[_ii] = ("ffsocket", _iobj) + elif isinstance(_obj, eforcefields.FFDirect): + _iobj = iforcefields.InputFFDirect() + _iobj.store(_obj) + self.extra[_ii] = ("ffdirect", _iobj) elif isinstance(_obj, eforcefields.FFLennardJones): _iobj = iforcefields.InputFFLennardJones() _iobj.store(_obj) @@ -322,17 +330,18 @@ def fetch(self): # of system objects with the desired properties set # automatically to many values. syslist += v.fetch() - elif ( - k == "ffsocket" - or k == "fflj" - or k == "ffdebye" - or k == "ffdmd" - or k == "ffplumed" - or k == "ffsgdml" - or k == "ffyaff" - or k == "ffcommittee" - or k == "ffcavphsocket" - ): + elif k in [ + "ffsocket", + "ffdirect", + "fflj", + "ffdebye", + "ffdmd", + "ffplumed", + "ffsgdml", + "ffyaff", + "ffcommittee", + "ffcavphsocket", + ]: new_ff = v.fetch() if k == "ffsocket": # overrides ffsocket prefix diff --git a/ipi/inputs/system.py b/ipi/inputs/system.py index 2d69bc82f..82fe28969 100644 --- a/ipi/inputs/system.py +++ b/ipi/inputs/system.py @@ -90,7 +90,7 @@ def fetch(self): for label, to_insert in sorted(zip(labels, ins), reverse=True): # sort from longest to smallest label, to avoid replacing 'string' in 'string1' sys = sys.replace(label, to_insert) - print("Generating system from template: \n", sys) + print(" @inputsystemplate.fetch: Generating system from template:", sys) xsys = xml_parse_string(sys) # parses the string to an XML object isys = InputSystem() isys.parse( diff --git a/ipi/interfaces/sockets.py b/ipi/interfaces/sockets.py index 8c9c17810..8aecbb35a 100644 --- a/ipi/interfaces/sockets.py +++ b/ipi/interfaces/sockets.py @@ -486,11 +486,15 @@ def getforce(self): if mxtra: try: mxtradict = json.loads(mxtra) - info("Extra string JSON has been loaded.", verbosity.debug) + info( + "@driver.getforce: Extra string JSON has been loaded.", + verbosity.debug, + ) except: # if we can't parse it as a dict, issue a warning and carry on info( - "Extra string could not be loaded as a dictionary. Extra=" + mxtra, + "@driver.getforce: Extra string could not be loaded as a dictionary. Extra=" + + mxtra, verbosity.debug, ) mxtradict = {} @@ -654,7 +658,9 @@ def open(self): try: self.server.bind(self.sockets_prefix + self.address) info( - "Created unix socket with address " + self.address, verbosity.medium + " @interfacesocket.open: Created unix socket with address " + + self.address, + verbosity.medium, ) except socket.error: raise RuntimeError( @@ -676,7 +682,7 @@ def open(self): self.server.bind((self.address, self.port)) info( - "Created inet socket with address " + " @interfacesocket.open: Created inet socket with address " + self.address + " and port number " + str(self.port), @@ -700,7 +706,10 @@ def open(self): def close(self): """Closes down the socket.""" - info(" @SOCKET: Shutting down the driver interface.", verbosity.low) + info( + " @interfacesocket.close: Shutting down the driver interface.", + verbosity.low, + ) for c in self.clients: try: @@ -718,7 +727,7 @@ def close(self): self.server.close() except: info( - " @SOCKET: Problem shutting down the server socket. Will just continue and hope for the best.", + " @interfacesocket.close: Problem shutting down the server socket. Will just continue and hope for the best.", verbosity.low, ) if self.mode == "unix": @@ -795,7 +804,7 @@ def pool_update(self): client.settimeout(TIMEOUT) driver = Driver(client) info( - " @SOCKET: Client asked for connection from " + " @interfacesocket.pool_update: Client asked for connection from " + str(address) + ". Now hand-shaking.", verbosity.low, @@ -805,7 +814,7 @@ def pool_update(self): driver.exit_on_disconnect = self.exit_on_disconnect self.clients.append(driver) info( - " @SOCKET: Handshaking was successful. Added to the client list.", + " @interfacesocket.pool_update: Handshaking was successful. Added to the client list.", verbosity.low, ) self.poll_iter = UPDATEFREQ # if a new client was found, will try again harder next time @@ -948,7 +957,7 @@ def dispatch_free_client(self, fc, match_ids="any", send_threads=[]): r["status"] = "Running" self.prlist.remove(r) info( - " @SOCKET: %s Assigning [%5s] request id %4s to client with last-id %4s (% 3d/% 3d : %s)" + " @interfacesocket.dispatch_free_client: %s Assigning [%5s] request id %4s to client with last-id %4s (% 3d/% 3d : %s)" % ( time.strftime("%y/%m/%d-%H:%M:%S"), match_ids, diff --git a/drivers/py/pes/__init__.py b/ipi/pes/__init__.py similarity index 100% rename from drivers/py/pes/__init__.py rename to ipi/pes/__init__.py diff --git a/drivers/py/pes/ase.py b/ipi/pes/ase.py similarity index 52% rename from drivers/py/pes/ase.py rename to ipi/pes/ase.py index 7d5597a52..ee8ef677b 100644 --- a/drivers/py/pes/ase.py +++ b/ipi/pes/ase.py @@ -1,48 +1,66 @@ """Interface with ASE calculators""" -import sys import numpy as np from .dummy import Dummy_driver from ipi.utils.units import unit_to_internal, unit_to_user from ipi.utils.messages import warning -try: - from ase.io import read -except ImportError: - warning("Could not find or import the ASE module") - MetatensorCalculator = None + +read = None __DRIVER_NAME__ = "ase" __DRIVER_CLASS__ = "ASEDriver" -ERROR_MSG = """ -This ASE driver requires specification of and ASE calculator -and an ASE-readable template file that describes the chemical makeup of the structure. - -Example: python driver.py -m ase -u -o template.xyz,model_parameters -""" - class ASEDriver(Dummy_driver): - """Abstract base class using an arbitrary ASE calculator as i-pi driver""" - - def __init__(self, args=None, verbose=False, error_msg=ERROR_MSG): - super().__init__(args, verbose, error_msg=error_msg) - - def check_arguments(self): + """ + Base class using an arbitrary ASE calculator as i-pi driver. + Should not be called directly as it does not set a calculator. + + Parameters: + :param verbose: bool, whether to print verbose output + :param template: string, ASE-readable filename where to get the structure data from + :param has_energy: bool, whether the model can compute energy + :param has_forces: bool, whether the model can compute forces + :param has_stress: bool, whether the model can compute stress + """ + + def __init__( + self, + template, + has_energy=True, + has_forces=True, + has_stress=True, + *args, + **kwargs + ): + global read + try: + from ase.io import read + except ImportError: + warning("Could not find or import the ASE module") + + global all_changes + from ase.calculators.calculator import all_changes + + self.template = template + self.capabilities = [] + if has_energy: + self.capabilities.append("energy") + if has_forces: + self.capabilities.append("forces") + if has_stress: + self.capabilities.append("stress") + super().__init__(*args, **kwargs) + + def check_parameters(self): """Check the arguments required to run the driver This loads the potential and atoms template in metatensor """ - if len(self.args) >= 1: - self.template = self.args[0] - else: - sys.exit(self.error_msg) - self.template_ase = read(self.template) - self.ase_calculator = None def __call__(self, cell, pos): @@ -63,10 +81,15 @@ def __call__(self, cell, pos): structure.calc = self.ase_calculator # Do the actual calculation - properties = structure.get_properties(["energy", "forces", "stress"]) - pot = properties["energy"] - force = properties["forces"] - stress = properties["stress"] + properties = structure.get_properties(self.capabilities) + + pot = properties["energy"] if "energy" in self.capabilities else 0.0 + force = ( + properties["forces"] + if "forces" in self.capabilities + else np.zeros_like(pos) + ) + stress = properties["stress"] if "stress" in self.capabilities else np.zeros(9) if len(stress) == 6: # converts from voight notation stress = np.array(stress[[0, 5, 4, 5, 1, 3, 4, 3, 2]]) diff --git a/drivers/py/pes/bath.py b/ipi/pes/bath.py similarity index 79% rename from drivers/py/pes/bath.py rename to ipi/pes/bath.py index f4d62d95e..c49c63de6 100644 --- a/drivers/py/pes/bath.py +++ b/ipi/pes/bath.py @@ -2,22 +2,29 @@ import numpy as np -__DRIVER_NAME__ = None -__DRIVER_CLASS__ = "driver_tools" +from ipi.utils.messages import verbosity, warning + +__DRIVER_NAME__ = "bath" +__DRIVER_CLASS__ = "Harmonic_Bath_explicit" class Harmonic_Bath_explicit(object): """Explicit description of an Harmonic bath""" - def __init__(self, nbath, parameters): + def __init__(self, nbath, m, eta0, eps1, eps2, deltaQ, w_c, *args, **kwargs): + warning( + "THIS PES HAS NOT BEEN TESTED FOLLOWING CONVERSION TO THE NEW PES API.", + verbosity.low, + ) + super().__init__(*args, **kwargs) + self.nbath = nbath - self.m = parameters["m"] - # self.delta = parameters["delta"] - self.eta0 = parameters["eta0"] - self.eps1 = parameters["eps1"] - self.eps2 = parameters["eps2"] - self.deltaQ = parameters["deltaQ"] - self.w_c = parameters["w_c"] + self.m = m + self.eta0 = eta0 + self.eps1 = eps1 + self.eps2 = eps2 + self.deltaQ = deltaQ + self.w_c = w_c self.set_ci_and_wi() diff --git a/drivers/py/pes/doubledoublewell.py b/ipi/pes/doubledoublewell.py similarity index 71% rename from drivers/py/pes/doubledoublewell.py rename to ipi/pes/doubledoublewell.py index 94b5c90e5..e4f633639 100644 --- a/drivers/py/pes/doubledoublewell.py +++ b/ipi/pes/doubledoublewell.py @@ -28,7 +28,7 @@ class DDW_with_explicit_bath_driver(Dummy_driver): - """Adds to a double-double well (DDW) potential coupled to two (explicit) harmonic baths. + r"""Adds to a double-double well (DDW) potential coupled to two (explicit) harmonic baths. pos[0:2] = DDW pos[2:n//2+1] = bath1 pos[n//2+1:] = bath2 @@ -47,49 +47,61 @@ class DDW_with_explicit_bath_driver(Dummy_driver): ! and ! ! DDW(q1,q2) = DW(q1) + DW(q2) + C(q1q2)^2 - """ - def __init__(self, args=None, verbose=None): - self.error_msg = """\nDW+explicit_bath driver expects 11 arguments.\n - Example: python driver.py -m DoubleWell_with_explicit_bath -o wb1 (cm^-1) V1 (cm^-1) wb2 (cm^-1) V2 (cm^-1) coupling(au) mass delta(\AA) eta0 eps1 eps2 deltaQ omega_c(cm^-1) \n - python driver.py -m DoubleWell -o 500,2085,500,2085,0.1,1837,0.00,1,0,0,1,500\n""" - super(DDW_with_explicit_bath_driver, self).__init__( - args, error_msg=self.error_msg - ) - self.init = False + DW+explicit_bath driver expects 11 arguments.\n + Example: + i-pi-py_driver.py -m DoubleWell_with_explicit_bath -o wb1 (cm^-1) V1 (cm^-1) wb2 (cm^-1) V2 (cm^-1) coupling(au) mass delta(\AA) eta0 eps1 eps2 deltaQ omega_c(cm^-1) \n + i-pi-py_driver.py -m DoubleWell -o 500,2085,500,2085,0.1,1837,0.00,1,0,0,1,500 + """ - def check_arguments(self): - """Function that checks the arguments required to run the driver""" + def __init__( + self, + wb1=None, + v1=None, + wb2=None, + v2=None, + C=None, + m=None, + delta=None, + eta0=None, + eps1=None, + eps2=None, + deltaQ=None, + w_c=None, + *args, + **kwargs + ): + self.init = False try: - param = list(map(float, self.args)) - assert len(param) == 12 - wb1 = param[0] * invcm2au - v1 = param[1] * invcm2au - wb2 = param[2] * invcm2au - v2 = param[3] * invcm2au - self.C = param[4] - self.m = param[5] - self.delta = param[6] * A2au + wb1 = wb1 * invcm2au + v1 = v1 * invcm2au + wb2 = wb2 * invcm2au + v2 = v2 * invcm2au + self.C = C + self.m = m + self.delta = delta * A2au self.bath_parameters = {} self.bath_parameters["m"] = self.m + self.bath_parameters["eta0"] = eta0 + self.bath_parameters["eps1"] = eps1 + self.bath_parameters["eps2"] = eps2 + self.bath_parameters["deltaQ"] = deltaQ + self.bath_parameters["w_c"] = w_c * invcm2au self.bath_parameters["delta"] = self.delta - self.bath_parameters["eta0"] = param[7] - self.bath_parameters["eps1"] = param[8] - self.bath_parameters["eps2"] = param[9] - self.bath_parameters["deltaQ"] = param[10] - self.bath_parameters["w_c"] = param[11] * invcm2au + # def __init__(self, nbath, m, eta0, eps1, eps2, deltaQ, w_c, *args, **kwargs): except: print("Received arguments:") - sys.exit(self.error_msg) + sys.exit(self.__doc__) self.A1 = -0.5 * self.m * (wb1) ** 2 self.B1 = ((self.m**2) * (wb1) ** 4) / (16 * v1) self.A2 = -0.5 * self.m * (wb2) ** 2 self.B2 = ((self.m**2) * (wb2) ** 4) / (16 * v2) + super().__init__(*args, **kwargs) def __call__(self, cell, pos): """DoubleWell potential""" diff --git a/drivers/py/pes/doublewell.py b/ipi/pes/doublewell.py similarity index 73% rename from drivers/py/pes/doublewell.py rename to ipi/pes/doublewell.py index b75dad204..10987414f 100644 --- a/drivers/py/pes/doublewell.py +++ b/ipi/pes/doublewell.py @@ -28,15 +28,14 @@ class DoubleWell_driver(Dummy_driver): - def __init__(self, args=None, verbose=None): - self.error_msg = """\nDW driver accepts 0 or 4 arguments.\nExample: python driver.py -m DoubleWell -o omega_b (cm^-1) V0 (cm^-1) mass(a.u) delta(angs) \n + """ + DW driver accepts 0 or 4 arguments.\nExample: python driver.py -m DoubleWell -o omega_b (cm^-1) V0 (cm^-1) mass(a.u) delta(angs) \n python driver.py -m DoubleWell -o 500,2085,1837,0.00 \n""" - super(DoubleWell_driver, self).__init__(args, error_msg=self.error_msg) - def check_arguments(self): - """Function that checks the arguments required to run the driver""" - self.k = 1837.36223469 * (3800.0 / 219323.0) ** 2 - if self.args == "": + def __init__(self, w_b=None, v0=None, m=None, delta=None, *args, **kwargs): + + if w_b == None or v0 == None or m == None or delta == None: + print("using default values from Craig-JCP-2005") # We used Craig's values (J. Chem. Phys. 122, 084106, 2005) w_b = 500 * invcm2au # Tc = 115K v0 = 2085 * invcm2au @@ -44,17 +43,16 @@ def check_arguments(self): self.delta = 00 else: try: - param = list(map(float, self.args)) - assert len(param) == 4 - w_b = param[0] * invcm2au - v0 = param[1] * invcm2au - m = param[2] - self.delta = param[3] * A2au + w_b = w_b * invcm2au + v0 = v0 * invcm2au + self.delta = delta * A2au except: - sys.exit(self.error_msg) + sys.exit(self.__doc__) + self.k = 1837.36223469 * (3800.0 / 219323.0) ** 2 self.A = -0.5 * m * (w_b) ** 2 self.B = ((m**2) * (w_b) ** 4) / (16 * v0) + super().__init__(*args, **kwargs) def __call__(self, cell, pos): """DoubleWell potential l""" diff --git a/drivers/py/pes/doublewell_with_bath.py b/ipi/pes/doublewell_with_bath.py similarity index 65% rename from drivers/py/pes/doublewell_with_bath.py rename to ipi/pes/doublewell_with_bath.py index d5b8567f2..a79354f8e 100644 --- a/drivers/py/pes/doublewell_with_bath.py +++ b/ipi/pes/doublewell_with_bath.py @@ -30,50 +30,57 @@ class DoubleWell_with_explicit_bath_driver(Dummy_driver): - """Adds to the double well potential an explicit harmonic bath. First dof correpond to the DW, the rest to the bath discretization + r"""Adds to the double well potential an explicit harmonic bath. First dof correpond to the DW, the rest to the bath discretization ! V(q,x1,..,xn) = DW(q) + ! sum_2^(3*N) [ 0.5 m w_i^2(q - (c_i s(q))/(m w_i)^2)^2 ] ! s(q) = q *sd(q) ! sd(q) = [1+eps1*exp( q^2 / (2 deltaQ^2) ) ] + eps2 tanh(q/deltaQ) ! If eps1=eps2=0 then sd(q) =1 and s(q) = q --->Spatially independent bath - """ - def __init__(self, args=None, verbose=None): - self.error_msg = """\nDW+explicit_bath driver expects 9 arguments.\n + DW+explicit_bath driver expects 9 arguments. Example: python driver.py -m DoubleWell_with_explicit_bath -o omega_b (cm^-1) V0 (cm^-1) mass delta(\AA) eta0 eps1 eps2 deltaQ omega_c(cm^-1) \n - python driver.py -m DoubleWell -o 500,2085,1837,0.00,1,0,0,1,500\n""" - super(DoubleWell_with_explicit_bath_driver, self).__init__( - args, error_msg=self.error_msg - ) + python driver.py -m DoubleWell -o 500,2085,1837,0.00,1,0,0,1,500 + """ - self.init = False + def __init__( + self, + w_b=None, + v0=None, + m=None, + delta=None, + eta0=None, + eps1=None, + eps2=None, + deltaQ=None, + w_c=None, + *args, + **kwargs + ): - def check_arguments(self): - """Function that checks the arguments required to run the driver""" + self.init = False try: - param = list(map(float, self.args)) - assert len(param) == 9 - w_b = param[0] * invcm2au - v0 = param[1] * invcm2au - self.m = param[2] - self.delta = param[3] * A2au + w_b = w_b * invcm2au + v0 = v0 * invcm2au + self.m = m + self.delta = delta * A2au self.bath_parameters = {} - self.bath_parameters["m"] = param[2] + self.bath_parameters["m"] = self.m - self.bath_parameters["eta0"] = param[4] - self.bath_parameters["eps1"] = param[5] - self.bath_parameters["eps2"] = param[6] - self.bath_parameters["deltaQ"] = param[7] - self.bath_parameters["w_c"] = param[8] * invcm2au + self.bath_parameters["eta0"] = eta0 + self.bath_parameters["eps1"] = eps1 + self.bath_parameters["eps2"] = eps2 + self.bath_parameters["deltaQ"] = deltaQ + self.bath_parameters["w_c"] = w_c * invcm2au except: - sys.exit(self.error_msg) + sys.exit(self.__doc__) self.A = -0.5 * self.m * (w_b) ** 2 self.B = ((self.m**2) * (w_b) ** 4) / (16 * v0) + super().__init__(*args, **kwargs) def __call__(self, cell, pos): """DoubleWell potential""" @@ -85,7 +92,7 @@ def __call__(self, cell, pos): if not self.init: self.nbath = np.size(x) - self.bath = Harmonic_Bath_explicit(self.nbath, self.bath_parameters) + self.bath = Harmonic_Bath_explicit(self.nbath, **self.bath_parameters) # Harmonic bath pot, fq, fx = self.bath(q, x) diff --git a/drivers/py/pes/doublewell_with_friction.py b/ipi/pes/doublewell_with_friction.py similarity index 71% rename from drivers/py/pes/doublewell_with_friction.py rename to ipi/pes/doublewell_with_friction.py index dfacdb7b8..d456cfb43 100644 --- a/drivers/py/pes/doublewell_with_friction.py +++ b/ipi/pes/doublewell_with_friction.py @@ -1,7 +1,5 @@ """ Harmonic potential """ -import sys - try: from .doublewell import DoubleWell_driver except: @@ -10,6 +8,7 @@ import numpy as np from ipi.utils import units import json +import sys __DRIVER_NAME__ = "DW_friction" @@ -29,42 +28,48 @@ class DoubleWell_with_friction_driver(DoubleWell_driver): - """Adds to the double well potential the calculation of the friction tensor. + r"""Adds to the double well potential the calculation of the friction tensor. friction(q) = eta0 [\partial sd(q) \partial q ]^2 with q = position, and sd(q) = [1+eps1 exp( (q-0)^2 / (2deltaQ^2) ) ] + eps2 tanh(q/deltaQ) - """ - def __init__(self, args=None, verbose=None): - self.error_msg = """\nDW+fric driver expects 8 arguments.\n - Example: python driver.py -m DoubleWell_with_fric -o omega_b (cm^-1) V0 (cm^-1) mass delta(\AA) eta0 eps1 eps2 deltaQ \n - python driver.py -m DoubleWell -o 500,2085,1837,0.00,1,0,0,1\n""" - self.args = args.split(",") - self.verbose = verbose - self.check_arguments() + DW+fric driver expects 8 arguments. + Example: python driver.py -m DoubleWell_with_fric -o omega_b (cm^-1) V0 (cm^-1) mass delta(\AA) eta0 eps1 eps2 deltaQ + python driver.py -m DoubleWell -o 500,2085,1837,0.00,1,0,0,1 + """ - def check_arguments(self): - """Function that checks the arguments required to run the driver""" + def __init__( + self, + w_b=None, + v0=None, + m=None, + eta0=None, + eps1=None, + eps2=None, + delta=None, + deltaQ=None, + *args, + **kwargs + ): - self.k = 1837.36223469 * (3800.0 / 219323.0) ** 2 try: - param = list(map(float, self.args)) - assert len(param) == 8 - w_b = param[0] * invcm2au - v0 = param[1] * invcm2au - m = param[2] - self.delta = param[3] * A2au - self.eta0 = param[4] - self.eps1 = param[5] - self.eps2 = param[6] - self.deltaQ = param[7] + w_b = w_b * invcm2au + v0 = v0 * invcm2au + self.delta = delta * A2au + self.eta0 = eta0 + self.eps1 = eps1 + self.eps2 = eps2 + self.deltaQ = deltaQ + self.k = 1837.36223469 * (3800.0 / 219323.0) ** 2 + self.A = -0.5 * m * (w_b) ** 2 + self.B = ((m**2) * (w_b) ** 4) / (16 * v0) + except: - sys.exit(self.error_msg) + sys.exit(self.__doc__) - self.A = -0.5 * m * (w_b) ** 2 - self.B = ((m**2) * (w_b) ** 4) / (16 * v0) + super().__init__(*args, **kwargs) def check_dimensions(self, pos): """Functions that checks dimensions of the received position""" diff --git a/drivers/py/pes/driverdipole.py b/ipi/pes/driverdipole.py similarity index 95% rename from drivers/py/pes/driverdipole.py rename to ipi/pes/driverdipole.py index be0929042..2a87b9242 100644 --- a/drivers/py/pes/driverdipole.py +++ b/ipi/pes/driverdipole.py @@ -4,6 +4,9 @@ import json import numpy as np import warnings + +from ipi.utils.messages import verbosity, warning + import importlib from .dummy import Dummy_driver @@ -118,6 +121,9 @@ def get_model(instructions, parameters: str): class driverdipole_driver(Dummy_driver): + """The parameters of 'driverdipole_driver' are not correctly formatted. \ + They should be two or three strings, separated by a comma.""" + opts_default = { "dipole": { "send": True, # whether to send the dipole to i-PI @@ -131,19 +137,21 @@ class driverdipole_driver(Dummy_driver): "restart": False, # whether remove the files (if already existing) where the dipole and BEC will be saved. } - def __init__(self, args=None): - self.error_msg = """The parameters of 'driverdipole_driver' are not correctly formatted. \ - They should be two or three strings, separated by a comma.""" + def __init__(self, *args, **kwargs): + warning( + "THIS PES HAS NOT BEEN TESTED FOLLOWING CONVERSION TO THE NEW PES API.", + verbosity.low, + ) self.opts = dict() self.count = 0 - super().__init__(args) + super().__init__(*args, **kwargs) - def check_arguments(self): + def check_parameters(self): """Check the arguments required to run the driver.""" try: - arglist = self.args.split(",") + arglist = self.args except ValueError: - sys.exit(self.error_msg) + sys.exit(self.__doc__) if len(arglist) >= 2: info_file = arglist[0] # json file to properly allocate a 'model' object @@ -154,7 +162,7 @@ def check_arguments(self): print("\tNo options file provided: using the default values") opts_file = None else: - sys.exit(self.error_msg) # to be modified + sys.exit(self._error_msg) # to be modified print("\n\tThe driver is 'driverdipole_driver'") print("\tLoading model ...") diff --git a/drivers/py/pes/dummy.py b/ipi/pes/dummy.py similarity index 57% rename from drivers/py/pes/dummy.py rename to ipi/pes/dummy.py index ca756a54e..83430a93c 100644 --- a/drivers/py/pes/dummy.py +++ b/ipi/pes/dummy.py @@ -2,20 +2,27 @@ __DRIVER_NAME__ = "dummy" __DRIVER_CLASS__ = "Dummy_driver" +import json + class Dummy_driver(object): - """Base class providing the structure of a PES for the python driver.""" + """Base class providing the structure of a PES for the python driver. + + Command line: + i-pi-py_driver -m dummy [...] + Init arguments: + :param verbose: bool to determine whether the PES should output verbose info. + """ - def __init__( - self, args="", verbose=False, error_msg="Invalid arguments for the PES" - ): + def __init__(self, verbose=False, *args, **kwargs): """Initialized dummy drivers""" - self.error_msg = error_msg - self.args = args.split(",") self.verbose = verbose - self.check_arguments() + self.args = args + self.kwargs = kwargs + + self.check_parameters() - def check_arguments(self): + def check_parameters(self): """Dummy function that checks the arguments required to run the driver""" pass @@ -24,5 +31,7 @@ def __call__(self, cell, pos): pot = 0.0 force = pos * 0.0 # makes a zero force with same shape as pos vir = cell * 0.0 # makes a zero virial with same shape as cell - extras = "nada" + extras = json.dumps( + {"dipole": [0.0, 0.0, 0.0]} + ) # have json formatting to potentially work with some test examples. meaningless value return pot, force, vir, extras diff --git a/ipi/pes/elphmod.py b/ipi/pes/elphmod.py new file mode 100644 index 000000000..5e776b254 --- /dev/null +++ b/ipi/pes/elphmod.py @@ -0,0 +1,33 @@ +"""Interface with [elphmod](https://github.com/janberges/elphmod) MD driver.""" + +import os +from .dummy import Dummy_driver + +__DRIVER_NAME__ = "elphmod" +__DRIVER_CLASS__ = "ModelIIIDriver" + + +class ModelIIIDriver(Dummy_driver): + """Wrapper around elphmod MD driver. + A pickled driver instance is required (see elphmod.md.Driver.save). + + Example: python3 driver.py -u -m elphmod -o driver=driver.pickle + """ + + def __init__(self, driver, *args, **kwargs): + import elphmod + + if not os.path.exists(driver): + raise ValueError(f"File '{driver}' does not exist.") + self.driver = elphmod.md.Driver.load(driver) + if self.driver is None: + raise ValueError( + f"Some error occured within `ModelIIIDriver.__init__` when trying to load the driver from file '{driver}'." + ) + super().__init__(*args, **kwargs) + pass + + def __call__(self, cell, pos): + """Calculate energy and forces for given structure.""" + + return self.driver(cell, pos) diff --git a/drivers/py/pes/harmonic.py b/ipi/pes/harmonic.py similarity index 60% rename from drivers/py/pes/harmonic.py rename to ipi/pes/harmonic.py index d92f7bac9..df3974815 100644 --- a/drivers/py/pes/harmonic.py +++ b/ipi/pes/harmonic.py @@ -1,33 +1,37 @@ """ Harmonic potential """ -import sys from .dummy import Dummy_driver import numpy as np __DRIVER_NAME__ = "harmonic" __DRIVER_CLASS__ = "Harmonic_driver" -ERROR_MSG = """ -Harmonic driver requires specification of force constant. -Example: python driver.py -m harmonic -u -o 1.3 -""" - class Harmonic_driver(Dummy_driver): - def __init__(self, args=None, verbose=False): - super(Harmonic_driver, self).__init__(args, verbose, error_msg=ERROR_MSG) + """ + Harmonic driver, generating either an isotropic or 3D confining + potential for each atom. + + Command-line: + i-pi-py_driver -m harmonic -u -o 1.3 [...] + i-pi-py_driver -m harmonic -u -o 1.3,2.1,2.3 [...] + + Init parameters: + :param k1: float, spring constant of the oscillator (in a.u.) + :param k2: float, spring constant of the oscillator along y (in a.u.), optional + :param k3: float, spring constant of the oscillator along z (in a.u.), optional + """ - def check_arguments(self): - """Function that checks the arguments required to run the driver""" + def __init__(self, k1, k2=None, k3=None, *args, **kwargs): - if len(self.args) == 1: - self.k = float(self.args[0]) + if k2 == None or k3 == None: + self.k = k1 self.type = "isotropic" - elif len(self.args) == 3: - self.k = np.asarray(list(map(float, self.args))) - self.type = "non-isotropic" else: - sys.exit(self.error_msg) + self.k = np.asarray([k1, k2, k3]) + self.type = "non-isotropic" + + super().__init__(*args, **kwargs) def __call__(self, cell, pos): """Silly harmonic potential""" diff --git a/ipi/pes/mace.py b/ipi/pes/mace.py new file mode 100644 index 000000000..0aea548bb --- /dev/null +++ b/ipi/pes/mace.py @@ -0,0 +1,53 @@ +""" An interface for the [MACE](https://github.com/ACEsuit/mace) calculator """ + +from .ase import ASEDriver + +from ipi.utils.messages import verbosity, warning + +MACECalculator = None + +__DRIVER_NAME__ = "mace" +__DRIVER_CLASS__ = "MACE_driver" + + +class MACE_driver(ASEDriver): + """ + Driver for the MACE MLIPs. + The driver requires specification of a .json model, + and a template file that describes the chemical makeup + of the structure. + + Command-line: + i-pi-py_driver.py -m mace -u -o template=template.xyz,model=model.json + + Parameters: + :param template: string, filename of an ASE-readable structure file + to initialize atomic number and types + :param model: string, filename of the json-formatted model file + """ + + def __init__(self, template, model, device="cpu", *args, **kwargs): + warning( + "THIS PES HAS NOT BEEN TESTED FOLLOWING CONVERSION TO THE NEW PES API.", + verbosity.low, + ) + global MACECalculator + + try: + from mace.calculators import MACECalculator + except: + raise ImportError("Couldn't load mace bindings") + + self.model = model + self.device = device + super().__init__(template, *args, **kwargs) + + def check_parameters(self): + """Check the arguments requuired to run the driver + + This loads the potential and atoms template in MACE + """ + + super().check_parameters() + + self.ase_calculator = MACECalculator(model_paths=self.model, device=self.device) diff --git a/ipi/pes/metatensor.py b/ipi/pes/metatensor.py new file mode 100644 index 000000000..4e3dc133d --- /dev/null +++ b/ipi/pes/metatensor.py @@ -0,0 +1,99 @@ +""" +Interface with metatensor +(https://lab-cosmo.github.io/metatensor/latest/atomistic/index.html), that can +be used to perform calculations based on different types of machine learning +potentials +""" + +from ipi.utils.messages import warning + +from .ase import ASEDriver + +MetatensorCalculator = None +mtt = None + +__DRIVER_NAME__ = "metatensor" +__DRIVER_CLASS__ = "MetatensorDriver" + + +class MetatensorDriver(ASEDriver): + """ + Driver for `metatensor` MLIPs + The driver requires specification of a torchscript model, + and a template file that describes the chemical makeup + of the structure. Requires the metatensor-torch library + + Command-line: + i-pi-py_driver -m metatensor -o template=template.xyz,model=model.json [...] + + Parameters: + :param template: string, filename of an ASE-readable structure file + to initialize atomic number and types + :param model: string, filename of the torchscript model file + :param device: string, optional, ["cpu" | "cuda"] + """ + + def __init__( + self, + template, + model, + device="cpu", + extensions="", + check_consistency=False, + *args, + **kwargs, + ): + global MetatensorCalculator, mtt + if MetatensorCalculator is None: + try: + import metatensor.torch as mtt + from metatensor.torch.atomistic.ase_calculator import ( + MetatensorCalculator, + ) + except ImportError as e: + warning(f"Could not find or import metatensor.torch: {e}") + + self.model = model + self.device = device + self.extensions = extensions + self.check_consistency = check_consistency + print("ARGS ", kwargs) + super().__init__(template, *args, **kwargs) + + def check_parameters(self): + """Check the arguments required to run the driver + + This loads the potential and atoms template in metatensor + """ + + if MetatensorCalculator is None: + raise ImportError("could not import metatensor.torch, is it installed?") + + metatensor_major, metatensor_minor, *_ = mtt.__version__.split(".") + metatensor_major = int(metatensor_major) + metatensor_minor = int(metatensor_minor) + + if metatensor_major != 0 or metatensor_minor < 5: + raise ImportError( + "this code is only compatible with metatensor-torch >= v0.5, " + f"found version v{mtt.__version__} " + f"at '{mtt.__file__}'" + ) + + super().check_parameters() + + self.model_path = self.model + + device = self.device + extensions_directory = self.extensions + check_consistency = self.check_consistency + + self.ase_calculator = MetatensorCalculator( + self.model_path, + device=device, + extensions_directory=extensions_directory, + check_consistency=check_consistency, + ) + + # Show the model metadata to the users + print(self.ase_calculator.metadata()) diff --git a/drivers/py/pes/pet.py b/ipi/pes/pet.py similarity index 53% rename from drivers/py/pes/pet.py rename to ipi/pes/pet.py index f072336e2..7e54c37e3 100644 --- a/drivers/py/pes/pet.py +++ b/ipi/pes/pet.py @@ -1,78 +1,65 @@ """Interface with [PET](https://github.com/serfg/pet) models to run machine learning potentials""" -import sys import numpy as np from .dummy import Dummy_driver from ipi.utils.units import unit_to_internal, unit_to_user from ipi.utils.messages import warning -try: - from pet import SingleStructCalculator as PETCalc - - try: - from ase.io import read - except ImportError: - warning("The PET driver has an ASE dependency") - raise -except ImportError: - warning("Could not find or import the PET module") - PETCalc = None +PETCalc = None +read = None __DRIVER_NAME__ = "pet" __DRIVER_CLASS__ = "PET_driver" class PET_driver(Dummy_driver): - def __init__(self, args=None, verbose=False): - self.error_msg = """ -The PET driver requires (a) a path to the results/experiment_name folder emitted by pet_train - (b) a path to an ase.io.read-able file with a prototype structure - -Other arguments to the pet.SingleStructCalculator class can be optionally -supplied in key=value form after the required arguments. - -Example: python driver.py -m pet -u -o "path/to/results/name,template.xyz,device=cuda" -""" - - super().__init__(args, verbose) - - if PETCalc is None: - raise ImportError("Couldn't load PET bindings") - - def check_arguments(self): + """ + Driver for `PET` MLIPs + The driver requires specification of the folder containing the + outputs from a PET model training, a template file that describes the chemical makeup + of the structure, and optional parameters specific for the PET architecture. + Requires the pet library + + Command-line: + i-pi-py_driver -m pet -o model_path=path_to_results/prefix,template=template.xyz,device=cuda [...] + + Parameters: + :param template: string, filename of an ASE-readable structure file + to initialize atomic number and types + :param model: string, filename of the torchscript model file + :param device: string, optional, ["cpu" | "cuda"] + """ + + def __init__(self, model_path, template, *args, **kwargs): + global PETCalc, read + + try: + from pet import SingleStructCalculator as PETCalc + + try: + from ase.io import read + except ImportError: + warning("The PET driver has an ASE dependency") + raise + except ImportError: + raise ImportError("Could not find or import the PET module") + + self.model_path = model_path + self.template = template + super().__init__(*args, **kwargs) + + def check_parameters(self): """Check the arguments required to run the driver This loads the potential and atoms template in PET """ - args = self.args - - if len(args) >= 2: - self.model_path = args[0] - self.template = args[1] - kwargs = {} - if len(args) > 2: - for arg in args[2:]: - key, value = arg.split("=") - lookup = { - "None": None, - "False": False, - "True": True, - } - - if value in lookup: - value = lookup[value] - - kwargs[key] = value - - else: - sys.exit(self.error_msg) self.template_ase = read(self.template) self.template_ase.arrays["forces"] = np.zeros_like(self.template_ase.positions) self.pet_calc = PETCalc( self.model_path, - **kwargs, + **self.kwargs, ) def __call__(self, cell, pos): diff --git a/drivers/py/pes/rascal.py b/ipi/pes/rascal.py similarity index 56% rename from drivers/py/pes/rascal.py rename to ipi/pes/rascal.py index c7ac7da31..7bef90025 100644 --- a/drivers/py/pes/rascal.py +++ b/ipi/pes/rascal.py @@ -1,45 +1,53 @@ """Interface with librascal to run machine learning potentials""" -import sys from .dummy import Dummy_driver from ipi.utils.mathtools import det_ut3x3 from ipi.utils.units import unit_to_internal, unit_to_user +from ipi.utils.messages import verbosity, warning -try: - from rascal.models.genericmd import GenericMDCalculator as RascalCalc -except: - RascalCalc = None +RascalCalc = None __DRIVER_NAME__ = "rascal" __DRIVER_CLASS__ = "Rascal_driver" -ERROR_MSG = """ -Rascal driver requires specification of a .json model file fitted with librascal, -and a template file that describes the chemical makeup of the structure. -Example: python driver.py -m rascal -u -o model.json,template.xyz -""" - class Rascal_driver(Dummy_driver): - def __init__(self, args=None, verbose=False): - super().__init__(args, verbose, error_msg=ERROR_MSG) + """ + Driver for `librascal` MLIPs + The driver requires specification of the model JSON-formated definition, + and a template file that describes the chemical makeup + of the structure. Requires the librascal library + + Command-line: + i-pi-py_driver -m rascal -o model=model.json,template=template.xyz [...] + + Parameters: + :param template: string, filename of an ASE-readable structure file + to initialize atomic number and types + :param model: string, filename of the torchscript model file + """ - if RascalCalc is None: + def __init__(self, model, template, *args, **kwargs): + global RascalCalc + warning( + "THIS PES HAS NOT BEEN TESTED FOLLOWING CONVERSION TO THE NEW PES API.", + verbosity.low, + ) + try: + from rascal.models.genericmd import GenericMDCalculator as RascalCalc + except: raise ImportError("Couldn't load librascal bindings") + self.model = model + self.template = template - def check_arguments(self): + super().__init__(*args, **kwargs) + + def check_parameters(self): """Check the arguments required to run the driver This loads the potential and atoms template in librascal """ - arglist = self.args - - if len(arglist) == 2: - self.model = arglist[0] - self.template = arglist[1] - else: - sys.exit(self.error_msg) self.rascal_calc = RascalCalc(self.model, True, self.template) diff --git a/ipi/pes/so3lr.py b/ipi/pes/so3lr.py new file mode 100644 index 000000000..c0ee083c5 --- /dev/null +++ b/ipi/pes/so3lr.py @@ -0,0 +1,37 @@ +""" An interface for the [SO3LR](https://github.com/general-molecular-simulations/so3lr) calculator """ + +from .ase import ASEDriver +from ipi.utils.messages import verbosity, warning + +So3lrCalculator = None + +__DRIVER_NAME__ = "so3lr" +__DRIVER_CLASS__ = "SO3LR_driver" + + +class SO3LR_driver(ASEDriver): + """ + SO3LR driver requires a template file that describes the chemical makeup of the structure. + + Optionally, lr_cutoff and dispersion_energy_lr_cutoff_damping can be specified. + + Example: python driver.py -m so3lr -u -o template.xyz,lr_cutoff=12,dispersion_energy_lr_cutoff_damping=2 + """ + + def __init__(self, *args, **kwargs): + warning( + "THIS PES HAS NOT BEEN TESTED FOLLOWING CONVERSION TO THE NEW PES API.", + verbosity.low, + ) + global So3lrCalculator + try: + from so3lr import So3lrCalculator + except: + raise ImportError("Couldn't load so3lr bindings") + + super().__init__(*args, **kwargs) + + def check_parameters(self): + super().check_parameters() + + self.ase_calculator = So3lrCalculator(**self.kwargs) diff --git a/drivers/py/pes/spline.py b/ipi/pes/spline.py similarity index 81% rename from drivers/py/pes/spline.py rename to ipi/pes/spline.py index eb7de4ea4..354890721 100644 --- a/drivers/py/pes/spline.py +++ b/ipi/pes/spline.py @@ -3,8 +3,13 @@ import numpy as np import sys from .dummy import Dummy_driver -from scipy import interpolate import json +from ipi.utils.messages import verbosity, warning + +try: + from scipy import interpolate +except ImportError: + raise ImportError("Could not import scipy. Please install to use this.") """Spline driver. This is not a serious interpolation, use it if you know what you are doing. """ factor_coord = 5 @@ -18,21 +23,27 @@ class Spline_driver(Dummy_driver): - def __init__(self, args=None, verbose=None): - self.error_msg = """\nspline driver requires specification of filename that contains 5 columns (pos, f1,f2,f3,e) to perform 3x1D spline.\nExample: python driver.py -m spline -u -o \n""" - super(Spline_driver, self).__init__(args) + """\nspline driver requires specification of filename that contains 5 columns (pos, f1,f2,f3,e) to perform 3x1D spline.\nExample: python driver.py -m spline -u -o \n""" + + def __init__(self, data_file, *args, **kwargs): + warning( + "THIS PES HAS NOT BEEN TESTED FOLLOWING CONVERSION TO THE NEW PES API.", + verbosity.low, + ) + self.data_file = data_file + super().__init__(*args, **kwargs) self.get_spline() if friction and not SI: self.get_spline_fric() self.k = 1836 * (3800.0 / 219323.0) ** 2 - def check_arguments(self): + def check_parameters(self): """Function that checks the arguments required to run the driver""" try: - data = np.loadtxt(self.args[0]).reshape(-1, 5) + data = np.loadtxt(self.data_file).reshape(-1, 5) except ValueError: - sys.exit(self.error_msg) + sys.exit(self._error_msg) self.data = data def get_spline(self): diff --git a/ipi/pes/xtb.py b/ipi/pes/xtb.py new file mode 100644 index 000000000..7c0d0e14b --- /dev/null +++ b/ipi/pes/xtb.py @@ -0,0 +1,86 @@ +import numpy as np + +from ipi.utils.units import unit_to_internal, unit_to_user +from ipi.utils.io import read_file_name +from .dummy import Dummy_driver + +tb = None + +__DRIVER_NAME__ = "xtb" +__DRIVER_CLASS__ = "TBLiteDriver" + + +class TBLiteDriver(Dummy_driver): + """ + Interface with tblite to provide GFN1-xTB and GFN2-xTB calculators. + + Example:: + + i-pi-py_driver -m xtb -u -o template=input.xyz,method=GFN2-xTB + """ + + def __init__( + self, template, method, charge=None, uhf=None, periodic=None, *args, **kwargs + ): + + super().__init__(*args, **kwargs) + + global tb + try: + import tblite.interface as tb + except ImportError: + raise ModuleNotFoundError( + "Could not find tblite for xtb driver. Please install tblite-python with mamba" + ) + + input_data = read_file_name(template) + atoms = input_data["atoms"] + symbols = atoms.names[:] + numbers = np.asarray(tb.symbols_to_numbers(symbols)) + self.periodic = periodic + self.verbosity = 1 if self.verbose else 0 + + pos = unit_to_user("length", "atomic_unit", atoms.q[:]) + cell = unit_to_user("length", "atomic_unit", input_data["cell"].h.T) + + self.calc = tb.Calculator( + method, + numbers, + np.asarray(pos), + charge, + uhf, # unpaired electrons + np.asarray(cell) if self.periodic else None, + np.repeat(self.periodic, 3) if self.periodic else None, + ) + self.calc.set("verbosity", self.verbosity) + + def __call__(self, cell, pos): + """ + Get energies, forces, and stresses from the tblite library + This routine assumes that the client will take positions + in bohr, and return energies in hartree, and forces + in hartree/abohr. + """ + + pos = unit_to_user("length", "atomic_unit", pos) + cell = unit_to_user("length", "atomic_unit", cell.T) + + self.calc.update(np.asarray(pos), np.asarray(cell) if self.periodic else None) + + # Do the actual calculation + results = self.calc.singlepoint() + pot = results.get("energy") + grad = results.get("gradient") + vir = results.get("virial") + + # converts to internal quantities + pot_ipi = np.asarray(unit_to_internal("energy", "atomic_unit", pot), np.float64) + force_ipi = np.asarray( + unit_to_internal("force", "atomic_unit", -grad), np.float64 + ) + vir_ipi = np.array( + unit_to_internal("energy", "atomic_unit", -vir.T), np.float64 + ) + extras = "" + + return pot_ipi, force_ipi, vir_ipi, extras diff --git a/ipi/utils/hesstools.py b/ipi/utils/hesstools.py index 01dde88fe..817e50c1f 100644 --- a/ipi/utils/hesstools.py +++ b/ipi/utils/hesstools.py @@ -176,7 +176,7 @@ def clean_hessian(h, q, natoms, nbeads, m, m3, asr, mofi=False): def get_hessian( - gm, x0, natoms, nbeads=1, fixatoms=[], d=0.001, new_disc=False, friction=False + gm, x0, natoms, nbeads=1, fixatoms_dof=[], d=0.001, new_disc=False, friction=False ): """Compute the physical hessian given a function to evaluate energy and forces (gm). The intermediate steps are written as a temporary files so the full hessian calculations is only ONE step. @@ -185,19 +185,16 @@ def get_hessian( x0 = position vector natoms = number of atoms nbeads = number of beads - fixatoms = indexes of fixed atoms + fixatoms_dof = indexes of fixed degrees of freedom d = displacement - OUT h = physical hessian ( (natoms-len(fixatoms) )*3 , nbeads*( natoms-len(fixatoms) )*3) + OUT h = physical hessian (3*natoms-len(fixatoms_dof) , nbeads*( 3*natoms-len(fixatoms_dof) )) """ info(" @get_hessian: Computing hessian", verbosity.low) - fixdofs = list() - for i in fixatoms: - fixdofs.extend([3 * i, 3 * i + 1, 3 * i + 2]) ii = natoms * 3 - activedof = np.delete(np.arange(ii), fixdofs) - ncalc = ii - len(fixdofs) + activedof = np.delete(np.arange(ii), fixatoms_dof) + ncalc = ii - len(fixatoms_dof) if x0.size != natoms * 3 * nbeads: raise ValueError( "The position vector is not consistent with the number of atoms/beads." @@ -250,7 +247,7 @@ def get_hessian( # Start calculation: for j in range(i0 + 1, ii): - if j in fixdofs: + if j in fixatoms_dof: continue else: ndone = len(activedof[activedof < j]) diff --git a/ipi/utils/instools.py b/ipi/utils/instools.py index 7c90f0298..929350730 100644 --- a/ipi/utils/instools.py +++ b/ipi/utils/instools.py @@ -4,6 +4,7 @@ from ipi.utils.messages import verbosity, info from ipi.utils import units import ipi.utils.mathtools as mt +from ipi.utils.softexit import softexit def banded_hessian(h, sm, masses=True, shift=0.001): @@ -307,14 +308,23 @@ def ms_pathway(pos, m3): class Fix(object): """Class that applies a fixatoms type constrain""" - def __init__(self, fixatoms, beads, nbeads=None): + def __init__(self, fixatoms_dof, beads, nbeads=None): self.natoms = beads.natoms if nbeads is None: self.nbeads = beads.nbeads else: self.nbeads = nbeads - self.fixatoms = fixatoms + self.fixatoms_dof = fixatoms_dof + if len(self.fixatoms_dof) > 0: + if np.mod(len(self.fixatoms_dof), 3) == 0: + self.fixatoms = np.unique(self.fixatoms_dof // 3) + else: + softexit.trigger( + message="fixatoms_dof is not yet implemented. please use fixatoms", + ) + else: + self.fixatoms = self.fixatoms_dof self.mask0 = np.delete(np.arange(self.natoms), self.fixatoms) self.nactive = len(self.mask0) @@ -327,7 +337,7 @@ def __init__(self, fixatoms, beads, nbeads=None): mask2 = np.tile(mask1, self.nbeads) self.mask2 = np.arange(3 * self.natoms * self.nbeads)[mask2] - self.fixbeads = Beads(beads.natoms - len(fixatoms), beads.nbeads) + self.fixbeads = Beads(beads.natoms - len(self.fixatoms), beads.nbeads) self.fixbeads.q[:] = self.get_active_vector(beads.clone().q, 1) self.fixbeads.m[:] = self.get_active_vector(beads.clone().m, 0) self.fixbeads.names[:] = self.get_active_vector(beads.clone().names, 0) diff --git a/ipi/utils/io/__init__.py b/ipi/utils/io/__init__.py index bd0a076b7..b6efb5609 100644 --- a/ipi/utils/io/__init__.py +++ b/ipi/utils/io/__init__.py @@ -456,7 +456,9 @@ def open_backup(filename, mode="r", buffering=-1): if fn_backup != filename: os.rename(filename, fn_backup) info( - "Backup performed: {0:s} -> {1:s}".format(filename, fn_backup), + " @open_backup: Backup performed: {0:s} -> {1:s}".format( + filename, fn_backup + ), verbosity.low, ) diff --git a/ipi/utils/io/inputs/__init__.py b/ipi/utils/io/inputs/__init__.py index e766bce28..ca18a14e2 100644 --- a/ipi/utils/io/inputs/__init__.py +++ b/ipi/utils/io/inputs/__init__.py @@ -8,3 +8,41 @@ __all__ = ["io_xml"] + + +def read_value(s): + """Attempt to parse a string to int or float; fallback to string.""" + s = s.strip() + for cast in (int, float): + try: + return cast(s) + except ValueError: + continue + if s.lower() == "false": + return False + if s.lower() == "true": + return True + return s + + +def read_args_kwargs(input_str): + """ + Parses a string into positional arguments and keyword arguments. + + Args: + input_str (str): The input string containing comma-separated values and key-value pairs. + + Returns: + tuple: A tuple containing a list of positional arguments and a dictionary of keyword arguments. + """ + args = [] + kwargs = {} + tokens = input_str.split(",") + for token in tokens: + token = token.strip() + if "=" in token: + key, value = token.split("=", 1) + kwargs[key.strip()] = read_value(value) + elif len(token) > 0: + args.append(read_value(token)) + return args, kwargs diff --git a/ipi/utils/io/inputs/io_xml.py b/ipi/utils/io/inputs/io_xml.py index 7ecb2ac68..c2a508792 100644 --- a/ipi/utils/io/inputs/io_xml.py +++ b/ipi/utils/io/inputs/io_xml.py @@ -12,12 +12,14 @@ import numpy as np from ipi import ipi_global_settings +from . import read_value __all__ = [ "xml_node", "xml_handler", "xml_parse_string", "xml_parse_file", + "xml_edit", "xml_write", "read_type", "read_float", @@ -55,9 +57,10 @@ def __init__(self, attribs=None, name="", fields=None): Args: attribs: An optional dictionary giving attribute data. Defaults to {}. - fields: An optional dictionary holding all the data between the start + fields: An optional list holding all the data between the start and end tags, including information about other nodes. - Defaults to {}. + This is stored as a list of tuples [(key, value)] to allow for + duplicated entries. name: An optional string giving the tag name. Defaults to ''. """ @@ -243,6 +246,38 @@ def xml_write(xml, name="", indent="", text=""): return rstr +def xml_edit(root, path, node, full_path=False, mode="add"): + """Edits an xml_node, "add"-ing, "remove"-ing + or "replace"-ing the node at the desired location(s)""" + + n_edited = 0 + + for idx in range(len(root.fields) - 1, -1, -1): + # iterate backwards to avoid index errors as we are editing the list in place + name, field = root.fields[idx] + if name == "_text": # reached a dead end + continue + print(name, field) + if name == path[0]: + if len(path) == 1: + if mode == "add": + field.fields.append((node.name, node)) + elif mode == "remove": + root.fields.pop(idx) + elif mode == "replace": + root.fields[idx] = (node.name, node) + else: + raise ValueError(f"Invalid editing mode {mode}") + n_edited += 1 + else: + n_edited += xml_edit(field, path[1:], node, full_path, mode) + elif not full_path: + # see if the path is to be found somewhere >>within<< + n_edited += xml_edit(field, path, node, full_path, mode) + + return n_edited + + def read_type(type, data): """Reads a string and outputs data of a specified type. @@ -448,7 +483,7 @@ def mystrip(data): rtuple = list(map(mystrip, s.split(key_split))) if not len(rtuple) == 2: raise ValueError("Format for a key:value format is wrong for item " + s) - rdict[rtuple[0]] = rtuple[1] + rdict[rtuple[0]] = read_value(rtuple[1]) return rdict diff --git a/ipi/utils/io/io_units.py b/ipi/utils/io/io_units.py index 059b61e21..64ef7fe68 100755 --- a/ipi/utils/io/io_units.py +++ b/ipi/utils/io/io_units.py @@ -113,7 +113,7 @@ def process_units( ) info( - " # Interpreting input with dimension %s, units %s and cell units %s" + " @process_units: Interpreting input with dimension %s, units %s and cell units %s" % (dimension, units, cell_units), verbosity.high, ) diff --git a/ipi/utils/parsing.py b/ipi/utils/parsing.py index ef9455bb1..ef4ea1a42 100644 --- a/ipi/utils/parsing.py +++ b/ipi/utils/parsing.py @@ -9,6 +9,7 @@ import re import numpy as np from ipi.utils.units import unit_to_user +from ipi.utils.messages import warning, verbosity try: import ase @@ -138,8 +139,7 @@ def read_trajectory( raise ValueError(f"Unrecognized file format: {format}") file_handle = open(filename, "r") - bohr2angstrom = unit_to_user("length", "angstrom", 1.0) - comment_regex = re.compile(r"([^)]+)\{([^}]+)\}") + comment_regex = re.compile(r"(\w+)\{([^}]+)\}") step_regex = re.compile(r"Step:\s+(\d+)") frames = [] @@ -200,17 +200,17 @@ def read_trajectory( frame = ase.Atoms( ret["atoms"].names, - positions=ret["atoms"].q.reshape((-1, 3)) * bohr2angstrom, - cell=ret["cell"].h.T * bohr2angstrom, + # will apply conversion later! + positions=ret["atoms"].q.reshape((-1, 3)), + cell=ret["cell"].h.T * unit_to_user("length", "ase"), pbc=True, ) # parse comment to get the property matches = comment_regex.findall(ret["comment"]) - # get what we have found - if len(matches) >= 2: - what = matches[-2][0] + if len(matches) == 2: + what = matches[0][0] else: # defaults to reading positions what = "positions" @@ -219,13 +219,25 @@ def read_trajectory( if len(matches) >= 1: frame.info["step"] = int(matches[-1][0]) - # if we have forces, set positions to zero (that data is missing!) and set forces instead - if what == "forces": - # set forces and convert to eV/angstrom - frame.positions *= 0 - frame.arrays["forces"] = ret["atoms"].q.reshape( - (-1, 3) - ) * unit_to_user("force", "ev/ang", 1.0) + # fetch the list of known traj types, cf. `engine/properties.py`` + from ipi.engine.properties import Trajectories # avoids circular import + + traj_types = Trajectories().traj_dict + if not what in traj_types: + warning( + f"{what} is not a known trajectory type. Will apply no units conversion", + verbosity.low, + ) + elif traj_types[what]["dimension"] == "length": + # positions is the right place to store, and we just need to convert + frame.positions *= unit_to_user("length", "ase") + else: + # if we have another type of value, set positions to zero + # (that data is missing!) and set an array instead + frame.positions *= 0.0 + frame.arrays[what] = ret["atoms"].q.reshape((-1, 3)) * unit_to_user( + traj_types[what]["dimension"], "ase" + ) frames.append(frame) diff --git a/ipi/utils/prng.py b/ipi/utils/prng.py index 273a7e0b4..890907fe6 100644 --- a/ipi/utils/prng.py +++ b/ipi/utils/prng.py @@ -14,6 +14,7 @@ import numpy as np import concurrent.futures +import time __all__ = ["Random"] @@ -39,7 +40,7 @@ class Random(object): Gaussian random number returned. """ - def __init__(self, seed=12345, state=None, n_threads=1): + def __init__(self, seed=-1, state=None, n_threads=1): """Initialises Random. Args: @@ -49,7 +50,12 @@ def __init__(self, seed=12345, state=None, n_threads=1): arrays to be filled are large!) """ + # Here we make the seed random if it has not been specified in the input file + if seed == -1: + seed = int(time.time() * 1000) + self.seed = seed + self.rng = [ np.random.Generator(np.random.MT19937(s)) for s in np.random.SeedSequence(seed).spawn(n_threads) diff --git a/ipi/utils/scripting.py b/ipi/utils/scripting.py new file mode 100644 index 000000000..2549bf1b3 --- /dev/null +++ b/ipi/utils/scripting.py @@ -0,0 +1,279 @@ +import numpy as np +from ipi.utils.depend import dstrip +from ipi.utils.units import Elements, unit_to_internal, unit_to_user +from ipi.inputs.beads import InputBeads +from ipi.inputs.cell import InputCell +from ipi.engine.beads import Beads +from ipi.engine.cell import Cell +from ipi.engine.simulation import Simulation +from ipi.utils.io.inputs.io_xml import xml_parse_string, xml_write, write_dict +from ipi.pes import __drivers__ + +from ipi.utils.io.backends.io_ase import ase, _asecheck + +__all__ = [ + "simulation_xml", + "motion_nvt_xml", + "forcefield_xml", + "InteractiveSimulation", +] + + +DEFAULT_OUTPUTS = """ + + [ step, time{picosecond}, conserved{electronvolt}, temperature{kelvin}, potential{electronvolt} ] + positions{angstrom} + + +""" + + +def simulation_xml( + structures, + forcefield, + motion, + temperature=None, + output=None, + verbosity="quiet", + safe_stride=20, + prefix=None, +): + """ + A helper function to generate an XML string for an i-PI simulation input. + """ + + if type(structures) is list: + nbeads = len(structures) + natoms = len(structures[0]) + q = np.vstack([frame.positions.reshape(1, -1) for frame in structures]) + structure = structures[0] + else: + structure = structures + nbeads = 1 + natoms = len(structure) + q = structure.positions.flatten() + + beads = Beads(nbeads=nbeads, natoms=natoms) + beads.q = q * unit_to_internal("length", "ase", 1.0) + beads.names = np.array(structure.symbols) + if "mass" in structure.arrays: + beads.m = structure.arrays["mass"] * unit_to_internal("mass", "ase", 1.0) + else: + beads.m = np.array([Elements.mass(n) for n in beads.names]) + + input_beads = InputBeads() + input_beads.store(beads) + + cell = Cell(h=np.array(structure.cell) * unit_to_internal("length", "ase", 1.0)) + input_cell = InputCell() + input_cell.store(cell) + + # gets ff name + xml_ff = xml_parse_string(forcefield).fields[0][1] + ff_name = xml_ff.attribs["name"] + + # parses the outputs and overrides prefix + if output is None: + output = DEFAULT_OUTPUTS + if prefix is not None: + xml_output = xml_parse_string(output) + if xml_output.fields[0][0] != "output": + raise ValueError("the output parameter should be a valid 'output' block") + xml_output.fields[0][1].attribs["prefix"] = prefix + output = xml_write(xml_output) + + return f""" + +{forcefield} +{output} + +{input_beads.write("beads")} +{input_cell.write("cell")} +{( + f"" + f" {temperature} " + "" + f"" + f" {temperature} " + "" + if temperature is not None else "" +)} + + + +{motion} + + +""" + + +def forcefield_xml( + name, mode="direct", parameters=None, pes=None, address=None, port=None +): + """ + A helper function to generate an XML string for a forcefield block. + """ + + if mode == "direct": + if pes is None: + raise ValueError(f"Must specify 'pes' for {mode} forcefields") + elif pes not in __drivers__.keys(): + raise ValueError(f"Invalid value {pes} for 'pes'") + if parameters is None: + parameters = "" + elif type(parameters) is dict: + parameters = f"{write_dict(parameters)}" + else: + parameters = f"{parameters}" + + xml_ff = f""" + +{"dummy" if pes is None else pes} +{parameters} + +""" + elif mode == "unix" or mode == "inet": + if address is None: + raise ValueError("Must specify address for {mode} forcefields") + if mode == "inet" and port is None: + raise ValueError("Must specify port for {mode} forcefields") + xml_ff = f""" + +
{address}
+{f"{port}" if mode=="inet" else ""} + 1e-4 +
+""" + else: + raise ValueError( + "Invalid forcefield mode, use ['direct', 'unix', 'inet'] or set up manually" + ) + + return xml_ff + + +def motion_nvt_xml(timestep, thermostat=None, path_integrals=False): + """ + A helper function to generate an XML string for a MD simulation input. + """ + + # sets up thermostat + if thermostat is None: + if path_integrals: + # defaults to pile_g + xml_thermostat = f""" + + {10*timestep} + 0.5 + +""" + else: + # defaults to svr + xml_thermostat = f""" + + {10*timestep} + +""" + + return f""" + + + {timestep} +{xml_thermostat} + + +""" + + +class InteractiveSimulation: + """A wrapper to `Simulation` that allows accessing + properties and configurations in a "safe" way from Python. + The object is initialized from an XML input, and supports + a minimalistic API to step through the simulation, extract + properties and structures, and set configurations interactively. + + :param xml_input: An open XML file, or an XML-formatted string + containing the i-PI simulation that should be run. + """ + + def __init__(self, xml_input): + self.simulation = Simulation.load_from_xml(xml_input) + + def run(self, steps=1, write_outputs=True): + """Stepper through the simulation. + Run the simulation interactively for the specified number of steps. + + :param steps: int, number of steps the simulation should be advanced by + """ + + print(self.simulation.step) + self.simulation.tsteps = self.simulation.step + steps + self.simulation.run(write_outputs=write_outputs) + # saves the RESTART file + self.simulation.chk.write(store=True) + self.simulation.step += 1 + + def run_step(self, step): + self.simulation.run_step(step) + + def properties(self, property): + """Fetches properties from the simulation state. + + :param property: the name of a property to be fetched from the simulation + """ + props = [] + for system in self.simulation.syslist: + value, dimension, unit = system.properties[property] + props.append(value * unit_to_user(dimension, "ase", 1.0)) + if len(props) == 1: + return props[0] + else: + return props + + def get_structures(self): + _asecheck() + + sys_structures = [] + for system in self.simulation.syslist: + structures = [] + for b in range(system.beads.nbeads): + struc = ase.Atoms( + positions=dstrip(system.beads.q[b]).reshape(-1, 3) + * unit_to_user("length", "ase", 1.0), + symbols=dstrip(system.beads.names), + cell=dstrip(system.cell.h) * unit_to_user("length", "ase", 1.0), + ) + struc.arrays["ipi_velocities"] = dstrip(system.beads.p[b]).reshape( + -1, 3 + ) * unit_to_user("velocity", "ase", 1.0) + struc.arrays["ipi_forces"] = dstrip(system.forces.f[b]).reshape( + -1, 3 + ) * unit_to_user("force", "ase", 1.0) + struc.info["ipi_potential"] = dstrip( + system.forces.pots[b] + ) * unit_to_user("energy", "ase", 1.0) + structures.append(struc) + if len(structures) == 1: # flatten the structure if there's just one beads + structures = structures[0] + sys_structures.append(structures) + if len(sys_structures) == 1: # flatten the structure if there's just one system + sys_structures = sys_structures[0] + return sys_structures + + def set_structures(self, sys_structures): + _asecheck() + + if len(self.simulation.syslist) == 1: + sys_structures = [sys_structures] + for system, structures in zip(self.simulation.syslist, sys_structures): + if system.beads.nbeads == 1: + structures = [structures] + for b, struc in enumerate(structures): + system.beads.q[b] = struc.positions.flatten() * unit_to_internal( + "length", "ase", 1.0 + ) + system.cell.h = struc.cell * unit_to_internal("length", "ase", 1.0) + if "ipi_velocities" in struc.arrays: + system.beads.p[b] = struc.arrays[ + "ipi_velocities" + ].flatten() * unit_to_internal("velocity", "ase", 1.0) diff --git a/ipi/utils/softexit.py b/ipi/utils/softexit.py index a49924785..70b675c40 100644 --- a/ipi/utils/softexit.py +++ b/ipi/utils/softexit.py @@ -77,17 +77,21 @@ def trigger(self, status="restartable", message=""): message: The message to output to standard output. """ - print("SOFTEXIT CALLED FROM THREAD", threading.currentThread(), message) + print( + " @softexit.trigger: SOFTEXIT CALLED FROM THREAD", + threading.currentThread(), + message, + ) if not self.triggered: # avoid double calls from different threads self.exiting = True self.triggered = True if status == "restartable": - message += "\nRestartable as is: YES." + message += " Restartable as is: YES." elif status == "success": - message += "\nI-PI reports success. Restartable as is: NO." + message += " I-PI reports success. Restartable as is: NO." elif status == "bad": - message += "\nI-PI reports a problem. Restartable as is: NO." + message += " I-PI reports a problem. Restartable as is: NO." else: raise ValueError("Unknown option for softexit status.") diff --git a/ipi/utils/units.py b/ipi/utils/units.py index f6cb3eb9b..6f621bbf2 100644 --- a/ipi/utils/units.py +++ b/ipi/utils/units.py @@ -13,7 +13,7 @@ try: import ase - from ase.units import Bohr, Hartree, eV, Angstrom, Pascal, kB, Debye, _amu + from ase.units import Bohr, Hartree, eV, Angstrom, kB except ImportError: ase = None @@ -298,43 +298,35 @@ def mass(cls, label): # Conditionally includes "ase" units for each quantity if ase is not None: - # Conversion factors from atomic units to ASE units - conversion_factors = { - "undefined": {"ase": 1}, - "energy": {"ase": 1 / (Hartree / eV)}, - "temperature": {"ase": kB}, - "time": { - "ase": 1 - / ((Bohr / Angstrom) * (1 / (Hartree / eV)) ** 0.5 * (_amu / 1) ** 0.5) - }, - "frequency": { - "ase": (Bohr / Angstrom) * (1 / (Hartree / eV)) ** 0.5 * (_amu / 1) ** 0.5 - }, - "electric-field": {"ase": 1 / (Hartree / (Bohr * eV / Angstrom))}, - "electric-dipole": {"ase": 1 / (Bohr / Debye)}, - "length": {"ase": 1 / (Bohr / Angstrom)}, - "volume": {"ase": 1 / ((Bohr**3) / (Angstrom**3))}, - "velocity": { - "ase": 1 / ((Hartree / eV) ** 0.5 * (Bohr / Angstrom) / (_amu / 1) ** 0.5) - }, - "momentum": {"ase": 1 / ((Bohr / Angstrom) * (Hartree / eV) ** 0.5)}, - "mass": {"ase": 1}, # Atomic unit of mass to amu - "pressure": {"ase": 1 / (Hartree / (Bohr**3 * Pascal))}, - "density": { - "ase": 1 / (_amu / (Angstrom**3)) - }, # Atomic unit of density to g/cm^3 - "force": {"ase": 1 / (Hartree / Bohr)}, # Atomic unit of force to N - "hessian": { - "ase": 1 / (Hartree / (Bohr**2)) - }, # Atomic unit of Hessian to eV/Å^2 - } - - # Update UnitMap with ASE conversion factors - for quantity, factors in conversion_factors.items(): - if quantity in UnitMap: - UnitMap[quantity].update(factors) + UnitMap["undefined"]["ase"] = 1.0 + UnitMap["energy"]["ase"] = eV / Hartree + UnitMap["length"]["ase"] = Angstrom / Bohr + UnitMap["temperature"]["ase"] = kB * eV / Hartree + UnitMap["time"]["ase"] = (Angstrom / Bohr) * (Constants.amu / (eV / Hartree)) ** 0.5 + UnitMap["velocity"]["ase"] = UnitMap["length"]["ase"] / UnitMap["time"]["ase"] + UnitMap["force"]["ase"] = UnitMap["energy"]["ase"] / UnitMap["length"]["ase"] + UnitMap["volume"]["ase"] = UnitMap["length"]["ase"] ** 3 + UnitMap["frequency"]["ase"] = 1 / UnitMap["time"]["ase"] + UnitMap["mass"]["ase"] = ( + UnitMap["energy"]["ase"] / UnitMap["velocity"]["ase"] ** 2 + ) # to check + UnitMap["pressure"]["ase"] = ( + UnitMap["energy"]["ase"] / UnitMap["volume"]["ase"] + ) # to check + UnitMap["momentum"]["ase"] = ( + UnitMap["mass"]["ase"] * UnitMap["velocity"]["ase"] + ) # to check + UnitMap["density"]["ase"] = ( + UnitMap["mass"]["ase"] / UnitMap["volume"]["ase"] + ) # to check + UnitMap["hessian"]["ase"] = ( + UnitMap["energy"]["ase"] / UnitMap["length"]["ase"] ** 2 + ) # to check + # since ASe handles charges in atomic_units, dipole and electric field should have the same units as lenth and force, respectively + UnitMap["electric-dipole"]["ase"] = UnitMap["length"]["ase"] + UnitMap["electric-field"]["ase"] = UnitMap["force"]["ase"] # a list of magnitude prefixes UnitPrefix = { @@ -373,7 +365,7 @@ def mass(cls, label): # -def unit_to_internal(family, unit, number): +def unit_to_internal(family, unit, number=1.0): """Converts a number of given dimensions and units into internal units. Args: @@ -419,7 +411,7 @@ def unit_to_internal(family, unit, number): return number * UnitMap[family][base.lower()] * UnitPrefix[prefix] -def unit_to_user(family, unit, number): +def unit_to_user(family, unit, number=1.0): """Converts a number of given dimensions from internal to user units. Args: @@ -431,4 +423,4 @@ def unit_to_user(family, unit, number): The number in the user specified units """ - return number / unit_to_internal(family, unit, 1.0) + return number / unit_to_internal(family, unit) diff --git a/ipi_tests/README.md b/ipi_tests/README.md index 97b667f3e..152d4a5ac 100644 --- a/ipi_tests/README.md +++ b/ipi_tests/README.md @@ -14,7 +14,10 @@ * To run the unitary, example and regression tests, please use i-pi/bin/i-pi-tests. For details of usage call it with "-h" option. - * In some situations it is desirable to perform regresion/examples tests only for a selected set. + * The tests can be customized to an extent by including a `test_settings.dat` file that specifies how to run the test, + mostly by describing the driver that should be used. See some of the existing files as examples. + + * In some situations it is desirable to perform regression/examples tests only for a selected set. For these cases, we also provide more flexible scripts for performing the regresion tests and testing the provided examples. See i-pi/ipi_tests/regression_tests/test_run.py and i-pi/ipi_tests/examples/test_examples.py, respectively. For details of usage call them with "-h" option. diff --git a/ipi_tests/examples/excluded_test.txt b/ipi_tests/examples/excluded_test.txt index bb6434db1..49f775043 100644 --- a/ipi_tests/examples/excluded_test.txt +++ b/ipi_tests/examples/excluded_test.txt @@ -8,8 +8,6 @@ temp/ph2/rpmd # long and complicated # Needs infrastructure fixing -clients/fhi_aims/zundel # dummy driver has an issue with extra_type. example works with actual backends. - # Need of external dependency clients/yaff/mil53_ffyaff clients/yaff/mil53_ffsocket diff --git a/ipi_tests/profiling/classical_md_direct/init.xyz b/ipi_tests/profiling/classical_md_direct/init.xyz new file mode 100644 index 000000000..f2f3870f8 --- /dev/null +++ b/ipi_tests/profiling/classical_md_direct/init.xyz @@ -0,0 +1,10 @@ +8 +# CELL(abcABC): 50.0 50.0 50.0 90.00000 90.00000 90.00000 +H 0 0 0 +H 0 0 1 +H 0 0 2 +H 0 0 3 +H 0 0 4 +H 0 0 5 +H 0 0 6 +H 0 0 7 diff --git a/ipi_tests/profiling/classical_md_direct/input.xml b/ipi_tests/profiling/classical_md_direct/input.xml new file mode 100644 index 000000000..21d038b66 --- /dev/null +++ b/ipi_tests/profiling/classical_md_direct/input.xml @@ -0,0 +1,34 @@ + + + dummy + 1.00000000e-04 + + 10000 + + positions + [ step, time, conserved, temperature, kinetic_md, potential, pressure_md, volume ] + + + 18885 + + + + + + + init.xyz + [10.0, 0, 0, 0, 10.0, 0, 0, 0, 10.0] + [1.0] + 1 + + + 1 + + + False + + 0.01 + + + + diff --git a/ipi_tests/profiling/run_profiling.sh b/ipi_tests/profiling/run_profiling.sh index c475445c0..b8ae0bfb8 100755 --- a/ipi_tests/profiling/run_profiling.sh +++ b/ipi_tests/profiling/run_profiling.sh @@ -1,5 +1,5 @@ #!/bin/bash -# usage: run_profile.sh [-p] natoms [ndriver] +# usage: run_profiling.sh [-p] natoms [ndriver] # run a mock simulation using an natoms box, -p activates yappi profiling # Default value for natoms diff --git a/ipi_tests/regression_tests/tests/GEOP/BFGS-TRM/harmonic/input.xml b/ipi_tests/regression_tests/tests/GEOP/BFGS-TRM/harmonic/input.xml index 51d87a02e..641e0690a 100644 --- a/ipi_tests/regression_tests/tests/GEOP/BFGS-TRM/harmonic/input.xml +++ b/ipi_tests/regression_tests/tests/GEOP/BFGS-TRM/harmonic/input.xml @@ -4,6 +4,9 @@ x_centroid f_centroid + + 123456 + 10
localhost
diff --git a/ipi_tests/regression_tests/tests/GEOP/BFGS-TRM/pswater/input.xml b/ipi_tests/regression_tests/tests/GEOP/BFGS-TRM/pswater/input.xml index 5ea1d33ba..ae2402bf4 100644 --- a/ipi_tests/regression_tests/tests/GEOP/BFGS-TRM/pswater/input.xml +++ b/ipi_tests/regression_tests/tests/GEOP/BFGS-TRM/pswater/input.xml @@ -4,6 +4,9 @@ x_centroid f_centroid + + 123456 + 10
localhost
diff --git a/ipi_tests/regression_tests/tests/GEOP/BFGS/harmonic/input.xml b/ipi_tests/regression_tests/tests/GEOP/BFGS/harmonic/input.xml index ee9066b2d..153a972cf 100644 --- a/ipi_tests/regression_tests/tests/GEOP/BFGS/harmonic/input.xml +++ b/ipi_tests/regression_tests/tests/GEOP/BFGS/harmonic/input.xml @@ -4,6 +4,9 @@ x_centroid f_centroid + + 123456 + 10
localhost
diff --git a/ipi_tests/regression_tests/tests/GEOP/BFGS/pswater/input.xml b/ipi_tests/regression_tests/tests/GEOP/BFGS/pswater/input.xml index c4979cc42..3efa27ed8 100644 --- a/ipi_tests/regression_tests/tests/GEOP/BFGS/pswater/input.xml +++ b/ipi_tests/regression_tests/tests/GEOP/BFGS/pswater/input.xml @@ -4,6 +4,9 @@ x_centroid f_centroid + + 123456 + 10
localhost
diff --git a/ipi_tests/regression_tests/tests/GEOP/CG/harmonic/input.xml b/ipi_tests/regression_tests/tests/GEOP/CG/harmonic/input.xml index 3470a0605..07b7b96d6 100644 --- a/ipi_tests/regression_tests/tests/GEOP/CG/harmonic/input.xml +++ b/ipi_tests/regression_tests/tests/GEOP/CG/harmonic/input.xml @@ -4,6 +4,9 @@ x_centroid f_centroid + + 123456 + 10
localhost
diff --git a/ipi_tests/regression_tests/tests/GEOP/LBFGS/harmonic/input.xml b/ipi_tests/regression_tests/tests/GEOP/LBFGS/harmonic/input.xml index d09ca38d4..895b00640 100644 --- a/ipi_tests/regression_tests/tests/GEOP/LBFGS/harmonic/input.xml +++ b/ipi_tests/regression_tests/tests/GEOP/LBFGS/harmonic/input.xml @@ -4,6 +4,9 @@ x_centroid f_centroid + + 123456 + 10
localhost
diff --git a/ipi_tests/regression_tests/tests/GEOP/LBFGS/pswater/input.xml b/ipi_tests/regression_tests/tests/GEOP/LBFGS/pswater/input.xml index e14abf876..6cfafbec5 100644 --- a/ipi_tests/regression_tests/tests/GEOP/LBFGS/pswater/input.xml +++ b/ipi_tests/regression_tests/tests/GEOP/LBFGS/pswater/input.xml @@ -4,6 +4,9 @@ x_centroid f_centroid + + 123456 + 10
localhost
diff --git a/ipi_tests/regression_tests/tests/INSTANTON/070K_D/input.xml b/ipi_tests/regression_tests/tests/INSTANTON/070K_D/input.xml index 0cecd81da..b4e10c099 100644 --- a/ipi_tests/regression_tests/tests/INSTANTON/070K_D/input.xml +++ b/ipi_tests/regression_tests/tests/INSTANTON/070K_D/input.xml @@ -2,6 +2,9 @@ [ step, potential{electronvolt}] + + 123456 + 1000
localhost
diff --git a/ipi_tests/regression_tests/tests/INSTANTON/100K_implicit_friction/input.xml b/ipi_tests/regression_tests/tests/INSTANTON/100K_implicit_friction/input.xml index e6f349dcb..84f44a879 100644 --- a/ipi_tests/regression_tests/tests/INSTANTON/100K_implicit_friction/input.xml +++ b/ipi_tests/regression_tests/tests/INSTANTON/100K_implicit_friction/input.xml @@ -2,6 +2,9 @@ [ step, potential{electronvolt}] + + 123456 + 35
localhost
diff --git a/ipi_tests/regression_tests/tests/INSTANTON/100K_implicit_friction/simulation.instanton_FINAL_15.ener b/ipi_tests/regression_tests/tests/INSTANTON/100K_implicit_friction/simulation.instanton_FINAL_15.ener deleted file mode 100644 index 6a2a6e394..000000000 --- a/ipi_tests/regression_tests/tests/INSTANTON/100K_implicit_friction/simulation.instanton_FINAL_15.ener +++ /dev/null @@ -1,33 +0,0 @@ -#Bead Energy (eV) -0 -0.11866259790715851 -1 -0.11691012681205774 -2 -0.11342166079444242 -3 -0.1082351949410836 -4 -0.10141984639090063 -5 -0.09308898239047224 -6 -0.08341517679588735 -7 -0.0726445585426023 -8 -0.06110741669327686 -9 -0.049221487325502286 -10 -0.03748445701371601 -11 -0.026453159043353814 -12 -0.016708861462551 -13 -0.008810819030011201 -14 -0.0032433701350644724 -15 -0.0003644451312916968 -16 -0.0003644451319317277 -17 -0.0032433701369415356 -18 -0.008810819032999921 -19 -0.016708861466452396 -20 -0.026453159047914718 -21 -0.03748445701864777 -22 -0.04922148733051311 -23 -0.06110741669809458 -24 -0.07264455854700659 -25 -0.0834151767997177 -26 -0.09308898239364362 -27 -0.10141984639339816 -28 -0.10823519494296141 -29 -0.11342166079580748 -30 -0.11691012681305872 -31 -0.11866259790797011 diff --git a/ipi_tests/regression_tests/tests/INSTANTON/100K_implicit_friction/test_settings.dat b/ipi_tests/regression_tests/tests/INSTANTON/100K_implicit_friction/test_settings.dat index 42ec12ec1..0d6ab5051 100644 --- a/ipi_tests/regression_tests/tests/INSTANTON/100K_implicit_friction/test_settings.dat +++ b/ipi_tests/regression_tests/tests/INSTANTON/100K_implicit_friction/test_settings.dat @@ -1,6 +1,6 @@ driver_model DW_friction driver_code python -flags -o 500,2085,1837.36223469,0,1.5,-1.0,0,1 +flags -o 'w_b=500,v0=2085,m=1837.36223469,delta=0,eta0=1.5,eps1=-1.0,eps2=0,deltaQ=1' address localhost port 33335 socket_mode unix diff --git a/ipi_tests/regression_tests/tests/INSTANTON/200K/input.xml b/ipi_tests/regression_tests/tests/INSTANTON/200K/input.xml index 161af8767..0104b02b0 100644 --- a/ipi_tests/regression_tests/tests/INSTANTON/200K/input.xml +++ b/ipi_tests/regression_tests/tests/INSTANTON/200K/input.xml @@ -2,6 +2,9 @@ [ step, potential{electronvolt}] + + 123456 + 100
localhost
diff --git a/ipi_tests/regression_tests/tests/NEB/DAMPED_BFGS/zundel/input.xml b/ipi_tests/regression_tests/tests/NEB/DAMPED_BFGS/zundel/input.xml index 001bcabb5..b81e1bc68 100644 --- a/ipi_tests/regression_tests/tests/NEB/DAMPED_BFGS/zundel/input.xml +++ b/ipi_tests/regression_tests/tests/NEB/DAMPED_BFGS/zundel/input.xml @@ -12,6 +12,9 @@ forces [step, bead_potentials] + + 123456 + diff --git a/ipi_tests/regression_tests/tests/NEB/FIRE/zundel/input.xml b/ipi_tests/regression_tests/tests/NEB/FIRE/zundel/input.xml index 4d1e70407..1c251ec57 100644 --- a/ipi_tests/regression_tests/tests/NEB/FIRE/zundel/input.xml +++ b/ipi_tests/regression_tests/tests/NEB/FIRE/zundel/input.xml @@ -7,6 +7,9 @@ 600
localhost
+ + 123456 + positions{angstrom} forces diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/RESTART b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/RESTART new file mode 100644 index 000000000..6a7d23d8b --- /dev/null +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/RESTART @@ -0,0 +1,196 @@ + + + 123456 + [{"bit_generator": "MT19937", "state": {"key": [2147483648, 3937517930, 2150135538, 3482449142, 3600184337, 2193183394, 3870949520, 466887795, 1694788931, 382247763, 2565505168, 2564250736, 3547816048, 4128831427, 293226672, 881666154, 1369266778, 3204483163, 2325049, 2708179724, 1237571652, 1993078096, 4157003436, 2557478615, 3791609784, 133015286, 1322052982, 1897231026, 2257305484, 400786104, 776975173, 591145179, 1808533771, 2049898229, 3485570715, 1984709931, 1864373927, 3630755699, 2281311056, 3612254441, 217833916, 2802250141, 971383580, 3452932456, 627211621, 1298867632, 4262104640, 1625003068, 111332965, 339610725, 1438371105, 763220250, 266960750, 1777435498, 1158178530, 3496739019, 3329547059, 2531628286, 3158486648, 3760018874, 2702453011, 3212597543, 521210011, 3691282915, 2597305608, 3000553731, 2360713071, 322590301, 1703260930, 1754800259, 2140410046, 3012909618, 44044007, 3177763059, 3811329622, 572222652, 142270333, 2602722041, 2494373479, 2519584970, 1815784445, 3705713595, 74504042, 2979481072, 2069245649, 2339418347, 3465749753, 2516180318, 1557569169, 2660386697, 3260210920, 3289500086, 1639287986, 265421449, 654994688, 1632441514, 2366458826, 2961026214, 393536814, 321613388, 2667801220, 2069500993, 1016063269, 2547594878, 3338352572, 1124158874, 2661534041, 1377252528, 997224311, 3357731065, 2590164776, 257364400, 2546391809, 524728093, 2815922765, 73384504, 2315726464, 2306108399, 2827377772, 4111142828, 1310973796, 760944448, 1286894478, 3014167567, 1618857082, 452347053, 348755011, 1138394173, 4033969078, 657052914, 2099870195, 818855849, 1052460092, 4239752366, 2513349092, 2715202161, 2517309004, 2265227935, 1564212033, 2609431343, 1761665543, 3481566815, 1540668446, 1907769681, 2467834079, 1845465764, 505605688, 1783944243, 3122017169, 1273231480, 204667736, 800283924, 1502441418, 2812327611, 1950260612, 2498315086, 3375570996, 1875323548, 343662449, 4121832009, 3275258367, 2071932836, 2664735118, 3922341549, 1648053180, 826365530, 731040056, 2482427985, 2324727767, 4056758102, 2385993421, 1537403653, 304048664, 579877451, 599383539, 4011583484, 2310654334, 1831570800, 2463013972, 2010245046, 2868822649, 624738215, 3493282269, 3316293901, 3680677413, 2567170840, 3992049099, 1689857310, 91514227, 3500982007, 4207822660, 4026647014, 4251695788, 206382998, 3172621504, 2820829509, 405190305, 2642759070, 1799714415, 1131855569, 592398088, 1537705532, 2577582808, 1260104124, 1043249449, 2049932276, 1500694968, 1636793192, 1970825919, 1425826727, 1215170932, 2805755739, 4027848083, 928707777, 545011734, 2601289643, 3181047773, 3716781202, 1660110921, 3084899960, 1888648597, 1149587934, 3148792740, 3502283047, 2667159614, 80414736, 1818463289, 2854927181, 1304789058, 3147910330, 3931100645, 3092368886, 1718609704, 3935616015, 562625650, 2606866886, 3944793895, 3764144263, 24635965, 2536400329, 2034541955, 3518319086, 3911668413, 403604073, 2631925863, 1810940267, 3733259375, 1873305871, 731169491, 267750894, 4260333781, 580333872, 718436053, 2018303511, 248422468, 2597781808, 1353870197, 4029617140, 926076392, 174221573, 1828406908, 2432014574, 783729820, 1387853087, 296727016, 3961225600, 1570247138, 2774305275, 2646292156, 2968357174, 3499502940, 3924356367, 4276809005, 779927847, 2277562842, 2763601630, 365739083, 1585767711, 2083608923, 3821446497, 4053051347, 1996369893, 3859476912, 4142636364, 1806019234, 83282349, 1329147443, 2282421229, 3436254742, 2180105514, 3330902995, 961421865, 1069563463, 3709841924, 9621560, 304958858, 3323478879, 647833606, 698660702, 3023696030, 349463763, 1021746237, 1333353267, 1405259557, 335639750, 945743877, 1915891368, 3594564135, 4016969705, 3016200540, 225667737, 2207759152, 3596874532, 842631202, 2063678779, 4192298054, 3208068912, 2180292527, 4115742427, 3132489554, 4107889438, 3900175276, 1155433220, 2437299233, 3994689693, 4166219848, 3251286752, 1207473759, 501942700, 1882936736, 560801815, 2961802798, 813395836, 2195239683, 616618506, 2800764951, 3336505624, 778504508, 851543515, 2448870801, 1545109919, 1409886098, 2011863424, 2104479176, 1057224004, 1405338328, 1814641811, 4282698467, 4194893583, 2419053940, 3294902894, 1219204428, 3195826363, 1921607250, 3903868650, 602752650, 850939711, 1894897642, 1727490909, 566896749, 4104916459, 3386314572, 627158683, 1061466595, 1263339338, 3508373958, 3761844595, 3442428872, 571963088, 3346114346, 4114668762, 1244816469, 3040610747, 2212256071, 801441583, 1603583283, 425594905, 804249076, 2279687387, 419610277, 417869039, 2741138745, 4115841496, 1738262652, 2470707331, 2315788755, 3295816872, 4279896189, 1827827317, 3999684221, 1926578943, 1144668061, 4166647837, 7790061, 340135484, 4082906107, 4222441642, 3747165826, 1378564577, 2211584821, 1276149719, 2653153656, 4006939343, 3740530836, 2532448117, 3076283591, 917691864, 1741176175, 3084130707, 800122539, 56774360, 1086979950, 3284214470, 2975517697, 2474376305, 2781733418, 4154041694, 3395421881, 3936528888, 589073531, 4208712540, 4056837845, 3893296804, 4143301970, 647443408, 998524191, 3903368274, 172167908, 2874256214, 1050766970, 3384953736, 495152484, 3203728946, 1926687373, 2685690510, 3172468095, 2449891969, 768737098, 2989230022, 1279459556, 2984496292, 1048056931, 2404184950, 4274900842, 4079651629, 704875608, 1442854794, 3238189285, 3700855633, 885774096, 4172033398, 25116696, 4077335936, 3005332282, 396318389, 2946222652, 2717830585, 2201622177, 1729949798, 1024063406, 1001014445, 3133784850, 1756200039, 778808460, 1695695573, 3288132775, 805251813, 963938579, 3854899266, 2087946216, 1913474663, 3016898421, 3267766401, 2289731937, 845851856, 1729474226, 3016304334, 2522405635, 2295620830, 1869536905, 2875780527, 3031937132, 1607322519, 2845282544, 804354678, 3747213378, 1862864035, 3381728310, 3028594115, 2525730832, 7291285, 3638295164, 643916390, 430831990, 2640822829, 2488782512, 3976173624, 2822830107, 3765600232, 2705990445, 3677900735, 1210428094, 2477288770, 3618808085, 2119565074, 833227697, 550029810, 3580505805, 3820533695, 2133041528, 2379722589, 3904400223, 3714805420, 2987928003, 3047168890, 158876191, 3186663287, 2221982827, 2489879106, 3148559372, 3841739963, 2639182037, 3145100044, 2785718957, 1033113235, 4293037625, 2518607828, 3313805667, 3548411975, 631915249, 729381219, 360804326, 2977857785, 1565765320, 2056070119, 2821424780, 3859527756, 2207224468, 3401683323, 3628829676, 3471054819, 1571444977, 3901177229, 1096833671, 744541863, 3480515503, 247676825, 817279953, 4242007376, 1702429282, 2239447505, 2562563866, 676898079, 3386052424, 1209441004, 673809550, 2695387311, 3847699852, 208831544, 1568348572, 2504129926, 3408479090, 3937253943, 725378907, 1829666185, 2050760871, 458178725, 3065026071, 3590605635, 2500781845, 18656038, 3117202539, 2249887261, 1074468432, 2327692599, 1734855296, 3022263267, 1805629508, 600238108, 740079995, 3630665440, 2639144277, 3571020787, 1094547610, 331652995, 1890430262, 4276601757, 1424869962, 2870008855, 3616734793, 3134789651, 3743255034, 2709972545, 4219331622, 2109085356, 1082000409, 1119065908, 1898109625, 116597913, 333744963, 1132069181, 4153720463, 420793774, 842280851, 1071035089, 1879182681, 947042936, 2052636607, 2212881698, 3545571214, 1941633504, 509989634, 2173760535, 4108200901, 3255686055, 2706919679, 1397236239, 237924533, 1158433526, 343204563, 2560707750, 3475922933, 1579428718, 1162832808], "pos": 623}}] + + + [ step, potential{electronvolt} ] + x_centroid{angstrom} + + 18 + 400 + + + + + + + + + 1.00000000e+00 + -1.00000000e+00 + + [ -1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00, + -1.00000000e+00, -1.00000000e+00, -1.00000000e+00, -1.00000000e+00 ] + + [ 1.00000000e+00 ] + + + False + [ 15, 16, 17 ] + + 1.00000000e-03 + + [ 1.10121998e-04, 6.20723956e-05, 5.30603870e-05, -2.99891972e-05, -1.63566873e-05, + -1.39820783e-05, 5.44213521e-06, 5.25867636e-06, 4.56361859e-06, -6.27405220e-06, + -6.83805153e-06, -3.58412000e-06, -5.76548661e-06, -4.02963077e-06, -5.77365907e-06, + -2.82939271e-09, -6.25397001e-10, -5.33249133e-10, 6.20723502e-05, 7.02329835e-05, + 3.86844149e-05, -1.63568462e-05, -1.94790438e-05, -1.01932777e-05, -9.43210463e-06, + -5.16714180e-06, -4.32853579e-06, 9.09978467e-06, 5.88997838e-06, 5.77741900e-06, + -5.27609231e-06, -3.71499414e-06, -4.94632228e-06, -6.19354517e-10, 2.31124978e-10, + -1.04232833e-10, 5.30603372e-05, 3.86844118e-05, 5.80461712e-05, -1.39821995e-05, + -1.01932676e-05, -1.62676833e-05, -8.77110985e-06, -4.89472854e-06, -4.10260130e-06, + -5.87773480e-06, -5.82588576e-06, -3.44227422e-06, 9.85515398e-06, 7.22316163e-06, + 5.65397107e-06, -5.25696029e-10, -1.04232833e-10, 2.61337394e-10, -2.99891999e-05, + -1.63568619e-05, -1.39822166e-05, 2.53920002e-05, -1.41248865e-09, -1.22271164e-09, + -1.48500901e-05, 1.18257507e-05, 1.10152511e-05, -2.25429810e-05, 1.57260919e-05, + -1.31771503e-05, -2.02684900e-05, -1.11895889e-05, 1.61487786e-05, -1.62441354e-09, + -5.19007128e-10, -4.42862743e-10, -1.63566746e-05, -1.94790486e-05, -1.01932689e-05, + -1.42034849e-09, 2.53908301e-05, 1.84439934e-09, 1.18255503e-05, -2.67146298e-05, + -1.78477011e-05, 1.57256714e-05, -2.40527202e-05, 1.38239793e-05, -1.11891329e-05, + -1.74020372e-05, 1.42107512e-05, -5.12880568e-10, 9.23360067e-11, -1.22531194e-10, + -1.39820638e-05, -1.01932759e-05, -1.62676885e-05, -1.23171242e-09, 1.84097651e-09, + 2.53907260e-05, 1.10150957e-05, -1.78477541e-05, -2.41785549e-05, -1.31766816e-05, + 1.38238494e-05, -1.91384259e-05, 1.61483423e-05, 1.42109491e-05, -2.80634480e-05, + -4.40237075e-10, -1.23406417e-10, 1.31283422e-10, 5.44213521e-06, -9.43210916e-06, + -8.77111287e-06, -1.48500849e-05, 1.18255407e-05, 1.10150883e-05, 5.26689474e-05, + -4.48744207e-05, -4.17990264e-05, -3.56000898e-06, 6.25249262e-06, 7.40210373e-06, + -3.28879213e-06, 7.23277523e-06, 5.14443264e-06, -2.64358635e-10, -1.45019594e-10, + -1.28402766e-10, 5.25867636e-06, -5.16714029e-06, -4.89473458e-06, 1.18257616e-05, + -2.67146255e-05, -1.78477563e-05, -4.48744478e-05, 9.76895055e-05, 6.77308879e-05, + 3.33303217e-06, -6.09507536e-06, -7.92679973e-06, -4.53919941e-06, 5.79080763e-06, + 6.70062733e-06, -2.08465667e-10, -4.68292440e-11, -7.70416595e-11, 4.56361255e-06, + -4.32853730e-06, -4.10260432e-06, 1.10152585e-05, -1.78476976e-05, -2.41785510e-05, + -4.17990626e-05, 6.77308743e-05, 8.80651865e-05, -4.80713670e-06, 7.44745256e-06, + 5.82898102e-06, 4.01844462e-06, -9.24002466e-06, -6.32793453e-06, -1.87316976e-10, + -7.40204179e-11, -2.56805532e-11, -6.27405522e-06, 9.09978770e-06, -5.87772875e-06, + -2.25429766e-05, 1.57256705e-05, -1.31766847e-05, -3.56000898e-06, 3.33303066e-06, + -4.80714275e-06, 8.18629477e-05, -5.96778607e-05, 5.00047078e-05, 5.78893749e-06, + -7.03943389e-06, 6.16572407e-06, -1.73721389e-10, -3.02124155e-11, -5.28717271e-11, + -6.83804246e-06, 5.88997989e-06, -5.82588727e-06, 1.57260893e-05, -2.40527171e-05, + 1.38238586e-05, 6.25249262e-06, -6.09507385e-06, 7.44744501e-06, -5.96778668e-05, + 8.75895237e-05, -5.24629108e-05, 5.97741764e-06, -4.35522241e-06, 3.12182623e-06, + 3.77655194e-11, 2.56805532e-11, 7.55310387e-12, -3.58411396e-06, 5.77740843e-06, + -3.44227573e-06, -1.31771490e-05, 1.38239702e-05, -1.91384229e-05, 7.40210675e-06, + -7.92680728e-06, 5.82897951e-06, 5.00046912e-05, -5.24628912e-05, 6.89408921e-05, + -8.33550120e-06, 6.89238705e-06, -5.26235321e-06, -9.06372465e-11, -1.96380701e-11, + -1.35955870e-11, -5.76549114e-06, -5.27608777e-06, 9.85516002e-06, -2.02684869e-05, + -1.11891329e-05, 1.61483335e-05, -3.28878608e-06, -4.53920696e-06, 4.01844613e-06, + 5.78894202e-06, 5.97741160e-06, -8.33549818e-06, 7.32316881e-05, 4.24624789e-05, + -6.12816113e-05, -1.72210768e-10, -5.74035894e-11, -2.56805532e-11, -4.02962623e-06, + -3.71500169e-06, 7.22315861e-06, -1.11895863e-05, -1.74020337e-05, 1.42109346e-05, + 7.23277825e-06, 5.79080159e-06, -9.24002164e-06, -7.03943540e-06, -4.35522241e-06, + 6.89238403e-06, 4.24624729e-05, 6.23507169e-05, -5.39312070e-05, -8.91266257e-11, + -1.51062077e-11, -1.35955870e-11, -5.77366058e-06, -4.94632077e-06, 5.65397409e-06, + 1.61487878e-05, 1.42107635e-05, -2.80634458e-05, 5.14442811e-06, 6.70062582e-06, + -6.32793604e-06, 6.16572256e-06, 3.12182321e-06, -5.26236076e-06, -6.12816445e-05, + -5.39312508e-05, 1.02810418e-04, 5.13611063e-11, 1.20849662e-11, 2.56805532e-11, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00 ] + + + [ 1.10121998e-04, 6.20723956e-05, 5.30603870e-05, -2.99891972e-05, -1.63566873e-05, + -1.39820783e-05, 5.44213521e-06, 5.25867636e-06, 4.56361859e-06, -6.27405220e-06, + -6.83805153e-06, -3.58412000e-06, -5.76548661e-06, -4.02963077e-06, -5.77365907e-06, + -2.82939271e-09, -6.25397001e-10, -5.33249133e-10, 6.20723502e-05, 7.02329835e-05, + 3.86844149e-05, -1.63568462e-05, -1.94790438e-05, -1.01932777e-05, -9.43210463e-06, + -5.16714180e-06, -4.32853579e-06, 9.09978467e-06, 5.88997838e-06, 5.77741900e-06, + -5.27609231e-06, -3.71499414e-06, -4.94632228e-06, -6.19354517e-10, 2.31124978e-10, + -1.04232833e-10, 5.30603372e-05, 3.86844118e-05, 5.80461712e-05, -1.39821995e-05, + -1.01932676e-05, -1.62676833e-05, -8.77110985e-06, -4.89472854e-06, -4.10260130e-06, + -5.87773480e-06, -5.82588576e-06, -3.44227422e-06, 9.85515398e-06, 7.22316163e-06, + 5.65397107e-06, -5.25696029e-10, -1.04232833e-10, 2.61337394e-10, -2.99891999e-05, + -1.63568619e-05, -1.39822166e-05, 2.53920002e-05, -1.41248865e-09, -1.22271164e-09, + -1.48500901e-05, 1.18257507e-05, 1.10152511e-05, -2.25429810e-05, 1.57260919e-05, + -1.31771503e-05, -2.02684900e-05, -1.11895889e-05, 1.61487786e-05, -1.62441354e-09, + -5.19007128e-10, -4.42862743e-10, -1.63566746e-05, -1.94790486e-05, -1.01932689e-05, + -1.42034849e-09, 2.53908301e-05, 1.84439934e-09, 1.18255503e-05, -2.67146298e-05, + -1.78477011e-05, 1.57256714e-05, -2.40527202e-05, 1.38239793e-05, -1.11891329e-05, + -1.74020372e-05, 1.42107512e-05, -5.12880568e-10, 9.23360067e-11, -1.22531194e-10, + -1.39820638e-05, -1.01932759e-05, -1.62676885e-05, -1.23171242e-09, 1.84097651e-09, + 2.53907260e-05, 1.10150957e-05, -1.78477541e-05, -2.41785549e-05, -1.31766816e-05, + 1.38238494e-05, -1.91384259e-05, 1.61483423e-05, 1.42109491e-05, -2.80634480e-05, + -4.40237075e-10, -1.23406417e-10, 1.31283422e-10, 5.44213521e-06, -9.43210916e-06, + -8.77111287e-06, -1.48500849e-05, 1.18255407e-05, 1.10150883e-05, 5.26689474e-05, + -4.48744207e-05, -4.17990264e-05, -3.56000898e-06, 6.25249262e-06, 7.40210373e-06, + -3.28879213e-06, 7.23277523e-06, 5.14443264e-06, -2.64358635e-10, -1.45019594e-10, + -1.28402766e-10, 5.25867636e-06, -5.16714029e-06, -4.89473458e-06, 1.18257616e-05, + -2.67146255e-05, -1.78477563e-05, -4.48744478e-05, 9.76895055e-05, 6.77308879e-05, + 3.33303217e-06, -6.09507536e-06, -7.92679973e-06, -4.53919941e-06, 5.79080763e-06, + 6.70062733e-06, -2.08465667e-10, -4.68292440e-11, -7.70416595e-11, 4.56361255e-06, + -4.32853730e-06, -4.10260432e-06, 1.10152585e-05, -1.78476976e-05, -2.41785510e-05, + -4.17990626e-05, 6.77308743e-05, 8.80651865e-05, -4.80713670e-06, 7.44745256e-06, + 5.82898102e-06, 4.01844462e-06, -9.24002466e-06, -6.32793453e-06, -1.87316976e-10, + -7.40204179e-11, -2.56805532e-11, -6.27405522e-06, 9.09978770e-06, -5.87772875e-06, + -2.25429766e-05, 1.57256705e-05, -1.31766847e-05, -3.56000898e-06, 3.33303066e-06, + -4.80714275e-06, 8.18629477e-05, -5.96778607e-05, 5.00047078e-05, 5.78893749e-06, + -7.03943389e-06, 6.16572407e-06, -1.73721389e-10, -3.02124155e-11, -5.28717271e-11, + -6.83804246e-06, 5.88997989e-06, -5.82588727e-06, 1.57260893e-05, -2.40527171e-05, + 1.38238586e-05, 6.25249262e-06, -6.09507385e-06, 7.44744501e-06, -5.96778668e-05, + 8.75895237e-05, -5.24629108e-05, 5.97741764e-06, -4.35522241e-06, 3.12182623e-06, + 3.77655194e-11, 2.56805532e-11, 7.55310387e-12, -3.58411396e-06, 5.77740843e-06, + -3.44227573e-06, -1.31771490e-05, 1.38239702e-05, -1.91384229e-05, 7.40210675e-06, + -7.92680728e-06, 5.82897951e-06, 5.00046912e-05, -5.24628912e-05, 6.89408921e-05, + -8.33550120e-06, 6.89238705e-06, -5.26235321e-06, -9.06372465e-11, -1.96380701e-11, + -1.35955870e-11, -5.76549114e-06, -5.27608777e-06, 9.85516002e-06, -2.02684869e-05, + -1.11891329e-05, 1.61483335e-05, -3.28878608e-06, -4.53920696e-06, 4.01844613e-06, + 5.78894202e-06, 5.97741160e-06, -8.33549818e-06, 7.32316881e-05, 4.24624789e-05, + -6.12816113e-05, -1.72210768e-10, -5.74035894e-11, -2.56805532e-11, -4.02962623e-06, + -3.71500169e-06, 7.22315861e-06, -1.11895863e-05, -1.74020337e-05, 1.42109346e-05, + 7.23277825e-06, 5.79080159e-06, -9.24002164e-06, -7.03943540e-06, -4.35522241e-06, + 6.89238403e-06, 4.24624729e-05, 6.23507169e-05, -5.39312070e-05, -8.91266257e-11, + -1.51062077e-11, -1.35955870e-11, -5.77366058e-06, -4.94632077e-06, 5.65397409e-06, + 1.61487878e-05, 1.42107635e-05, -2.80634458e-05, 5.14442811e-06, 6.70062582e-06, + -6.32793604e-06, 6.16572256e-06, 3.12182321e-06, -5.26236076e-06, -6.12816445e-05, + -5.39312508e-05, 1.02810418e-04, 5.13611063e-11, 1.20849662e-11, 2.56805532e-11, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00 ] + + + + + + [ 3.08195430e+00, 2.57505417e+00, 2.17658652e+00, 1.59676375e+00, 1.49229969e+00, + 1.25102891e+00, 2.44371820e+00, 1.19985513e-01, -2.72464489e-02, 3.82756463e-01, + 2.76593540e+00, 1.83830665e-01, 4.78648724e-01, 5.08340100e-01, 2.67107115e+00, + 1.10153457e+01, 4.11835568e+00, 3.50096326e+00 ] + +

+ [ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, 0.00000000e+00, + 0.00000000e+00, 0.00000000e+00, 0.00000000e+00 ] +

+ + [ 1.83736223e+03, 2.18941669e+04, 1.83736223e+03, 1.83736223e+03, 1.83736223e+03, + 1.83736223e+03 ] + + + [ H, C, H, H, H, + H ] + +
+ + [ 2.00000000e+02, 1.22464680e-14, 1.22464680e-14, 0.00000000e+00, 2.00000000e+02, + 1.22464680e-14, 0.00000000e+00, 0.00000000e+00, 2.00000000e+02 ] + +
+
diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/files_to_check.txt b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/files_to_check.txt new file mode 100644 index 000000000..d84e4fc2f --- /dev/null +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/files_to_check.txt @@ -0,0 +1,8 @@ + filename format +---------------------------------------------------------- +ref_vib.xc.xyz xyz +ref_vib.out numpy +ref_vib.phonons.dynmat numpy all,1e-8,1e-8 +ref_vib.phonons.eigval numpy all,1e-8,1e-8 +ref_vib.phonons_full.hess numpy all,1e-8,1e-8 +ref_vib.phonons.hess numpy all,1e-8,1e-8 diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/init.xyz b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/init.xyz new file mode 100644 index 000000000..dbca316e8 --- /dev/null +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/init.xyz @@ -0,0 +1,8 @@ +6 +# CELL(abcABC): 130.18034 170.29206 240.21758 90.00000 90.00000 90.00000 cell{atomic_unit} Traj: x_centroid{angstrom} Step: 31 Bead: 0 + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/input.xml b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/input.xml new file mode 100644 index 000000000..7daf71557 --- /dev/null +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/input.xml @@ -0,0 +1,31 @@ + + + [ step, potential{electronvolt}] + x_centroid{angstrom} + + + 123456 + + 400 + +
localhost
+
+ + + init.xyz + [200.0, 200.0, 200.0 ] + + + + + + + 0.001 + phonons + none + + [5] + False + + +
diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.out b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.out new file mode 100644 index 000000000..4cfacf68d --- /dev/null +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.out @@ -0,0 +1,21 @@ +# column 1 --> step : The current simulation time step. +# column 2 --> potential{electronvolt} : The physical system potential energy. + 0.00000000e+00 1.95280225e-04 + 1.00000000e+00 1.95280225e-04 + 2.00000000e+00 1.95280225e-04 + 3.00000000e+00 1.95280225e-04 + 4.00000000e+00 1.95280225e-04 + 5.00000000e+00 1.95280225e-04 + 6.00000000e+00 1.95280225e-04 + 7.00000000e+00 1.95280225e-04 + 8.00000000e+00 1.95280225e-04 + 9.00000000e+00 1.95280225e-04 + 1.00000000e+01 1.95280225e-04 + 1.10000000e+01 1.95280225e-04 + 1.20000000e+01 1.95280225e-04 + 1.30000000e+01 1.95280225e-04 + 1.40000000e+01 1.95280225e-04 + 1.50000000e+01 1.95280225e-04 + 1.60000000e+01 1.95280225e-04 + 1.70000000e+01 1.95280225e-04 + 1.80000000e+01 1.95280225e-04 diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons.dynmat b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons.dynmat new file mode 100644 index 000000000..af973ddb1 --- /dev/null +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons.dynmat @@ -0,0 +1,16 @@ +# Dynamical matrix (atomic units) +0.0001101219975760934 6.207237290100471e-05 5.3060362091722285e-05 -2.9989198538358056e-05 -1.635668074439156e-05 -1.398207106391325e-05 5.44213521017396e-06 5.25867635962322e-06 4.563615571453957e-06 -6.274053708628827e-06 -6.838046995940226e-06 -3.5841169764577915e-06 -5.765488874076954e-06 -4.02962774458168e-06 -5.773659821844923e-06 +6.207237290100471e-05 7.023298349101703e-05 3.8684413356645466e-05 -1.6356854257314196e-05 -1.947904644361773e-05 -1.0193276800148814e-05 -9.432106893500162e-06 -5.167141049117342e-06 -4.328536543115602e-06 9.099786184681162e-06 5.889979132083694e-06 5.777413714468959e-06 -5.276090040598499e-06 -3.714997915650036e-06 -4.9463215255776125e-06 +5.3060362091722285e-05 3.8684413356645466e-05 5.804617124433905e-05 -1.3982208255089154e-05 -1.0193268704337794e-05 -1.626768590073058e-05 -8.771111359100843e-06 -4.894731560205483e-06 -4.102602812944615e-06 -5.8777317741563825e-06 -5.825886513873404e-06 -3.4422749729275175e-06 9.855156996641971e-06 7.2231608795780515e-06 5.653972582589943e-06 +-2.9989198538358056e-05 -1.6356854257314196e-05 -1.3982208255089154e-05 2.5392000229534728e-05 -1.4164185724508237e-09 -1.2272120281580773e-09 -1.4850087510863192e-05 1.1825756175314149e-05 1.1015254776700651e-05 -2.2542978548165433e-05 1.57260908035912e-05 -1.317714964834266e-05 -2.0268488449715702e-05 -1.1189587564305096e-05 1.6148783161916823e-05 +-1.635668074439156e-05 -1.947904644361773e-05 -1.0193268704337794e-05 -1.4164185724508237e-09 2.5390830128091632e-05 1.8426879226580996e-09 1.1825545465421972e-05 -2.6714627872291677e-05 -1.7847699606772132e-05 1.5725670915446764e-05 -2.405271864531717e-05 1.3823974753514476e-05 -1.1189133104859558e-05 -1.7402035712890755e-05 1.4210757376248656e-05 +-1.398207106391325e-05 -1.0193276800148814e-05 -1.626768590073058e-05 -1.2272120281580773e-09 1.8426879226580996e-09 2.5390726048645822e-05 1.1015091985257475e-05 -1.784775518342075e-05 -2.4178552930002482e-05 -1.3176683154583447e-05 1.3823853972766311e-05 -1.9138424384864035e-05 1.614833789231082e-05 1.421094182945645e-05 -2.8063446877416384e-05 +5.44213521017396e-06 -9.432106893500162e-06 -8.771111359100843e-06 -1.4850087510863192e-05 1.1825545465421972e-05 1.1015091985257475e-05 5.266894740883502e-05 -4.487443425284377e-05 -4.179904450267109e-05 -3.560008979521381e-06 6.2524926183178194e-06 7.402105239944917e-06 -3.2887891044692504e-06 7.232776736116601e-06 5.144430376397122e-06 +5.25867635962322e-06 -5.167141049117342e-06 -4.894731560205483e-06 1.1825756175314149e-05 -2.6714627872291677e-05 -1.784775518342075e-05 -4.487443425284377e-05 9.768950551979373e-05 6.773088112246937e-05 3.333031410395381e-06 -6.0950746039841555e-06 -7.926803504365884e-06 -4.539203184431533e-06 5.790804612322384e-06 6.700626579416211e-06 +4.563615571453957e-06 -4.328536543115602e-06 -4.102602812944615e-06 1.1015254776700651e-05 -1.7847699606772132e-05 -2.4178552930002482e-05 -4.179904450267109e-05 6.773088112246937e-05 8.806518648366636e-05 -4.80713972523081e-06 7.447448788415481e-06 5.828980265219088e-06 4.018445374300222e-06 -9.240023153638786e-06 -6.327935285715509e-06 +-6.274053708628827e-06 9.099786184681162e-06 -5.8777317741563825e-06 -2.2542978548165433e-05 1.5725670915446764e-05 -1.3176683154583447e-05 -3.560008979521381e-06 3.333031410395381e-06 -4.80713972523081e-06 8.186294768664584e-05 -5.967786374179331e-05 5.000469953824066e-05 5.788939750976561e-06 -7.039434649150267e-06 6.165723316354731e-06 +-6.838046995940226e-06 5.889979132083694e-06 -5.825886513873404e-06 1.57260908035912e-05 -2.405271864531717e-05 1.3823853972766311e-05 6.2524926183178194e-06 -6.0950746039841555e-06 7.447448788415481e-06 -5.967786374179331e-05 8.758952372488826e-05 -5.246290100115717e-05 5.977414617808231e-06 -4.3552216590928985e-06 3.1218247221526523e-06 +-3.5841169764577915e-06 5.777413714468959e-06 -3.4422749729275175e-06 -1.317714964834266e-05 1.3823974753514476e-05 -1.9138424384864035e-05 7.402105239944917e-06 -7.926803504365884e-06 5.828980265219088e-06 5.000469953824066e-05 -5.246290100115717e-05 6.89408921392033e-05 -8.335499688910675e-06 6.8923855358111205e-06 -5.262356987139703e-06 +-5.765488874076954e-06 -5.276090040598499e-06 9.855156996641971e-06 -2.0268488449715702e-05 -1.1189133104859558e-05 1.614833789231082e-05 -3.2887891044692504e-06 -4.539203184431533e-06 4.018445374300222e-06 5.788939750976561e-06 5.977414617808231e-06 -8.335499688910675e-06 7.323168808820519e-05 4.246247591306891e-05 -6.128162788237306e-05 +-4.02962774458168e-06 -3.714997915650036e-06 7.2231608795780515e-06 -1.1189587564305096e-05 -1.7402035712890755e-05 1.421094182945645e-05 7.232776736116601e-06 5.790804612322384e-06 -9.240023153638786e-06 -7.039434649150267e-06 -4.3552216590928985e-06 6.8923855358111205e-06 4.246247591306891e-05 6.235071686362824e-05 -5.393122892559988e-05 +-5.773659821844923e-06 -4.9463215255776125e-06 5.653972582589943e-06 1.6148783161916823e-05 1.4210757376248656e-05 -2.8063446877416384e-05 5.144430376397122e-06 6.700626579416211e-06 -6.327935285715509e-06 6.165723316354731e-06 3.1218247221526523e-06 -5.262356987139703e-06 -6.128162788237306e-05 -5.393122892559988e-05 0.00010281041779666677 diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons.eigval b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons.eigval new file mode 100644 index 000000000..819aaee93 --- /dev/null +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons.eigval @@ -0,0 +1,16 @@ +# Eigenvalues (atomic units) +-2.4763115873088654e-09 +-5.26448939308928e-10 +-7.76963935107596e-11 +-7.171694690119285e-11 +6.718850205792285e-10 +1.689876552396044e-09 +3.976568907066896e-05 +3.9771038868769635e-05 +3.9772351908703205e-05 +4.9955417931153435e-05 +4.996111516618837e-05 +0.00018609221525559008 +0.00020814086696308373 +0.0002081495150672616 +0.00020817711461012942 \ No newline at end of file diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons.hess b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons.hess new file mode 100644 index 000000000..75120ef4f --- /dev/null +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons.hess @@ -0,0 +1,16 @@ +# Hessian matrix (atomic units) +0.20233399955493778 0.11404943378590104 0.09749110546630745 -0.19020698627247867 -0.1037425173544548 -0.08868151629704002 0.009999173711250363 0.009662093347628797 0.008385014904632726 -0.011527709342651347 -0.01256396930937598 -0.006585321177254856 -0.010593291521754367 -0.007403885837753422 -0.010608304512604859 +0.11404943378590104 0.12904343149600098 0.07107728017263781 -0.10374361786302798 -0.12354617329179975 -0.06465102619923613 -0.017330196999676417 -0.009493909824964673 -0.007953089575796211 0.016719603479486974 0.010822025220402766 0.010615201773145344 -0.009694088587419714 -0.0068257968721674445 -0.009088184371730534 +0.09749110546630745 0.07107728017263781 0.10665184291269725 -0.08868238643433557 -0.06465097485142124 -0.10317806609094758 -0.016115708767472373 -0.008993394917666818 -0.0075379674724374 -0.010799522387472392 -0.010704263864180774 -0.006324706036675565 0.018107493282570886 0.013271563015226919 0.01038839569922345 +-0.19020698627247867 -0.10374361786302798 -0.08868238643433557 0.555936691126746 -3.1011304635342185e-05 -2.6868784974709566e-05 -0.09418692492602077 0.07500505355695351 0.0698644350705102 -0.14297921319128548 0.0997429902560576 -0.08357628894506419 -0.12855322223392918 -0.07097014365076147 0.10242392350923167 +-0.1037425173544548 -0.12354617329179975 -0.06465097485142124 -3.1011304635342185e-05 0.5559110727304528 4.034411693609741e-05 0.07500371712598763 -0.16943796782298293 -0.11319932907705164 0.09974032710857726 -0.15255476465414475 0.08767878784121662 -0.0709672612342338 -0.11037269848079845 0.09013196300422521 +-0.08868151629704002 -0.06465102619923613 -0.10317806609094758 -2.6868784974709566e-05 4.034411693609741e-05 0.5559087939976947 0.06986340256309731 -0.11319968157286199 -0.15335287067985703 -0.08357333020070357 0.08767802178732963 -0.12138577226705749 0.10242109937941278 0.0901331329017374 -0.17799287460595892 +0.009999173711250363 -0.017330196999676417 -0.016115708767472373 -0.09418692492602077 0.07500371712598763 0.06986340256309731 0.09677193490986723 -0.08245059079925454 -0.07679998581533454 -0.006541026054129873 0.011488093809575162 0.013600348625075755 -0.006042696898411747 0.013289230826885046 0.009452182092584136 +0.009662093347628797 -0.009493909824964673 -0.008993394917666818 0.07500505355695351 -0.16943796782298293 -0.11319968157286199 -0.08245059079925454 0.17949100816760935 0.12444616309670309 0.006123986040496021 -0.011198859894978598 -0.014564409400730227 -0.008340160506659087 0.010639805703149818 0.012311478225779384 +0.008385014904632726 -0.007953089575796211 -0.0075379674724374 0.0698644350705102 -0.11319932907705164 -0.15335287067985703 -0.07679998581533454 0.12444616309670309 0.16180764783602086 -0.008832456988017157 0.013683661148622406 0.010709948206066855 0.007383339772903952 -0.016977269590157107 -0.011626709317535955 +-0.011527709342651347 0.016719603479486974 -0.010799522387472392 -0.14297921319128548 0.09974032710857726 -0.08357333020070357 -0.006541026054129873 0.006123986040496021 -0.008832456988017157 0.1504118884998462 -0.1096498530861467 0.09187674648858389 0.01063637927734007 -0.012933991377916954 0.01132866717101777 +-0.01256396930937598 0.010822025220402766 -0.010704263864180774 0.0997429902560576 -0.15255476465414475 0.08767802178732963 0.011488093809575162 -0.011198859894978598 0.013683661148622406 -0.1096498530861467 0.16093368304659353 -0.09639335302180639 0.010982675879844807 -0.00800211980012122 0.005735922847804887 +-0.006585321177254856 0.010615201773145344 -0.006324706036675565 -0.08357628894506419 0.08767878784121662 -0.12138577226705749 0.013600348625075755 -0.014564409400730227 0.010709948206066855 0.09187674648858389 -0.09639335302180639 0.12666939164240887 -0.015315332335674723 0.012663808890422956 -0.009668855993627544 +-0.010593291521754367 -0.009694088587419714 0.018107493282570886 -0.12855322223392918 -0.0709672612342338 0.10242109937941278 -0.006042696898411747 -0.008340160506659087 0.007383339772903952 0.01063637927734007 0.010982675879844807 -0.015315332335674723 0.13455313807586577 0.07801894963410662 -0.112596548751398 +-0.007403885837753422 -0.0068257968721674445 0.013271563015226919 -0.07097014365076147 -0.11037269848079845 0.0901331329017374 0.013289230826885046 0.010639805703149818 -0.016977269590157107 -0.012933991377916954 -0.00800211980012122 0.012663808890422956 0.07801894963410662 0.11456085247107949 -0.09909120329831819 +-0.010608304512604859 -0.009088184371730534 0.01038839569922345 0.10242392350923167 0.09013196300422521 -0.17799287460595892 0.009452182092584136 0.012311478225779384 -0.011626709317535955 0.01132866717101777 0.005735922847804887 -0.009668855993627544 -0.112596548751398 -0.09909120329831819 0.18889997899229624 diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons_full.hess b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons_full.hess new file mode 100644 index 000000000..943e68151 --- /dev/null +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.phonons_full.hess @@ -0,0 +1,19 @@ +# Hessian matrix (atomic units) +0.20233399955493778 0.11404943378590104 0.09749110546630745 -0.19020698627247867 -0.1037425173544548 -0.08868151629704002 0.009999173711250363 0.009662093347628797 0.008385014904632726 -0.011527709342651347 -0.01256396930937598 -0.006585321177254856 -0.010593291521754367 -0.007403885837753422 -0.010608304512604859 -2.599309656403648e-06 -5.745404152435185e-07 -4.898859096158503e-07 +0.11404943378590104 0.12904343149600098 0.07107728017263781 -0.10374361786302798 -0.12354617329179975 -0.06465102619923613 -0.017330196999676417 -0.009493909824964673 -0.007953089575796211 0.016719603479486974 0.010822025220402766 0.010615201773145344 -0.009694088587419714 -0.0068257968721674445 -0.009088184371730534 -5.689893001203928e-07 2.123301534595612e-07 -9.575673587391975e-08 +0.09749110546630745 0.07107728017263781 0.10665184291269725 -0.08868238643433557 -0.06465097485142124 -0.10317806609094758 -0.016115708767472373 -0.008993394917666818 -0.0075379674724374 -0.010799522387472392 -0.010704263864180774 -0.006324706036675565 0.018107493282570886 0.013271563015226919 0.01038839569922345 -4.829470157119431e-07 -9.575673587391975e-08 2.400857290751901e-07 +-0.19020698627247867 -0.10374361786302798 -0.08868238643433557 0.555936691126746 -3.1011304635342185e-05 -2.6868784974709566e-05 -0.09418692492602077 0.07500505355695351 0.0698644350705102 -0.14297921319128548 0.0997429902560576 -0.08357628894506419 -0.12855322223392918 -0.07097014365076147 0.10242392350923167 -5.151434834260727e-06 -1.6459056340067946e-06 -1.4044321261508232e-06 +-0.1037425173544548 -0.12354617329179975 -0.06465097485142124 -3.1011304635342185e-05 0.5559110727304528 4.034411693609741e-05 0.07500371712598763 -0.16943796782298293 -0.11319932907705164 0.09974032710857726 -0.15255476465414475 0.08767878784121662 -0.0709672612342338 -0.11037269848079845 0.09013196300422521 -1.6264767310758545e-06 2.9282132274488504e-07 -3.885780586188048e-07 +-0.08868151629704002 -0.06465102619923613 -0.10317806609094758 -2.6868784974709566e-05 4.034411693609741e-05 0.5559087939976947 0.06986340256309731 -0.11319968157286199 -0.15335287067985703 -0.08357333020070357 0.08767802178732963 -0.12138577226705749 0.10242109937941278 0.0901331329017374 -0.17799287460595892 -1.3961054534661343e-06 -3.9135361618036773e-07 4.1633363423443365e-07 +0.009999173711250363 -0.017330196999676417 -0.016115708767472373 -0.09418692492602077 0.07500371712598763 0.06986340256309731 0.09677193490986723 -0.08245059079925454 -0.07679998581533454 -0.006541026054129873 0.011488093809575162 0.013600348625075755 -0.006042696898411747 0.013289230826885046 0.009452182092584136 -2.42861286636753e-07 -1.3322676295501878e-07 -1.179611963664229e-07 +0.009662093347628797 -0.009493909824964673 -0.008993394917666818 0.07500505355695351 -0.16943796782298293 -0.11319968157286199 -0.08245059079925454 0.17949100816760935 0.12444616309670309 0.006123986040496021 -0.011198859894978598 -0.014564409400730227 -0.008340160506659087 0.010639805703149818 0.012311478225779384 -1.915134717478395e-07 -4.3021142204224816e-08 -7.077671781985373e-08 +0.008385014904632726 -0.007953089575796211 -0.0075379674724374 0.0698644350705102 -0.11319932907705164 -0.15335287067985703 -0.07679998581533454 0.12444616309670309 0.16180764783602086 -0.008832456988017157 0.013683661148622406 0.010709948206066855 0.007383339772903952 -0.016977269590157107 -0.011626709317535955 -1.7208456881689926e-07 -6.800116025829084e-08 -2.359223927328458e-08 +-0.011527709342651347 0.016719603479486974 -0.010799522387472392 -0.14297921319128548 0.09974032710857726 -0.08357333020070357 -0.006541026054129873 0.006123986040496021 -0.008832456988017157 0.1504118884998462 -0.1096498530861467 0.09187674648858389 0.01063637927734007 -0.012933991377916954 0.01132866717101777 -1.5959455978986625e-07 -2.7755575615628917e-08 -4.85722573273506e-08 +-0.01256396930937598 0.010822025220402766 -0.010704263864180774 0.0997429902560576 -0.15255476465414475 0.08767802178732963 0.011488093809575162 -0.011198859894978598 0.013683661148622406 -0.1096498530861467 0.16093368304659353 -0.09639335302180639 0.010982675879844807 -0.00800211980012122 0.005735922847804887 3.469446951953615e-08 2.359223927328458e-08 6.938893903907229e-09 +-0.006585321177254856 0.010615201773145344 -0.006324706036675565 -0.08357628894506419 0.08767878784121662 -0.12138577226705749 0.013600348625075755 -0.014564409400730227 0.010709948206066855 0.09187674648858389 -0.09639335302180639 0.12666939164240887 -0.015315332335674723 0.012663808890422956 -0.009668855993627544 -8.326672684688674e-08 -1.8041124150158794e-08 -1.2490009027033011e-08 +-0.010593291521754367 -0.009694088587419714 0.018107493282570886 -0.12855322223392918 -0.0709672612342338 0.10242109937941278 -0.006042696898411747 -0.008340160506659087 0.007383339772903952 0.01063637927734007 0.010982675879844807 -0.015315332335674723 0.13455313807586577 0.07801894963410662 -0.112596548751398 -1.582067810090848e-07 -5.273559366969494e-08 -2.359223927328458e-08 +-0.007403885837753422 -0.0068257968721674445 0.013271563015226919 -0.07097014365076147 -0.11037269848079845 0.0901331329017374 0.013289230826885046 0.010639805703149818 -0.016977269590157107 -0.012933991377916954 -0.00800211980012122 0.012663808890422956 0.07801894963410662 0.11456085247107949 -0.09909120329831819 -8.049116928532385e-08 -1.3877787807814458e-08 -1.2490009027033011e-08 +-0.010608304512604859 -0.009088184371730534 0.01038839569922345 0.10242392350923167 0.09013196300422521 -0.17799287460595892 0.009452182092584136 0.012311478225779384 -0.011626709317535955 0.01132866717101777 0.005735922847804887 -0.009668855993627544 -0.112596548751398 -0.09909120329831819 0.18889997899229624 4.718447854656916e-08 1.1102230246251565e-08 2.359223927328458e-08 +-2.599309656403648e-06 -5.689893001203928e-07 -4.829470157119431e-07 -5.151434834260727e-06 -1.6264767310758545e-06 -1.3961054534661343e-06 -2.42861286636753e-07 -1.915134717478395e-07 -1.7208456881689926e-07 -1.5959455978986625e-07 3.469446951953615e-08 -8.326672684688674e-08 -1.582067810090848e-07 -8.049116928532385e-08 4.718447854656916e-08 0.0 0.0 0.0 +-5.745404152435185e-07 2.123301534595612e-07 -9.575673587391975e-08 -1.6459056340067946e-06 2.9282132274488504e-07 -3.9135361618036773e-07 -1.3322676295501878e-07 -4.3021142204224816e-08 -6.800116025829084e-08 -2.7755575615628917e-08 2.359223927328458e-08 -1.8041124150158794e-08 -5.273559366969494e-08 -1.3877787807814458e-08 1.1102230246251565e-08 0.0 0.0 0.0 +-4.898859096158503e-07 -9.575673587391975e-08 2.400857290751901e-07 -1.4044321261508232e-06 -3.885780586188048e-07 4.1633363423443365e-07 -1.179611963664229e-07 -7.077671781985373e-08 -2.359223927328458e-08 -4.85722573273506e-08 6.938893903907229e-09 -1.2490009027033011e-08 -2.359223927328458e-08 -1.2490009027033011e-08 2.359223927328458e-08 0.0 0.0 0.0 diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.xc.xyz b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.xc.xyz new file mode 100644 index 000000000..ee3b02967 --- /dev/null +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/ref_vib.xc.xyz @@ -0,0 +1,152 @@ +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 0 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 1 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 2 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 3 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 4 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 5 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 6 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 7 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 8 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 9 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 10 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 11 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 12 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 13 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 14 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 15 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 16 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 17 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 +6 +# CELL(abcABC): 200.00000 200.00000 200.00000 90.00000 90.00000 90.00000 Step: 18 Bead: 0 x_centroid{angstrom} cell{atomic_unit} + H 1.63090e+00 1.36266e+00 1.15180e+00 + C 8.44971e-01 7.89691e-01 6.62016e-01 + H 1.29316e+00 6.34936e-02 -1.44182e-02 + H 2.02546e-01 1.46367e+00 9.72790e-02 + H 2.53290e-01 2.69002e-01 1.41347e+00 + H 5.82907e+00 2.17934e+00 1.85263e+00 diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/test_settings.dat b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/test_settings.dat new file mode 100644 index 000000000..b2a2c6afc --- /dev/null +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixatoms/test_settings.dat @@ -0,0 +1,4 @@ +driver_model ch4hcbe +address localhost +port 32343 +socket_mode unix diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixdofs/input.xml b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixdofs/input.xml index aeb38b9e4..29206ac00 100644 --- a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixdofs/input.xml +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe-with_fixdofs/input.xml @@ -3,6 +3,9 @@ [ step, potential{electronvolt}] x_centroid{angstrom}
+ + 123456 + 400
localhost
@@ -21,7 +24,7 @@ phonons none - [5] + [15,16,17] False
diff --git a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe/input.xml b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe/input.xml index c88f42945..b3862e598 100644 --- a/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe/input.xml +++ b/ipi_tests/regression_tests/tests/PHONONS/fd_phonons/ch4hcbe/input.xml @@ -3,6 +3,9 @@ [ step, potential{electronvolt}] x_centroid{angstrom} + + 123456 + 400
localhost
diff --git a/ipi_tests/regression_tests/tests/PLUMED/BIAS.NOAUTO/input.xml b/ipi_tests/regression_tests/tests/PLUMED/BIAS.NOAUTO/input.xml index 37d944682..bdf83bea6 100644 --- a/ipi_tests/regression_tests/tests/PLUMED/BIAS.NOAUTO/input.xml +++ b/ipi_tests/regression_tests/tests/PLUMED/BIAS.NOAUTO/input.xml @@ -6,6 +6,9 @@ extras_bias extras_bias + + 123456 + 100
localhost
diff --git a/ipi_tests/regression_tests/tests/PLUMED/METAD.NOAUTO/input.xml b/ipi_tests/regression_tests/tests/PLUMED/METAD.NOAUTO/input.xml index 1f2237eda..567960428 100644 --- a/ipi_tests/regression_tests/tests/PLUMED/METAD.NOAUTO/input.xml +++ b/ipi_tests/regression_tests/tests/PLUMED/METAD.NOAUTO/input.xml @@ -5,6 +5,9 @@ f_centroid extras_bias + + 123456 + 100
localhost
diff --git a/setup.py b/setup.py index bf8364962..e865e9c79 100644 --- a/setup.py +++ b/setup.py @@ -6,13 +6,6 @@ scripts = [str(p) for p in Path("bin").iterdir() if p.name != "i-pi-driver"] setup( - packages=[ - *find_packages(exclude=["ipi_tests*"]), - "ipi._driver", - "ipi._driver.pes", - ], - package_dir={ - "ipi._driver": "drivers/py", - }, + packages=[*find_packages(exclude=["ipi_tests*"])], scripts=scripts, ) diff --git a/tools/py/Instanton_interpolation.py b/tools/py/Instanton_interpolation.py index befe7fd25..0b5ac63fd 100755 --- a/tools/py/Instanton_interpolation.py +++ b/tools/py/Instanton_interpolation.py @@ -122,7 +122,7 @@ if os.path.exists(chk): simulation = Simulation.load_from_xml( - chk, custom_verbosity="low", request_banner=False, read_only=True + open(chk), custom_verbosity="low", request_banner=False, read_only=True ) else: print("We can't find {}".format(chk)) diff --git a/tools/py/Instanton_postproc.py b/tools/py/Instanton_postproc.py index 5dd91b384..2737e0741 100755 --- a/tools/py/Instanton_postproc.py +++ b/tools/py/Instanton_postproc.py @@ -204,7 +204,6 @@ def get_rp_freq(w0, nbeads, temp, mode="rate"): sys.exit() if mode == "rate": - for n in range(w0.size): for k in range(nbeads): if w0[n] == 0 and k == 0: @@ -259,7 +258,7 @@ def save_frequencies(d, nzeros, filename="freq.dat"): print("\nWe are ready to start. Reading {} ... (This can take a while)".format(inputt)) simulation = Simulation.load_from_xml( - inputt, custom_verbosity="quiet", request_banner=False, read_only=True + open(inputt), custom_verbosity="quiet", request_banner=False, read_only=True ) diff --git a/tools/py/committee-reweight.py b/tools/py/committee-reweight.py index 724b52474..fc3cfffa7 100755 --- a/tools/py/committee-reweight.py +++ b/tools/py/committee-reweight.py @@ -262,7 +262,7 @@ def commitee_reweight( # Load kbT from i-PI, we could make it into a small function if args.input != "": simul = Simulation.load_from_xml( - args.input, custom_verbosity="quiet", read_only=True + open(args.input), custom_verbosity="quiet", read_only=True ) kt = float(simul.syslist[0].ensemble.temp) else: diff --git a/tools/py/neb_interpolate.py b/tools/py/neb_interpolate.py index aaaa9a45b..d524affe9 100755 --- a/tools/py/neb_interpolate.py +++ b/tools/py/neb_interpolate.py @@ -352,7 +352,10 @@ def spline_resample(q, nbeads_old, nbeads_new, k=3): input_chk = args.chk if os.path.exists(input_chk): simulation = Simulation.load_from_xml( - input_chk, custom_verbosity="low", request_banner=False, read_only=True + open(input_chk), + custom_verbosity="low", + request_banner=False, + read_only=True, ) else: print("Error: cannot find {}.".format(input_chk))