Git Product home page Git Product logo

pyiron / pyiron Goto Github PK

View Code? Open in Web Editor NEW
326.0 16.0 45.0 46.04 MB

pyiron - an integrated development environment (IDE) for computational materials science.

Home Page: http://pyiron.org

License: BSD 3-Clause "New" or "Revised" License

Python 8.68% Shell 0.07% Dockerfile 0.06% Jupyter Notebook 91.20%
pyiron python molecular-dynamics ab-initio development-environment simulation ide ase hdf5 vasp

pyiron's Introduction

pyiron

Coverage Status

Codacy Badge

Release_Date

Build Status

Downloads

Documentation Status

Screenshot of pyiron running inside jupyterlab.

pyiron - an integrated development environment (IDE) for computational materials science. It combines several tools in a common platform:

  • Atomic structure objects – compatible to the Atomic Simulation Environment (ASE).
  • Atomistic simulation codes – like LAMMPS and VASP.
  • Feedback Loops – to construct dynamic simulation life cycles.
  • Hierarchical data management – interfacing with storage resources like SQL and HDF5.
  • Integrated visualization – based on NGLview.
  • Interactive simulation protocols - based on Jupyter notebooks.
  • Object oriented job management – for scaling complex simulation protocols from single jobs to high-throughput simulations.

pyiron (called pyron) is developed in the Computational Materials Design department of Joerg Neugebauer at the Max Planck Institut für Eisenforschung (Max Planck Institute for iron research). While its original focus was to provide a framework to develop and run complex simulation protocols as needed for ab initio thermodynamics it quickly evolved into a versatile tool to manage a wide variety of simulation tasks. In 2016 the Interdisciplinary Centre for Advanced Materials Simulation (ICAMS) joined the development of the framework with a specific focus on high throughput applications. In 2018 pyiron was released as open-source project. See the Documentation page for more details.

Note

pyiron: This is the documentation page for the pyiron meta package, that combines the other packages in a common interface. The API documentation for pyiron_base and pyiron_atomistics are available as separate pages.

Installation

You can test pyiron on Mybinder.org (beta). For a local installation we recommend to install pyiron inside an anaconda environment:

conda install -c conda-forge pyiron

After the installation of pyiron you need to configure pyiron. The default configuration can be generated automatically. Start a new Python session and import pyiron:

> import pyiron
> pyiron.install()
>>> It appears that pyiron is not yet configured, do you want to create a default start configuration (recommended: yes). [yes/no]:
> yes
> exit()

See the Documentation-Installation page for more details.

Example

After the successful configuration you can start your first pyiron calculation. Navigate to the the projects directory and start a jupyter notebook or jupyter lab session correspondingly:

cd ~/pyiron/projects
jupyter notebook

Open a new jupyter notebook and inside the notebook you can now validate your pyiron calculation by creating a test project, setting up an initial structure of bcc Fe and visualize it using NGLview:

from pyiron import Project
pr = Project('test')
structure = pr.create_structure('Fe', 'bcc', 2.78)
structure.plot3d()

Finally a first lammps calculation can be executed by:

job = pr.create_job(job_type=pr.job_type.Lammps, job_name='lammpstestjob')
job.structure = structure
job.potential = job.list_potentials()[0]
job.run()

Getting started:

Test pyiron with mybinder:

mybinder

License and Acknowledgments

pyiron is licensed under the BSD license.

If you use pyiron in your scientific work, please consider citing :

@article{pyiron-paper,
  title = {pyiron: An integrated development environment for computational materials science},
  journal = {Computational Materials Science},
  volume = {163},
  pages = {24 - 36},
  year = {2019},
  issn = {0927-0256},
  doi = {https://doi.org/10.1016/j.commatsci.2018.07.043},
  url = {http://www.sciencedirect.com/science/article/pii/S0927025618304786},
  author = {Jan Janssen and Sudarsan Surendralal and Yury Lysogorskiy and Mira Todorova and Tilmann Hickel and Ralf Drautz and Jörg Neugebauer},
  keywords = {Modelling workflow, Integrated development environment, Complex simulation protocols},
}

pyiron's People

Contributors

ahmed-aslam avatar alaukiksaxena avatar ashtonmv avatar caglayanoaras avatar codacy-badger avatar dependabot-preview[bot] avatar dependabot[bot] avatar feloch avatar ibrsam avatar jan-janssen avatar jkitchin avatar jnmpi avatar leimeroth avatar liamhuber avatar ligerzero-ai avatar max-hassani avatar niklassiemer avatar pmrv avatar prince-mathews avatar pyiron-runner avatar pyironlandingpage avatar raynol-dsouza avatar samwaseda avatar sanderborgmans avatar srmnitc avatar sudarsan-surendralal avatar t-brink avatar tnecnivkcots avatar uday-gajera avatar zendegani avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

pyiron's Issues

calc_md() in Vasp

I see that the parameter dt is now replaced by time_step in calc_md(). Also parameters like retain_charge_density which were unique to Vasp are now gone. Should I restore this?

Another thing is the stream of warning messages everytime I call calc_md()

job = pr.create_job("Vasp", "test")
job.calc_md()

2019-01-16 09:50:35,690 - pyiron_log - WARNING - rescale_velocitytag not relevant for vasp
2019-01-16 09:50:35,691 - pyiron_log - WARNING - langevintag not relevant for vasp
2019-01-16 09:50:35,692 - pyiron_log - WARNING - seedtag not relevant for vasp
2019-01-16 09:50:35,693 - pyiron_log - WARNING - time_steptag not relevant for vasp
2019-01-16 09:50:35,693 - pyiron_log - WARNING - delta_presstag not relevant for vasp
2019-01-16 09:50:35,694 - pyiron_log - WARNING - delta_temptag not relevant for vasp
2019-01-16 09:50:35,695 - pyiron_log - WARNING - pressuretag not relevant for vasp
2019-01-16 09:50:35,695 - pyiron_log - WARNING - tlooptag not relevant for vasp

Water example not working

https://travis-ci.org/jan-janssen/release-testing/builds/580849202

------------------
1042plt.plot(ham_eq["output/generic/temperatures"])
1043plt.xlabel("Steps")
1044plt.ylabel("Temperature [K]");
1045------------------
1046
1047---------------------------------------------------------------------------
1048ValueError                                Traceback (most recent call last)
1049<ipython-input-11-134c7249d655> in <module>
1050----> 1 plt.plot(ham_eq["output/generic/temperatures"])
1051      2 plt.xlabel("Steps")
1052      3 plt.ylabel("Temperature [K]");
1053
1054~/miniconda/lib/python3.7/site-packages/matplotlib/pyplot.py in plot(scalex, scaley, data, *args, **kwargs)
1055   2793     return gca().plot(
1056   2794         *args, scalex=scalex, scaley=scaley, **({"data": data} if data
1057-> 2795         is not None else {}), **kwargs)
1058   2796 
1059   2797 
1060
1061~/miniconda/lib/python3.7/site-packages/matplotlib/axes/_axes.py in plot(self, scalex, scaley, data, *args, **kwargs)
1062   1664         """
1063   1665         kwargs = cbook.normalize_kwargs(kwargs, mlines.Line2D._alias_map)
1064-> 1666         lines = [*self._get_lines(*args, data=data, **kwargs)]
1065   1667         for line in lines:
1066   1668             self.add_line(line)
1067
1068~/miniconda/lib/python3.7/site-packages/matplotlib/axes/_base.py in __call__(self, *args, **kwargs)
1069    223                 this += args[0],
1070    224                 args = args[1:]
1071--> 225             yield from self._plot_args(this, kwargs)
1072    226 
1073    227     def get_next_color(self):
1074
1075~/miniconda/lib/python3.7/site-packages/matplotlib/axes/_base.py in _plot_args(self, tup, kwargs)
1076    375         # downstream.
1077    376         if any(v is None for v in tup):
1078--> 377             raise ValueError("x, y, and format string must not be None")
1079    378 
1080    379         kw = {}
1081
1082ValueError: x, y, and format string must not be None
1083ValueError: x, y, and format string must not be None
1084
1085The command "./build.sh" exited with 1.

interactive VASP gives an error

Following code gives an index error with interactive_energy_pot_getter

vasp = pr.create_job('Vasp', 'vasp')
vasp.structure = pr.create_structure('Fe', 'bcc', 2.83)
vasp.interactive_open()
vasp.run()
vasp.interactive_close()

git ImportError

I just merged my branch with the master branch and I now can't run pyiron because I get the following error

from pyiron import Project

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
/u/system/SLES12/soft/pyiron/dev/anaconda3/lib/python3.7/site-packages/git/__init__.py in <module>
     82 try:
---> 83     refresh()
     84 except Exception as exc:

/u/system/SLES12/soft/pyiron/dev/anaconda3/lib/python3.7/site-packages/git/__init__.py in refresh(path)
     72 
---> 73     if not Git.refresh(path=path):
     74         return

/u/system/SLES12/soft/pyiron/dev/anaconda3/lib/python3.7/site-packages/git/cmd.py in refresh(cls, path)
    286                     else:
--> 287                         raise ImportError(err)
    288                 else:

ImportError: Bad git executable.
The git executable must be specified in one of the following ways:
    - be included in your $PATH
    - be set via $GIT_PYTHON_GIT_EXECUTABLE
    - explicitly set via git.refresh()

All git commands will error until this is rectified.

This initial warning can be silenced or aggravated in the future by setting the
$GIT_PYTHON_REFRESH environment variable. Use one of the following values:
    - quiet|q|silence|s|none|n|0: for no warning or exception
    - warn|w|warning|1: for a printed warning
    - error|e|raise|r|2: for a raised exception

Example:
    export GIT_PYTHON_REFRESH=quiet


During handling of the above exception, another exception occurred:

ImportError                               Traceback (most recent call last)
<ipython-input-1-3048f6d97ed8> in <module>
----> 1 from pyiron import Project
      2 pr = Project("debug_restart")
      3 pr.remove_jobs()
      4 basis = pr.create_ase_bulk("Al")
      5 ham = pr.create_job(pr.job_type.Vasp, "test")

/cmmc/u/chandu/programs/pyiron_mpie/pyiron/pyiron/__init__.py in <module>
      2 __all__ = []
      3 
----> 4 from pyiron.project import Project
      5 from pyiron.atomistics.structure.atoms import ase_to_pyiron, pyiron_to_ase, Atoms
      6 from pyiron.base.job.script import Notebook

/cmmc/u/chandu/programs/pyiron_mpie/pyiron/pyiron/project.py in <module>
      9 import types
     10 from string import punctuation
---> 11 from pyiron.base.project.generic import Project as ProjectCore
     12 
     13 try:

/cmmc/u/chandu/programs/pyiron_mpie/pyiron/pyiron/base/project/generic.py in <module>
     11 import numpy as np
     12 import pkgutil
---> 13 from git import Repo, InvalidGitRepositoryError
     14 from pyiron.base.project.path import ProjectPath
     15 from pyiron.base.database.filetable import FileTable

/u/system/SLES12/soft/pyiron/dev/anaconda3/lib/python3.7/site-packages/git/__init__.py in <module>
     83     refresh()
     84 except Exception as exc:
---> 85     raise ImportError('Failed to initialize: {0}'.format(exc))
     86 #################

ImportError: Failed to initialize: Bad git executable.
The git executable must be specified in one of the following ways:
    - be included in your $PATH
    - be set via $GIT_PYTHON_GIT_EXECUTABLE
    - explicitly set via git.refresh()

All git commands will error until this is rectified.

This initial warning can be silenced or aggravated in the future by setting the
$GIT_PYTHON_REFRESH environment variable. Use one of the following values:
    - quiet|q|silence|s|none|n|0: for no warning or exception
    - warn|w|warning|1: for a printed warning
    - error|e|raise|r|2: for a raised exception

Example:
    export GIT_PYTHON_REFRESH=quiet


from pyiron import Project

executed in 36ms, finished 13:57:06 2019-11-24

---------------------------------------------------------------------------
ImportError                               Traceback (most recent call last)
/u/system/SLES12/soft/pyiron/dev/anaconda3/lib/python3.7/site-packages/git/__init__.py in <module>
     82 try:
---> 83     refresh()
     84 except Exception as exc:

/u/system/SLES12/soft/pyiron/dev/anaconda3/lib/python3.7/site-packages/git/__init__.py in refresh(path)
     72 
---> 73     if not Git.refresh(path=path):
     74         return

/u/system/SLES12/soft/pyiron/dev/anaconda3/lib/python3.7/site-packages/git/cmd.py in refresh(cls, path)
    286                     else:
--> 287                         raise ImportError(err)
    288                 else:

ImportError: Bad git executable.
The git executable must be specified in one of the following ways:
    - be included in your $PATH
    - be set via $GIT_PYTHON_GIT_EXECUTABLE
    - explicitly set via git.refresh()

All git commands will error until this is rectified.

This initial warning can be silenced or aggravated in the future by setting the
$GIT_PYTHON_REFRESH environment variable. Use one of the following values:
    - quiet|q|silence|s|none|n|0: for no warning or exception
    - warn|w|warning|1: for a printed warning
    - error|e|raise|r|2: for a raised exception

Example:
    export GIT_PYTHON_REFRESH=quiet


During handling of the above exception, another exception occurred:

ImportError                               Traceback (most recent call last)
<ipython-input-2-4b4fd9c5b3c4> in <module>
----> 1 from pyiron import Project

/cmmc/u/chandu/programs/pyiron_mpie/pyiron/pyiron/__init__.py in <module>
      2 __all__ = []
      3 
----> 4 from pyiron.project import Project
      5 from pyiron.atomistics.structure.atoms import ase_to_pyiron, pyiron_to_ase, Atoms
      6 from pyiron.base.job.script import Notebook

/cmmc/u/chandu/programs/pyiron_mpie/pyiron/pyiron/project.py in <module>
      9 import types
     10 from string import punctuation
---> 11 from pyiron.base.project.generic import Project as ProjectCore
     12 
     13 try:

/cmmc/u/chandu/programs/pyiron_mpie/pyiron/pyiron/base/project/generic.py in <module>
     11 import numpy as np
     12 import pkgutil
---> 13 from git import Repo, InvalidGitRepositoryError
     14 from pyiron.base.project.path import ProjectPath
     15 from pyiron.base.database.filetable import FileTable

/u/system/SLES12/soft/pyiron/dev/anaconda3/lib/python3.7/site-packages/git/__init__.py in <module>
     83     refresh()
     84 except Exception as exc:
---> 85     raise ImportError('Failed to initialize: {0}'.format(exc))
     86 #################

ImportError: Failed to initialize: Bad git executable.
The git executable must be specified in one of the following ways:
    - be included in your $PATH
    - be set via $GIT_PYTHON_GIT_EXECUTABLE
    - explicitly set via git.refresh()

All git commands will error until this is rectified.

This initial warning can be silenced or aggravated in the future by setting the
$GIT_PYTHON_REFRESH environment variable. Use one of the following values:
    - quiet|q|silence|s|none|n|0: for no warning or exception
    - warn|w|warning|1: for a printed warning
    - error|e|raise|r|2: for a raised exception

Example:
    export GIT_PYTHON_REFRESH=quiet

I understand that this is due to the recent changes #451 and can be solved if I simply add the git executable path to my .bashrc file. However, isn't this a bit dangerous? We are forcing git installation for all users even if they are not developers.

snapshot defined but not used

I see the option snapshot in def restart but I don't see it inside the function. It's probably not used, is it? I guess it's better to say in the Doc string that it won't be reflected or simply remove it altogether.

def restart(self, snapshot=-1, job_name=None, job_type=None):

ase update: Can't import `Prism`

It looks like the tests fail due to the absence of certain functions in the latest ase versions

Traceback (most recent call last):
  File "/Users/travis/build/pyiron/pyiron/tests/lammps/test_lammps.py", line 125, in test_lammps_water
    self.job_water.run(run_mode="manual")
  File "/Users/travis/build/pyiron/pyiron/pyiron/base/job/generic.py", line 580, in run
    self._run_if_new(debug=debug)
  File "/Users/travis/build/pyiron/pyiron/pyiron/base/job/generic.py", line 1054, in _run_if_new
    self._create_job_structure(debug=debug)
  File "/Users/travis/build/pyiron/pyiron/pyiron/base/job/generic.py", line 1281, in _create_job_structure
    self.write_input()
  File "/Users/travis/build/pyiron/pyiron/pyiron/lammps/base.py", line 232, in write_input
    lmp_structure = self._get_lammps_structure(structure=self.structure, cutoff_radius=self.cutoff_radius)
  File "/Users/travis/build/pyiron/pyiron/pyiron/lammps/base.py", line 738, in _get_lammps_structure
    lmp_structure.structure = structure
  File "/Users/travis/build/pyiron/pyiron/pyiron/lammps/structure.py", line 189, in structure
    input_str = self.structure_full()
  File "/Users/travis/build/pyiron/pyiron/pyiron/lammps/structure.py", line 345, in structure_full
    coords = self.rotate_positions(self._structure)
  File "/Users/travis/build/pyiron/pyiron/pyiron/lammps/structure.py", line 536, in rotate_positions
    prism = UnfoldingPrism(self._structure.cell)
  File "/Users/travis/build/pyiron/pyiron/pyiron/lammps/structure.py", line 81, in __init__
    apre[1, :], n1 = fold(apre[1, :], apre[0, :], 0)
  File "/Users/travis/build/pyiron/pyiron/pyiron/lammps/structure.py", line 79, in fold
    return [float(self.f2qdec(vec_a)) for vec_a in (vec + n * pvec)], n
  File "/Users/travis/build/pyiron/pyiron/pyiron/lammps/structure.py", line 79, in <listcomp>
    return [float(self.f2qdec(vec_a)) for vec_a in (vec + n * pvec)], n
AttributeError: 'UnfoldingPrism' object has no attribute 'f2qdec'

LAMMPS: temperature vs temperatures

I noticed the in LAMMPS output, the temperatures are stored as "temperatures" but according to what we decided here it should be "temperature". This is how it is in VASP. Shall I correct this? Otherwise job.output.temperature won't work.

Lammps non-metallic units not safe

Our current implementation of Lammps handles non-metallic units in some ways precariously, in others simply wrongly.

The precariousness comes from the fact that the 'units' attribute of the input.control object of a Lammps job is updated only when the potential is assigned to the job (automatically based on some units property of the potential object). Currently, other aspects of the input, such as those written by calc_md and calc_minimize, rely on this units attribute to properly convert from pyiron units to Lammps units. Thus, if these are called in an a-typical order (i.e. calc before setting the potential), errors follow. It is certainly canonical to set the potential first, but there are no rules and certainly no safety checks making sure it has been done this way.

The wrongness comes from the fact that, while carefully accounted for in most (now all?) of the calc methods, units are either ignored or hard-coded into the output interpretation. Thus, while the input is in pyiron units, and the output at the moment is ok for "metal" units, all other outputs have at least some non-pyiron units.

The attached notebook demonstrates these claims. [Ok, actually Github won't let me upload a notebook, so I just PDF'd it, but I'd be happy to e-mail over the raw NB if anyone's keen.]

There, I use water and "real" units as an example, because there we have a public example notebook from which I'll draw heavily, e.g. to set up a cell of water. (I also found that one of the statements in this notebook doesn't hold, although it's a fairly low-priority statement.)

lammps_units_problems.pdf

restart in vasp

There's this line super(Vasp, self).restart(snapshot=snapshot, job_name=job_name, job_type=job_type) in vasp.py but I don't see restart in GeneridDFTJob (which vasp is derived from). What does this super.restart refer to?

ValueError: Was not able to locate a periodic table.

Hi all,

I have used Pyiron as a first try after successfully installation and configuration,

from pyiron import Project
pr = Project('test')
basis = pr.create_structure(element='Fe', bravais_basis='bcc', lattice_constant=2.75)

But got below issue:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-13-8f2356a42527> in <module>
      1 from pyiron import Project
      2 pr = Project('test')
----> 3 basis = pr.create_structure(element='Fe', bravais_basis='bcc', lattice_constant=2.75)

~/miniconda3/envs/psi4/lib/python3.7/site-packages/pyiron/project.py in create_structure(element, bravais_basis, lattice_constant)
    473             element=element,
    474             bravais_basis=bravais_basis,
--> 475             lattice_constants=[lattice_constant],
    476         )
    477 

~/miniconda3/envs/psi4/lib/python3.7/site-packages/pyiron/atomistics/structure/atoms.py in __new__(cls, *args, **kwargs)
   4021 class CrystalStructure(object):
   4022     def __new__(cls, *args, **kwargs):
-> 4023         basis = _CrystalStructure(*args, **kwargs).atoms()
   4024         return basis
   4025 

~/miniconda3/envs/psi4/lib/python3.7/site-packages/pyiron/atomistics/structure/atoms.py in __init__(self, element, bravais_lattice, bravais_basis, lattice_constants, dimension, rel_coords, pse, **kwargs)
   3591             scaled_positions=self.coordinates,
   3592             cell=self.amat,  # tag = "Crystal",
-> 3593             pbc=[True, True, True][0 : self.dimension],
   3594         )
   3595 

~/miniconda3/envs/psi4/lib/python3.7/site-packages/pyiron/atomistics/structure/atoms.py in __init__(self, symbols, positions, numbers, tags, momenta, masses, magmoms, charges, scaled_positions, cell, pbc, celldisp, constraint, calculator, info, indices, elements, dimension, species, high_symmetry_points, **qwargs)
    127         self._species = list()
    128         self.positions = None
--> 129         self._pse = PeriodicTable()
    130         self._tag_list = SparseArray()
    131         self.indices = np.array([])

~/miniconda3/envs/psi4/lib/python3.7/site-packages/pyiron/atomistics/structure/periodic_table.py in __init__(self, file_name)
    193             file_name (str): Possibility to choose an source hdf5 file
    194         """
--> 195         self.dataframe = self._get_periodic_table_df(file_name)
    196         if "Abbreviation" not in self.dataframe.columns.values:
    197             self.dataframe["Abbreviation"] = None

~/miniconda3/envs/psi4/lib/python3.7/site-packages/pyiron/atomistics/structure/periodic_table.py in _get_periodic_table_df(file_name)
    388                                 os.path.join(path, periodic_table_file_name), mode="r"
    389                             )
--> 390             raise ValueError("Was not able to locate a periodic table. ")
    391         else:
    392             if file_name.endswith(".h5"):

ValueError: Was not able to locate a periodic table. 

Any suggestion?

Python 2.7 compatibility

I just realised that setuptools was updated on pip which is the reason why our Azure tests fail since #494 . As there is no more official Python 2.7 support I guess we can remove Python 2.7 after all and release a new pyiron 0.3 version only supporting python 3.X . @sudarsan-surendralal Can you take a look at this and start removing all the Python 2.7 vs. 3. version splits?

Tests failing

On travis the Python 2.7 tests fail for mac os x and linux, even though they work on azure.

======================================================================
2161ERROR: test_install (base.settings.test_install.TestInstall)
2162----------------------------------------------------------------------
2163Traceback (most recent call last):
2164  File "/home/travis/build/pyiron/pyiron/tests/base/settings/test_install.py", line 24, in test_install
2165    '-p', os.path.join(self.execution_path, 'project')])
2166  File "pyiron/base/settings/install.py", line 143, in command_line
2167    git_folder_name=git_folder_name)
2168  File "pyiron/base/settings/install.py", line 103, in install_pyiron
2169    git_folder_name=git_folder_name)
2170  File "pyiron/base/settings/install.py", line 46, in _download_resources
2171    urllib2.urlretrieve(giturl_for_zip_file, temp_zip_file)
2172  File "/home/travis/miniconda/lib/python2.7/urllib.py", line 98, in urlretrieve
2173    return opener.retrieve(url, filename, reporthook, data)
2174  File "/home/travis/miniconda/lib/python2.7/urllib.py", line 245, in retrieve
2175    fp = self.open(url, data)
2176  File "/home/travis/miniconda/lib/python2.7/urllib.py", line 213, in open
2177    return getattr(self, name)(url)
2178  File "/home/travis/miniconda/lib/python2.7/urllib.py", line 443, in open_https
2179    h.endheaders(data)
2180  File "/home/travis/miniconda/lib/python2.7/httplib.py", line 1055, in endheaders
2181    self._send_output(message_body)
2182  File "/home/travis/miniconda/lib/python2.7/httplib.py", line 893, in _send_output
2183    self.send(msg)
2184  File "/home/travis/miniconda/lib/python2.7/httplib.py", line 855, in send
2185    self.connect()
2186  File "/home/travis/miniconda/lib/python2.7/httplib.py", line 1280, in connect
2187    server_hostname=server_hostname)
2188  File "/home/travis/miniconda/lib/python2.7/ssl.py", line 369, in wrap_socket
2189    _context=self)
2190  File "/home/travis/miniconda/lib/python2.7/ssl.py", line 599, in __init__
2191    self.do_handshake()
2192  File "/home/travis/miniconda/lib/python2.7/ssl.py", line 828, in do_handshake
2193    self._sslobj.do_handshake()
2194IOError: [Errno socket error] [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:727)
2195
2196======================================================================
2197ERROR: tearDownClass (base.settings.test_install.TestInstall)
2198----------------------------------------------------------------------
2199Traceback (most recent call last):
2200  File "/home/travis/build/pyiron/pyiron/tests/base/settings/test_install.py", line 17, in tearDownClass
2201    shutil.rmtree(os.path.join(execution_path, 'resources'))
2202  File "/home/travis/miniconda/lib/python2.7/shutil.py", line 262, in rmtree
2203    onerror(os.listdir, path, sys.exc_info())
2204  File "/home/travis/miniconda/lib/python2.7/shutil.py", line 260, in rmtree
2205    names = os.listdir(path)
2206OSError: [Errno 2] No such file or directory: '/home/travis/build/pyiron/pyiron/tests/base/settings/resources'
2207
2208----------------------------------------------------------------------

It seems to be an issue with the travis SSL certificates.

Phonopy master wrong run mode - modal instead of non_modal

pyiron version: 0.2.10

pr=Project("test-phonopy")
atoms = pr.create_ase_bulk("Mo")
job = pr.create_job(pr.job_type.PhonopyJob,"phonopy")
engine_job = pr.create_job(pr.job_type.Vasp,"vasp_engine")
engine_job.structure = atoms
engine_job.executable.mpi =True
engine_job.server.queue = "xxx"
engine_job.server.cores=4
job.ref_job = engine_job
job.server.run_mode = "non_modal"
job.run(run_mode="non_modal")

expected behavior: run master job in non_modal mode in background
actual behavior:

The job phonopy was saved and received the ID: 9
2020-01-17 13:26:02,965 - pyiron_log - INFO - job: phonopy id: 9 run parallel master (modal)
2020-01-17 13:26:04,567 - pyiron_log - INFO - phonopy: run job supercell_phonon_0
2020-01-17 13:26:04,572 - pyiron_log - INFO - run job: supercell_phonon_0 id: None, status: initialized
The job supercell_phonon_0 was saved and received the ID: 10
2020-01-17 13:26:05,112 - pyiron_log - INFO - run job: supercell_phonon_0 id: 10, status: created
Queue system id: 2812640
2020-01-17 13:26:05,202 - pyiron_log - INFO - job: supercell_phonon_0 id: 10, status: submitted, submitted: queue id 2812640
2020-01-17 13:26:05,203 - pyiron_log - INFO - phonopy: submitted job supercell_phonon_0

Lammps Fe C example not working

https://travis-ci.org/jan-janssen/release-testing/builds/580849202

[NbConvertApp] ERROR | Error while converting 'lammps-fe-c-example.ipynb'
958Traceback (most recent call last):
959  File "/home/travis/miniconda/lib/python3.7/site-packages/nbconvert/nbconvertapp.py", line 410, in export_single_notebook
960    output, resources = self.exporter.from_filename(notebook_filename, resources=resources)
961  File "/home/travis/miniconda/lib/python3.7/site-packages/nbconvert/exporters/exporter.py", line 179, in from_filename
962    return self.from_file(f, resources=resources, **kw)
963  File "/home/travis/miniconda/lib/python3.7/site-packages/nbconvert/exporters/exporter.py", line 197, in from_file
964    return self.from_notebook_node(nbformat.read(file_stream, as_version=4), resources=resources, **kw)
965  File "/home/travis/miniconda/lib/python3.7/site-packages/nbconvert/exporters/notebook.py", line 32, in from_notebook_node
966    nb_copy, resources = super(NotebookExporter, self).from_notebook_node(nb, resources, **kw)
967  File "/home/travis/miniconda/lib/python3.7/site-packages/nbconvert/exporters/exporter.py", line 139, in from_notebook_node
968    nb_copy, resources = self._preprocess(nb_copy, resources)
969  File "/home/travis/miniconda/lib/python3.7/site-packages/nbconvert/exporters/exporter.py", line 316, in _preprocess
970    nbc, resc = preprocessor(nbc, resc)
971  File "/home/travis/miniconda/lib/python3.7/site-packages/nbconvert/preprocessors/base.py", line 47, in __call__
972    return self.preprocess(nb, resources)
973  File "/home/travis/miniconda/lib/python3.7/site-packages/nbconvert/preprocessors/execute.py", line 405, in preprocess
974    nb, resources = super(ExecutePreprocessor, self).preprocess(nb, resources)
975  File "/home/travis/miniconda/lib/python3.7/site-packages/nbconvert/preprocessors/base.py", line 69, in preprocess
976    nb.cells[index], resources = self.preprocess_cell(cell, resources, index)
977  File "/home/travis/miniconda/lib/python3.7/site-packages/nbconvert/preprocessors/execute.py", line 448, in preprocess_cell
978    raise CellExecutionError.from_cell_and_msg(cell, out)
979nbconvert.preprocessors.execute.CellExecutionError: An error occurred while executing the following cell:
980------------------
981job.output.temperatures
982------------------
983
984---------------------------------------------------------------------------
985AttributeError                            Traceback (most recent call last)
986<ipython-input-15-212654ccf9a4> in <module>
987----> 1 job.output.temperatures
988
989AttributeError: 'GenericInteractiveOutput' object has no attribute 'temperatures'
990AttributeError: 'GenericInteractiveOutput' object has no attribute 'temperatures'
991
992

DeprecationWarning: This method will be removed in future versions.

@sudarsan-surendralal : Can you take a look at this?

DeprecationWarning: This method will be removed in future versions.  Use 'list(elem)' or iteration over elem instead.
  if not len(node.getchildren()) > 0:
/Users/travis/build/pyiron/pyiron/pyiron/vasp/vasprun.py:173: DeprecationWarning: This method will be removed in future versions.  Use 'list(elem)' or iteration over elem instead.

LAMMPS: Shoud get_structure() return centered coordinates?

In LAMMPS calculations, the atoms often leave the unit cell during the simulation. To visualize this properly, we need to fold them back into the unit cell

final_struct = job_lammps.get_structure(iteration_step=-1).center_coordinates_in_unit_cell()

Is it okay if I call center_coordinates_in_unit_cell() inside get_structure()? Or are there cases where the unwrapped structure is needed? Also can I implement this at a generic level?

@jan-janssen @samwaseda @liamhuber

Restart erases output of finished jobs

A very dangerous bug that I detected which needs to be fixed. Suppose you have a workflow where you create new jobs from already finished jobs

from pyiron import Project
pr = Project("debug_restart")
pr.remove_jobs()
basis = pr.create_ase_bulk("Al")
ham = pr.create_job(pr.job_type.Vasp, "test")
ham.structure = basis
ham.write_charge_density = True
ham.run()

ham_new = ham.restart_from_charge_density()
ham_new.run()
print("output 1:", ham_new["output"])

ham_new = ham.restart_from_charge_density()
ham_new.run()
print("output 2:", ham_new["output"])

The output node is completely removed from the output of completed jobs when the restart function is called again. This is because of this line which copies the input only regardless of the state of the job

new_ham = self.copy_to(
new_job_name=job_name, new_database_entry=False, input_only=True
)

What is this good for?

So it took me some time to understand that this function killed my custom potential class. (Despite the missing docstrings) I understand what it does, but I don't understand what it is good for. Why shouldn't we simply pass the original lines from the static version?

def _interactive_set_potential(self):

Visualization of clusters without cell

When constructing clusters with no cell attribute, the plot3d(), get_final_structure() and animate_structure() do not seem to work (probably some other functions as well). It would be nice to be able to visualize these clusters without cell attribute, since it would be strange to define a unit cell for a cluster object.

If it helps, the plot3d_ase() does work for these clusters.

tags not updated in get_structure

I noticed that the spins are not updated when I get the final structures via get_structure, which is not difficult to understand since the tags were historically used for initial structures, but I still find it quite confusing that I see the initial magnetic moments in the final structure. Shall we apply individual updates (i.e. spin is updated while selective_dynamics isn't etc.)?

def get_structure(self, iteration_step=-1, wrap_atoms=True):

Is 'set_kmesh_density' necessary?

I understand that set_kmesh_density sets automatically the kmesh density according to the box size, but:

  • I find it very difficult to know whether it's set_kpoints or set_kmesh_density, which allows me to set specific k points.
  • There is no argument, except for kspace_per_in_ang.
  • kspace_per_in_ang is also not quite easy to understand

My suggestion would be to erase the function altogether and make _get_k_mesh_by_cell a public function. What do you think?

waves/dos.py - VisibleDeprecationWarning

@sudarsan-surendralal Can you take a look at this?

pyiron/pyiron/dft/waves/dos.py:39: VisibleDeprecationWarning: Passing `normed=True` on non-uniform bins has always been broken, and computes neither the probability density function nor the probability mass function. The result is only correct if the bins are uniform, when density=True will produce the same result anyway. The argument will be removed in a future version of numpy.
  self.t_dos, self.energies = np.histogram(self.es_obj.eigenvalues, bins=int(n_bins), normed=True)

Outcar parsing

The OUTCAR parsing fails when getting the Broyden mesh

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-27-dccf7de60ce2> in <module>()
----> 1 ham.collect_output()

/cmmc/u/chandu/programs/pyiron_mpie/pyiron/pyiron/vasp/base.py in collect_output(self)
    251         self._output_parser.structure = self.structure.copy()
    252         try:
--> 253             self._output_parser.collect(directory=self.working_directory)
    254         except VaspCollectError:
    255             self.status.aborted = True

/cmmc/u/chandu/programs/pyiron_mpie/pyiron/pyiron/vasp/base.py in collect(self, directory)
   1139             raise IOError("Either the OUTCAR or vasprun.xml files need to be present")
   1140         if "OUTCAR" in files_present:
-> 1141             self.outcar.from_file(filename=posixpath.join(directory, "OUTCAR"))
   1142             outcar_working = True
   1143         if "vasprun.xml" in files_present:

/cmmc/u/chandu/programs/pyiron_mpie/pyiron/pyiron/vasp/outcar.py in from_file(self, filename)
     62             irreducible_kpoints = None
     63         magnetization, final_magmom_lst = self.get_magnetization(filename)
---> 64         broyden_mixing = self.get_broyden_mixing_mesh(filename)
     65 
     66         self.parse_dict["energies"] = energies

/cmmc/u/chandu/programs/pyiron_mpie/pyiron/pyiron/vasp/outcar.py in get_broyden_mixing_mesh(filename)
    564                 if trigger in line:
    565                     line_ngx = lines[i-2].split()
--> 566                     return int(line_ngx[2]) * int(line_ngx[5]) * int(line_ngx[8])
    567 
    568     @staticmethod

ValueError: invalid literal for int() with base 10: 'NGZ'

Is this distinction necessary?

I'm having a box which is orthogonal at the beginning of the simulation (interactive), which is sheared over the course of the calculation. Since block is set (which is due to the orthogonal box at the beginning of the simulation), I was not allowed to shear the box. But is this distinction anyway required?

if self._interactive_prism.is_skewed():

Error in get_broyden_mixing()

So, I had a calculation which ran successfully but the parsing failed because the OUTCAR parser could not get the broyden mixing mesh

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-340-2919e271a3c5> in <module>()
----> 1 oc.get_broyden_mixing_mesh(ham_repair.working_directory+"/OUTCAR")

/cmmc/u/chandu/programs/pyiron_mpie/pyiron/pyiron/vasp/outcar.py in get_broyden_mixing_mesh(filename)
    562             for line in f.readlines():
    563                 if trigger in line:
--> 564                     return int(line.split()[4])
    565 
    566     @staticmethod

ValueError: invalid literal for int() with base 10: '******'

I checked the line and of course it gives out garbage although the calculation is fine


Broyden mixing: mesh for mixing (old mesh)
   NGX =123   NGY =103   NGZ = 81
  (NGX  =500   NGY  =420   NGZ  =320)
  gives a total of ****** points

Currently we try to parse the line gives a total of ****** points. But I realized from other calculations that this is the same as NGX*NGY*NGZ where NGX =123 NGY =103 NGZ = 81. Is this always the case? Then I can simply parse this line instead.

@jan-janssen I think you need this for your analysis right? Can you comment on this? Have you ever encountered this error?

Error I'm correcting

par_single = par.split()[0]

This line should be par_single = par.split()[0].split(self.multi_word_separator)[0], but since I'm changing this part anyway in my current branch, I'm not going to open an extra branch for this (I opened this issue just in case I fail to finish the branch)

Magnetic moments for ISPIN=2, LORBIT=10 Vasp calculations not read

Per-atom magnetic moments not read.

Input script:
from pyiron import Project
pr=Project("test-magmom")
atoms = pr.create_ase_bulk("Fe", cubic = True)
engine_job = pr.create_job(pr.job_type.Vasp,"vasp_engine")
engine_job.structure = atoms
engine_job.input.incar["LORBIT"]=10
engine_job.input.incar["ISPIN"]=2
engine_job.set_exchange_correlation_functional("PBE")
engine_job.executable.mpi =True
engine_job.server.queue = "XXX"
engine_job.server.cores=2
engine_job.run()

Output
engine_job["output"]

{'groups': ['charge_density', 'electronic_structure', 'generic', 'outcar', 'structure'], 'nodes': ['description']}

engine_job["output/outcar"]

{'groups': [], 'nodes': ['broyden_mixing', 'irreducible_kpoints', 'kin_energy_error', 'stresses']}

engine_job["output/electronic_structure"]

{'groups': ['dos'], 'nodes': ['TYPE', 'efermi', 'eig_matrix', 'k_points', 'k_weights', 'occ_matrix']}

engine_job["output/generic"]

{'groups': ['dft'], 'nodes': ['cells', 'energy_pot', 'energy_tot', 'forces', 'positions', 'positions_unwrapped', 'pressures', 'steps', 'temperature', 'volume']}

No info about magnetic moments...
However this code works:
from pyiron.vasp.outcar import Outcar
outcar = Outcar()
outcar_file_name=".../pyiron/projects/test-magmom/vasp_engine_hdf5/vasp_engine/OUTCAR"
outcar.from_file(outcar_file_name)
outcar.get_magnetization(outcar_file_name)

([array([2. , 2. , 2. , 2. , 4.8420694, 3.8795071,
3.9383515, 4.0114096, 3.9909919, 3.9988781, 3.9988781])],
[[2.008, 2.008], [2.008, 2.008]])

Issue with the automated build system

For some reason Anaconda tries to remove setuptools

## Package Plan ##

  environment location: /usr/share/miniconda

  added / updated specs:
    - conda


The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    asn1crypto-1.0.1           |           py37_0         161 KB
    ca-certificates-2019.8.28  |                0         132 KB
    certifi-2019.9.11          |           py37_0         154 KB
    chardet-3.0.4              |        py37_1003         174 KB
    conda-4.7.12               |           py37_0         3.0 MB
    conda-package-handling-1.6.0|   py37h7b6447c_0         797 KB
    openssl-1.1.1d             |       h7b6447c_2         2.5 MB
    pysocks-1.7.1              |           py37_0          30 KB
    sqlite-3.30.0              |       h7b6447c_0         1.9 MB
    tqdm-4.36.1                |             py_0          50 KB
    ------------------------------------------------------------
                                           Total:         8.9 MB

The following packages will be REMOVED:

  bzip2-1.0.8-h7b6447c_0
  libarchive-3.3.3-h5d8350f_5
  libxml2-2.9.9-hea5a465_1
  lz4-c-1.8.1.2-h14c3975_0
  lzo-2.10-h49e0be7_2
  pip-19.1.1-py37_0
  python-libarchive-c-2.8-py37_11
  setuptools-41.0.1-py37_0
  wheel-0.33.4-py37_0
  zstd-1.3.7-h0b5b093_0

The following packages will be UPDATED:

  asn1crypto                                  0.24.0-py37_0 --> 1.0.1-py37_0
  ca-certificates                               2019.5.15-0 --> 2019.8.28-0
  certifi                                  2019.6.16-py37_0 --> 2019.9.11-py37_0
  chardet                                      3.0.4-py37_1 --> 3.0.4-py37_1003
  conda                                       4.7.10-py37_0 --> 4.7.12-py37_0
  conda-package-han~                          1.3.11-py37_0 --> 1.6.0-py37h7b6447c_0
  openssl                                 1.1.1c-h7b6447c_1 --> 1.1.1d-h7b6447c_2
  pysocks                                      1.7.0-py37_0 --> 1.7.1-py37_0
  sqlite                                  3.29.0-h7b6447c_0 --> 3.30.0-h7b6447c_0
  tqdm                                          4.32.1-py_0 --> 4.36.1-py_0


Preparing transaction: ...working... done
Verifying transaction: ...working... failed

RemoveError: 'setuptools' is a dependency of conda and cannot be removed from
conda's operating environment.

First pyiron Workshop - http://potentials.rub.de - in Bochum - Germany - 31st of March to 2nd of April 2020

WORKSHOP

"WORKFLOWS FOR ATOMISTIC SIMULATION"

SCOPE

It is increasingly common that atomistic simulations such as molecular
dynamics or structural relaxation are used as engines that drive more
complex simulation tasks, for example, the computation of phase diagrams
or the search for novel materials with specific properties, etc.

The workflow along the simulation chain then becomes an integral part of
research and for transparent and reproducible results or for
transferring to other materials systems it is essential that the
workflow along the simulation chain is well documented.

At this workshop leading international researchers will give an
introduction to simulations and workflows that they use in their
research. In the afternoons hands-on tutorials using pyiron will
enable the participants to set up their own simulation tasks and
workflows.

REGISTRATION

Participation is free of charge, limited to a maximum of 50
participants. We ask you to provide us with some information on your
background and your motivation for taking part in the workshop, which we
will use as the basis to select participants. For a binding registration
please send an email with your name, contact details and a few lines on
your background and motivation for attending the workshop to:
[email protected] We will then inform you regarding acceptance at
the workshop as soon as possible.

DATES AND PLACE

31 March-2 April 2020, Bochum, Germany

WEBSITE

http://potentials.rub.de

Langevin thermostat/barostat overwrites geometrical constraints

If I have a LAMMPS calculation with some atoms fixed in their original positions and then run MD with a Langevin thermostat/barostat, the constraints are overwritten. This is because for some reason, the fix langevin all command is written at the very end (before the run command). Is there a reason why the Langevin command should be called at the very end? Example code below

import numpy as np
import matplotlib.pylab as plt
from pyiron import Project

pr = Project("langevin_test")

a = 3.1904
c = 5.1895
Mg_surf = pr.create_surface(element="Mg", surface_type="hcp0001", 
                            size=(3, 4, 8), a=a, c=c, vacuum=10.0,
                            orthogonal=True)

Mg_surf.add_tag(selective_dynamics=[True, True, True])
fix_indices = np.argsort(Mg_surf.positions[:, 2])[0:48]
Mg_surf.selective_dynamics[fix_indices] = [False, False, False]


langevin_list = [False, True]
for langevin in langevin_list:
    ham = pr.create_job(pr.job_type.Lammps, "job_langevin_{}".format(str(langevin)))
    ham.structure = Mg_surf
    ham.potential = ham.list_potentials()[0]
    ham.calc_md(temperature=350, time_step=0.01, langevin=langevin, n_ionic_steps=10000)
    ham.run()

fig, ax = plt.subplots(ncols=2, nrows=1, sharey=True)

ham = pr.inspect("job_langevin_False")
ax[0].plot(ham["output/generic/positions"][:, fix_indices, 2], color="green");
ax[0].set_title("Nose Hoover")

ham = pr.inspect("job_langevin_True")
ax[1].plot(ham["output/generic/positions"][:, fix_indices, 2])
ax[1].set_title("Langevin");

Lammps structures can be read wrong

Beyond some level of cell shape complexity, there is a breakdown in communication between pyiron and Lammps. For a concrete example, Al run with a cubic or orthogonal cell is fine, but with the primitive structure pyiron reads the structure wrong.

MWE:

job = pr.create_job(pr.job_type.Lammps, 'primitive_trouble')
job.structure = pr.create_ase_bulk('Al').repeat(3)
job.potential = job.list_potentials()[0]
job.run()

job.structure.plot3d()  # Fine
job.get_final_structure().plot3d()  # Uh-oh

The average energies under a simple MD run are fine regardless of whether I use the primitive, orthorhombic, or cubic cells, so things are getting passed to Lammps fine, but when we try to read the Lammps output we're misinterpreting it.

Docker builds fail

fetch http://nl.alpinelinux.org/alpine/edge/testing/x86_64/APKINDEX.tar.gz
ERROR: http://nl.alpinelinux.org/alpine/edge/testing: operation timed out

It seems to be an alpinelinux related issue. Maybe we can even disable the docker image part, since we have mybinder as a test environment for new users.

Possible bug in list_nodes

Given is the attached hdf (rename it from minimize.txt to minimize.h5) file
and the path to a group minimize/graph/vertices/calc_static/archive/input/structure

However during deserialization in from_hdf method
hdf.list_nodes() of the parent path yields
['TYPE', 'interesting_keys', 'ref_job_full_path', 'structure']

while structure is a group
I verified it with HDFCompass and h5py module which clearly states

import h5py
h = h5py.File('minimize.h5', 'r')
h['minimize/graph/vertices/calc_static/archive/input/structure']

<HDF5 group "/minimize/graph/vertices/calc_static/archive/input/structure" (17 members)>

Lammps gets stuck while parsing output

I have a code below:

pr = Project('LAMMPS')
lmp = pr.create_job('Lammps', 'lmp')
lmp.structure = pr.create_structure('Fe', 'bcc', 2.855312531).repeat(10)
lmp.potential = 'Fe_C_Becquart_eam'
lmp.calc_md(temperature=300, n_ionic_steps=1e6)
lmp.server.cores = 4
lmp.server.queue = 's_cmfe'
lmp.run()

and the status gets stuck with collect, when the job stops running at the end. When the number of steps is reduced to something like 100, then it ends in a regular way. Similarly, if the job is not submitted, it ends correctly as well.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.