diff --git a/.binder/environment.yml b/.binder/environment.yml index 9d891bbb..60cd8379 100644 --- a/.binder/environment.yml +++ b/.binder/environment.yml @@ -7,14 +7,17 @@ dependencies: - cloudpickle =3.0.0 - graphviz =8.1.0 - matplotlib =3.8.2 -- pympipool =0.7.9 +- pympipool =0.7.13 - python-graphviz =0.20.1 - toposort =1.10 - typeguard =4.1.5 - ase =3.22.1 -- atomistics =0.1.12 +- atomistics =0.1.23 - lammps +- matgl =0.9.2 +- pandas =2.2.0 - phonopy =2.21.0 -- pyiron_atomistics =0.3.5 -- pyiron-data =0.0.24 -- numpy =1.26.0 +- pyiron_atomistics =0.4.15 +- pyiron_contrib =0.1.15 +- pyiron-data =0.0.27 +- numpy =1.26.4 diff --git a/.binder/postBuild b/.binder/postBuild index c63d4551..69f4a01b 100644 --- a/.binder/postBuild +++ b/.binder/postBuild @@ -24,7 +24,6 @@ if [ -d "${HOME}/pyiron_workflow" ]; then ${HOME}/CONTRIBUTING.rst \ ${HOME}/LICENSE \ ${HOME}/MANIFEST.in \ - ${HOME}/README.md \ ${HOME}/setup.cfg \ ${HOME}/setup.py \ ${HOME}/versioneer.py diff --git a/.ci_support/environment-notebooks.yml b/.ci_support/environment-notebooks.yml index 79506622..18f41564 100644 --- a/.ci_support/environment-notebooks.yml +++ b/.ci_support/environment-notebooks.yml @@ -2,10 +2,12 @@ channels: - conda-forge dependencies: - ase =3.22.1 - - atomistics =0.1.12 + - atomistics =0.1.23 - lammps + - matgl =0.9.2 + - pandas =2.2.0 - phonopy =2.21.0 - - pyiron_atomistics =0.3.5 - - pyiron_contrib =0.1.13 - - pyiron-data =0.0.24 - - numpy =1.26.0 \ No newline at end of file + - pyiron_atomistics =0.4.15 + - pyiron_contrib =0.1.15 + - pyiron-data =0.0.27 + - numpy =1.26.4 \ No newline at end of file diff --git a/.ci_support/environment.yml b/.ci_support/environment.yml index 5491c58f..1999ce1f 100644 --- a/.ci_support/environment.yml +++ b/.ci_support/environment.yml @@ -7,7 +7,7 @@ dependencies: - cloudpickle =3.0.0 - graphviz =8.1.0 - matplotlib =3.8.2 -- pympipool =0.7.9 +- pympipool =0.7.13 - python-graphviz =0.20.1 - toposort =1.10 - typeguard =4.1.5 diff --git a/.github/delete-merged-branch-config.yml b/.github/delete-merged-branch-config.yml deleted file mode 100644 index 76898c70..00000000 --- a/.github/delete-merged-branch-config.yml +++ /dev/null @@ -1,3 +0,0 @@ -exclude: - - main -delete_closed_pr: false diff --git a/.github/workflows/push-pull.yml b/.github/workflows/push-pull.yml index 60412a46..5d77861d 100644 --- a/.github/workflows/push-pull.yml +++ b/.github/workflows/push-pull.yml @@ -12,6 +12,7 @@ jobs: uses: pyiron/actions/.github/workflows/push-pull-main.yml@main secrets: inherit with: + docs-env-files: .ci_support/environment.yml notebooks-env-files: .ci_support/environment.yml .ci_support/environment-notebooks.yml tests-in-python-path: true runner-alt2: 'macos-11' diff --git a/README.md b/docs/README.md similarity index 90% rename from README.md rename to docs/README.md index 278707f5..9b06a860 100644 --- a/README.md +++ b/docs/README.md @@ -4,8 +4,7 @@ [![License](https://img.shields.io/badge/License-BSD_3--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/0b4c75adf30744a29de88b5959246882)](https://app.codacy.com/gh/pyiron/pyiron_workflow/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [![Coverage Status](https://coveralls.io/repos/github/pyiron/pyiron_workflow/badge.svg?branch=main)](https://coveralls.io/github/pyiron/pyiron_workflow?branch=main) - -[//]: # ([![Documentation Status](https://readthedocs.org/projects/pyiron-workflow/badge/?version=latest)](https://pyiron-workflow.readthedocs.io/en/latest/?badge=latest)) +[![Documentation Status](https://readthedocs.org/projects/pyiron-workflow/badge/?version=latest)](https://pyiron-workflow.readthedocs.io/en/latest/?badge=latest) [![Anaconda](https://anaconda.org/conda-forge/pyiron_workflow/badges/version.svg)](https://anaconda.org/conda-forge/pyiron_workflow) [![Last Updated](https://anaconda.org/conda-forge/pyiron_workflow/badges/latest_release_date.svg @@ -51,7 +50,7 @@ But the intent is to collect them together into a workflow and leverage existing ```python >>> from pyiron_workflow import Workflow ->>> Workflow.register("plotting", "pyiron_workflow.node_library.plotting") +>>> Workflow.register("pyiron_workflow.node_library.plotting", "plotting") >>> >>> @Workflow.wrap_as.single_value_node() ... def Arange(n: int): @@ -85,18 +84,18 @@ But the intent is to collect them together into a workflow and leverage existing Which gives the workflow `diagram` -![](docs/_static/readme_diagram.png) +![](_static/readme_diagram.png) And the resulting figure (when axes are not cleared) -![](docs/_static/readme_fig.png) +![](_static/readme_fig.png) ## Installation `conda install -c conda-forge pyiron_workflow` -To unlock the associated node packages and ensure that the demo notebooks run, also make sure your conda environment has the packages listed in our [notebooks dependencies](.ci_support/environment-notebooks.yml) +To unlock the associated node packages and ensure that the demo notebooks run, also make sure your conda environment has the packages listed in our [notebooks dependencies](../.ci_support/environment-notebooks.yml) ## Learning more -Check out the demo [notebooks](notebooks), read through the docstrings, and don't be scared to raise an issue on this GitHub repo! \ No newline at end of file +Check out the demo [notebooks](../notebooks), read through the docstrings, and don't be scared to raise an issue on this GitHub repo! \ No newline at end of file diff --git a/docs/_static/readme_fig.png b/docs/_static/readme_fig.png new file mode 100644 index 00000000..bd074851 Binary files /dev/null and b/docs/_static/readme_fig.png differ diff --git a/docs/conf.py b/docs/conf.py index 4968c2dd..15ab975d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -34,14 +34,25 @@ # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. -extensions = ['nbsphinx', 'sphinx.ext.mathjax', 'sphinx.ext.autodoc', 'sphinx.ext.viewcode', - 'sphinx.ext.autosummary', 'sphinx.ext.napoleon'] +extensions = [ + 'myst_parser', + 'nbsphinx', + 'sphinx_gallery.load_style', + 'sphinx.ext.mathjax', + 'sphinx.ext.autodoc', + 'sphinx.ext.viewcode', + 'sphinx.ext.autosummary', + 'sphinx.ext.napoleon' +] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = { + '.rst': 'restructuredtext', + '.md': 'markdown' +} # The encoding of source files. # source_encoding = 'utf-8-sig' @@ -50,7 +61,7 @@ master_doc = 'index' # General information about the project. -project = u'pyiron' +project = u'pyiron_workflow' copyright = u'2021, Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department ' \ u'All rights reserved' @@ -228,7 +239,7 @@ # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'pyiron.tex', u'pyiron Documentation', + ('index', 'pyiron_workflow.tex', u'pyiron_workflow Documentation', u'Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department', 'manual'), ] @@ -259,8 +270,8 @@ # (source start file, name, description, authors, manual section). man_pages = [ ('index', - 'pyiron', - u'pyiron Documentation', + 'pyiron_workflow', + u'pyiron_workflow Documentation', [u'Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department'], 1) ] @@ -276,10 +287,10 @@ texinfo_documents = [ ('index', 'pyiron_workflow', - u'pyiron Documentation', + u'pyiron_workflow Documentation', u'Max-Planck-Institut für Eisenforschung GmbH - Computational Materials Design (CM) Department', 'pyiron_workflow', - 'One line description of project.', + 'Graph-based workflow management.', 'Miscellaneous'), ] diff --git a/docs/environment.yml b/docs/environment.yml index 0bcf36d0..8528c9cf 100644 --- a/docs/environment.yml +++ b/docs/environment.yml @@ -2,14 +2,17 @@ channels: - conda-forge dependencies: - ipykernel +- myst-parser - nbsphinx +- sphinx-gallery +- sphinx-rtd-theme - coveralls - coverage - bidict =0.22.1 - cloudpickle =3.0.0 - graphviz =8.1.0 - matplotlib =3.8.2 -- pympipool =0.7.9 +- pympipool =0.7.13 - python-graphviz =0.20.1 - toposort =1.10 - typeguard =4.1.5 diff --git a/docs/index.rst b/docs/index.rst index 05b6a5f6..41541a7e 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1,13 +1,13 @@ + .. pyiron_workflow documentation master file .. _index: - -=============== -pyiron_workflow -=============== +.. include:: README.md + :parser: myst_parser.sphinx_ .. toctree:: :hidden: + source/examples.rst source/indices.rst \ No newline at end of file diff --git a/docs/source/examples.rst b/docs/source/examples.rst new file mode 100644 index 00000000..de824f08 --- /dev/null +++ b/docs/source/examples.rst @@ -0,0 +1,11 @@ +.. _examples: + + +Example Notebooks +================= + +.. nbgallery:: + :maxdepth: 2 + :glob: + + notebooks/* \ No newline at end of file diff --git a/docs/source/indices.rst b/docs/source/indices.rst index 2e2007f3..28767e9f 100644 --- a/docs/source/indices.rst +++ b/docs/source/indices.rst @@ -9,4 +9,4 @@ API Documentation .. toctree:: - :maxdepth:2 + :maxdepth: 2 diff --git a/notebooks/atomistics_nodes.ipynb b/notebooks/atomistics_nodes.ipynb index 915ac795..4b34fb26 100644 --- a/notebooks/atomistics_nodes.ipynb +++ b/notebooks/atomistics_nodes.ipynb @@ -27,8 +27,8 @@ "metadata": {}, "outputs": [], "source": [ - "Workflow.register(\"atomistics\", \"pyiron_workflow.node_library.atomistics\")\n", - "Workflow.register(\"plotting\", \"pyiron_workflow.node_library.plotting\")" + "Workflow.register(\"pyiron_workflow.node_library.atomistics\", \"atomistics\")\n", + "Workflow.register(\"pyiron_workflow.node_library.plotting\", \"plotting\")" ] }, { @@ -39,7 +39,7 @@ "outputs": [ { "data": { - "image/png": "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", + "image/png": "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rYthbztv2LBhWrRokVavXq0XXnhBTU1NKi8v1/79+0O2T8V7LkkrVqzQV199pZtuuilsm1S55ycL/G7b+b0PnGf3nER35MgRzZo1Sz/4wQ/a3Sht4MCBevnll1VTU6PXXntNOTk5GjFihD799NMY9rbzxo4dq1dffVV//OMf9etf/1p//vOfdfnll+vo0aNhz0nF+/7KK6+oR48euvbaa9tt5+R9T4pde2Pt1L8KDcNo9y/FUO1DHU8Wd911l/73f/9X7777brvtzj//fJ1//vmt35eVlWnnzp164okndOmllzrdzagZO3Zs639fcMEFKisr07nnnqtXXnlFM2bMCHlOqt1zSVq4cKHGjh2rgoKCsG1S5Z6HYvf3PtJzEtWxY8d04403yu/3a968ee22HT58eFCi54gRIzRkyBA988wzevrpp53uatRMmjSp9b9LSko0dOhQFRYW6q233mr3gzmV7rskvfjii/qXf/mXDnM/nLzvjIycpHfv3srMzGwT4e7du7dNJBzQp0+fkO27dOmiXr16OdZXp9x9992qqanRO++8o379+tk+f/jw4Un319GpTjvtNF1wwQVhryPV7rkkbd++XX/4wx9066232j432e95YOWUnd/7wHl2z0lUx44d08SJE9XY2Kja2lrb28dnZGToe9/7XlL/HEjmyF9hYWG715FK912S1q9fr48//jii3/1o3neCkZNkZWWptLS0dUVBQG1trcrLy0OeU1ZW1qb922+/raFDh6pr166O9TXaDMPQXXfdpWXLlumPf/yjioqKInqd+vp65efnR7l3sXX06FFt27Yt7HWkyj0/2UsvvaSzzz5b48aNs31ust/zoqIi9enTJ+ietrS0aO3atWF/76XwPwftnZOIAoHIp59+qj/84Q8RBdSGYWjTpk1J/XMgSfv379fOnTvbvY5Uue8BCxcuVGlpqS688ELb50b1vjuSFpvE/uu//svo2rWrsXDhQqOhocGYPn26cdpppxl/+9vfDMMwjFmzZhmTJ09ubf/5558b3bt3N37yk58YDQ0NxsKFC42uXbsaS5YsidclRORHP/qRkZuba6xZs8bweDytj0OHDrW2OfXaf/Ob3xjLly83PvnkE2PLli3GrFmzDEnG0qVL43EJEfvpT39qrFmzxvj888+N999/3/j+979v9OjRI+XveYDP5zMGDBhgzJw5s81zqXLPDxw4YNTX1xv19fWGJOPJJ5806uvrW1eMzJkzx8jNzTWWLVtmbN682fjnf/5nIz8/3/B6va2vMXny5KBVde+9956RmZlpzJkzx9i2bZsxZ84co0uXLsb7778f8+trT3vXfuzYMaOystLo16+fsWnTpqDf/aNHj7a+xqnX/uCDDxqrVq0yPvvsM6O+vt64+eabjS5duhgffPBBPC4xrPau/cCBA8ZPf/pTo66uzmhsbDTeeecdo6yszOjbt2/K3/eA5uZmo3v37sb8+fNDvkYs7zvBSAjPPvusUVhYaGRlZRlDhgwJWt46depUY9SoUUHt16xZY1x00UVGVlaWcc4554S9sYlMUsjHSy+91Nrm1Gt/7LHHjHPPPdfIyckxzjzzTOOSSy4x3nrrrdh3vpMmTZpk5OfnG127djUKCgqMa6+91ti6dWvr86l6zwNWr15tSDI+/vjjNs+lyj0PLEk+9TF16lTDMMzlvQ888IDRp08fIzs727j00kuNzZs3B73GqFGjWtsHvPHGG8b5559vdO3a1Rg4cGBCBmXtXXtjY2PY3/133nmn9TVOvfbp06cbAwYMMLKysoyzzjrLqKioMOrq6mJ/cR1o79oPHTpkVFRUGGeddZbRtWtXY8CAAcbUqVONHTt2BL1GKt73gOeee87o1q2b8dVXX4V8jVjed5dhnMi8AwAAiANyRgAAQFwRjAAAgLgiGAEAAHFFMAIAAOKKYAQAAMQVwQgAAIgrghEAABBXBCMAACCuCEYAAEBcEYwAAIC4IhgBAABxRTACAADi6v8DLdRAq+S5ePgAAAAASUVORK5CYII=", "text/plain": [ "
" ] @@ -59,23 +59,23 @@ " calculator=wf.calculator,\n", ")\n", "wf.ev_plot = wf.create.plotting.Scatter(\n", - " wf.ev.outputs.result_dict['volume'],\n", - " wf.ev.outputs.result_dict['energy']\n", + " wf.ev.outputs.result_dict[\"volume\"],\n", + " wf.ev.outputs.result_dict[\"energy\"]\n", ")\n", "\n", "wf.elastic = wf.create.atomistics.macro.ElasticMatrix(\n", " structure=wf.structure, \n", " calculator=wf.calculator,\n", ")\n", - "wf.C = wf.elastic.outputs.result_dict[\"C\"]\n", + "wf.C = wf.elastic.outputs.result_dict[\"elastic_matrix\"]\n", "\n", "wf.phonons = wf.create.atomistics.macro.Phonons(\n", " structure=wf.structure, \n", " calculator=wf.calculator,\n", ")\n", "wf.dos_plot = wf.create.plotting.Scatter(\n", - " wf.phonons.outputs.result_dict[1][\"frequency_points\"],\n", - " wf.phonons.outputs.result_dict[1][\"total_dos\"],\n", + " wf.phonons.outputs.result_dict[\"total_dos_dict\"][\"frequency_points\"],\n", + " wf.phonons.outputs.result_dict[\"total_dos_dict\"][\"total_dos\"],\n", ")\n", "\n", "out = wf()" @@ -91,18 +91,18 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", " warn(\n", - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", " warn(\n", - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", " warn(\n" ] }, { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 4, @@ -111,7 +111,7 @@ }, { "data": { - "image/png": "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", + "image/png": "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", "text/plain": [ "
" ] @@ -136,18 +136,18 @@ { "data": { "text/plain": [ - "array([[53.26140026, 24.22288983, 24.22288983, 0. , 0. ,\n", + "array([[47.25994412, 28.71281131, 28.71281131, 0. , 0. ,\n", " 0. ],\n", - " [24.22288983, 53.26140026, 24.22288983, 0. , 0. ,\n", + " [28.71281131, 47.25994412, 28.71281131, 0. , 0. ,\n", " 0. ],\n", - " [24.22288983, 24.22288983, 53.26140026, 0. , 0. ,\n", + " [28.71281131, 28.71281131, 47.25994412, 0. , 0. ,\n", " 0. ],\n", - " [ 0. , 0. , 0. , 32.8950073 , 0. ,\n", + " [ 0. , 0. , 0. , 31.72112464, 0. ,\n", " 0. ],\n", - " [ 0. , 0. , 0. , 0. , 32.8950073 ,\n", + " [ 0. , 0. , 0. , 0. , 31.72112464,\n", " 0. ],\n", " [ 0. , 0. , 0. , 0. , 0. ,\n", - " 32.8950073 ]])" + " 31.72112464]])" ] }, "execution_count": 5, @@ -168,7 +168,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 6, @@ -177,7 +177,7 @@ }, { "data": { - "image/png": "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qKKigmAkCcgZSZB+/fppwoQJqqmpCTpeU1Oj6667zqZROVMgENDixYv14osvatu2bSoqKrJ7SI41bdo0vf3226qrq+t8TJw4UX/zN3+juro6ApE4mjx5co8S9XfeeUeXXXaZTSNytk8++UR9+gRfErOysijtTRJmRhKovLxct912myZOnKiysjKtX79ex44d04IFC+wemqMsWrRIzz33nF5++WXl5eV1zka53W7179/f5tE5S15eXo9cnIEDB2rIkCHk6MTZvffeq+uuu04///nP9Vd/9Vfau3ev1q9fr/Xr19s9NEeaO3eufvazn+nSSy9VSUmJDh48qH/+53/W97//fbuHlhkCSKhf/OIXgcsuuyzQr1+/wPjx4wM7duywe0iOIynk45lnnrF7aBnhxhtvDCxZssTuYTjS5s2bA6WlpYGcnJzAVVddFVi/fr3dQ3Isv98fWLJkSeDSSy8N5ObmBi6//PLAj370o0Bra6vdQ8sI9BkBAAC2ImcEAADYimAEAADYimAEAADYimAEAADYimAEAADYimAEAADYimAEAADYimAEAADYimAEAADYimAEAADYimAEAADYimAEAADY6v8BEKVk8pHuah4AAAAASUVORK5CYII=", + "image/png": "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4TjKvn371NzcrMLCwu5rPp9PO3fu1IYNG9TR0aHU1FQDR+gMOTk5ysvLC7o2ceJEvfjiiwaNyHl+9rOfadWqVfre974nSbriiiv0ySefqKKigjAiakYSIi0tTYWFhaqpqQm6XlNTo5kzZxo0Kufx+/1atmyZXnrpJb3xxhvKzc01ekiOc+211+rDDz9UfX1999u0adP0N3/zN6qvryeIJMmsWbN6bWv/6KOPNH78eING5DxnzpxRSkrwIzc1NZWtvX/EzEiClJWV6ZZbbtG0adNUVFSkTZs26ejRoyotLTV6aI5x22236YUXXtArr7yi4cOHd89Uud1uDRkyxODROcPw4cN71egMGzZMo0aNonYniVauXKmZM2fqV7/6lW666Sbt3btXmzZt0qZNm4wemmOUlJTol7/8pS666CJNmjRJdXV1evjhh/XDH/7Q6KGZgx8J8/jjj/vHjx/vT0tL8xcUFPjffPNNo4fkKJJCvj377LNGD83Rrr76av/y5cuNHobj7Nixw5+fn+9PT0/3X3755f5NmzYZPSRHaWtr8y9fvtx/0UUX+TMyMvyXXHKJf82aNf6Ojg6jh2YK9BkBAACGomYEAAAYijACAAAMRRgBAACGIowAAABDEUYAAIChCCMAAMBQhBEAAGAowggAADAUYQQAABiKMAIAAAxFGAEAAIYijAAAAEP9f46xw198D3usAAAAAElFTkSuQmCC", "text/plain": [ "
" ] diff --git a/notebooks/deepdive.ipynb b/notebooks/deepdive.ipynb index 33b2b06f..b913fd02 100644 --- a/notebooks/deepdive.ipynb +++ b/notebooks/deepdive.ipynb @@ -524,9 +524,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel ran was not connected to run, andthus could not disconnect from it.\n", - " warn(\n", - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", " warn(\n" ] }, @@ -985,13 +983,13 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", " warn(\n" ] }, { "data": { - "image/png": "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iIo3sAIAgNgV02dGAABA5CNGAACAVcQIAACwihgBAABWESMAAMCqqI6RHTt2KCcnR06nUwUFBWpubv7e/fft26eCggI5nU7NnTtXzz77bJgmjR/BHJM333xTy5Yt0yWXXKK0tDQVFxfr3XffDeO08SHYfycjDhw4oKSkJF111VWTO2CcCfZ4DA4OauvWrZozZ45SUlI0b9487dq1K0zTxodgj8mePXu0aNEiXXTRRXK73brzzjt16tSpME0bo0yU+stf/mKmTJliXnjhBePxeMz9999vpk2bZj799NMx9z927Ji56KKLzP333288Ho954YUXzJQpU8wbb7wR5sljV7DH5P777zePPvqoaWlpMR999JHZsmWLmTJlijl8+HCYJ49dwR6TEV988YWZO3euKS0tNYsWLQrPsHEglONx8803m8WLF5umpibT0dFh/vnPf5oDBw6EcerYFuwxaW5uNgkJCebJJ580x44dM83NzeaKK64wK1euDPPksSVqY6SoqMhUVFT4bbv88svN5s2bx9z/d7/7nbn88sv9tt19993m6quvnrQZ402wx2Qsubm5prq6eqJHi1uhHpPy8nLzxz/+0VRVVREjEyjY4/G3v/3NuFwuc+rUqXCMF5eCPSZ/+tOfzNy5c/22PfXUU2b27NmTNmM8iMrLNKdPn1Zra6tKS0v9tpeWlurgwYNjvub9998P2P+GG27QoUOH9O23307arPEilGPyXcPDw+rv71d6evpkjBh3Qj0mL730kj755BNVVVVN9ohxJZTj8c4776iwsFCPPfaYZs2apQULFuiBBx7QN998E46RY14ox6SkpEQnTpxQQ0ODjDH6/PPP9cYbb+imm24Kx8gxKyo+tfe7enp6NDQ0pMzMTL/tmZmZ6urqGvM1XV1dY+5/5swZ9fT0yO12T9q88SCUY/Jdjz/+uL766iutWrVqMkaMO6Eck48//libN29Wc3OzkpKi8n8eIlYox+PYsWPav3+/nE6n3nrrLfX09Oiee+5Rb28v7xuZAKEck5KSEu3Zs0fl5eUaGBjQmTNndPPNN+vpp58Ox8gxKyrPjIxwOBx+z40xAdt+aP+xtiN0wR6TEa+99poefvhh1dXVKSMjY7LGi0vne0yGhoZ02223qbq6WgsWLAjXeHEnmH8jw8PDcjgc2rNnj4qKinTjjTfqiSee0Msvv8zZkQkUzDHxeDzasGGDHnroIbW2tqqxsVEdHR2qqKgIx6gxKyr/r8+MGTOUmJgYUK7d3d0BhTsiKytrzP2TkpI0ffr0SZs1XoRyTEbU1dVp3bp1ev3113X99ddP5phxJdhj0t/fr0OHDunIkSO67777JJ39Y2iMUVJSkvbu3avrrrsuLLPHolD+jbjdbs2aNUsul2t028KFC2WM0YkTJzR//vxJnTnWhXJMampqtGTJEj344IOSpCuvvFLTpk3T0qVL9cgjj3CWPURReWYkOTlZBQUFampq8tve1NSkkpKSMV9TXFwcsP/evXtVWFioKVOmTNqs8SKUYyKdPSNyxx136NVXX+Wa6wQL9pikpaXpgw8+UFtb2+ijoqJCl112mdra2rR48eJwjR6TQvk3smTJEp08eVJffvnl6LaPPvpICQkJmj179qTOGw9COSZff/21EhL8/3QmJiZK+u/ZdoTA1jtnL9TI7Vg7d+40Ho/HbNy40UybNs385z//McYYs3nzZnP77beP7j9ya++mTZuMx+MxO3fu5NbeCRbsMXn11VdNUlKS2b59u/F6vaOPL774wtavEHOCPSbfxd00EyvY49Hf329mz55tbrnlFvPhhx+affv2mfnz55u77rrL1q8Qc4I9Ji+99JJJSkoyO3bsMJ988onZv3+/KSwsNEVFRbZ+hZgQtTFijDHbt283c+bMMcnJySY/P9/s27dv9Gtr164111xzjd/+f//7381Pf/pTk5ycbC699FJTW1sb5oljXzDH5JprrjGSAh5r164N/+AxLNh/J+ciRiZesMfj6NGj5vrrrzdTp041s2fPNpWVlebrr78O89SxLdhj8tRTT5nc3FwzdepU43a7za9+9Stz4sSJME8dWxzGcF4JAADYE5XvGQEAALGDGAEAAFYRIwAAwCpiBAAAWEWMAAAAq4gRAABgFTECAACsIkYAAIBVxAgAALCKGAEAAFYRIwAAwKr/B+Y4x3CewomWAAAAAElFTkSuQmCC", + "image/png": "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9+/fr5tvvllXX321fD6f7r//fl28eDGsggEAQHJxHEYOHTqkbdu2aefOnWpvb9fy5cu1evVqdXd3T9n/2LFj2rhxozZv3qy3335bP/nJT/Rv//ZveuCBB2ZdPAAASHyOw8hTTz2lzZs364EHHtCSJUv0ve99TwsXLlRTU9OU/X/1q1/pM5/5jLZu3arCwkLddttt+qu/+iudOHFi1sUDAIDE5yiMXLp0SSdPnlRVVVVIe1VVlY4fPz7lOZWVlTp//ryOHDkiY4zee+89/fSnP9U999wz7XVGRkY0ODgYcgAAgOTkKIz09/crGAwqLy8vpD0vL0+9vb1TnlNZWan9+/dr7dq1ysjIUH5+vq699lr94Ac/mPY6DQ0N8nq9E8fChQudlAkAABJIWA+wulyhm+MYYya1jevs7NTWrVv16KOP6uTJk2publZXV5dqamqm/fN37NihQCAwcfT09IRTJgAASACONj2bN2+e3G73pLsgfX19k+6WjGtoaNCyZcv0yCOPSJI+//nP65prrtHy5cv1xBNPyOebvP1wZmamMjMznZQGAAASlKM7IxkZGSotLVVLS0tIe0tLiyorK6c856OPPlJaWuhl3G63pLE7KgAAILU5nqapra3Vj370I+3du1dnzpzRQw89pO7u7olplx07dmjjxo0T/aurq/Xyyy+rqalJ586d05tvvqmtW7eqvLxc8+fPj9xIAABAQnL83TRr167VxYsX9fjjj8vv96u4uFhHjhxRQUGBJMnv94fsOXLfffdpaGhIzzzzjP7mb/5G1157rW6//XY9+eSTkRsFAABIWC6TAHMlg4OD8nq9CgQCys7Otl0OAACYgZl+fvPdNAAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMAqwggAALCKMAIAAKwijAAAAKsIIwAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMCqdNsFJKvgqFFb14D6hoaVm+VReWGO3Gku22UBABB3CCNR0NzhV/3hTvkDwxNtPq9HddVFWlXss1gZAADxh2maCGvu8GvLvlMhQUSSegPD2rLvlJo7/JYqAwAgPhFGIig4alR/uFNmip+Nt9Uf7lRwdKoeAACkJsJIBLV1DUy6I3IlI8kfGFZb10DsigIAIM4RRiKob2j6IBJOPwAAUgFhJIJyszwR7QcAQCogjERQeWGOfF6PplvA69LYqprywpxYlgUAQFwjjESQO82luuoiSZoUSMZf11UXsd8IAABXIIxE2Kpin5rWlyjfGzoVk+/1qGl9CfuMAADwf7DpWRSsKvZpZVE+O7ACADADhJEocae5VLForu0yAACIe0zTAAAAqwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMAqwggAALCKMAIAAKwijAAAAKsIIwAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADAKsIIAACwijACAACsIowAAACrCCMAAMAqwggAALCKMAIAAKwijAAAAKsIIwAAwCrCCAAAsIowAgAArCKMAAAAqwgjAADAKsIIAACwKqww0tjYqMLCQnk8HpWWlqq1tfVj+4+MjGjnzp0qKChQZmamFi1apL1794ZVMAAASC7pTk84dOiQtm3bpsbGRi1btkzPPfecVq9erc7OTn3605+e8px7771X7733nvbs2aPPfvaz6uvr0+XLl2ddPAAASHwuY4xxcsLSpUtVUlKipqamibYlS5ZozZo1amhomNS/ublZX/nKV3Tu3Dnl5OSEVeTg4KC8Xq8CgYCys7PD+jMAAEBszfTz29E0zaVLl3Ty5ElVVVWFtFdVVen48eNTnvPqq6+qrKxM3/rWt3Tdddfpxhtv1MMPP6zf/e53015nZGREg4ODIQcAAEhOjqZp+vv7FQwGlZeXF9Kel5en3t7eKc85d+6cjh07Jo/Ho1deeUX9/f366le/qoGBgWmfG2loaFB9fb2T0gAAQIIK6wFWl8sV8toYM6lt3OjoqFwul/bv36/y8nLdfffdeuqpp/TCCy9Me3dkx44dCgQCE0dPT084ZQIAgATg6M7IvHnz5Ha7J90F6evrm3S3ZJzP59N1110nr9c70bZkyRIZY3T+/HndcMMNk87JzMxUZmamk9IAAECCcnRnJCMjQ6WlpWppaQlpb2lpUWVl5ZTnLFu2TBcuXNAHH3ww0Xb27FmlpaVpwYIFYZQMAACSieNpmtraWv3oRz/S3r17debMGT300EPq7u5WTU2NpLEplo0bN070X7dunebOnav7779fnZ2deuONN/TII4/oL/7iLzRnzpzIjQQAACQkx/uMrF27VhcvXtTjjz8uv9+v4uJiHTlyRAUF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V5vnnnsuxpXPjtNxj3v//ffN9ddfb6qqqszNN98cm2IjxOmYf/nLXxpJ5j//8z+N3++fOC5fvhzjymcnnPf6S1/6klm6dKlpaWkxXV1d5l//9V/Nm2++GcOqZ8fpmN9///2Q97inp8fk5OSYurq62BY+S07H3draatLS0sz3v/99c+7cOdPa2mpuuukms2bNGsfXJoxEQXl5uampqQlp+9znPme2b9/+ieeuWLEiYcPIbMY9rqioyNTX10e6tKiJxJj/5E/+xKxfvz7SpUVVuONeu3at+du//VtTV1eXcGHE6ZjHw8j//u//xqC66HE67p///OfG6/WaixcvxqK8qJjtv+tXXnnFuFwu89///d/RKC9qnI777/7u78z1118f0vb000+bBQsWOL420zQRdunSJZ08eVJVVVUh7VVVVTp+/LilqqIvEuMeHR3V0NCQcnJyolFixEVizO3t7Tp+/LhWrFgRjRKjItxxP//883rnnXdUV1cX7RIjbjbv9a233iqfz6c77rhDv/zlL6NZZsSFM+5XX31VZWVl+ta3vqXrrrtON954ox5++GH97ne/i0XJsxaJf9d79uzRnXfeqYKCgmiUGBXhjLuyslLnz5/XkSNHZIzRe++9p5/+9Ke65557HF8/Ib4oL5H09/crGAwqLy8vpD0vL0+9vb2Wqoq+SIz7O9/5jj788EPde++90Sgx4mYz5gULFuh//ud/dPnyZT322GN64IEHollqRIUz7t/85jfavn27WltblZ6eeL92whmzz+fT7t27VVpaqpGREf34xz/WHXfcoddff11//Md/HIuyZy2ccZ87d07Hjh2Tx+PRK6+8ov7+fn31q1/VwMBAQjw3MtvfZX6/Xz//+c914MCBaJUYFeGMu7KyUvv379fatWs1PDysy5cv60tf+pJ+8IMfOL5+4v1WSBAulyvktTFmUlsyCnfcBw8e1GOPPaZ/+qd/Um5ubrTKi4pwxtza2qoPPvhAv/rVr7R9+3Z99rOf1Z/92Z9Fs8yIm+m4g8Gg1q1bp/r6et14442xKi8qnLzXixcv1uLFiydeV1RUqKenR9/+9rcTJoyMczLu0dFRuVwu7d+/f+LbWp966il9+ctf1q5duzRnzpyo1xsJ4f4ue+GFF3TttddqzZo1UaosupyMu7OzU1u3btWjjz6qu+66S36/X4888ohqamq0Z88eR9cljETYvHnz5Ha7JyXJvr6+SYkzmcxm3IcOHdLmzZv1k5/8RHfeeWc0y4yo2Yy5sLBQkvRHf/RHeu+99/TYY48lTBhxOu6hoSGdOHFC7e3t+vrXvy5p7APLGKP09HS99tpruv3222NSe7gi9e/6C1/4gvbt2xfp8qImnHH7fD5dd911IV8bv2TJEhljdP78ed1www1RrXm2ZvNeG2O0d+9ebdiwQRkZGdEsM+LCGXdDQ4OWLVumRx55RJL0+c9/Xtdcc42WL1+uJ554Qj6fb8bX55mRCMvIyFBpaalaWlpC2ltaWlRZWWmpqugLd9wHDx7UfffdpwMHDoQ1z2hTpN5rY4xGRkYiXV7UOB13dna2fv3rX+v06dMTR01NjRYvXqzTp09r6dKlsSo9bJF6r9vb2x39grYtnHEvW7ZMFy5c0AcffDDRdvbsWaWlpWnBggVRrTcSZvNeHz16VP/1X/+lzZs3R7PEqAhn3B999JHS0kJjhNvtljT2e80Rx4+84hONL4/as2eP6ezsNNu2bTPXXHPNxJPV27dvNxs2bAg5p7293bS3t5vS0lKzbt06097ebt5++20b5YfN6bgPHDhg0tPTza5du0KWxb3//vu2huCY0zE/88wz5tVXXzVnz541Z8+eNXv37jXZ2dlm586dtoYQlnD+jl8pEVfTOB3zd7/7XfPKK6+Ys2fPmo6ODrN9+3Yjybz00ku2hhAWp+MeGhoyCxYsMF/+8pfN22+/bY4ePWpuuOEG88ADD9gagmPh/v1ev369Wbp0aazLjRin437++edNenq6aWxsNO+88445duyYKSsrM+Xl5Y6vTRiJkl27dpmCggKTkZFhSkpKzNGjRyd+tmnTJrNixYqQ/pImHQUFBbEtOgKcjHvFihVTjnvTpk2xL3wWnIz56aefNjfddJO5+uqrTXZ2trn11ltNY2OjCQaDFiqfHad/x6+UiGHEGGdjfvLJJ82iRYuMx+Mxf/iHf2huu+0288///M8Wqp49p+/1mTNnzJ133mnmzJljFixYYGpra81HH30U46pnx+mY33//fTNnzhyze/fuGFcaWU7H/fTTT5uioiIzZ84c4/P5zJ//+Z+b8+fPO76uyxin91IAAAAih2dGAACAVYQRAABgFWEEAABYRRgBAABWEUYAAIBVhBEAAGAVYQQAAFhFGAEAAFYRRgAAgFWEEQAAYBVhBAAAWEUYAQAAVv0/s+IfGSmJreoAAAAASUVORK5CYII=", "text/plain": [ "
" ] @@ -1583,7 +1581,7 @@ "\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 41, @@ -1606,7 +1604,7 @@ "\n", "To access prebuilt nodes we can `.create` them. This works both from the workflow class _and_ from a workflow instance.\n", "\n", - "There are a few of nodes that are always available under the `Workflow.create.standard` namespace, otherwise we need to register new node packages. This is done with the `register` method, which takes the domain (namespace/key/attribute/whatever you want to call it) under which you want to register the new nodes, and a string import path to a module that has a list of nodes under the name `nodes`, i.e. the module has the property `nodes: list[pyiron_workflow.nodes.Node]`. (You can also register a package with arbitrary nesting, as long as each non-package sub-module has such a `nodes` attribute; Cf. the atomistics demo notebook for an example of this.) (This API is subject to change, as we work to improve usability and bring node packages more and more in line with \"FAIR\" principles.)\n", + "There are a few of nodes that are always available under the `Workflow.create.standard` namespace, otherwise we need to register new node packages. This is done with the `register` method, which takes the domain (namespace/key/attribute/whatever you want to call it) under which you want to register the new nodes, and a string import path to a module that has a list of nodes under the name `nodes`, i.e. the module has the property `nodes: list[pyiron_workflow.nodes.Node]`. (You can also register a package with arbitrary nesting, where each non-package sub-module (i.e. a leaf .py file) with a `nodes` attribute will attempt to read those nodes as a package. Cf. the atomistics demo notebook for an example of this.) (This API is subject to change, as we work to improve usability and bring node packages more and more in line with \"FAIR\" principles.)\n", "\n", "You can make your own `.py` files with nodes for reuse this way, but `pyiron_workflow` also comes with a couple of packages. In this example we'll use atomistics and plotting:" ] @@ -1617,18 +1615,10 @@ "id": "ae500d5e-e55b-432c-8b5f-d5892193cdf5", "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/h5py/__init__.py:36: UserWarning: h5py is running against HDF5 1.14.3 when it was built against 1.14.2, this may cause problems\n", - " _warn((\"h5py is running against HDF5 {0} when it was built against {1}, \"\n" - ] - }, { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "79f71f503b1540ffafcc45934f0e1956", + "model_id": "49b823d50af54026a277c866f96814fb", "version_major": 2, "version_minor": 0 }, @@ -1637,17 +1627,25 @@ "metadata": {}, "output_type": "display_data" }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/work/pyiron/pyiron_atomistics/pyiron_atomistics/lammps/base.py:294: UserWarning: No potential set via job.potential - use default potential, 1995--Angelo-J-E--Ni-Al-H--LAMMPS--ipr1\n", + " warnings.warn(\n" + ] + }, { "name": "stdout", "output_type": "stream", "text": [ - "The job JUSTAJOBNAME was saved and received the ID: 9562\n" + "The job JUSTAJOBNAME was saved and received the ID: 9563\n" ] }, { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 42, @@ -1666,8 +1664,8 @@ } ], "source": [ - "wf.register(\"pyiron_atomistics\", \"pyiron_workflow.node_library.pyiron_atomistics\")\n", - "wf.register(\"plotting\", \"pyiron_workflow.node_library.plotting\")\n", + "wf.register(\"pyiron_workflow.node_library.pyiron_atomistics\", \"pyiron_atomistics\")\n", + "wf.register(\"pyiron_workflow.node_library.plotting\", \"plotting\")\n", "\n", "wf = Workflow(\"with_prebuilt\")\n", "\n", @@ -1712,27 +1710,27 @@ "clusterwith_prebuilt\n", "\n", "with_prebuilt: Workflow\n", - "\n", - "clusterwith_prebuiltInputs\n", + "\n", + "clusterwith_prebuiltOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterwith_prebuiltOutputs\n", + "\n", + "clusterwith_prebuiltInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Inputs\n", "\n", "\n", "\n", @@ -1907,7 +1905,7 @@ "\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 43, @@ -1965,7 +1963,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", " warn(\n" ] }, @@ -2256,27 +2254,27 @@ "\n", "min_phase2: LammpsMinimize\n", "\n", - "\n", - "clusterphase_preferencemin_phase2Outputs\n", + "\n", + "clusterphase_preferencemin_phase2Inputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterphase_preferencemin_phase2Inputs\n", + "\n", + "clusterphase_preferencemin_phase2Outputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Outputs\n", "\n", "\n", "clusterphase_preferencee1\n", @@ -3096,7 +3094,7 @@ "\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 49, @@ -3114,12 +3112,34 @@ "id": "b51bef25-86c5-4d57-80c1-ab733e703caf", "metadata": {}, "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/work/pyiron/pyiron_atomistics/pyiron_atomistics/lammps/base.py:294: UserWarning: No potential set via job.potential - use default potential, 1995--Angelo-J-E--Ni-Al-H--LAMMPS--ipr1\n", + " warnings.warn(\n" + ] + }, { "name": "stdout", "output_type": "stream", "text": [ - "The job JUSTAJOBNAME was saved and received the ID: 9562\n", - "The job JUSTAJOBNAME was saved and received the ID: 9562\n", + "The job JUSTAJOBNAME was saved and received the ID: 9563\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/work/pyiron/pyiron_atomistics/pyiron_atomistics/lammps/base.py:294: UserWarning: No potential set via job.potential - use default potential, 1995--Angelo-J-E--Ni-Al-H--LAMMPS--ipr1\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The job JUSTAJOBNAME was saved and received the ID: 9563\n", "Al: E(hcp) - E(fcc) = 1.17 eV/atom\n" ] } @@ -3139,16 +3159,32 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", - " warn(\n" + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_atomistics/pyiron_atomistics/lammps/base.py:294: UserWarning: No potential set via job.potential - use default potential, 1997--Liu-X-Y--Al-Mg--LAMMPS--ipr1\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The job JUSTAJOBNAME was saved and received the ID: 9563\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/work/pyiron/pyiron_atomistics/pyiron_atomistics/lammps/base.py:294: UserWarning: No potential set via job.potential - use default potential, 1997--Liu-X-Y--Al-Mg--LAMMPS--ipr1\n", + " warnings.warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "The job JUSTAJOBNAME was saved and received the ID: 9562\n", - "The job JUSTAJOBNAME was saved and received the ID: 9562\n", + "The job JUSTAJOBNAME was saved and received the ID: 9563\n", "Mg: E(hcp) - E(fcc) = -4.54 eV/atom\n" ] } @@ -3180,15 +3216,15 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel job was not connected to job, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel job was not connected to job, andthus could not disconnect from it.\n", " warn(\n", - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", " warn(\n", - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel element was not connected to user_input, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel element was not connected to user_input, andthus could not disconnect from it.\n", " warn(\n", - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel structure was not connected to obj, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel structure was not connected to obj, andthus could not disconnect from it.\n", " warn(\n", - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel energy was not connected to obj, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel energy was not connected to obj, andthus could not disconnect from it.\n", " warn(\n" ] } @@ -3218,16 +3254,32 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", - " warn(\n" + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_atomistics/pyiron_atomistics/lammps/base.py:294: UserWarning: No potential set via job.potential - use default potential, 1995--Angelo-J-E--Ni-Al-H--LAMMPS--ipr1\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The job JUSTAJOBNAME was saved and received the ID: 9563\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/work/pyiron/pyiron_atomistics/pyiron_atomistics/lammps/base.py:294: UserWarning: No potential set via job.potential - use default potential, 1995--Angelo-J-E--Ni-Al-H--LAMMPS--ipr1\n", + " warnings.warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "The job JUSTAJOBNAME was saved and received the ID: 9562\n", - "The job JUSTAJOBNAME was saved and received the ID: 9562\n", + "The job JUSTAJOBNAME was saved and received the ID: 9563\n", "Al: E(hcp) - E(fcc) = -5.57 eV/atom\n" ] } @@ -3248,16 +3300,32 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", - " warn(\n" + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_atomistics/pyiron_atomistics/lammps/base.py:294: UserWarning: No potential set via job.potential - use default potential, 1995--Angelo-J-E--Ni-Al-H--LAMMPS--ipr1\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The job JUSTAJOBNAME was saved and received the ID: 9563\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/work/pyiron/pyiron_atomistics/pyiron_atomistics/lammps/base.py:294: UserWarning: No potential set via job.potential - use default potential, 1995--Angelo-J-E--Ni-Al-H--LAMMPS--ipr1\n", + " warnings.warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ - "The job JUSTAJOBNAME was saved and received the ID: 9562\n", - "The job JUSTAJOBNAME was saved and received the ID: 9562\n", + "The job JUSTAJOBNAME was saved and received the ID: 9563\n", "Al: E(hcp) - E(fcc) = 0.03 eV/atom\n" ] } @@ -3309,7 +3377,7 @@ "output_type": "stream", "text": [ "None 1\n", - " \n" + " \n" ] } ], @@ -3391,7 +3459,7 @@ "output_type": "stream", "text": [ "None 1\n", - " \n", + " \n", "Finally 5\n", "b (Add) output single-value: 6\n" ] @@ -3453,7 +3521,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "6.013545583002269\n" + "6.019378479017178\n" ] } ], @@ -3485,7 +3553,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "2.503649155027233\n" + "3.3633984430052806\n" ] } ], @@ -3626,9 +3694,9 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel run was not connected to true, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to true, andthus could not disconnect from it.\n", " warn(\n", - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", " warn(\n" ] } @@ -3709,11 +3777,14 @@ "name": "stdout", "output_type": "stream", "text": [ - "0.684 > 0.2\n", - "0.598 > 0.2\n", - "0.846 > 0.2\n", - "0.021 <= 0.2\n", - "Finally 0.021\n" + "0.879 > 0.2\n", + "0.214 > 0.2\n", + "0.550 > 0.2\n", + "0.477 > 0.2\n", + "0.826 > 0.2\n", + "0.288 > 0.2\n", + "0.028 <= 0.2\n", + "Finally 0.028\n" ] } ], diff --git a/notebooks/phonopy_wf.ipynb b/notebooks/phonopy_wf.ipynb index d995564f..facd4ca2 100644 --- a/notebooks/phonopy_wf.ipynb +++ b/notebooks/phonopy_wf.ipynb @@ -18,8 +18,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 1.24 s, sys: 305 ms, total: 1.55 s\n", - "Wall time: 578 ms\n" + "CPU times: user 585 ms, sys: 216 ms, total: 800 ms\n", + "Wall time: 1.21 s\n" ] } ], @@ -49,7 +49,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "742cca50b5ba4092b1312488fb336700", + "model_id": "6eef0fc5d4a44051ad0d55ce2f8fdc7a", "version_major": 2, "version_minor": 0 }, @@ -62,15 +62,15 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 5.63 s, sys: 1.06 s, total: 6.69 s\n", - "Wall time: 16.8 s\n" + "CPU times: user 1.51 s, sys: 734 ms, total: 2.25 s\n", + "Wall time: 3.59 s\n" ] } ], "source": [ "%%time\n", "wf = Workflow('phonopy')\n", - "wf.register('atomistic', 'pyiron_workflow.node_library.atomistic')" + "wf.register('pyiron_workflow.node_library.atomistic', domain='atomistic')" ] }, { @@ -144,818 +144,818 @@ "\n", "\n", - "\n", - "\n", + "\n", + "\n", "clusterbulk_rotation\n", - "\n", - "bulk_rotation: bulk_rotation\n", - "\n", - "clusterbulk_rotationangle\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "angle: UserInput\n", - "\n", - "\n", - "clusterbulk_rotationangleInputs\n", + "\n", + "bulk_rotation: bulk_rotation\n", + "\n", + "clusterbulk_rotationInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationangleOutputs\n", + "\n", + "clusterbulk_rotationOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationstructure\n", + "\n", + "clusterbulk_rotationname\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "structure: bulk\n", + "\n", + "name: UserInput\n", "\n", - "\n", - "clusterbulk_rotationstructureInputs\n", + "\n", + "clusterbulk_rotationnameInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationstructureOutputs\n", + "\n", + "clusterbulk_rotationnameOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationrepeat\n", + "\n", + "clusterbulk_rotationcubic\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "repeat: repeat\n", + "\n", + "cubic: UserInput\n", "\n", - "\n", - "clusterbulk_rotationrepeatInputs\n", + "\n", + "clusterbulk_rotationcubicInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationrepeatOutputs\n", + "\n", + "clusterbulk_rotationcubicOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationrotate\n", + "\n", + "clusterbulk_rotationrepeat_cell\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "rotate: rotate_axis_angle\n", + "\n", + "repeat_cell: UserInput\n", "\n", - "\n", - "clusterbulk_rotationrotateInputs\n", + "\n", + "clusterbulk_rotationrepeat_cellInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationrotateOutputs\n", + "\n", + "clusterbulk_rotationrepeat_cellOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationInputs\n", + "\n", + "clusterbulk_rotationangle\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "angle: UserInput\n", + "\n", + "\n", + "clusterbulk_rotationangleInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationOutputs\n", + "\n", + "clusterbulk_rotationangleOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationcubic\n", + "\n", + "clusterbulk_rotationaxis\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "cubic: UserInput\n", + "\n", + "axis: UserInput\n", "\n", - "\n", - "clusterbulk_rotationcubicInputs\n", + "\n", + "clusterbulk_rotationaxisInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationcubicOutputs\n", + "\n", + "clusterbulk_rotationaxisOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationrepeat_cell\n", + "\n", + "clusterbulk_rotationstructure\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "repeat_cell: UserInput\n", + "\n", + "structure: bulk\n", "\n", - "\n", - "clusterbulk_rotationrepeat_cellInputs\n", + "\n", + "clusterbulk_rotationstructureInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationrepeat_cellOutputs\n", + "\n", + "clusterbulk_rotationstructureOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationname\n", + "\n", + "clusterbulk_rotationrepeat\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "name: UserInput\n", + "\n", + "repeat: repeat\n", "\n", - "\n", - "clusterbulk_rotationnameInputs\n", + "\n", + "clusterbulk_rotationrepeatInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationnameOutputs\n", + "\n", + "clusterbulk_rotationrepeatOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationaxis\n", + "\n", + "clusterbulk_rotationrotate\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "axis: UserInput\n", + "\n", + "rotate: rotate_axis_angle\n", "\n", - "\n", - "clusterbulk_rotationaxisInputs\n", + "\n", + "clusterbulk_rotationrotateInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationaxisOutputs\n", + "\n", + "clusterbulk_rotationrotateOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "\n", "clusterbulk_rotationInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationInputsname\n", - "\n", - "name\n", + "\n", + "name\n", "\n", "\n", "\n", "clusterbulk_rotationnameInputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationInputsname->clusterbulk_rotationnameInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationInputscubic\n", - "\n", - "cubic: bool\n", + "\n", + "cubic: bool\n", "\n", "\n", "\n", "clusterbulk_rotationcubicInputsuser_input\n", - "\n", - "user_input: bool\n", + "\n", + "user_input: bool\n", "\n", "\n", "\n", "clusterbulk_rotationInputscubic->clusterbulk_rotationcubicInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationInputsrepeat_cell\n", - "\n", - "repeat_cell\n", + "\n", + "repeat_cell\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellInputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationInputsrepeat_cell->clusterbulk_rotationrepeat_cellInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationInputsangle\n", - "\n", - "angle\n", + "\n", + "angle\n", "\n", "\n", "\n", "clusterbulk_rotationangleInputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationInputsangle->clusterbulk_rotationangleInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationInputsaxis\n", - "\n", - "axis\n", + "\n", + "axis\n", "\n", "\n", "\n", "clusterbulk_rotationaxisInputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationInputsaxis->clusterbulk_rotationaxisInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationOutputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", "\n", "clusterbulk_rotationnameInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationnameOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationnameInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationnameOutputsran->clusterbulk_rotationstructureInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationnameOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsname\n", - "\n", - "name\n", + "\n", + "name\n", "\n", "\n", "\n", "clusterbulk_rotationnameOutputsuser_input->clusterbulk_rotationstructureInputsname\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationcubicInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationcubicOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationcubicInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationcubicOutputsran->clusterbulk_rotationstructureInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationcubicOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputscubic\n", - "\n", - "cubic\n", + "\n", + "cubic\n", "\n", "\n", "\n", "clusterbulk_rotationcubicOutputsuser_input->clusterbulk_rotationstructureInputscubic\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellOutputsran->clusterbulk_rotationrepeatInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatInputsrepeat_scalar\n", - "\n", - "repeat_scalar: int\n", + "\n", + "repeat_scalar: int\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellOutputsuser_input->clusterbulk_rotationrepeatInputsrepeat_scalar\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationangleInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationangleOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationangleInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationangleOutputsran->clusterbulk_rotationrotateInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationangleOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsangle\n", - "\n", - "angle\n", + "\n", + "angle\n", "\n", "\n", "\n", "clusterbulk_rotationangleOutputsuser_input->clusterbulk_rotationrotateInputsangle\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationaxisInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationaxisOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationaxisInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationaxisOutputsran->clusterbulk_rotationrotateInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationaxisOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsaxis\n", - "\n", - "axis: list\n", + "\n", + "axis: list\n", "\n", "\n", "\n", "clusterbulk_rotationaxisOutputsuser_input->clusterbulk_rotationrotateInputsaxis\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationstructureOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputscrystalstructure\n", - "\n", - "crystalstructure\n", + "\n", + "crystalstructure\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsa\n", - "\n", - "a\n", + "\n", + "a\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsc\n", - "\n", - "c\n", + "\n", + "c\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputscovera\n", - "\n", - "covera\n", + "\n", + "covera\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsu\n", - "\n", - "u\n", + "\n", + "u\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsorthorhombic\n", - "\n", - "orthorhombic\n", + "\n", + "orthorhombic\n", "\n", "\n", "\n", "clusterbulk_rotationstructureOutputsran->clusterbulk_rotationrepeatInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationstructureOutputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatInputsstructure\n", - "\n", - "structure: Atoms\n", + "\n", + "structure: Atoms\n", "\n", "\n", "\n", "clusterbulk_rotationstructureOutputsstructure->clusterbulk_rotationrepeatInputsstructure\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatOutputsran->clusterbulk_rotationrotateInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatOutputsstructure\n", - "\n", - "structure: Atoms\n", + "\n", + "structure: Atoms\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsstructure\n", - "\n", - "structure: Atoms\n", + "\n", + "structure: Atoms\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatOutputsstructure->clusterbulk_rotationrotateInputsstructure\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationrotateOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputscenter\n", - "\n", - "center\n", + "\n", + "center\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsrotate_cell\n", - "\n", - "rotate_cell: bool\n", + "\n", + "rotate_cell: bool\n", "\n", "\n", "\n", "clusterbulk_rotationrotateOutputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", "\n", "clusterbulk_rotationrotateOutputsstructure->clusterbulk_rotationOutputsstructure\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 6, @@ -984,7 +984,7 @@ "value": "'Al'" }, "text/plain": [ - "" + "" ] }, "execution_count": 7, @@ -1071,818 +1071,818 @@ "\n", "\n", - "\n", - "\n", + "\n", + "\n", "clusterbulk_rotation\n", - "\n", - "bulk_rotation: bulk_rotation\n", + "\n", + "bulk_rotation: bulk_rotation\n", "\n", "clusterbulk_rotationInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", "\n", "clusterbulk_rotationOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationcubic\n", + "\n", + "clusterbulk_rotationname\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "cubic: UserInput\n", + "\n", + "name: UserInput\n", "\n", - "\n", - "clusterbulk_rotationcubicInputs\n", + "\n", + "clusterbulk_rotationnameInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationcubicOutputs\n", + "\n", + "clusterbulk_rotationnameOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationrepeat_cell\n", + "\n", + "clusterbulk_rotationcubic\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "repeat_cell: UserInput\n", + "\n", + "cubic: UserInput\n", "\n", - "\n", - "clusterbulk_rotationrepeat_cellInputs\n", + "\n", + "clusterbulk_rotationcubicInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationrepeat_cellOutputs\n", + "\n", + "clusterbulk_rotationcubicOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationangle\n", + "\n", + "clusterbulk_rotationrepeat_cell\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "angle: UserInput\n", + "\n", + "repeat_cell: UserInput\n", "\n", - "\n", - "clusterbulk_rotationangleInputs\n", + "\n", + "clusterbulk_rotationrepeat_cellInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationangleOutputs\n", + "\n", + "clusterbulk_rotationrepeat_cellOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationstructure\n", + "\n", + "clusterbulk_rotationangle\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "structure: bulk\n", + "\n", + "angle: UserInput\n", "\n", - "\n", - "clusterbulk_rotationstructureInputs\n", + "\n", + "clusterbulk_rotationangleInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationstructureOutputs\n", + "\n", + "clusterbulk_rotationangleOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationrepeat\n", + "\n", + "clusterbulk_rotationaxis\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "repeat: repeat\n", + "\n", + "axis: UserInput\n", "\n", - "\n", - "clusterbulk_rotationrepeatInputs\n", + "\n", + "clusterbulk_rotationaxisInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationrepeatOutputs\n", + "\n", + "clusterbulk_rotationaxisOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationrotate\n", + "\n", + "clusterbulk_rotationstructure\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "rotate: rotate_axis_angle\n", + "\n", + "structure: bulk\n", "\n", - "\n", - "clusterbulk_rotationrotateInputs\n", + "\n", + "clusterbulk_rotationstructureInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationrotateOutputs\n", + "\n", + "clusterbulk_rotationstructureOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationname\n", + "\n", + "clusterbulk_rotationrepeat\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "name: UserInput\n", + "\n", + "repeat: repeat\n", "\n", - "\n", - "clusterbulk_rotationnameInputs\n", + "\n", + "clusterbulk_rotationrepeatInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationnameOutputs\n", + "\n", + "clusterbulk_rotationrepeatOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterbulk_rotationaxis\n", + "\n", + "clusterbulk_rotationrotate\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "axis: UserInput\n", + "\n", + "rotate: rotate_axis_angle\n", "\n", - "\n", - "clusterbulk_rotationaxisInputs\n", + "\n", + "clusterbulk_rotationrotateInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterbulk_rotationaxisOutputs\n", + "\n", + "clusterbulk_rotationrotateOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "\n", "clusterbulk_rotationInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationInputsname\n", - "\n", - "name\n", + "\n", + "name\n", "\n", "\n", "\n", "clusterbulk_rotationnameInputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationInputsname->clusterbulk_rotationnameInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationInputscubic\n", - "\n", - "cubic: bool\n", + "\n", + "cubic: bool\n", "\n", "\n", "\n", "clusterbulk_rotationcubicInputsuser_input\n", - "\n", - "user_input: bool\n", + "\n", + "user_input: bool\n", "\n", "\n", "\n", "clusterbulk_rotationInputscubic->clusterbulk_rotationcubicInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationInputsrepeat_cell\n", - "\n", - "repeat_cell\n", + "\n", + "repeat_cell\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellInputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationInputsrepeat_cell->clusterbulk_rotationrepeat_cellInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationInputsangle\n", - "\n", - "angle\n", + "\n", + "angle\n", "\n", "\n", "\n", "clusterbulk_rotationangleInputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationInputsangle->clusterbulk_rotationangleInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationInputsaxis\n", - "\n", - "axis\n", + "\n", + "axis\n", "\n", "\n", "\n", "clusterbulk_rotationaxisInputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationInputsaxis->clusterbulk_rotationaxisInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationOutputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", "\n", "clusterbulk_rotationnameInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationnameOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationnameInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationnameOutputsran->clusterbulk_rotationstructureInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationnameOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsname\n", - "\n", - "name\n", + "\n", + "name\n", "\n", "\n", "\n", "clusterbulk_rotationnameOutputsuser_input->clusterbulk_rotationstructureInputsname\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationcubicInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationcubicOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationcubicInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationcubicOutputsran->clusterbulk_rotationstructureInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationcubicOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputscubic\n", - "\n", - "cubic\n", + "\n", + "cubic\n", "\n", "\n", "\n", "clusterbulk_rotationcubicOutputsuser_input->clusterbulk_rotationstructureInputscubic\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellOutputsran->clusterbulk_rotationrepeatInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatInputsrepeat_scalar\n", - "\n", - "repeat_scalar: int\n", + "\n", + "repeat_scalar: int\n", "\n", "\n", "\n", "clusterbulk_rotationrepeat_cellOutputsuser_input->clusterbulk_rotationrepeatInputsrepeat_scalar\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationangleInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationangleOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationangleInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationangleOutputsran->clusterbulk_rotationrotateInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationangleOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsangle\n", - "\n", - "angle\n", + "\n", + "angle\n", "\n", "\n", "\n", "clusterbulk_rotationangleOutputsuser_input->clusterbulk_rotationrotateInputsangle\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationaxisInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationaxisOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationaxisInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterbulk_rotationaxisOutputsran->clusterbulk_rotationrotateInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationaxisOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsaxis\n", - "\n", - "axis: list\n", + "\n", + "axis: list\n", "\n", "\n", "\n", "clusterbulk_rotationaxisOutputsuser_input->clusterbulk_rotationrotateInputsaxis\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationstructureOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputscrystalstructure\n", - "\n", - "crystalstructure\n", + "\n", + "crystalstructure\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsa\n", - "\n", - "a\n", + "\n", + "a\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsc\n", - "\n", - "c\n", + "\n", + "c\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputscovera\n", - "\n", - "covera\n", + "\n", + "covera\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsu\n", - "\n", - "u\n", + "\n", + "u\n", "\n", "\n", "\n", "clusterbulk_rotationstructureInputsorthorhombic\n", - "\n", - "orthorhombic\n", + "\n", + "orthorhombic\n", "\n", "\n", "\n", "clusterbulk_rotationstructureOutputsran->clusterbulk_rotationrepeatInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationstructureOutputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatInputsstructure\n", - "\n", - "structure: Atoms\n", + "\n", + "structure: Atoms\n", "\n", "\n", "\n", "clusterbulk_rotationstructureOutputsstructure->clusterbulk_rotationrepeatInputsstructure\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatOutputsran->clusterbulk_rotationrotateInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatOutputsstructure\n", - "\n", - "structure: Atoms\n", + "\n", + "structure: Atoms\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsstructure\n", - "\n", - "structure: Atoms\n", + "\n", + "structure: Atoms\n", "\n", "\n", "\n", "clusterbulk_rotationrepeatOutputsstructure->clusterbulk_rotationrotateInputsstructure\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterbulk_rotationrotateOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputscenter\n", - "\n", - "center\n", + "\n", + "center\n", "\n", "\n", "\n", "clusterbulk_rotationrotateInputsrotate_cell\n", - "\n", - "rotate_cell: bool\n", + "\n", + "rotate_cell: bool\n", "\n", "\n", "\n", "clusterbulk_rotationrotateOutputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", "\n", "clusterbulk_rotationrotateOutputsstructure->clusterbulk_rotationOutputsstructure\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 9, @@ -1954,10 +1954,12 @@ " atoms=wf.structure.outputs.structure,\n", " engine=wf.engine,\n", " )\n", + " \n", + " wf.phonopy_input = wf.create.atomistic.property.phonons.PhonopyParameters(distance=displacement)\n", "\n", " wf.phonopy = wf.create.atomistic.property.phonons.create_phonopy(\n", " structure=wf.relaxed_structure.outputs.structure,\n", - " parameters=InputPhonopyGenerateSupercells(distance=displacement.run()),\n", + " parameters=wf.phonopy_input,\n", " engine=wf.engine,\n", " max_workers=max_workers,\n", " )\n", @@ -1998,10 +2000,11 @@ "name": "stdout", "output_type": "stream", "text": [ - "energy: 0.8013167095855369 0.7996059979144441\n", + "energy: 0.8013167095856435 0.799605997914508\n", "max_workers: 1\n", - "CPU times: user 6.96 s, sys: 296 ms, total: 7.25 s\n", - "Wall time: 2.75 s\n" + "WARNING: 3 imaginary modes exist\n", + "CPU times: user 14.1 s, sys: 319 ms, total: 14.4 s\n", + "Wall time: 8.48 s\n" ] } ], @@ -2026,1524 +2029,1664 @@ "\n", "\n", - "\n", - "\n", + "\n", + "\n", "clusterrun_phonopy\n", - "\n", - "run_phonopy: run_phonopy\n", - "\n", - "clusterrun_phonopyengine\n", + "\n", + "run_phonopy: run_phonopy\n", + "\n", + "clusterrun_phonopydisplacement\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "engine: EMT\n", - "\n", - "\n", - "clusterrun_phonopyengineInputs\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "Inputs\n", + "\n", + "displacement: UserInput\n", "\n", - "\n", - "clusterrun_phonopyengineOutputs\n", + "\n", + "clusterrun_phonopydisplacementOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopyInputs\n", + "\n", + "clusterrun_phonopydisplacementInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_final\n", + "\n", + "clusterrun_phonopymax_workers\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "relaxed_structure__out_GetAttr_final: GetAttr\n", + "\n", + "max_workers: UserInput\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalInputs\n", + "\n", + "clusterrun_phonopymax_workersInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalOutputs\n", + "\n", + "clusterrun_phonopymax_workersOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial\n", + "\n", + "clusterrun_phonopyengine\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "relaxed_structure__out_GetAttr_initial: GetAttr\n", + "\n", + "engine: EMT\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialInputs\n", + "\n", + "clusterrun_phonopyengineInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialOutputs\n", + "\n", + "clusterrun_phonopyengineOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopyphonopy__out_GetItem_energies\n", + "\n", + "clusterrun_phonopyInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterrun_phonopyOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterrun_phonopyelement\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "phonopy__out_GetItem_energies: GetItem\n", + "\n", + "element: UserInput\n", "\n", - "\n", - "clusterrun_phonopyphonopy__out_GetItem_energiesInputs\n", + "\n", + "clusterrun_phonopyelementInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopyphonopy__out_GetItem_energiesOutputs\n", + "\n", + "clusterrun_phonopyelementOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopymax_workers\n", + "\n", + "clusterrun_phonopycell_size\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "max_workers: UserInput\n", + "\n", + "cell_size: UserInput\n", "\n", - "\n", - "clusterrun_phonopymax_workersInputs\n", + "\n", + "clusterrun_phonopycell_sizeInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopymax_workersOutputs\n", + "\n", + "clusterrun_phonopycell_sizeOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterrun_phonopyvacancy_index\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "vacancy_index: UserInput\n", + "\n", + "\n", + "clusterrun_phonopyvacancy_indexInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterrun_phonopyvacancy_indexOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "clusterrun_phonopystructure\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "structure: cubic_bulk_cell\n", + "\n", + "structure: cubic_bulk_cell\n", "\n", "\n", "clusterrun_phonopystructureInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", "\n", "clusterrun_phonopystructureOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "clusterrun_phonopyrelaxed_structure\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "relaxed_structure: minimize\n", + "\n", + "relaxed_structure: minimize\n", "\n", "\n", "clusterrun_phonopyrelaxed_structureInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", "\n", "clusterrun_phonopyrelaxed_structureOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", - "clusterrun_phonopyphonopy\n", + "clusterrun_phonopyphonopy_input\n", "\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", - "phonopy: create_phonopy\n", + "\n", + "phonopy_input: PhonopyParameters\n", "\n", "\n", - "clusterrun_phonopyphonopyInputs\n", + "clusterrun_phonopyphonopy_inputInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", "\n", - "clusterrun_phonopyphonopyOutputs\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "Outputs\n", - "\n", - "\n", - "clusterrun_phonopyOutputs\n", + "clusterrun_phonopyphonopy_inputOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopyelement\n", + "\n", + "clusterrun_phonopyphonopy\n", "\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", - "element: UserInput\n", + "\n", + "phonopy: create_phonopy\n", "\n", - "\n", - "clusterrun_phonopyelementInputs\n", + "\n", + "clusterrun_phonopyphonopyInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopyelementOutputs\n", + "\n", + "clusterrun_phonopyphonopyOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopycell_size\n", + "\n", + "clusterrun_phonopycheck_consistency\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "cell_size: UserInput\n", + "\n", + "check_consistency: check_consistency\n", "\n", - "\n", - "clusterrun_phonopycell_sizeInputs\n", + "\n", + "clusterrun_phonopycheck_consistencyInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopycell_sizeOutputs\n", + "\n", + "clusterrun_phonopycheck_consistencyOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopyvacancy_index\n", + "\n", + "clusterrun_phonopytotal_dos\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "vacancy_index: UserInput\n", + "\n", + "total_dos: get_total_dos\n", "\n", - "\n", - "clusterrun_phonopyvacancy_indexInputs\n", + "\n", + "clusterrun_phonopytotal_dosInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopyvacancy_indexOutputs\n", + "\n", + "clusterrun_phonopytotal_dosOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopycheck_consistency\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_final\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "check_consistency: check_consistency\n", + "\n", + "relaxed_structure__out_GetAttr_final: GetAttr\n", "\n", - "\n", - "clusterrun_phonopycheck_consistencyInputs\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopycheck_consistencyOutputs\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopytotal_dos\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energy\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "total_dos: get_total_dos\n", + "\n", + "relaxed_structure__out_GetAttr_final__getattr_GetAttr_energy: GetAttr\n", "\n", - "\n", - "clusterrun_phonopytotal_dosInputs\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopytotal_dosOutputs\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopydisplacement\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "displacement: UserInput\n", + "\n", + "relaxed_structure__out_GetAttr_initial: GetAttr\n", "\n", - "\n", - "clusterrun_phonopydisplacementInputs\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopydisplacementOutputs\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energy\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energy\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "relaxed_structure__out_GetAttr_final__getattr_GetAttr_energy: GetAttr\n", + "\n", + "relaxed_structure__out_GetAttr_initial__getattr_GetAttr_energy: GetAttr\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyInputs\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyOutputs\n", + "\n", + "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energy\n", + "\n", + "clusterrun_phonopyphonopy__out_GetItem_energies\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "relaxed_structure__out_GetAttr_initial__getattr_GetAttr_energy: GetAttr\n", + "\n", + "phonopy__out_GetItem_energies: GetItem\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyInputs\n", + "\n", + "clusterrun_phonopyphonopy__out_GetItem_energiesInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyOutputs\n", + "\n", + "clusterrun_phonopyphonopy__out_GetItem_energiesOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "\n", "clusterrun_phonopyInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterrun_phonopyOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterrun_phonopyInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterrun_phonopyInputselement\n", - "\n", - "element: str\n", + "\n", + "element: str\n", "\n", "\n", "\n", "clusterrun_phonopyelementInputsuser_input\n", - "\n", - "user_input: str\n", + "\n", + "user_input: str\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyInputselement->clusterrun_phonopyelementInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyInputscell_size\n", - "\n", - "cell_size: int\n", + "\n", + "cell_size: int\n", "\n", "\n", "\n", "clusterrun_phonopycell_sizeInputsuser_input\n", - "\n", - "user_input: int\n", + "\n", + "user_input: int\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyInputscell_size->clusterrun_phonopycell_sizeInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyInputsvacancy_index\n", - "\n", - "vacancy_index\n", + "\n", + "vacancy_index\n", "\n", "\n", "\n", "clusterrun_phonopyvacancy_indexInputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyInputsvacancy_index->clusterrun_phonopyvacancy_indexInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyInputsdisplacement\n", - "\n", - "displacement: float\n", + "\n", + "displacement: float\n", "\n", "\n", "\n", "clusterrun_phonopydisplacementInputsuser_input\n", - "\n", - "user_input: float\n", + "\n", + "user_input: float\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyInputsdisplacement->clusterrun_phonopydisplacementInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyInputsmax_workers\n", - "\n", - "max_workers: int\n", + "\n", + "max_workers: int\n", "\n", "\n", "\n", "clusterrun_phonopymax_workersInputsuser_input\n", - "\n", - "user_input: int\n", + "\n", + "user_input: int\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyInputsmax_workers->clusterrun_phonopymax_workersInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyOutputsimaginary_modes\n", - "\n", - "imaginary_modes\n", + "\n", + "imaginary_modes\n", "\n", "\n", "\n", "clusterrun_phonopyOutputstotal_dos\n", - "\n", - "total_dos\n", + "\n", + "total_dos\n", "\n", "\n", "\n", "clusterrun_phonopyOutputsenergy_relaxed\n", - "\n", - "energy_relaxed\n", + "\n", + "energy_relaxed\n", "\n", "\n", "\n", "clusterrun_phonopyOutputsenergy_initial\n", - "\n", - "energy_initial\n", + "\n", + "energy_initial\n", "\n", "\n", "\n", "clusterrun_phonopyOutputsenergy_displaced\n", - "\n", - "energy_displaced\n", + "\n", + "energy_displaced\n", "\n", "\n", "\n", "clusterrun_phonopyelementInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterrun_phonopyelementOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterrun_phonopyelementInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterrun_phonopystructureInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyelementOutputsran->clusterrun_phonopystructureInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyelementOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterrun_phonopystructureInputselement\n", - "\n", - "element: str\n", + "\n", + "element: str\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyelementOutputsuser_input->clusterrun_phonopystructureInputselement\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopycell_sizeInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterrun_phonopycell_sizeOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterrun_phonopycell_sizeInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopycell_sizeOutputsran->clusterrun_phonopystructureInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopycell_sizeOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterrun_phonopystructureInputscell_size\n", - "\n", - "cell_size: int\n", + "\n", + "cell_size: int\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopycell_sizeOutputsuser_input->clusterrun_phonopystructureInputscell_size\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyvacancy_indexInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterrun_phonopyvacancy_indexOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterrun_phonopyvacancy_indexInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyvacancy_indexOutputsran->clusterrun_phonopystructureInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyvacancy_indexOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterrun_phonopystructureInputsvacancy_index\n", - "\n", - "vacancy_index\n", + "\n", + "vacancy_index\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyvacancy_indexOutputsuser_input->clusterrun_phonopystructureInputsvacancy_index\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopydisplacementInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterrun_phonopydisplacementOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterrun_phonopydisplacementInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterrun_phonopydisplacementOutputsran->clusterrun_phonopyphonopy_inputInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopydisplacementOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputInputsdistance\n", + "\n", + "distance: float\n", + "\n", + "\n", + "\n", + "clusterrun_phonopydisplacementOutputsuser_input->clusterrun_phonopyphonopy_inputInputsdistance\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopymax_workersInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterrun_phonopymax_workersOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterrun_phonopymax_workersInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopymax_workersOutputsran->clusterrun_phonopyphonopyInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopymax_workersOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyInputsmax_workers\n", - "\n", - "max_workers\n", + "\n", + "max_workers\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopymax_workersOutputsuser_input->clusterrun_phonopyphonopyInputsmax_workers\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyengineInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterrun_phonopyengineOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterrun_phonopyengineInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterrun_phonopyrelaxed_structureInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyengineOutputsran->clusterrun_phonopyrelaxed_structureInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyengineOutputsran->clusterrun_phonopyphonopyInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyengineOutputsengine\n", - "\n", - "engine\n", + "\n", + "engine\n", "\n", "\n", "\n", "clusterrun_phonopyrelaxed_structureInputsengine\n", - "\n", - "engine\n", + "\n", + "engine\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyengineOutputsengine->clusterrun_phonopyrelaxed_structureInputsengine\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyInputsengine\n", - "\n", - "engine\n", + "\n", + "engine\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyengineOutputsengine->clusterrun_phonopyphonopyInputsengine\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopystructureInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterrun_phonopystructureOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopystructureOutputsran->clusterrun_phonopyrelaxed_structureInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopystructureOutputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", "\n", "clusterrun_phonopyrelaxed_structureInputsatoms\n", - "\n", - "atoms\n", + "\n", + "atoms\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopystructureOutputsstructure->clusterrun_phonopyrelaxed_structureInputsatoms\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyrelaxed_structureInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterrun_phonopyrelaxed_structureOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterrun_phonopyrelaxed_structureInputsfmax\n", - "\n", - "fmax\n", + "\n", + "fmax\n", "\n", "\n", "\n", "clusterrun_phonopyrelaxed_structureInputslog_file\n", - "\n", - "log_file\n", + "\n", + "log_file\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structureOutputsran->clusterrun_phonopyphonopyInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structureOutputsran->clusterrun_phonopyrelaxed_structure__out_GetAttr_finalInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structureOutputsran->clusterrun_phonopyrelaxed_structure__out_GetAttr_initialInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyrelaxed_structureOutputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyInputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structureOutputsstructure->clusterrun_phonopyphonopyInputsstructure\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterrun_phonopyrelaxed_structureOutputsout\n", - "\n", - "out\n", + "\n", + "out\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalInputsobj\n", - "\n", - "obj\n", + "\n", + "obj\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structureOutputsout->clusterrun_phonopyrelaxed_structure__out_GetAttr_finalInputsobj\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialInputsobj\n", - "\n", - "obj\n", + "\n", + "obj\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structureOutputsout->clusterrun_phonopyrelaxed_structure__out_GetAttr_initialInputsobj\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "clusterrun_phonopyphonopyInputsrun\n", - "\n", - "run\n", + "clusterrun_phonopyphonopy_inputInputsrun\n", + "\n", + "run\n", "\n", - "\n", - "\n", - "clusterrun_phonopyphonopyOutputsran\n", - "\n", - "ran\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputOutputsran\n", + "\n", + "ran\n", "\n", - "\n", - "\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputInputsis_plusminus\n", + "\n", + "is_plusminus: Union\n", + "\n", + "\n", "\n", - "clusterrun_phonopyphonopyInputsexecutor\n", - "\n", - "executor\n", + "clusterrun_phonopyphonopy_inputInputsis_diagonal\n", + "\n", + "is_diagonal: bool\n", "\n", - "\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputInputsis_trigonal\n", + "\n", + "is_trigonal: bool\n", + "\n", + "\n", "\n", + "clusterrun_phonopyphonopy_inputInputsnumber_of_snapshots\n", + "\n", + "number_of_snapshots: Optional\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputInputsrandom_seed\n", + "\n", + "random_seed: Optional\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputInputstemperature\n", + "\n", + "temperature: Optional\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputInputscutoff_frequency\n", + "\n", + "cutoff_frequency: Optional\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputInputsmax_distance\n", + "\n", + "max_distance: Optional\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputOutputsran->clusterrun_phonopyphonopyInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputOutputsparameters\n", + "\n", + "parameters: dict\n", + "\n", + "\n", + "\n", "clusterrun_phonopyphonopyInputsparameters\n", - "\n", - "parameters\n", + "\n", + "parameters: Union\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopy_inputOutputsparameters->clusterrun_phonopyphonopyInputsparameters\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopyInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopyOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterrun_phonopyphonopyInputsexecutor\n", + "\n", + "executor\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopycheck_consistencyInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyOutputsran->clusterrun_phonopycheck_consistencyInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopytotal_dosInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyOutputsran->clusterrun_phonopytotal_dosInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopy__out_GetItem_energiesInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyOutputsran->clusterrun_phonopyphonopy__out_GetItem_energiesInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyOutputsphonopy\n", - "\n", - "phonopy\n", + "\n", + "phonopy\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopycheck_consistencyInputsphonopy\n", - "\n", - "phonopy\n", + "\n", + "phonopy\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyOutputsphonopy->clusterrun_phonopycheck_consistencyInputsphonopy\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopytotal_dosInputsphonopy\n", - "\n", - "phonopy\n", + "\n", + "phonopy\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyOutputsphonopy->clusterrun_phonopytotal_dosInputsphonopy\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyOutputsout\n", - "\n", - "out\n", + "\n", + "out\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopy__out_GetItem_energiesInputsobj\n", - "\n", - "obj\n", + "\n", + "obj\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopyOutputsout->clusterrun_phonopyphonopy__out_GetItem_energiesInputsobj\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopycheck_consistencyInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopycheck_consistencyOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopycheck_consistencyInputstolerance\n", - "\n", - "tolerance: float\n", + "\n", + "tolerance: float\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopycheck_consistencyOutputshas_imaginary_modes\n", - "\n", - "has_imaginary_modes\n", + "\n", + "has_imaginary_modes\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopycheck_consistencyOutputshas_imaginary_modes->clusterrun_phonopyOutputsimaginary_modes\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopytotal_dosInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopytotal_dosOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopytotal_dosInputsmesh\n", - "\n", - "mesh\n", + "\n", + "mesh\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopytotal_dosOutputstotal_dos\n", - "\n", - "total_dos\n", + "\n", + "total_dos\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopytotal_dosOutputstotal_dos->clusterrun_phonopyOutputstotal_dos\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalInputsname\n", - "\n", - "name\n", + "\n", + "name\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalOutputsran->clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalOutputsgetattr\n", - "\n", - "getattr\n", + "\n", + "getattr\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyInputsobj\n", - "\n", - "obj\n", + "\n", + "obj\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_finalOutputsgetattr->clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyInputsobj\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyInputsname\n", - "\n", - "name\n", + "\n", + "name\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyOutputsgetattr\n", - "\n", - "getattr\n", + "\n", + "getattr\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_final__getattr_GetAttr_energyOutputsgetattr->clusterrun_phonopyOutputsenergy_relaxed\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialInputsname\n", - "\n", - "name\n", + "\n", + "name\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialOutputsran->clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialOutputsgetattr\n", - "\n", - "getattr\n", + "\n", + "getattr\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyInputsobj\n", - "\n", - "obj\n", + "\n", + "obj\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initialOutputsgetattr->clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyInputsobj\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyInputsname\n", - "\n", - "name\n", + "\n", + "name\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyOutputsgetattr\n", - "\n", - "getattr\n", + "\n", + "getattr\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyrelaxed_structure__out_GetAttr_initial__getattr_GetAttr_energyOutputsgetattr->clusterrun_phonopyOutputsenergy_initial\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopy__out_GetItem_energiesInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopy__out_GetItem_energiesOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopy__out_GetItem_energiesInputsitem\n", - "\n", - "item\n", + "\n", + "item\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopy__out_GetItem_energiesOutputsgetitem\n", - "\n", - "getitem\n", + "\n", + "getitem\n", "\n", "\n", - "\n", + "\n", "clusterrun_phonopyphonopy__out_GetItem_energiesOutputsgetitem->clusterrun_phonopyOutputsenergy_displaced\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 13, @@ -3605,25 +3748,25 @@ " \n", "
\n", " 0\n", - " (Atom('Al', [12.157071067811865, 2.01846947349...\n", + " (Atom('Al', [12.220710678118651, 2.08210908380...\n", " None\n", " None\n", " None\n", " None\n", " None\n", - " 0.801477\n", - " [[-0.023172401218313952, -0.02070281808992324,...\n", + " 0.816457\n", + " [[-0.23174580883328727, -0.19678867725572613, ...\n", "
\n", "
\n", " 1\n", - " (Atom('Al', [12.14292893218813, 2.004327337874...\n", + " (Atom('Al', [12.079289321881344, 1.94068772756...\n", " None\n", " None\n", " None\n", " None\n", " None\n", - " 0.801456\n", - " [[0.023223919284411358, 0.017716773608982852, ...\n", + " 0.816327\n", + " [[0.23692289961947316, 0.1920604717384136, -0....\n", "
\n", "
\n", " 2\n", @@ -3633,8 +3776,8 @@ " None\n", " None\n", " None\n", - " 0.801444\n", - " [[-0.00014853410845676318, -0.0045937310507214...\n", + " 0.817278\n", + " [[-0.000587229886297301, -0.02996349715915385,...\n", "
\n", "
\n", " 3\n", @@ -3644,8 +3787,8 @@ " None\n", " None\n", " None\n", - " 0.801514\n", - " [[0.00017067251835383226, 0.001684919320568755...\n", + " 0.817907\n", + " [[0.0028026803072436907, 0.032890474969282525,...\n", "
\n", "
\n", " 4\n", @@ -3655,8 +3798,8 @@ " None\n", " None\n", " None\n", - " 0.801395\n", - " [[8.120943302261999e-05, -0.001404462986399669...\n", + " 0.816751\n", + " [[0.0007383933558706632, -0.000762530426250261...\n", "
\n", "
\n", " 5\n", @@ -3666,8 +3809,8 @@ " None\n", " None\n", " None\n", - " 0.801562\n", - " [[-8.291373797127133e-05, -0.00156522675623289...\n", + " 0.818430\n", + " [[-0.0009088635560401334, -0.00237638063938759...\n", "
\n", "
\n", " 6\n", @@ -3677,8 +3820,8 @@ " None\n", " None\n", " None\n", - " 0.801523\n", - " [[0.004142511131204099, -0.0014405213332471072...\n", + " 0.817795\n", + " [[0.03740766557096164, -0.0010937097702645449,...\n", "
\n", "
\n", " 7\n", @@ -3688,8 +3831,8 @@ " None\n", " None\n", " None\n", - " 0.801430\n", - " [[-0.00423484191023942, -0.0015285012861156674...\n", + " 0.816850\n", + " [[-0.04661644245198296, -0.0019784637733218056...\n", "
\n", "
\n", " 8\n", @@ -3699,8 +3842,8 @@ " None\n", " None\n", " None\n", - " 0.801585\n", - " [[0.004360899946174978, -0.0014522923481744762...\n", + " 0.818396\n", + " [[0.037860451499658415, -0.0012044959256026812...\n", "
\n", "
\n", " 9\n", @@ -3710,8 +3853,8 @@ " None\n", " None\n", " None\n", - " 0.801368\n", - " [[-0.004498869592222, -0.0015165812487091986, ...\n", + " 0.816223\n", + " [[-0.051680428885871, -0.0018528473275288594, ...\n", "
\n", "
\n", " 10\n", @@ -3721,8 +3864,8 @@ " None\n", " None\n", " None\n", - " 0.801554\n", - " [[-0.00011784047553834581, 0.00142477612435064...\n", + " 0.818146\n", + " [[-0.0003305187577696926, 0.025945642954228774...\n", "
\n", "
\n", " 11\n", @@ -3732,8 +3875,8 @@ " None\n", " None\n", " None\n", - " 0.801399\n", - " [[0.00013874621284755764, -0.00442833626348643...\n", + " 0.816604\n", + " [[0.0024222880767723245, -0.03244830791909291,...\n", "
\n", "
\n", " 12\n", @@ -3743,8 +3886,8 @@ " None\n", " None\n", " None\n", - " 0.801477\n", - " [[-4.108496975095688e-08, -0.00148297837318412...\n", + " 0.817426\n", + " [[-4.780355590764535e-07, -0.00146815216264759...\n", "
\n", "
\n", " 13\n", @@ -3754,8 +3897,8 @@ " None\n", " None\n", " None\n", - " 0.801477\n", - " [[-7.357329572856008e-05, -0.00157679353232962...\n", + " 0.817452\n", + " [[-0.0006781361956909419, -0.00232068846765206...\n", "
\n", "
\n", " 14\n", @@ -3765,8 +3908,8 @@ " None\n", " None\n", " None\n", - " 0.801477\n", - " [[7.463133090528616e-05, -0.001389252089714850...\n", + " 0.817448\n", + " [[0.0007905956169687294, -0.000446523484565777...\n", "
\n", "
\n", " 15\n", @@ -3776,8 +3919,8 @@ " None\n", " None\n", " None\n", - " 0.801441\n", - " [[-4.315625166616266e-05, -0.00150097126860205...\n", + " 0.817074\n", + " [[-0.00041586999159231447, -0.0016627153818257...\n", "
\n", "
\n", " 16\n", @@ -3787,8 +3930,8 @@ " None\n", " None\n", " None\n", - " 0.801515\n", - " [[4.3497872165702486e-05, -0.00146724910634231...\n", + " 0.817817\n", + " [[0.0004504865976022159, -0.001328739988518425...\n", "
\n", "
\n", " 17\n", @@ -3798,8 +3941,8 @@ " None\n", " None\n", " None\n", - " 0.801450\n", - " [[-0.00014835242191742724, -0.0015730513522224...\n", + " 0.817147\n", + " [[-0.0013705275391669002, -0.00229917035819349...\n", "
\n", "
\n", " 18\n", @@ -3809,8 +3952,8 @@ " None\n", " None\n", " None\n", - " 0.801505\n", - " [[0.00015060250798282042, -0.00139334259427864...\n", + " 0.817694\n", + " [[0.001604907249663166, -0.0005055283077527381...\n", "
\n", "
\n", " 19\n", @@ -3820,8 +3963,8 @@ " None\n", " None\n", " None\n", - " 0.801477\n", - " [[6.158193767251408e-08, -0.001483930059153100...\n", + " 0.817430\n", + " [[6.755310115128671e-07, -0.001483325282608239...\n", "
\n", "
\n", " 20\n", @@ -3831,8 +3974,8 @@ " None\n", " None\n", " None\n", - " 0.801478\n", - " [[-5.993614836559413e-08, -0.00148404919709561...\n", + " 0.817439\n", + " [[-5.078225007431464e-07, -0.00148448447449355...\n", "
\n", "
\n", "\n", @@ -3840,8 +3983,8 @@ ], "text/plain": [ " atoms energy_pot force stress \\\n", - "0 (Atom('Al', [12.157071067811865, 2.01846947349... None None None \n", - "1 (Atom('Al', [12.14292893218813, 2.004327337874... None None None \n", + "0 (Atom('Al', [12.220710678118651, 2.08210908380... None None None \n", + "1 (Atom('Al', [12.079289321881344, 1.94068772756... None None None \n", "2 (Atom('Al', [12.149999999999997, 2.01139840568... None None None \n", "3 (Atom('Al', [12.149999999999997, 2.01139840568... None None None \n", "4 (Atom('Al', [12.149999999999997, 2.01139840568... None None None \n", @@ -3863,50 +4006,50 @@ "20 (Atom('Al', [12.149999999999997, 2.01139840568... None None None \n", "\n", " structure atomic_energies energy \\\n", - "0 None None 0.801477 \n", - "1 None None 0.801456 \n", - "2 None None 0.801444 \n", - "3 None None 0.801514 \n", - "4 None None 0.801395 \n", - "5 None None 0.801562 \n", - "6 None None 0.801523 \n", - "7 None None 0.801430 \n", - "8 None None 0.801585 \n", - "9 None None 0.801368 \n", - "10 None None 0.801554 \n", - "11 None None 0.801399 \n", - "12 None None 0.801477 \n", - "13 None None 0.801477 \n", - "14 None None 0.801477 \n", - "15 None None 0.801441 \n", - "16 None None 0.801515 \n", - "17 None None 0.801450 \n", - "18 None None 0.801505 \n", - "19 None None 0.801477 \n", - "20 None None 0.801478 \n", + "0 None None 0.816457 \n", + "1 None None 0.816327 \n", + "2 None None 0.817278 \n", + "3 None None 0.817907 \n", + "4 None None 0.816751 \n", + "5 None None 0.818430 \n", + "6 None None 0.817795 \n", + "7 None None 0.816850 \n", + "8 None None 0.818396 \n", + "9 None None 0.816223 \n", + "10 None None 0.818146 \n", + "11 None None 0.816604 \n", + "12 None None 0.817426 \n", + "13 None None 0.817452 \n", + "14 None None 0.817448 \n", + "15 None None 0.817074 \n", + "16 None None 0.817817 \n", + "17 None None 0.817147 \n", + "18 None None 0.817694 \n", + "19 None None 0.817430 \n", + "20 None None 0.817439 \n", "\n", " forces \n", - "0 [[-0.023172401218313952, -0.02070281808992324,... \n", - "1 [[0.023223919284411358, 0.017716773608982852, ... \n", - "2 [[-0.00014853410845676318, -0.0045937310507214... \n", - "3 [[0.00017067251835383226, 0.001684919320568755... \n", - "4 [[8.120943302261999e-05, -0.001404462986399669... \n", - "5 [[-8.291373797127133e-05, -0.00156522675623289... \n", - "6 [[0.004142511131204099, -0.0014405213332471072... \n", - "7 [[-0.00423484191023942, -0.0015285012861156674... \n", - "8 [[0.004360899946174978, -0.0014522923481744762... \n", - "9 [[-0.004498869592222, -0.0015165812487091986, ... \n", - "10 [[-0.00011784047553834581, 0.00142477612435064... \n", - "11 [[0.00013874621284755764, -0.00442833626348643... \n", - "12 [[-4.108496975095688e-08, -0.00148297837318412... \n", - "13 [[-7.357329572856008e-05, -0.00157679353232962... \n", - "14 [[7.463133090528616e-05, -0.001389252089714850... \n", - "15 [[-4.315625166616266e-05, -0.00150097126860205... \n", - "16 [[4.3497872165702486e-05, -0.00146724910634231... \n", - "17 [[-0.00014835242191742724, -0.0015730513522224... \n", - "18 [[0.00015060250798282042, -0.00139334259427864... \n", - "19 [[6.158193767251408e-08, -0.001483930059153100... \n", - "20 [[-5.993614836559413e-08, -0.00148404919709561... " + "0 [[-0.23174580883328727, -0.19678867725572613, ... \n", + "1 [[0.23692289961947316, 0.1920604717384136, -0.... \n", + "2 [[-0.000587229886297301, -0.02996349715915385,... \n", + "3 [[0.0028026803072436907, 0.032890474969282525,... \n", + "4 [[0.0007383933558706632, -0.000762530426250261... \n", + "5 [[-0.0009088635560401334, -0.00237638063938759... \n", + "6 [[0.03740766557096164, -0.0010937097702645449,... \n", + "7 [[-0.04661644245198296, -0.0019784637733218056... \n", + "8 [[0.037860451499658415, -0.0012044959256026812... \n", + "9 [[-0.051680428885871, -0.0018528473275288594, ... \n", + "10 [[-0.0003305187577696926, 0.025945642954228774... \n", + "11 [[0.0024222880767723245, -0.03244830791909291,... \n", + "12 [[-4.780355590764535e-07, -0.00146815216264759... \n", + "13 [[-0.0006781361956909419, -0.00232068846765206... \n", + "14 [[0.0007905956169687294, -0.000446523484565777... \n", + "15 [[-0.00041586999159231447, -0.0016627153818257... \n", + "16 [[0.0004504865976022159, -0.001328739988518425... \n", + "17 [[-0.0013705275391669002, -0.00229917035819349... \n", + "18 [[0.001604907249663166, -0.0005055283077527381... \n", + "19 [[6.755310115128671e-07, -0.001483325282608239... \n", + "20 [[-5.078225007431464e-07, -0.00148448447449355... " ] }, "execution_count": 15, @@ -3951,22 +4094,23 @@ "max_workers: 1\n", "energy: -0.0480655227588862 -0.0480655227588862\n", "max_workers: 1\n", - "energy: 0.9186046985116931 0.9179414222257574\n", + "energy: 0.9186046985116931 0.9179414222257662\n", "max_workers: 1\n", "WARNING: 3 imaginary modes exist\n", - "energy: 0.9186046985116931 0.9179414222257574\n", + "energy: 0.9186046985116931 0.9179414222257662\n", "max_workers: 1\n", "WARNING: 3 imaginary modes exist\n", "energy: -0.16222113933213578 -0.16222113933213578\n", "max_workers: 1\n", "energy: -0.16222113933213578 -0.16222113933213578\n", "max_workers: 1\n", - "energy: 0.8013167095855369 0.7996059979144441\n", + "energy: 0.8013167095856435 0.799605997914508\n", "max_workers: 1\n", - "energy: 0.8013167095855369 0.7996059979144441\n", + "energy: 0.8013167095856435 0.799605997914508\n", "max_workers: 1\n", - "CPU times: user 32.1 s, sys: 1.19 s, total: 33.3 s\n", - "Wall time: 11.1 s\n" + "WARNING: 3 imaginary modes exist\n", + "CPU times: user 51.8 s, sys: 1.16 s, total: 53 s\n", + "Wall time: 23.1 s\n" ] } ], @@ -4043,7 +4187,7 @@ "0 ...\n", " -0.006008\n", " -0.006008\n", - " 0 -0.005843\n", + " 0 0.010553\n", "Name: energy, dtype: float64\n", " \n", "
\n", @@ -4071,7 +4215,7 @@ "0 ...
\n", " 0.871288\n", " 0.871288\n", - " 0 0.871408\n", + " 0 0.883371\n", "Name: energy, dtype: float64\n", " \n", "
\n", @@ -4099,7 +4243,7 @@ "0 -...
\n", " -0.048066\n", " -0.048066\n", - " 0 -0.047905\n", + " 0 -0.031995\n", "Name: energy, dtype: float64\n", " \n", "
\n", @@ -4129,9 +4273,9 @@ "0 -...
\n", " 0.918605\n", " 0.917941\n", - " 0 0.918776\n", - "1 0.918736\n", - "2 0.918768\n", + " 0 0.933953\n", + "1 0.933630\n", + "2 0.935058\n", "3 ...\n", " \n", "
\n", @@ -4159,7 +4303,7 @@ "0 -...
\n", " -0.162221\n", " -0.162221\n", - " 0 -0.162061\n", + " 0 -0.14615\n", "Name: energy, dtype: float64\n", " \n", "
\n", @@ -4184,14 +4328,14 @@ " Al\n", " 0.0\n", " 0.10\n", - " False\n", + " True\n", " frequency_points total_dos\n", "0 -...\n", " 0.801317\n", " 0.799606\n", - " 0 0.801477\n", - "1 0.801456\n", - "2 0.801444\n", + " 0 0.816457\n", + "1 0.816327\n", + "2 0.817278\n", "3...\n", "
\n", " \n", @@ -4211,7 +4355,7 @@ "8 3 Al NaN 0.01 False \n", "9 3 Al NaN 0.10 False \n", "10 3 Al 0.0 0.01 False \n", - "11 3 Al 0.0 0.10 False \n", + "11 3 Al 0.0 0.10 True \n", "\n", " total_dos energy_relaxed \\\n", "0 frequency_points total_dos\n", @@ -4242,35 +4386,35 @@ " energy_initial energy_displaced \n", "0 -0.006008 0 -0.005843\n", "Name: energy, dtype: float64 \n", - "1 -0.006008 0 -0.005843\n", + "1 -0.006008 0 0.010553\n", "Name: energy, dtype: float64 \n", "2 0.871288 0 0.871408\n", "Name: energy, dtype: float64 \n", - "3 0.871288 0 0.871408\n", + "3 0.871288 0 0.883371\n", "Name: energy, dtype: float64 \n", "4 -0.048066 0 -0.047905\n", "Name: energy, dtype: float64 \n", - "5 -0.048066 0 -0.047905\n", + "5 -0.048066 0 -0.031995\n", "Name: energy, dtype: float64 \n", "6 0.917941 0 0.918776\n", "1 0.918736\n", "2 0.918768\n", "3 ... \n", - "7 0.917941 0 0.918776\n", - "1 0.918736\n", - "2 0.918768\n", + "7 0.917941 0 0.933953\n", + "1 0.933630\n", + "2 0.935058\n", "3 ... \n", "8 -0.162221 0 -0.162061\n", "Name: energy, dtype: float64 \n", - "9 -0.162221 0 -0.162061\n", + "9 -0.162221 0 -0.14615\n", "Name: energy, dtype: float64 \n", "10 0.799606 0 0.801477\n", "1 0.801456\n", "2 0.801444\n", "3... \n", - "11 0.799606 0 0.801477\n", - "1 0.801456\n", - "2 0.801444\n", + "11 0.799606 0 0.816457\n", + "1 0.816327\n", + "2 0.817278\n", "3... " ] }, @@ -4301,8 +4445,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 3.76 ms, sys: 416 µs, total: 4.18 ms\n", - "Wall time: 1.05 ms\n" + "CPU times: user 3.38 ms, sys: 150 µs, total: 3.53 ms\n", + "Wall time: 3.57 ms\n" ] } ], @@ -4327,26 +4471,53 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 9 µs, sys: 0 ns, total: 9 µs\n", - "Wall time: 4.05 µs\n" + "CPU times: user 4 µs, sys: 2 µs, total: 6 µs\n", + "Wall time: 9.78 µs\n" ] } ], "source": [ "%time\n", "wf = Workflow('phonopy')\n", - "wf.register('atomistic', 'pyiron_workflow.node_library.atomistic')\n", - "# wf.register('structure', 'pyiron_workflow.node_library.structure')\n", - "# wf.register('calculator', 'pyiron_workflow.node_library.calculator')\n", - "# wf.register('engine', 'pyiron_workflow.node_library.engine')\n", - "# wf.register('phonopy', 'pyiron_workflow.node_library.phonopy')\n", - "wf.register('databases', 'pyiron_workflow.node_library.databases')\n", - "#wf.register('property', 'pyiron_workflow.node_library.property')" + "wf.register('pyiron_workflow.node_library.atomistic', domain='atomistic')\n", + "wf.register('pyiron_workflow.node_library.databases', domain='databases')" ] }, { "cell_type": "code", "execution_count": 20, + "id": "a28ee850-afff-4036-8a05-e86136511514", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "File downloaded successfully\n" + ] + } + ], + "source": [ + "# Get the source data\n", + "# from Ref. de Jong et al. https://www.nature.com/articles/sdata20159#MOESM77\n", + "\n", + "import requests\n", + "\n", + "url = 'https://datadryad.org/stash/downloads/file_stream/88988'\n", + "destination_file = 'ec.json'\n", + "\n", + "response = requests.get(url)\n", + "if response.status_code == 200:\n", + " with open(destination_file, 'wb') as f:\n", + " f.write(response.content)\n", + " print('File downloaded successfully')\n", + "else:\n", + " print('Failed to download file:', response.status_code)" + ] + }, + { + "cell_type": "code", + "execution_count": 21, "id": "10ad0c84-0846-4d9d-91b8-cee47f5efef3", "metadata": {}, "outputs": [], @@ -4357,7 +4528,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 22, "id": "37b0972d-0ad3-4f85-8897-36f1d8d76fc2", "metadata": {}, "outputs": [ @@ -4365,8 +4536,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 12 s, sys: 778 ms, total: 12.8 s\n", - "Wall time: 3.6 s\n" + "CPU times: user 6.95 s, sys: 310 ms, total: 7.26 s\n", + "Wall time: 8.13 s\n" ] } ], @@ -4377,7 +4548,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 23, "id": "25a0f789-1248-4280-a09a-f2c9903b06f1", "metadata": {}, "outputs": [ @@ -4584,7 +4755,7 @@ " 194\n", " #\\#CIF1.1\\n###################################...\n", " 121.520152\n", - " (Atom('Ti', [1.5517152117138742, 0.89588144411...\n", + " (Atom('Ti', [1.5517152117138744, 0.89588144411...\n", " \n", "
\n", " 1177\n", @@ -4782,7 +4953,7 @@ "3 (Atom('Ga', [0.0, 1.09045796233546, 0.84078379... \n", "4 (Atom('Si', [1.0094264625, 4.247717077057611, ... \n", "... ... \n", - "1176 (Atom('Ti', [1.5517152117138742, 0.89588144411... \n", + "1176 (Atom('Ti', [1.5517152117138744, 0.89588144411... \n", "1177 (Atom('Sc', [0.0, 8.534175787117318, 0.9174096... \n", "1178 (Atom('Y', [0.0, 9.084548591046719, 0.96092093... \n", "1179 (Atom('Al', [5.1103587633892795, 2.07486753338... \n", @@ -4791,7 +4962,7 @@ "[1181 rows x 20 columns]" ] }, - "execution_count": 22, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -4802,7 +4973,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 24, "id": "0ba2176d-dfa3-4522-af61-fd7e3411d9ef", "metadata": {}, "outputs": [], @@ -4825,7 +4996,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 25, "id": "10bbf3ba-4c61-455b-a071-35efcbadfd92", "metadata": {}, "outputs": [ @@ -4844,7 +5015,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 26, "id": "9249849d-4685-4b33-b6ef-2536f4ab2a94", "metadata": {}, "outputs": [ @@ -4865,181 +5036,71 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 27, + "id": "8a36d2f6-3937-4c90-93fb-62eb54acca65", + "metadata": {}, + "outputs": [], + "source": [ + "try:\n", + " import matgl\n", + " MATGL_PRESENT = True\n", + "except ModuleNotFoundError:\n", + " MATGL_PRESENT = False" + ] + }, + { + "cell_type": "code", + "execution_count": 28, "id": "f6710a6d-e1d6-4807-b1e4-88fa14aad86a", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "max_workers: 1\n", - "CPU times: user 3min 33s, sys: 7.47 s, total: 3min 40s\n", - "Wall time: 57.9 s\n" - ] - } - ], + "outputs": [], "source": [ - "%%time\n", - "import warnings\n", - "warnings.filterwarnings(\"ignore\")\n", + "if MATGL_PRESENT:\n", + " import warnings\n", + " warnings.filterwarnings(\"ignore\")\n", "\n", - "out = Workflow.create.atomistic.property.elastic.elastic_constants().iter(structure=structures)" + " out = Workflow.create.atomistic.property.elastic.elastic_constants().iter(structure=structures)" ] }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 29, "id": "3e6f8e28-9bb2-4b8d-ab29-29b0781c536c", "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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rbnuAEuXLmXz5s38+OOPNfa19n///v378+6773LaaaeRlZXFzJkzOe+889ixY0err7to+dpy29wY5G++/trq94jG0By/m0hg1cA0TfN7rZSqsa21+jN1b2n359577+WXX37h22+/rbGvNdf/9NNPZ+vWrRQWFrJs2TLGjh3LunXrjP2tue4HDx7kgQceYNWqVQQGBtZZrrXeg8suu8z4vWfPngwcOJBTTjmFBQsWMGDAAKD11l20Hm25bW4M8jf/57XV7xGNoTl+N5GhgA0kMjISs9lcI8rNzs6uETG3Nr4MYUere2xsLG63m4KCgjrLNHf33XcfH3/8MV999RUJCQnG9rZQf6vVSteuXenbty8pKSn06tWLl156qU3UfdOmTWRnZ9OnTx8sFgsWi4V169bxj3/8A4vFYtShNd+DqoKCgujZsyd79uxpE//+omVry21zY5C/+fppy98jGkNz/G4igVUDsVqt9OnTh9WrV/ttX716Needd14TXdXJkZSURGxsrF/d3W4369atM+rep08fAgIC/MpkZGSwffv2Zn9/lFLce++9fPjhh3z55ZckJSX57W/t9a+NUgqXy9Um6n7JJZewbds2tm7davz07duXUaNGsXXrVpKTk1v9PajK5XKxa9cu4uLi2sS/v2jZ2nLb3Bjkb/7Pke8RJ0ez+G7yp9NeiBp8KV3ffvtttXPnTjVx4kQVFBSk0tLSmvrS6q2oqEht2bJFbdmyRQFq7ty5asuWLUa62tmzZyu73a4+/PBDtW3bNnXzzTfXmtYyISFBrVmzRm3evFldfPHFLSJN6F133aXsdrtau3atX8rpw4cPG2Vac/2nTp2qvv76a7Vv3z71yy+/qMcee0yZTCa1atUqpVTrrntdqmYFVKp134PJkyertWvXqtTUVPX999+rK664QoWEhBifa6257qJ1aM1tc2Noy+19Y2nr3yMaQ3P9biKBVQN75ZVXVOfOnZXValW9e/c2Umm2dF999ZUCavyMHTtWKeVNFTpt2jQVGxurbDabuvDCC9W2bdv8zlFaWqruvfdeFR4ertq1a6euuOIKdeDAgSaozYmprd6AmjdvnlGmNdd//Pjxxv/pqKgodckllxgfXEq17rrXpXpg1ZrvgW/tj4CAABUfH6+uvfZatWPHDmN/a667aD1aa9vcGNpye99Y2vr3iMbQXL+baEop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mM1mCgsLa91Wl3POOYdFixbVuX/EiBG43W4Ahg8fftz3QSll9PRFREQwdOhQXn75Ze677746x7LXZfbs2Zx99tlGjypA9+7dsdlsHDhwgMGDB9d5rNVqxePx1Ni+fft2EhIS6uzhFEKI1qJHjx4AfPvtt9x0001++7Zv346mafTs2bNFtU1Q//ZJ2ibRUsgTK9Fmbdq0CU3TiImJITMzk7179zJ//nymTZvGhAkT6NChA6mpqbjdbi688EIiIyMpLy9nyJAhgHc9jJ07d3LFFVdw9tln88orrxAQEMDu3bv9Prx9jZfFYiEvL48pU6awY8cOOnToUOu2ugwfPpwdO3bU2TNoNpvZtWsXu3bt8uvtrOqxxx7jm2++IS0tjW3btvH444+zdu1aRo0aZZR59dVXqaiooG/fvrz//vvs2rWL3bt3s2jRIn799dc6zw3Qs2dPRo0axT//+U9jW0hICA899BAPPvggCxYsYO/evWzZsoVXXnmFBQsWGOW6dOnCDz/8QFpaGrm5uUZv4jfffMOwYcPqfE8hhGgtevbsyVVXXcX999/PO++8w+7du9m1axdLlixh2rRpnHbaaQQHB7eotgkapn2Stkm0CE2Wj1CIJvboo4/6pVANCwtT/fr1U++8847yeDxKKaU++ugjNXLkSKWUUvv371dBQUEqIyNDKaXU448/rt57770a5126dKmaPHmy8bpv374qLS1NKaWU0+lU7777rurWrZtasWJFndvqMmDAAPX6668br33pbOtSPZ3t+PHjVefOnZXValVRUVHqkksuUatWrapx3B9//KHuvfdelZSUpAICAlRwcLDq16+fevbZZ1VJSclR3z8tLU3ZbLYaKW1feukldfrpp6uAgAAVFRWlhg8frtatW2eU2b17txowYIBq166dkdK2tLRUhYaGqu++++6o90UIIVoLl8ulZs+erc4880zVrl07FRoaqgYMGKBefPFF5XA4lFLNv21SqnHaJ2mbRHMngZUQRzFz5kz15JNPGq+vv/56NX/+fKWUUv/85z/9GoVffvlFKaXUq6++qv7+978rpZRat26dCgkJUbquq99++80oe8cdd6j//Oc/tW47mk8++USdccYZRuDX2r388stq6NChTX0ZQgjRrEjb1LSkbRJ1kaGAQhzFjh07/LIDjRw5klWrVgHetTkKCwvp1q0bvXr14r333gO8Y8mXL1/OLbfcwpo1azjjjDPQNI2nn36a008/nXPOOYfAwECuueaaWrcdzV/+8hfuvPNODh061HiVbkYCAgL8hm4IIYSQtqmpSdsk6qIppVRTX4QQQgghhBBCtGTyxEoIIYQQQggh6kkCKyGEEEIIIYSoJwmshBBCCCGEEKKeJLASQgghhBBCiHqSwEoIIYQQQggh6kkCKyGEEEIIIYSoJwmshBBCCCGEEKKeJLASQgghhBBCiHqSwEoIIYQQQggh6kkCKyGEEEIIIYSoJwmshBBCCCGEEKKeJLASQgghhBBCiHr6/xEna6/buhCjAAAAAElFTkSuQmCC", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ - "x = np.linspace(0, 500, 101)\n", + "if MATGL_PRESENT:\n", + " x = np.linspace(0, 500, 101)\n", "\n", - "plt.figure(figsize=(10,5))\n", - "plt.subplot(1,2,1)\n", - "plt.scatter(out.BR, unaries.K_Reuss)\n", - "plt.scatter(out.BV, unaries.K_Voigt, c='g', marker = 'x')\n", - "plt.xlabel('$B_{Reuss}$ (M3GNet)')\n", - "plt.ylabel('$B_{Reuss}$ (DFT)')\n", - "plt.title('Bulk Modulus')\n", - "plt.plot(x, x, 'k--');\n", + " plt.figure(figsize=(10,5))\n", + " plt.subplot(1,2,1)\n", + " plt.scatter(out.BR, unaries.K_Reuss)\n", + " plt.scatter(out.BV, unaries.K_Voigt, c='g', marker = 'x')\n", + " plt.xlabel('$B_{Reuss}$ (M3GNet)')\n", + " plt.ylabel('$B_{Reuss}$ (DFT)')\n", + " plt.title('Bulk Modulus')\n", + " plt.plot(x, x, 'k--');\n", "\n", - "plt.subplot(1,2,2)\n", - "x = np.linspace(0, 300, 101)\n", + " plt.subplot(1,2,2)\n", + " x = np.linspace(0, 300, 101)\n", "\n", - "plt.scatter(out.GR, unaries.G_Reuss)\n", - "plt.scatter(out.GV, unaries.G_Voigt, c='g', marker = 'x')\n", - "plt.xlabel('$G_{Reuss}$ (M3GNet)')\n", - "plt.ylabel('$G_{Reuss}$ (DFT)')\n", - "plt.title('Shear Modulus')\n", - "plt.plot(x, x, 'k--');" + " plt.scatter(out.GR, unaries.G_Reuss)\n", + " plt.scatter(out.GV, unaries.G_Voigt, c='g', marker = 'x')\n", + " plt.xlabel('$G_{Reuss}$ (M3GNet)')\n", + " plt.ylabel('$G_{Reuss}$ (DFT)')\n", + " plt.title('Shear Modulus')\n", + " plt.plot(x, x, 'k--');" ] }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 30, "id": "560c2439-b831-452c-b0f3-c42d17fb5591", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "Index(['G_Reuss', 'G_VRH', 'G_Voigt', 'K_Reuss', 'K_VRH', 'K_Voigt',\n", - " 'compliance_tensor', 'elastic_anisotropy', 'elastic_tensor',\n", - " 'elastic_tensor_original', 'formula', 'kpoint_density', 'material_id',\n", - " 'nsites', 'poisson_ratio', 'poscar', 'space_group', 'structure',\n", - " 'volume', 'atoms'],\n", - " dtype='object')" - ] - }, - "execution_count": 28, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "unaries.keys()" - ] - }, - { - "cell_type": "code", - "execution_count": 29, - "id": "3b5b6874-f2c3-40d0-9dc6-d29a7b6e1a3a", - "metadata": {}, - "outputs": [ - { - "ename": "NameError", - "evalue": "name 'xx' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[29], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mxx\u001b[49m\n", - "\u001b[0;31mNameError\u001b[0m: name 'xx' is not defined" - ] - } - ], + "outputs": [], "source": [ - "xx" + "if MATGL_PRESENT:\n", + " unaries.keys()" ] }, { @@ -5052,188 +5113,220 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 31, "id": "5f9c9dae-7a97-47e5-9750-c9adfb9c1072", "metadata": {}, "outputs": [], "source": [ - "from ase import units\n", - "from ase.build import bulk\n", - "from atomistics.calculators import calc_molecular_dynamics_langevin_with_ase" + "if MATGL_PRESENT:\n", + " from ase import units\n", + " from ase.build import bulk\n", + " from atomistics.calculators import calc_molecular_dynamics_langevin_with_ase" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 32, "id": "53847c37-2f8b-4ba1-bd3a-c27c9eee958a", "metadata": {}, "outputs": [], "source": [ - "import matgl\n", - "from matgl.ext.ase import M3GNetCalculator" + "if MATGL_PRESENT:\n", + " import matgl\n", + " from matgl.ext.ase import M3GNetCalculator" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 33, "id": "24632194-6f3b-44c4-a8dd-c9ee1b9147f5", "metadata": {}, "outputs": [], "source": [ - "%%time\n", - "structure = bulk(\"Al\", cubic=True).repeat([3, 3, 3])\n", - "ase_calculator = M3GNetCalculator(matgl.load_model(\"M3GNet-MP-2021.2.8-PES\"))\n", - "result_dict = calc_molecular_dynamics_langevin_with_ase(\n", - " structure=structure,\n", - " ase_calculator=ase_calculator,\n", - " run=1000,\n", - " thermo=10,\n", - " timestep=1 * units.fs,\n", - " temperature=1000,\n", - " friction=0.002,\n", - ")" + "if MATGL_PRESENT:\n", + "\n", + " structure = bulk(\"Al\", cubic=True).repeat([3, 3, 3])\n", + " ase_calculator = M3GNetCalculator(matgl.load_model(\"M3GNet-MP-2021.2.8-PES\"))\n", + " result_dict = calc_molecular_dynamics_langevin_with_ase(\n", + " structure=structure,\n", + " ase_calculator=ase_calculator,\n", + " run=1000,\n", + " thermo=10,\n", + " timestep=1 * units.fs,\n", + " temperature=1000,\n", + " friction=0.002,\n", + " )" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 34, "id": "47cb2507-7b1e-4172-b423-4a055f0256b4", "metadata": {}, "outputs": [], "source": [ - "result_dict.keys()" + "if MATGL_PRESENT:\n", + " result_dict.keys()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "id": "54dfd61f-4195-41b2-98b4-293957c7be70", "metadata": {}, "outputs": [], "source": [ - "plt.plot(result_dict['energy_pot']);" + "if MATGL_PRESENT:\n", + " plt.plot(result_dict['energy_pot']);" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "id": "759b4aa7-927e-404d-a637-828298ab672f", "metadata": {}, "outputs": [], "source": [ - "plt.plot(result_dict['positions'][:,:,0]);" + "if MATGL_PRESENT:\n", + " plt.plot(result_dict['positions'][:,:,0]);" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 37, "id": "e1e34c2a-1664-41d4-82e5-57e8d7a628b5", "metadata": {}, "outputs": [], "source": [ - "from pyiron_workflow.node_library.dev_tools import Output" + "# from pyiron_workflow.node_library.dev_tools import Output\n", + "# Does not exist in repo" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 38, "id": "a9d193fd-5ad7-42dd-bde6-ee2449c5a129", "metadata": {}, "outputs": [], "source": [ - "# Example usage:\n", - "def get_energy(arg1, arg2):\n", - " #print(f\"Function 1 called with arguments: {arg1}, {arg2}\")\n", - " return arg1 + arg2\n", + "# # Example usage:\n", + "# def get_energy(arg1, arg2):\n", + "# #print(f\"Function 1 called with arguments: {arg1}, {arg2}\")\n", + "# return arg1 + arg2\n", "\n", - "def function2(arg1, arg2):\n", - " print(f\"Function 2 called with arguments: {arg1}, {arg2}\")\n", - " return f\"Hello, {arg1} {arg2}!\"\n", + "# def function2(arg1, arg2):\n", + "# print(f\"Function 2 called with arguments: {arg1}, {arg2}\")\n", + "# return f\"Hello, {arg1} {arg2}!\"\n", "\n", - "def function3(arg):\n", - " print(f\"Function 3 called with argument: {arg}\")\n", - " return [i for i in range(arg)]\n", + "# def function3(arg):\n", + "# print(f\"Function 3 called with argument: {arg}\")\n", + "# return [i for i in range(arg)]\n", "\n", - "def to_dict(func, args=(), kwargs={}):\n", - " return (func, args, kwargs)\n", + "# def to_dict(func, args=(), kwargs={}):\n", + "# return (func, args, kwargs)\n", "\n", - "output = Output(keys_to_run=['energy'])\n", - "print ('keys to run: ', output._keys_to_run)\n", - "output['energy'] = to_dict(get_energy, args=(3, 2))\n", + "# output = Output(keys_to_run=['energy'])\n", + "# print ('keys to run: ', output._keys_to_run)\n", + "# output['energy'] = to_dict(get_energy, args=(3, 2))\n", "\n", - "output.run()\n", + "# output.run()\n", "\n", - "# Iterating over keys and values\n", - "for key, value in output.items():\n", - " print(f\"{key}: {value}\")" + "# # Iterating over keys and values\n", + "# for key, value in output.items():\n", + "# print(f\"{key}: {value}\")" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "id": "889829b1-080b-4255-983b-62f669cf041f", "metadata": {}, "outputs": [], "source": [ - "'energy' in output._functions" + "# 'energy' in output._functions" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 40, "id": "2bd4f113-9610-4daf-9567-0a85c4ad2d65", "metadata": {}, "outputs": [], "source": [ - "func, args, kwargs = output._functions['energy']" + "# func, args, kwargs = output._functions['energy']" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 41, "id": "dcf9026b-f620-4d55-bb9a-e14cdb38bda9", "metadata": {}, "outputs": [], "source": [ - "func, args, kwargs = to_dict(get_energy, args=(3, 2))" + "# func, args, kwargs = to_dict(get_energy, args=(3, 2))" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 42, "id": "080d9a25-8252-411b-b274-b75212ea793e", "metadata": {}, "outputs": [], "source": [ - "func(*args)" + "# func(*args)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 43, "id": "839cfcf8-14e0-4772-844b-770f7a129e0e", "metadata": {}, "outputs": [], "source": [ - "output._functions['energy']" + "# output._functions['energy']" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 44, "id": "edfdec4c-a490-4a81-af73-94a333697d50", "metadata": {}, "outputs": [], "source": [ - "func(*args, **kwargs)" + "# func(*args, **kwargs)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 45, "id": "6a9ff00f-5030-40e6-9296-50e4025f7332", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Function 1 called with arguments: 3, 4\n", + "7\n", + "Function 2 called with arguments: John, Doe\n", + "Hello, John Doe!\n", + "Function 3 called with argument: 5\n", + "[0, 1, 2, 3, 4]\n", + "Function 1 called with arguments: 3, 4\n", + "7\n", + "Function 1 called with arguments: 3, 4\n", + "Function 2 called with arguments: John, Doe\n", + "Function 1 called with arguments: 3, 4\n", + "Function 2 called with arguments: John, Doe\n", + "Function 3 called with argument: 5\n", + "Function 1 called with arguments: 3, 4\n", + "key1: 7\n", + "key2: Hello, John Doe!\n", + "key3: [0, 1, 2, 3, 4]\n", + "key4: 7\n" + ] + } + ], "source": [ "class LazyDict:\n", " def __init__(self, **kwargs):\n", @@ -5309,7 +5402,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 46, "id": "1f58da83-93f8-4df3-9b13-fe3f7756de88", "metadata": {}, "outputs": [], @@ -5322,7 +5415,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 47, "id": "7d836f6c-545c-4082-89b1-6a892c189884", "metadata": {}, "outputs": [], @@ -5342,7 +5435,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 48, "id": "123ddac3-bed1-474f-bf49-a7f20ad1c8e1", "metadata": {}, "outputs": [], @@ -5353,37 +5446,124 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 49, "id": "b6e76f6c-45b1-4982-8b14-ce0af3a75d2c", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "InputPhonopyGenerateSupercells(distance=1, is_plusminus='auto', is_diagonal=True, is_trigonal=False, number_of_snapshots=None, random_seed=None, temperature=None, cutoff_frequency=None, max_distance=10)" + ] + }, + "execution_count": 49, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "par" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 50, "id": "8ade9cdc-23cd-45af-af6f-54a7504dc758", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "1" + ] + }, + "execution_count": 50, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "par.distance" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 51, "id": "cded0af4-4735-4e22-b1ee-cf5503a9f06d", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "\u001b[0;31mType:\u001b[0m InputPhonopyGenerateSupercells\n", + "\u001b[0;31mString form:\u001b[0m InputPhonopyGenerateSupercells(distance=1, is_plusminus='auto', is_diagonal=True, is_trigonal=False, number_of_snapshots=None, random_seed=None, temperature=None, cutoff_frequency=None, max_distance=10)\n", + "\u001b[0;31mDocstring:\u001b[0m \n", + "Generate displacement dataset.\n", + "\n", + "There are two modes, finite difference method with systematic\n", + "displacements and fitting approach between arbitrary displacements and\n", + "their forces. The default approach is the finite difference method that\n", + "is built-in phonopy. The fitting approach requires external force\n", + "constant calculator.\n", + "\n", + "The random displacement supercells are created by setting positive\n", + "integer values 'number_of_snapshots' keyword argument. Unless this is\n", + "specified, systematic displacements are created for the finite\n", + "difference method as the default behaviour.\n", + "\n", + "Parameters\n", + "----------\n", + "distance : float, optional\n", + " Displacement distance. Unit is the same as that used for crystal\n", + " structure. Default is 0.01.\n", + "is_plusminus : 'auto', True, or False, optional\n", + " For each atom, displacement of one direction (False), both\n", + " direction, i.e., one directiona and its opposite direction (True),\n", + " and both direction if symmetry requires ('auto'). Default is 'auto'.\n", + "is_diagonal : bool, optional\n", + " Displacements are made only along basis vectors (False) and can be\n", + " made not being along basis vectors if the number of displacements\n", + " can be reduced by symmetry (True). Default is True.\n", + "is_trigonal : bool, optional\n", + " Existing only testing purpose. Default is False.\n", + "number_of_snapshots : int or None, optional\n", + " Number of snapshots of supercells with random displacements. Random\n", + " displacements are generated displacing all atoms in random\n", + " directions with a fixed displacement distance specified by\n", + " 'distance' parameter, i.e., all atoms in supercell are displaced\n", + " with the same displacement distance in direct space. Default is\n", + " None.\n", + "random_seed : 32bit unsigned int or None, optional\n", + " Random seed for random displacements generation. Default is None.\n", + "temperature : float or None, optional\n", + " With given temperature, random displacements at temperature is\n", + " generated by sampling probability distribution from canonical\n", + " ensemble of harmonic oscillators (harmonic phonons). Default is\n", + " None.\n", + "cutoff_frequency : float or None, optional\n", + " In random displacements generation from canonical ensemble of\n", + " harmonic phonons, phonon occupation number is used to determine the\n", + " deviation of the distribution function. To avoid too large\n", + " deviation, this value is used to exclude the phonon modes whose\n", + " absolute frequency are smaller than this value. Default is None.\n", + "max_distance : float or None, optional\n", + " In random displacements generation from canonical ensemble of\n", + " harmonic phonons, displacements larger than max distance are\n", + " renormalized to the max distance, i.e., a disptalcement d is shorten\n", + " by d -> d / |d| * max_distance if |d| > max_distance." + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "par??" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 52, "id": "63d3eb9a-ee79-43a3-bb36-1e8460bf07e6", "metadata": {}, "outputs": [], @@ -5393,17 +5573,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 53, "id": "d7671f4b-1f57-4f07-9be7-1ff0955b8295", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "{'distance': 1}" + ] + }, + "execution_count": 53, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "par.select(keys_to_store=['distance'])" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 54, "id": "888b113d-a7a4-41ad-acfc-efbc252eab9e", "metadata": {}, "outputs": [], @@ -5415,27 +5606,52 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 55, "id": "b144573b-0f23-4f0f-b900-c1a10e27b1a7", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('distance', 1)\n" + ] + } + ], "source": [ "test(**par.select(keys_to_store=['distance']))" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 56, "id": "c842e70f-7b4a-426a-9b9c-1e9614d3d171", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "('distance', 1)\n", + "('is_plusminus', 'auto')\n", + "('is_diagonal', True)\n", + "('is_trigonal', False)\n", + "('number_of_snapshots', None)\n", + "('random_seed', None)\n", + "('temperature', None)\n", + "('cutoff_frequency', None)\n", + "('max_distance', 10)\n", + "('distances', 0.2)\n" + ] + } + ], "source": [ "test(**par)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 57, "id": "0e4c64e2-10c5-47dd-a0ca-57f3d2b198ab", "metadata": {}, "outputs": [], @@ -5445,10 +5661,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 58, "id": "db423749-2af5-43e7-af45-48dd356e6717", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "array([[0. , 0. , 0. ],\n", + " [0. , 2.025, 2.025],\n", + " [2.025, 0. , 2.025],\n", + " [2.025, 2.025, 0. ]])" + ] + }, + "execution_count": 58, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "Al = build.bulk('Al', cubic=True)\n", "Al.get_positions(wrap=True)" @@ -5456,44 +5686,43 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 59, "id": "5478171f-cd4e-4a18-ad9d-db6e74f861d2", "metadata": {}, "outputs": [], "source": [ - "Al.get_stress()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3e938638-8a69-4125-8f3a-15dd3686f0cb", - "metadata": {}, - "outputs": [], - "source": [ - "Al.get_" + "# Al.get_stress()\n", + "# Al needs an ASE calculator object assigned first" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 60, "id": "c557b3b1-9eec-48b3-a06e-f56c1a394afa", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Address(street='', city='', zip_code='')\n" + ] + } + ], "source": [ - "from dataclasses import dataclass\n", + "from dataclasses import dataclass, field\n", "\n", "@dataclass\n", "class Address:\n", - " street: str\n", - " city: str\n", - " zip_code: str\n", + " street: str = \"\"\n", + " city: str = \"\"\n", + " zip_code: str = \"\"\n", "\n", "@dataclass\n", "class Person:\n", " name: str\n", " age: int\n", - " address: Address = Address(street='', city='', zip_code='')\n", + " address: Address = field(default_factory=Address)\n", "\n", "# Example usage\n", "person_with_default_address = Person(name='John Doe', age=30)\n", @@ -5504,10 +5733,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 61, "id": "429d927d-e694-4da1-9f66-2f878bd481be", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Address(street='', city='', zip_code='')\n" + ] + } + ], "source": [ "from dataclasses import dataclass, field\n", "\n", @@ -5540,7 +5777,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 62, "id": "39fa01fa-9ae8-4437-98d8-6b04a8a826b1", "metadata": {}, "outputs": [], @@ -5554,7 +5791,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 63, "id": "84e1a9ad-d324-4a75-88a5-f8b45ed7a0d7", "metadata": {}, "outputs": [], @@ -5568,7 +5805,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 64, "id": "a20e229c-0bf1-4d39-bd71-2929c12718f3", "metadata": {}, "outputs": [], @@ -5582,17 +5819,28 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 65, "id": "4a4f1794-05e8-4dd7-ad26-55b51f261699", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 65, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "VarFunc(func=np.sin, log_level=2).func" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 66, "id": "fb62cfa1-3320-4d74-9e57-0ec10a55f796", "metadata": {}, "outputs": [], @@ -5614,10 +5862,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 67, "id": "50330980-ea4d-4f40-88ee-dd752863201a", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(0.8414709848078965, array([1., 1., 1.]))" + ] + }, + "execution_count": 67, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "job = toy_job(1)\n", "job.get_energy(), job.get_forces()" @@ -5625,7 +5884,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 68, "id": "8b242761-5c56-4f9d-a08d-1d335b15e46d", "metadata": {}, "outputs": [], @@ -5661,10 +5920,27 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 69, "id": "6558e0f8-b2a3-488e-988f-66ac0f5fded8", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "angstrom" + ], + "text/latex": [ + "$\\mathrm{angstrom}$" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 69, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "import pint\n", "ureg = pint.UnitRegistry()\n", @@ -5673,7 +5949,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 70, "id": "c5b312fd-6dd2-45a5-8c6e-ef4d9a6a9b97", "metadata": {}, "outputs": [], @@ -5684,9 +5960,13 @@ "@dataclass\n", "class OutputEnergyStatic:\n", " distance: float = 0.01\n", - " energy: VarFunc = VarFunc(func=toy_job.get_energy, log_level=0, unit=ureg.eV)\n", - " forces: VarFunc = VarFunc(func=toy_job.get_forces, log_level=1, unit=ureg.eV/ureg.angstrom)\n", - " prop: VarType = VarType(toy_job.my_x, log_level=2)\n", + " energy: VarFunc = field(\n", + " default_factory=lambda: VarFunc(func=toy_job.get_energy, log_level=0, unit=ureg.eV)\n", + " )\n", + " forces: VarFunc = field(\n", + " default_factory=lambda: VarFunc(func=toy_job.get_forces, log_level=1, unit=ureg.eV/ureg.angstrom)\n", + " )\n", + " prop: VarType = field(default_factory=lambda: VarType(toy_job.my_x, log_level=2))\n", "\n", " def keys(self):\n", " return self.__dict__.keys()\n", @@ -5707,53 +5987,169 @@ }, { "cell_type": "code", - "execution_count": null, - "id": "40323f9b-25ae-4d30-b105-964d086f1e9c", + "execution_count": 71, + "id": "cef22996-86fd-4ed8-88e3-253a5a4ff063", "metadata": {}, - "outputs": [], - "source": [ - "xx" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cef22996-86fd-4ed8-88e3-253a5a4ff063", - "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "max_workers: 1\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'cell_size' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'element' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'vacancy_index' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'displacement' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'cell_size' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'element' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'vacancy_index' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'displacement' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'cell_size' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'element' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'vacancy_index' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'displacement' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'cell_size' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'element' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'vacancy_index' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'displacement' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n" + ] + } + ], "source": [ - "%%time\n", - "df = wf.iter(cell_size=list(range(1,4)), element=['Al'], vacancy_index=[None, 0], displacement=[0.01, 0.1]) #, Cu, Pd, Ag, Pt and Au])" + "# %%time\n", + "df = wf.iter(\n", + " cell_size=list(range(1,2)), # Or 1,4, but that takes longer\n", + " element=['Al'], \n", + " vacancy_index=[None, 0], \n", + " displacement=[0.01, 0.1]\n", + ") #, Cu, Pd, Ag, Pt and Au])\n" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 72, "id": "15426796-970d-467a-95b3-816f1067add0", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
cell_sizeelementvacancy_indexdisplacementdata__dataframe
01AlNaN0.01G_Reuss G_VRH G_Voigt K...
11AlNaN0.10G_Reuss G_VRH G_Voigt K...
21Al0.00.01G_Reuss G_VRH G_Voigt K...
31Al0.00.10G_Reuss G_VRH G_Voigt K...
\n", + "
" + ], + "text/plain": [ + " cell_size element vacancy_index displacement \\\n", + "0 1 Al NaN 0.01 \n", + "1 1 Al NaN 0.10 \n", + "2 1 Al 0.0 0.01 \n", + "3 1 Al 0.0 0.10 \n", + "\n", + " data__dataframe \n", + "0 G_Reuss G_VRH G_Voigt K... \n", + "1 G_Reuss G_VRH G_Voigt K... \n", + "2 G_Reuss G_VRH G_Voigt K... \n", + "3 G_Reuss G_VRH G_Voigt K... " + ] + }, + "execution_count": 72, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "df" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 73, "id": "89abfc53-4a70-4640-a34e-2825692ba8a6", "metadata": {}, "outputs": [], "source": [ - "df.energy_displaced" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3afaf54a-0c9c-4122-a518-49a99fb15cca", - "metadata": {}, - "outputs": [], - "source": [ - "xx" + "# df.energy_displaced\n", + "# Not a column" ] }, { @@ -5766,7 +6162,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 74, "id": "5e0b5714-18de-4ea6-be1f-ab1f44f9e6f5", "metadata": {}, "outputs": [], @@ -5781,10 +6177,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 75, "id": "1c37d595-1060-4969-8fc9-c78548bc1963", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "@single_value_node('out')\n", + "def sleep(time=1, a=None, b=10):\n", + " from time import sleep\n", + " \n", + " sleep(time) \n", + " return dict(times=time, a2=a, b2=b)\n", + "\n" + ] + } + ], "source": [ "import inspect\n", "\n", @@ -5793,10 +6203,100 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 76, "id": "95d87f0c-3776-46d9-ba64-c4029be57192", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "max_workers: 5\n", + "CPU times: user 9.81 ms, sys: 3.62 ms, total: 13.4 ms\n", + "Wall time: 1.01 s\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
atimesa2b2
011110
121210
231410
341510
451310
\n", + "
" + ], + "text/plain": [ + " a times a2 b2\n", + "0 1 1 1 10\n", + "1 2 1 2 10\n", + "2 3 1 4 10\n", + "3 4 1 5 10\n", + "4 5 1 3 10" + ] + }, + "execution_count": 76, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "%%time\n", "sleep().iter(a=[1,2,3,4,5], max_workers=5, executor=1)" @@ -5804,7 +6304,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 77, "id": "9556bca8-a7aa-4df6-a1b3-13f6c6bfae38", "metadata": {}, "outputs": [], @@ -5816,7 +6316,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 78, "id": "78a1c63a-0805-4e98-b2ab-0353bf753b72", "metadata": {}, "outputs": [], @@ -5835,7 +6335,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 79, "id": "2aa23533-8b09-46fa-8e9b-0fdc0b75d812", "metadata": {}, "outputs": [], @@ -5879,7 +6379,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 80, "id": "4fcc2d23-bdbb-4764-bbdb-ac941ed398d1", "metadata": {}, "outputs": [], @@ -5913,90 +6413,282 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 81, "id": "eb9a7e6f-2171-4d4b-9804-58d09bdd8206", "metadata": {}, - "outputs": [], - "source": [ - "iter(sleep, max_workers=10, a=[1,2,3,4], b=[1,3])" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "cfdce70a-08d5-4528-9c9a-c6f516b8e0df", - "metadata": {}, - "outputs": [], - "source": [ - "type(sleep())()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b228a8bd-f7e8-4fe1-aece-ee7dc56365e8", - "metadata": {}, - "outputs": [], - "source": [ - "import pandas as pd" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f63a9ab5-b265-4f2e-bbfd-28ea12d72346", - "metadata": {}, - "outputs": [], - "source": [ - "pd.DataFrame(dict(a=[1,2,3,4]), index=[2,1,4,3]).sort_index()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "93883fd6-8847-48be-9b10-64fef0588e1f", - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f62e3bcd-a671-4bac-a6d1-c9c2e32575ef", - "metadata": {}, - "outputs": [], - "source": [ - "%%time\n", - "from pyiron_workflow.node_library.atomistic.engine.lammps import Code" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "0a93e2cd-7636-4a33-a793-41d774fc639a", - "metadata": {}, - "outputs": [], - "source": [ - "%config IPCompleter.evaluation='unsafe'\n", - "\n", + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
abtimesa2b2
011111
113113
221121
323123
431131
533133
641141
743143
\n", + "
" + ], + "text/plain": [ + " a b times a2 b2\n", + "0 1 1 1 1 1\n", + "1 1 3 1 1 3\n", + "2 2 1 1 2 1\n", + "3 2 3 1 2 3\n", + "4 3 1 1 3 1\n", + "5 3 3 1 3 3\n", + "6 4 1 1 4 1\n", + "7 4 3 1 4 3" + ] + }, + "execution_count": 81, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "iter(sleep, max_workers=10, a=[1,2,3,4], b=[1,3])" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "id": "cfdce70a-08d5-4528-9c9a-c6f516b8e0df", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "NotData" + ] + }, + "execution_count": 82, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "type(sleep())()" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "id": "b228a8bd-f7e8-4fe1-aece-ee7dc56365e8", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "id": "f63a9ab5-b265-4f2e-bbfd-28ea12d72346", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
a
12
21
34
43
\n", + "
" + ], + "text/plain": [ + " a\n", + "1 2\n", + "2 1\n", + "3 4\n", + "4 3" + ] + }, + "execution_count": 84, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "pd.DataFrame(dict(a=[1,2,3,4]), index=[2,1,4,3]).sort_index()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "93883fd6-8847-48be-9b10-64fef0588e1f", + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 85, + "id": "f62e3bcd-a671-4bac-a6d1-c9c2e32575ef", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 10 µs, sys: 1 µs, total: 11 µs\n", + "Wall time: 15 µs\n" + ] + } + ], + "source": [ + "%%time\n", + "from pyiron_workflow.node_library.atomistic.engine.lammps import Code" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "id": "0a93e2cd-7636-4a33-a793-41d774fc639a", + "metadata": {}, + "outputs": [], + "source": [ + "%config IPCompleter.evaluation='unsafe'\n", + "\n", "from pyiron_workflow import Workflow\n", "import numpy as np" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 87, "id": "14ec45e1-7161-44fb-aac2-99c26a91b02e", "metadata": {}, "outputs": [], "source": [ "wf = Workflow('test')\n", - "wf.register('atomistic', 'pyiron_workflow.node_library.atomistic')" + "wf.register('pyiron_workflow.node_library.atomistic', domain='atomistic')" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 88, "id": "4f2acd98-05de-479c-b5ff-5d2a0a6a5515", "metadata": {}, "outputs": [], @@ -6004,20 +6696,1203 @@ "@Workflow.wrap_as.macro_node('energy_pot')\n", "def energy_at_volume(wf, element='Al', cell_size=2, strain=0):\n", "\n", - " wf.structure = wf.create.atomistic.build.cubic_bulk_cell(element=element, cubic=True, cell_size=cell_size)\n", - " wf.apply_strain = wf.create.atomistic.structure.transform.apply_strain(structure=wf.structure.outputs.structure, strain=strain)\n", - " wf.engine = wf.create.atomistic.engine.lammps.Code(structure=wf.apply_strain) # TODO: find a way to avoid structure=wf.structure !\n", - " wf.calc = wf.create.atomistic.calculator.generic.static(structure=wf.apply_strain, engine=wf.engine)\n", + " wf.structure = wf.create.atomistic.structure.build.cubic_bulk_cell(\n", + " element=element, \n", + " cubic=True, \n", + " cell_size=cell_size\n", + " )\n", + " wf.apply_strain = wf.create.atomistic.structure.transform.apply_strain(\n", + " structure=wf.structure.outputs.structure, \n", + " strain=strain\n", + " )\n", + " wf.engine = wf.create.atomistic.engine.lammps.Code(\n", + " structure=wf.apply_strain\n", + " ) # TODO: find a way to avoid structure=wf.structure !\n", + " wf.calc = wf.create.atomistic.calculator.generic.static(\n", + " structure=wf.apply_strain, \n", + " engine=wf.engine\n", + " )\n", " \n", " return wf.calc.outputs.generic.energy_pot" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 89, "id": "1d9470a3-de9d-4303-b0cd-1da4fd22eeaf", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:652: UserWarning: The keyword 'cubic' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + " warnings.warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Lammps: structure (UserInput) output single-value: \n", + "max_workers: 1\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAj4AAAHFCAYAAADyj/PrAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8g+/7EAAAACXBIWXMAAA9hAAAPYQGoP6dpAABrFElEQVR4nO3deVxUVf8H8M8MzAyLMLLvghsK4oKQa26p4JpmZmaaZFpa5pJm+qsntSe1UlseyyUrzcrKXCp33HPBFdzAXRQUENkRZJs5vz+QyZFFQOAyzOf9es0r586dO9/DJefjuefcIxNCCBAREREZAbnUBRARERHVFAYfIiIiMhoMPkRERGQ0GHyIiIjIaDD4EBERkdFg8CEiIiKjweBDRERERoPBh4iIiIwGgw8REREZDQYfolpk9erVkMlkpT72798vdYnVYurUqZDJZLh48WKp+7z//vuQyWQIDw8v93FlMhnmzJlTBRVKIyMjA/PmzUNgYCCsra2hUqng5eWFMWPGVOjnQET/MpW6ACIqbtWqVWjevHmx7b6+vhJUU/1ee+01fPnll/jhhx/w2WefFXtdq9VizZo1aNOmDdq2bStBhTXv2rVrCAoKQmJiIsaPH4+5c+eiXr16uHHjBtatW4eAgACkpaVBrVZLXSqRQWHwIaqF/Pz8EBgYKHUZyM/Ph0wmg6lp9f5V4efnh3bt2uGnn37C/Pnzi31eaGgobt26hffee69a66gtNBoNnnvuOSQlJSEsLAx+fn6617p164bRo0dj+/btUCgUT/xZQgjk5OTA3Nz8iY9FZAh4qYvIQMlkMkycOBE//fQTfHx8YGFhgdatW2PLli3F9r1y5QpGjBgBR0dHqFQq+Pj44JtvvtHbZ//+/ZDJZPjpp58wbdo0uLm5QaVS4erVqwCAlStXwtvbGyqVCr6+vli7di1CQkLg5eUFoPALtGnTpggODi72+ffu3YNarcZbb71Vantee+01JCQkYPv27cVeW7VqFVQqFV5++WUAQExMDEaOHKnXnsWLF0Or1Zb5M5szZw5kMlmx7UWXGG/cuKHb5uXlhQEDBmDLli3w9/eHubk5fHx8dD/f1atXw8fHB5aWlmjXrh1OnjxZ7LgnT57Es88+C1tbW5iZmcHf3x/r1q0rs0YA+PPPP3Hu3DnMmjVLL/Q8rG/fvrCwsAAAvfPwuPYW/d4sX74cPj4+UKlU+O677+Do6IhRo0YVO0ZaWhrMzc3xzjvv6LZlZGRg+vTpaNiwIZRKJdzc3DBlyhRkZWU9tm1EkhNEVGusWrVKABBHjx4V+fn5eo+CggK9fQEILy8v0a5dO7Fu3Tqxbds20b17d2FqaiquXbum2y8yMlKo1WrRsmVLsWbNGhEaGiqmTZsm5HK5mDNnjm6/ffv2CQDCzc1NDB06VPz9999iy5YtIjk5WaxYsUIAEM8//7zYsmWL+OWXX4S3t7fw9PQUnp6eumN89dVXQiaTicuXL+vV+s033wgAIjIystS2Z2RkCAsLCzF48GC97SkpKUKlUonhw4cLIYRITEwUbm5uwsHBQSxfvlzs2LFDTJw4UQAQEyZMKPYzmj17tu757NmzRUl/7RX93KOjo3XbPD09hbu7u/Dz8xO//vqr2LZtm2jfvr1QKBTiww8/FJ07dxYbN24UmzZtEt7e3sLJyUlkZ2fr3r93716hVCpFly5dxO+//y527NghQkJCBACxatWqUn8OQgjx+uuvCwDiwoULZe5XZPTo0Xrnoaz2Fp3jVq1aibVr14q9e/eK8+fPi6lTpwpzc3ORnp6ut//SpUsFAHH27FkhhBBZWVmiTZs2wt7eXnz++edi9+7d4quvvhJqtVo888wzQqvVlqtmIqkw+BDVIkVfwCU9TExM9PYFIJycnERGRoZuW0JCgpDL5WLBggW6bcHBwcLd3b3YF9rEiROFmZmZSElJEUL8G3y6du2qt59GoxHOzs6iffv2ettv3rwpFAqF3hduRkaGsLKyEpMnT9bb19fXV/To0eOx7R89erRQKBTizp07um1LliwRAMSuXbuEEELMnDlTABDHjh3Te++ECROETCYTly5d0m170uBjbm4ubt26pdt2+vRpAUC4uLiIrKws3fY///xTABB///23blvz5s2Fv7+/yM/P1/usAQMGCBcXF6HRaEr9OfTp00cAEDk5OaXu87CKBh+1Wq0770XOnj0rAIhvv/1Wb3u7du1EQECA7vmCBQuEXC4XJ06c0Ntv/fr1AoDYtm1buWomkgovdRHVQmvWrMGJEyf0HseOHSu2X48ePWBlZaV77uTkBEdHR9y8eRMAkJOTgz179uC5556DhYUFCgoKdI9+/fohJycHR48e1Tvm888/r/f80qVLSEhIwLBhw/S2N2jQAJ07d9bbZmVlhVdffRWrV6/WXfbYu3cvoqKiMHHiRN1+D9dRUFAAIQSAwstd+fn5+Omnn3T7rlq1Cp6enujZs6fueL6+vmjXrp3eZ4eEhEAIgb1795bxk62YNm3awM3NTffcx8cHANC9e3fdZaaHtxf93K9evYqLFy/qLs09+nOPj4/HpUuXqqzOinrmmWdgY2Ojt61ly5YICAjAqlWrdNsuXLiA48ePY8yYMbptW7ZsgZ+fH9q0aaPXruDg4Do985DqDgYfolrIx8cHgYGBeo+AgIBi+9nZ2RXbplKpcP/+fQBAcnIyCgoKsGTJEigUCr1Hv379AABJSUl673dxcdF7npycDKAwVD2qpG1vv/02MjMz8csvvwAAvv76a7i7u2PQoEEAgBs3bhSr5cCBAwCALl26wNvbW/fle/bsWYSHh+PVV1/VjVVJTk4uViMAuLq66tVbFWxtbfWeK5XKMrfn5OQAAO7cuQMAmD59erG2vvnmmwCK/9wf1qBBAwBAdHR0FbSiuJJ+fgAwZswYhIWF6W4rUDS26qWXXtLtc+fOHZw9e7ZYu6ysrCCEKLNdRLUBZ3UR1WE2NjYwMTHBqFGjSh1Y3LBhQ73njw6GLQpXRV/mD0tISCi2rUmTJujbty+++eYb9O3bF3///Tfmzp0LExMTAIUB5cSJE3rvadasme7PY8aMwcyZM3H8+HGsXbsWcrkcISEhevXEx8cX+9y4uDgAgL29fYntBAAzMzMAQG5uLlQqlW57VX9ZF9Uwa9YsDBkypMR9Hm7zo4KDg/Htt9/izz//xMyZMx/7eWZmZsjNzS22vbR2lTTAGwBeeuklvPPOO1i9ejXmzZuHn376CYMHD9brHbK3t4e5uTl++OGHEo9R1s+fqDZg8CGqwywsLNCjRw9ERESgVatWup6JimjWrBmcnZ2xbt06vZk9MTExOHLkiK6n5WGTJ09GUFAQRo8eDRMTE4wbN073mlKpLHOq/ujRo/HBBx9gxYoV+Pvvv9GzZ094enrqXu/ZsycWLFiA8PBwvXv6rFmzBjKZDD169Cj12EUzn86ePYunnnpKt33z5s1l/xAqqFmzZmjatCnOnDmD+fPnV/j9gwYNQsuWLbFgwQIMGDCgxJldO3fuRJcuXWBhYQEvLy8kJibizp07ul64vLw87Ny5s0Kfa2Njg8GDB2PNmjXo2LEjEhIS9C5zAcCAAQMwf/582NnZFQvNRIaAwYeoFjp//jwKCgqKbW/cuDEcHBwqdKyvvvoKTz/9NLp06YIJEybAy8sLmZmZuHr1KjZv3vzYMTFyuRxz587FG2+8gaFDh2LMmDFIS0vD3Llz4eLiArm8+BXz3r17w9fXF/v27dNNOy8vZ2dn9OvXD6tWrYIQAq+99pre61OnTsWaNWvQv39/fPTRR/D09MTWrVuxdOlSTJgwAd7e3qUeu1+/frC1tcVrr72Gjz76CKampli9ejViY2PLXV95rVixAn379kVwcDBCQkLg5uaGlJQUXLhwAeHh4fjjjz9Kfa+JiQk2bdqEoKAgdOzYERMmTECPHj1gaWmJmzdvYv369di8eTNSU1MBAC+++CI+/PBDDB8+HO+++y5ycnLwv//9DxqNpsJ1jxkzBr///jsmTpwId3d39OrVS+/1KVOmYMOGDejatSumTp2KVq1aQavVIiYmBqGhoZg2bRrat29f4c8lqjHSjq0mooeVNasLgFi5cqVuXwDirbfeKnYMT09PMXr0aL1t0dHRYsyYMcLNzU0oFArh4OAgOnXqJD7++GPdPkWzuv74448Sa/v2229FkyZNhFKpFN7e3uKHH34QgwYNEv7+/iXuP2fOHN3U/Ir666+/BABha2tb4symmzdvihEjRgg7OzuhUChEs2bNxMKFC4vNlMIjs7qEEOL48eOiU6dOwtLSUri5uYnZs2eL7777rsRZXf379y/22SX93KOjowUAsXDhQr3tZ86cEcOGDROOjo5CoVAIZ2dn8cwzz4jly5eX6+eQlpYm/vvf/4q2bduKevXqCYVCIRo0aCBGjhwpDh8+rLfvtm3bRJs2bYS5ublo1KiR+Prrr0ud1VXS700RjUYjPDw8BADx/vvvl7jPvXv3xAcffCCaNWsmlEql7nYJU6dOFQkJCeVqG5FUZEI8mE5BRFQBaWlp8Pb2xuDBg/Htt98Wez0wMBAymazYeB4iIinxUhcRPVZCQgLmzZuHHj16wM7ODjdv3sQXX3yBzMxMTJ48WbdfRkYGzp8/jy1btuDUqVPYtGmThFUTERXH4ENEj6VSqXDjxg28+eabSElJgYWFBTp06IDly5ejRYsWuv3Cw8N14Wj27NkYPHiwdEUTEZWAl7qIiIjIaPAGhkRERGQ0GHyIiIjIaDD4EBERkdHg4OZHaLVaxMXFwcrKqtTbuhMREVHtIoRAZmYmXF1dS7yxahEGn0fExcXBw8ND6jKIiIioEmJjY+Hu7l7q6ww+j7CysgJQ+IOztraWuBoiIiIqj4yMDHh4eOi+x0vD4POIostb1tbWDD5EREQG5nHDVDi4mYiIiIwGgw8REREZDQYfIiIiMhoc40NERAZHo9EgPz9f6jKoBikUCpiYmDzxcRh8iIjIYAghkJCQgLS0NKlLIQnUr18fzs7OT3SfPQYfIiIyGEWhx9HRERYWFrzRrJEQQiA7OxuJiYkAABcXl0ofi8GHiIgMgkaj0YUeOzs7qcuhGmZubg4ASExMhKOjY6Uve3FwMxERGYSiMT0WFhYSV0JSKTr3TzK+y6CCzz///IOBAwfC1dUVMpkMf/75p97rQgjMmTMHrq6uMDc3R/fu3REZGSlNsUREVC14ect4VcW5N6jgk5WVhdatW+Prr78u8fXPPvsMn3/+Ob7++mucOHECzs7O6N27NzIzM2u4UiIiIqqNDGqMT9++fdG3b98SXxNC4Msvv8T777+PIUOGAAB+/PFHODk5Ye3atXjjjTdqslQiIiKqhQyqx6cs0dHRSEhIQFBQkG6bSqVCt27dcOTIEQkrIyIioscpaQhLdagzwSchIQEA4OTkpLfdyclJ91pJcnNzkZGRofeoDvkaLY5dT66WYxMREZWEN3ksrs4EnyKPDnwSQpQ5GGrBggVQq9W6h4eHR5XXlFegRccFe/Hit0dxNfFelR+fiIhqPyEEPvvsMzRq1Ajm5uZo3bo11q9fDwDYv38/ZDIZ9uzZg8DAQFhYWKBTp064dOmS3jE2b96MgIAAmJmZoVGjRpg7dy4KCgp0r8tkMixfvhyDBg2CpaUlPv74YwDAxx9/DEdHR1hZWWHs2LGYOXMm2rRpA6Bw4pBCoSjWSTBt2jR07dr1se1avXo16tevjz///BPe3t4wMzND7969ERsbq7ffsmXL0LhxYyiVSjRr1gw//fST7jUvLy8AwHPPPQeZTKZ7Xh3qTPBxdnYGgGInLjExsVgv0MNmzZqF9PR03ePRE1UVlKZytHC1BgCERpXe+0RERBUjhEB2XoEkDyFEhWr94IMPsGrVKixbtgyRkZGYOnUqRo4ciQMHDuj2ef/997F48WKcPHkSpqamGDNmjO61nTt3YuTIkZg0aRKioqKwYsUKrF69GvPmzdP7nNmzZ2PQoEE4d+4cxowZg19++QXz5s3Dp59+ilOnTqFBgwZYtmyZbv+uXbuiUaNGekGkoKAAP//8M1599dVytS07Oxvz5s3Djz/+iMOHDyMjIwPDhw/Xvb5p0yZMnjwZ06ZNw/nz5/HGG2/g1Vdfxb59+wAAJ06cAACsWrUK8fHxuufVQSYqeuZqCZlMhk2bNmHw4MEACn/5XV1dMXXqVMyYMQMAkJeXB0dHR3z66aflHtyckZEBtVqN9PR0WFtbV1m9vxy7ifc3nUdrj/r4663OVXZcIiJjkZOTg+joaDRs2BBmZmYAgOy8Avh+uFOSeqI+CoaFsnxzhLKysmBvb4+9e/eiY8eOuu1jx45FdnY2Xn/9dfTo0QO7d+9Gz549AQDbtm1D//79cf/+fZiZmaFr167o27cvZs2apXv/zz//jBkzZiAuLg5A4XfjlClT8MUXX+j26dChAwIDA/VmRD/99NO4d+8eTp8+DaBwVvTq1asRFRUFAPjrr78wcuRIJCQkwNLSssy2rV69Gq+++iqOHj2K9u3bAwAuXrwIHx8fHDt2DO3atUPnzp3RokULfPvtt7r3DRs2DFlZWdi6dauu9oe/10tS0u9AkfJ+fxtUj0/RSSo6UdHR0Th9+jRiYmJ0J3v+/PnYtGkTzp8/j5CQEFhYWGDEiBHSFg6gt68TZDLgTGwaEtJzpC6HiIhqUFRUFHJyctC7d2/Uq1dP91izZg2uXbum269Vq1a6Pxcty1C0TMOpU6fw0Ucf6b1/3LhxiI+PR3Z2tu59gYGBep996dIltGvXTm/bo89DQkJw9epVHD16FADwww8/YNiwYY8NPUVMTU31Prd58+aoX78+Lly4AAC4cOECOnfW/0d/586dda/XJIOazn7y5En06NFD9/ydd94BAIwePRqrV6/GjBkzcP/+fbz55ptITU1F+/btERoaCisrK6lK1nG0MoO/R32Ex6RhV1QCRnX0krokIiKDZ64wQdRHwZJ9dnlptVoAwNatW+Hm5qb3mkql0oUfhUKh2140PrXovVqtFnPnztXdsuVhD/d+lBRWShr/+jBHR0cMHDgQq1atQqNGjbBt2zbs37+/vM0r8TMe3VbRMbjVxaCCT/fu3cu8piqTyTBnzhzMmTOn5oqqgOAWzgiPScPOyDsMPkREVUAmk5X7cpOUfH19oVKpEBMTg27duhV7/eFen9K0bdsWly5dQpMmTSr02c2aNcPx48cxatQo3baTJ08W22/s2LEYPnw43N3d0bhx42I9NGUpKCjAyZMndT1Jly5dQlpaGpo3bw4A8PHxwaFDh/DKK6/o3nPkyBH4+PjonisUCmg0mgq1rTJq/29LHRLUwhkLtl/E0evJSM/Oh9pC8fg3ERGRwbOyssL06dMxdepUaLVaPP3008jIyMCRI0dQr149eHp6PvYYH374IQYMGAAPDw+88MILkMvlOHv2LM6dO6ebvVWSt99+G+PGjUNgYCA6deqE33//HWfPnkWjRo309gsODoZarcbHH3+Mjz76qELtUygUePvtt/G///0PCoUCEydORIcOHXRB6N1338WwYcPQtm1b9OzZE5s3b8bGjRuxe/du3TG8vLywZ88edO7cGSqVCjY2NhWqobwMaoyPoWtobwlvp3oo0ArsvXRH6nKIiKgG/fe//8WHH36IBQsWwMfHB8HBwdi8eTMaNmxYrvcHBwdjy5Yt2LVrF5566il06NABn3/++WND08svv4xZs2Zh+vTpaNu2LaKjoxESElJscLBcLkdISAg0Go1ez0x5WFhY4L333sOIESPQsWNHmJub47ffftO9PnjwYHz11VdYuHAhWrRogRUrVmDVqlXo3r27bp/Fixdj165d8PDwgL+/f4U+vyIMdlZXdamuWV1FFu28hK/3XUVfP2csGxlQ5ccnIqqryprRQxXTu3dvODs7601hB4Bx48bhzp07+Pvvv8t9rNWrV2PKlClIS0ur4iqLq4pZXbzUVcOCWzjj631Xsf/SXeTka2BWgcFxREREFZWdnY3ly5cjODgYJiYm+PXXX7F7927s2rVLt096ejpOnDiBX375BX/99ZeE1VY/XuqqYX5u1nBVm+F+vgaHriRJXQ4REdVxMpkM27ZtQ5cuXRAQEIDNmzdjw4YN6NWrl26fQYMG4dlnn8Ubb7yB3r17672/b9++elPoH37Mnz+/ppvzxNjjU8NkMhmCWjhj9ZEb2BmZgF6+pd9VmoiI6EmZm5vrDSIuSVlT17/77jvcv3+/xNdsbW1ha2uLkJCQJ6iwZjH4SCDI1wmrj9zA7gt3UKDRwtSEHW9ERFQ7PXrfIUPHb1wJtGtoi/oWCqRm5+PkzVSpyyEiIjIaDD4SMDWRo2fzwktcoZGc1k5EVBFFdzIm41MV556XuiQS1MIJG8JvYWdkAv4zwEeS23YTERkSpVIJuVyOuLg4ODg4QKlU8u9OIyGEQF5eHu7evQu5XA6lUlnpYzH4SKRrUweYKeS4nXYfUfEZaOGqlrokIqJaTS6Xo2HDhoiPj9etRk7GxcLCAg0aNIBcXvkLVgw+EjFXmqBrUweERt3Bzsg7DD5EROWgVCrRoEEDFBQU1Mi6TlR7mJiYwNTU9Il7+Rh8JBTcwhmhUXcQGpmAd3p7S10OEZFBkMlkUCgUeiuZE5UXBzdLqKePI0zkMlxMyERMcrbU5RAREdV5DD4Sqm+hRPuGtgCAnZEJEldDRERU9zH4SCzowZ2bQ6MYfIiIiKobg4/Eglo4AwBO3kzF3cxciashIiKq2xh8JOZa3xwt3dQQAthzgTczJCIiqk4MPrVAcIvCy10c50NERFS9GHxqgaLLXYevJuNeboHE1RAREdVdDD61QFPHemhob4k8jRb7LyVKXQ4REVGdxeBTC8hksn9nd3HRUiIiomrD4FNLFF3u2ncxEXkFXHmYiIioOjD41BL+HvXhYKVCZm4Bwq4nS10OERFRncTgU0vI5TL09uXsLiIiourE4FOLBD+43LUr6g60WiFxNURERHUPg08t0rGRHaxUpribmYuI2DSpyyEiIqpzGHxqEaWpHD2aOwLg2l1ERETVgcGnlglq8e+0diF4uYuIiKgqMfjUMt2bOUJpIkd0UhauJt6TuhwiIqI6hcGnlqmnMkXnJnYAOLuLiIioqjH41EJFs7t28i7OREREVapOBp+lS5eiYcOGMDMzQ0BAAA4ePCh1SRXS08cJMhlw7nY64tLuS10OERFRnVHngs/vv/+OKVOm4P3330dERAS6dOmCvn37IiYmRurSys3BSoVATxsAQCgvdxEREVWZOhd8Pv/8c7z22msYO3YsfHx88OWXX8LDwwPLli2TurQKCfItvNwVGsXLXURERFWlTgWfvLw8nDp1CkFBQXrbg4KCcOTIkRLfk5ubi4yMDL1HbVA0zudYdApSs/IkroaIiKhuqFPBJykpCRqNBk5OTnrbnZyckJBQ8iWjBQsWQK1W6x4eHh41UepjNbCzQHNnK2i0AnsvJkpdDhERUZ1Qp4JPEZlMpvdcCFFsW5FZs2YhPT1d94iNja2JEsslSDe7i+N8iIiIqkKdCj729vYwMTEp1ruTmJhYrBeoiEqlgrW1td6jtgh+cBfnf67cxf08jcTVEBERGb46FXyUSiUCAgKwa9cuve27du1Cp06dJKqq8nxdrOFW3xw5+Vr8c+Wu1OUQEREZvDoVfADgnXfewXfffYcffvgBFy5cwNSpUxETE4Px48dLXVqFyWQy3SDnUN7MkIiI6ImZSl1AVXvxxReRnJyMjz76CPHx8fDz88O2bdvg6ekpdWmVEtTCCT8cjsaei3dQoNHC1KTOZVUiIqIaIxNcAlxPRkYG1Go10tPTa8V4nwKNFu3m70FKVh7WjmuPTo3tpS6JiIio1inv9ze7D2o5UxM5ejZ3BMDLXURERE+KwccA/DvOJwHsoCMiIqo8Bh8D8HRTe1goTRCXnoPzt2vHnaWJiIgMEYOPATBTmKCbtwMA3syQiIjoSTD4GIigBzczDI1i8CEiIqosBh8D8UwzJ5jKZbh85x6ik7KkLoeIiMggMfgYCLWFAh0b2wEoHORMREREFcfgY0CCfAsvd3GcDxERUeUw+BiQ3r6F09ojYtOQmJEjcTVERESGh8HHgDirzdDaoz6EAHZd4M0MiYiIKorBx8AEF83u4l2ciYiIKozBx8AEPbjcdeRaEjJy8iWuhoiIyLAw+BiYJo710NjBEvkagf2X7kpdDhERkUFh8DFAQQ/W7uLsLiIiooph8DFARYuW7r+YiNwCjcTVEBERGQ4GHwPUyk0NJ2sVsvI0OHI1WepyiIiIDAaDjwGSy2W6Qc5cu4uIiKj8GHwMVNGipbui7kCjFRJXQ0REZBgYfAxUh0Z2sDIzRdK9PITHpEpdDhERkUFg8DFQChM5ejZ3BMBFS4mIiMqLwceABeumtd+BELzcRURE9DgMPgasWzMHqEzliEnJxqU7mVKXQ0REVOsx+BgwC6UpujS1BwDsPM+1u4iIiB6HwcfAFd3FmdPaiYiIHo/Bx8D1bO4IuQyIjMtAbEq21OUQERHVagw+Bs6ungpPedkCKLynDxEREZWOwacO4KKlRERE5cPgUwcE+RbexfnEjRSkZOVJXA0REVHtxeBTB3jYWsDXxRpaAey+wMtdREREpWHwqSOKbmYYGsngQ0REVBoGnzqiaNHSg1fuIjuvQOJqiIiIaicGnzqiubMVGthaILdAi38u35W6HCIiolrJYILPvHnz0KlTJ1hYWKB+/fol7hMTE4OBAwfC0tIS9vb2mDRpEvLyjGOwr0wm0w1y3snLXURERCUymOCTl5eHF154ARMmTCjxdY1Gg/79+yMrKwuHDh3Cb7/9hg0bNmDatGk1XKl0gv0Kx/nsuXAH+RqtxNUQERHVPqZSF1Bec+fOBQCsXr26xNdDQ0MRFRWF2NhYuLq6AgAWL16MkJAQzJs3D9bW1jVVqmTaNrCBfT0lku7l4dj1FDz9YB0vIiIiKmQwPT6PExYWBj8/P13oAYDg4GDk5ubi1KlTpb4vNzcXGRkZeg9DZSKXoZdP0eUu3syQiIjoUXUm+CQkJMDJyUlvm42NDZRKJRISSg8BCxYsgFqt1j08PDyqu9RqVTStfVfUHWi1QuJqiIiIahdJg8+cOXMgk8nKfJw8ebLcx5PJZMW2CSFK3F5k1qxZSE9P1z1iY2Mr1ZbaomNjO1gqTZCQkYOzt9OlLoeIiKhWkXSMz8SJEzF8+PAy9/Hy8irXsZydnXHs2DG9bampqcjPzy/WE/QwlUoFlUpVrs8wBGYKE3Rv7oitZ+MRGpmANh71pS6JiIio1pA0+Njb28PevmoG4Hbs2BHz5s1DfHw8XFxcABQOeFapVAgICKiSzzAUQb5O2Ho2HjsjEzCjT3OpyyEiIqo1DGaMT0xMDE6fPo2YmBhoNBqcPn0ap0+fxr179wAAQUFB8PX1xahRoxAREYE9e/Zg+vTpGDdunFHM6HpYj+aOUJjIcO1uFq4m3pO6HCIiolrDYILPhx9+CH9/f8yePRv37t2Dv78//P39dWOATExMsHXrVpiZmaFz584YNmwYBg8ejEWLFklcec2zNlOgY+PCnrTQKM7uIiIiKiITQnDqz0MyMjKgVquRnp5u0D1Fvxy7ifc3nUcbj/r4863OUpdDRERUrcr7/W0wPT5UMb19nCCTAadj05CQniN1OURERLUCg08d5WhtBv8HM7p2XeDaXURERACDT50W9OBmhqG8izMREREABp86reguzmHXkpF+P1/iaoiIiKTH4FOHNbS3hLdTPRRoBfZdTJS6HCIiIskx+NRxQb4PLndxWjsRERGDT11XdLlr/6W7yMnXSFwNERGRtBh86jg/N2u4qs2QnafBoStJUpdDREQkKQafOk4mk/07u4uXu4iIyMgx+BiBIN/C1el3X0hEgUYrcTVERETSYfAxAu0a2kJtrkBKVh5O3UyVuhwiIiLJMPgYAVMTOXr6OAIAdkbyLs5ERGS8GHyMRPBD43y4Li0RERkrBh8j0bWpA8wUctxKvY+o+AypyyEiIpIEg4+RMFeaoGtTBwBAKC93ERGRkWLwMSJF09p3ctFSIiIyUgw+RqRnc0eYyGW4mJCJmORsqcshIiKqcQw+RsTGUol2XrYAeDNDIiIyTgw+Ria4ReHNDDnOh4iIjBGDj5EpGudz4mYKku7lSlwNERFRzWLwMTKu9c3R0k0NIYA9F9jrQ0RExoXBxwgVXe7iXZyJiMjYMPgYoaLLXYeuJOFeboHE1RAREdUcBh8j1NSxHhraWyJPo8WBS3elLoeIiKjGMPgYIZlMhiDfostdnNZORETGg8HHSBVd7tp3MRF5BVqJqyEiIqoZDD5Gyt+jPhysVMjMLUDY9WSpyyEiIqoRDD5GSi6Xobdv0c0MebmLiIiMA4OPESsa57Mr6g60WiFxNURERNWPwceIdWpsDyuVKRIzc3H6VprU5RAREVU7Bh8jpjSVo3tzRwCc3UVERMbBIILPjRs38Nprr6Fhw4YwNzdH48aNMXv2bOTl5entFxMTg4EDB8LS0hL29vaYNGlSsX1I38OLlgrBy11ERFS3mUpdQHlcvHgRWq0WK1asQJMmTXD+/HmMGzcOWVlZWLRoEQBAo9Ggf//+cHBwwKFDh5CcnIzRo0dDCIElS5ZI3ILaq3szRyhN5IhOysLVxHto6mQldUlERETVRiYM9J/5CxcuxLJly3D9+nUAwPbt2zFgwADExsbC1dUVAPDbb78hJCQEiYmJsLa2LtdxMzIyoFarkZ6eXu73GLpXVx3Hvkt38W5wM7zVo4nU5RAREVVYeb+/DeJSV0nS09Nha2urex4WFgY/Pz9d6AGA4OBg5Obm4tSpU1KUaDCCH9zMkON8iIiorjPI4HPt2jUsWbIE48eP121LSEiAk5OT3n42NjZQKpVISCj9Cz03NxcZGRl6D2PT08cJMhlw9lY64tLuS10OERFRtZE0+MyZMwcymazMx8mTJ/XeExcXhz59+uCFF17A2LFj9V6TyWTFPkMIUeL2IgsWLIBardY9PDw8qqZxBsTBSoVATxsAhff0ISIiqqskHdw8ceJEDB8+vMx9vLy8dH+Oi4tDjx490LFjR3z77bd6+zk7O+PYsWN621JTU5Gfn1+sJ+hhs2bNwjvvvKN7npGRYZThJ8jXGSdupCI0KgGjO3lJXQ4REVG1qFDwEULgwIEDOHjwIG7cuIHs7Gw4ODjA398fvXr1qnBgsLe3h729fbn2vX37Nnr06IGAgACsWrUKcrl+Z1XHjh0xb948xMfHw8XFBQAQGhoKlUqFgICAUo+rUqmgUqkqVHddFNTCCfO2XcDR6ylIy85DfQul1CURERFVuXJd6rp//z7mz58PDw8P9O3bF1u3bkVaWhpMTExw9epVzJ49Gw0bNkS/fv1w9OjRKi8yLi4O3bt3h4eHBxYtWoS7d+8iISFBb+xOUFAQfH19MWrUKERERGDPnj2YPn06xo0bZzSzs56Ep50lmjtbQaMV2HMhUepyiIiIqkW5eny8vb3Rvn17LF++HMHBwVAoFMX2uXnzJtauXYsXX3wRH3zwAcaNG1dlRYaGhuLq1au4evUq3N3d9V4rmo1vYmKCrVu34s0330Tnzp1hbm6OESNG6O7zQ48X1MIZFxMyERqVgOcD3B//BiIiIgNTrvv4nD9/Hn5+fuU6YF5eHm7evImmTZs+cXFSMMb7+BQ5fzsdA5YcgplCjoj/BMFcaSJ1SUREROVSpffx8fPzw+nTp8v1wUql0mBDj7Fr4WoNt/rmyMnX4uCVu1KXQ0REVOXKPZ29bdu2CAgIwLJly5Cenl6dNZFEZDIZgh6s3bUzktPaiYio7il38Dl8+DDatm2LmTNnwsXFBSNHjsS+ffuqszaSQNFdnPdcvIMCjVbiaoiIiKpWuYNPx44dsXLlSiQkJGDZsmW4desWevXqhcaNG2PevHm4detWddZJNSTQ0wY2FgqkZefj+I0UqcshIiKqUhW+c7O5uTlGjx6N/fv34/Lly3jppZewYsUK3XR2MmymJnL08im83BXKy11ERFTHPNGSFY0bN8bMmTPx/vvvw9raGjt37qyqukhCRZe7dkXdQTkm/RERERmMSgefAwcOYPTo0XB2dsaMGTMwZMgQHD58uCprI4k83dQeFkoT3E67j8g441u0lYiI6q4KBZ/Y2Fj897//RePGjdGjRw/dKulxcXFYuXIlOnToUF11Ug0yU5igm7cDAGBnZOkr2xMRERmacgef3r17o2HDhli6dCmGDh2KCxcu4NChQ3j11VdhaWlZnTWSBIqmtXOcDxER1SXlXqTU3NwcGzZswIABA2Biwjv61nXPNHOCqVyGS3cyEZ2UhYb2DLdERGT4yt3j8/fff2PQoEG60HP16lXs3LkT9+/fBwAOgq1j1BYKdGpiDwD45ehNiashIiKqGhUe3JycnIyePXvC29sb/fr1Q3x8PABg7NixmDZtWpUXSNIZ09kLALD2eAzSsvOkLYaIiKgKVDj4TJ06FQqFAjExMbCwsNBtf/HFF7Fjx44qLY6k1c3bAT4u1sjO02BNGHt9iIjI8FU4+ISGhuLTTz+Fu7u73vamTZvi5k1+OdYlMpkME7o3BgCsOhyN7LwCiSsiIiJ6MhUOPllZWXo9PUWSkpKgUqmqpCiqPfr5OaOBrQVSs/Ox7kSs1OUQERE9kQoHn65du2LNmjW65zKZDFqtFgsXLkSPHj2qtDiSnqmJHK93bQQAWHkwGvlcuJSIiAxYuaezF1m4cCG6d++OkydPIi8vDzNmzEBkZCRSUlJ45+Y6amiAO77cfQW30+5j85k4DGnr/vg3ERER1UIV7vHx9fXF2bNn0a5dO/Tu3RtZWVkYMmQIIiIi0Lhx4+qokSRmpjDBmKe9AADLD1yDVstbFxARkWGSCd6AR09GRgbUajXS09NhbW0tdTm1RkZOPjov2IvM3AJ890ogevk6SV0SERGRTnm/v8vV4xMTE1OhD799+3aF9qfaz9pMgZc7eAIAlu6/yhtWEhGRQSpX8Hnqqacwbtw4HD9+vNR90tPTsXLlSvj5+WHjxo1VViDVHmM6e0FpKkd4TBpO3EiVuhwiIqIKK9fg5gsXLmD+/Pno06cPFAoFAgMD4erqCjMzM6SmpiIqKgqRkZEIDAzEwoUL0bdv3+qumyTgaG2GoQHuWHssBsv2X0W7hu2kLomIiKhCKjTGJycnB9u2bcPBgwdx48YN3L9/H/b29vD390dwcDD8/Pyqs9YawTE+ZbuRlIVnFu+HVgDbJ3eBjwt/RkREJL3yfn9zcPMjGHweb+LacGw5G49BbVzx1XB/qcshIiKq2sHNRA8b363wtgWbz8QhJjlb4mqIiIjKj8GHKszPTY2u3g7QCmDlwetSl0NERFRuDD5UKRMe9PqsOxmLu5m5EldDRERUPgw+VCkdGtmijUd95BZosfpItNTlEBERlUulVmcnkslkmNC9sNdnTdhNZObkS1wRERHR41U4+Dg5OWHMmDE4dOhQddRDBqS3jxMaO1giM6cAa49V7O7eREREUqhw8Pn111+Rnp6Onj17wtvbG5988gni4uKqozaq5eRymW6G13eHopGTr5G4IiIiorJVOPgMHDgQGzZsQFxcHCZMmIBff/0Vnp6eGDBgADZu3IiCgoLqqJNqqUFt3OCiNsPdzFxsiuAabUREVLtVenCznZ0dpk6dijNnzuDzzz/H7t27MXToULi6uuLDDz9EdnbV3t/l2WefRYMGDWBmZgYXFxeMGjWqWE9TTEwMBg4cCEtLS9jb22PSpEnIy8ur0jpIn9JUjrFdGgEAVhy4Bo2W98MkIqLaq9LBJyEhAZ999hl8fHwwc+ZMDB06FHv27MEXX3yBTZs2YfDgwVVYJtCjRw+sW7cOly5dwoYNG3Dt2jUMHTpU97pGo0H//v2RlZWFQ4cO4bfffsOGDRswbdq0Kq2Dihv+lAfqWyhwIzkbO84nSF0OERFRqSq8ZMXGjRuxatUq7Ny5E76+vhg7dixGjhyJ+vXr6/aJjIyEv79/tfa2/P333xg8eDByc3OhUCiwfft2DBgwALGxsXB1dQUA/PbbbwgJCUFiYmK5l5/gkhWV88Wuy/hqzxX4uVlj88SnIZPJpC6JiIiMSLUtWfHqq6/C1dUVhw8fxunTpzFx4kS90AMAjRo1wvvvv1/hossrJSUFv/zyCzp16gSFQgEACAsLg5+fny70AEBwcDByc3Nx6tSpUo+Vm5uLjIwMvQdVXEgnL5grTHD+dgYOXU2SuhwiIqISVTj4xMfHY8WKFXjqqadK3cfc3ByzZ89+osJK8t5778HS0hJ2dnaIiYnBX3/9pXstISEBTk5Oevvb2NhAqVQiIaH0yy8LFiyAWq3WPTw8PKq8bmNgY6nES+0aAACW7b8mcTVEREQlq3DwKSgoKNZDkpGRgczMzApf2pozZw5kMlmZj5MnT+r2f/fddxEREYHQ0FCYmJjglVdewcNX6kq6vCKEKPOyy6xZs5Cenq57xMbGVqgN9K+xXRrCVC7DkWvJOB2bJnU5RERExZhW9A3169cvM0i4u7sjJCQEs2fPhlxedq6aOHEihg8fXuY+Xl5euj/b29vD3t4e3t7e8PHxgYeHB44ePYqOHTvC2dkZx44d03tvamoq8vPzi/UEPUylUkGlUpVZA5WPa31zDPZ3w/pTt7B8/zUsHxUgdUlERER6Khx8Vq9ejffffx8hISFo164dhBA4ceIEfvzxR3zwwQe4e/cuFi1aBJVKhf/7v/8r81hFQaYyinp6cnMLF8js2LEj5s2bh/j4eLi4uAAAQkNDoVKpEBDAL+CaMr5bI6w/dQs7oxJwNfEemjjWk7okIiIinQrP6urZsyfeeOMNDBs2TG/7unXrsGLFCuzZswc//fQT5s2bh4sXL1ZJkcePH8fx48fx9NNPw8bGBtevX8eHH36I+Ph4REZGQqVSQaPRoE2bNnBycsLChQuRkpKCkJAQDB48GEuWLCn3Z3FW15N7fc1JhEbdwbBAd3w2tLXU5RARkRGotlldYWFh8Pf3L7bd398fYWFhAICnn34aMTFVt3aTubk5Nm7ciJ49e6JZs2YYM2YM/Pz8cODAAd1lKhMTE2zduhVmZmbo3Lkzhg0bhsGDB2PRokVVVgeVz/gHi5duiriN+PT7EldDRET0rwpf6nJ3d8f333+PTz75RG/7999/r5sRlZycDBsbm6qpEEDLli2xd+/ex+7XoEEDbNmypco+lyqnbQMbdGhki6PXU/D9wWh8MMBX6pKIiIgAVCL4LFq0CC+88AK2b9+Op556CjKZDCdOnMDFixexfv16AMCJEyfw4osvVnmxZDgmdG+Co9ePY+3xGEx8pgnqWyilLomIiKjiY3wA4ObNm1i+fDkuXboEIQSaN2+ON954Q28GlqHiGJ+qIYRA//8dQlR8Bt7p7Y1JPZtKXRIREdVh5f3+rlDwyc/PR1BQEFasWAFvb+8qKbS2YfCpOpvPxOHtXyNgY6HA4ZnPwEJZ4Q5GIiKicqmWwc0KhQLnz5/nOkxULn39nOFpZ4HU7HysO8EbQxIRkfQqPKvrlVdewffff18dtVAdY2oix+tdGwEAVh6MRr5GK3FFRERk7Cp87SEvLw/fffcddu3ahcDAQFhaWuq9/vnnn1dZcWT4nm/rji92XcHttPvYfCYOQ9q6S10SEREZsQoHn/Pnz6Nt27YAgMuXL+u9xktg9CgzhQlee7ohPt1xEcsPXMPgNm6Qy/l7QkRE0qhw8Nm3b1911EF12MsdGmDpvqu4fOce9l5MRC/f0tdOIyIiqk4VHuNT5OrVq9i5cyfu3y+8M28lZsWTkbA2U2BkR08AwNL9V/m7QkREkqlw8ElOTkbPnj3h7e2Nfv36IT4+HgAwduxYTJs2rcoLpLrh1c5eUJrKER6ThuPRKVKXQ0RERqrCwWfq1KlQKBSIiYmBhYWFbvuLL76IHTt2VGlxVHc4WpnhhYDCgc3LDlyTuBoiIjJWFQ4+oaGh+PTTT+Hurj87p2nTprh582aVFUZ1z+tdG0EuA/ZfuououAypyyEiIiNU4eCTlZWl19NTJCkpSbdSOlFJPO0s0b+VKwBgOXt9iIhIAhUOPl27dsWaNWt0z2UyGbRaLRYuXIgePXpUaXFU94zvVnhDwy1n4xCTnC1xNUREZGwqPJ194cKF6N69O06ePIm8vDzMmDEDkZGRSElJweHDh6ujRqpDWriq0c3bAQcu38W3B6/h48EtpS6JiIiMSIV7fHx9fXH27Fm0a9cOvXv3RlZWFoYMGYKIiAg0bty4OmqkOmZC98Lfk3Unb+FuZq7E1RARkTGp0OrsxoCrs1c/IQSGLDuCiJg0vNm9MWb0aS51SUREZODK+/1d4UtdAJCWlobjx48jMTERWq3+wpOvvPJKZQ5JRkQmk2FCt8Z4/adT+CnsJsZ3bwxrM4XUZRERkRGocPDZvHkzXn75ZWRlZcHKykpvfS6ZTMbgQ+XSy8cJTRzr4WriPaw9FoPx3XiZlIiIql+Fx/hMmzYNY8aMQWZmJtLS0pCamqp7pKTwjrxUPnK5TBd2vj8UjZx8jcQVERGRMahw8Ll9+zYmTZpU4r18iCri2daucFWb4W5mLjaG35a6HCIiMgIVDj7BwcE4efJkddRCRkZpKsfYLoX39VnxzzVotBxnT0RE1avCY3z69++Pd999F1FRUWjZsiUUCv1Bqc8++2yVFUd13/B2Hvjf3iu4mZyN7efjMeDBnZ2JiIiqQ4Wns8vlpXcSyWQyaDSGPVaD09lr3pe7L+PL3VfQwtUaW95+Wm/APBERUXmU9/u7wpe6tFptqQ9DDz0kjdEdvWCuMEFkXAYOXkmSuhwiIqrDKhx8iKqajaUSL7VrAABYtp+LlxIRUfUpd/Dp168f0tPTdc/nzZuHtLQ03fPk5GT4+vpWaXFkPMZ2aQhTuQxh15MREZMqdTlERFRHlTv47Ny5E7m5/66r9Omnn+rdt6egoACXLl2q2urIaLjWN8dgfzcAwPID7PUhIqLqUe7g8+gYaC7xRVVtfLfCqe07I+/gamKmxNUQEVFdxDE+VGs0cbRCkK8TAGDFgesSV0NERHVRuYOPTCYrNs2Y046pqo3vXriMxZ+nbyMu7b7E1RARUV1T7hsYCiEQEhIClUoFAMjJycH48eNhaWkJAHrjf4gqq20DG3RoZIuj11Pw/aFo/GcAB8wTEVHVKXePz+jRo+Ho6Ai1Wg21Wo2RI0fC1dVV99zR0bFGVmbPzc1FmzZtIJPJcPr0ab3XYmJiMHDgQFhaWsLe3h6TJk1CXl5etddEVWtC9yYAgF+PxyA1i+ePiIiqTrl7fFatWlWddZTbjBkz4OrqijNnzuht12g06N+/PxwcHHDo0CEkJydj9OjREEJgyZIlElVLldG1qT18XawRFZ+BNWE3MblXU6lLIiKiOsKgBjdv374doaGhWLRoUbHXQkNDERUVhZ9//hn+/v7o1asXFi9ejJUrVyIjI0OCaqmyZDIZJjwY67P6SDSy8wokroiIiOoKgwk+d+7cwbhx4/DTTz/BwsKi2OthYWHw8/ODq+u/i1wGBwcjNzcXp06dKvW4ubm5yMjI0HuQ9Pr6OcPTzgKp2fn4/USs1OUQEVEdYRDBp2hg9fjx4xEYGFjiPgkJCXByctLbZmNjA6VSiYSEhFKPvWDBAt04JbVaDQ8PjyqtnSrH1ESO17sW3tdn5T/Xka/RSlwRERHVBZIGnzlz5uimyZf2OHnyJJYsWYKMjAzMmjWrzOOVNL1eCFHmtPtZs2YhPT1d94iNZe9CbfF8W3fY11MhLj0Hf5+Ok7ocIiKqA8o9uLk6TJw4EcOHDy9zHy8vL3z88cc4evSobip9kcDAQLz88sv48ccf4ezsjGPHjum9npqaivz8/GI9QQ9TqVTFjku1g5nCBK893RCf7riI5Qeu4Tl/N8jlvHcUERFVnkwYwNoTMTExemNv4uLiEBwcjPXr16N9+/Zwd3fH9u3bMWDAANy6dQsuLi4AgN9//x2jR49GYmIirK2ty/VZGRkZUKvVSE9PL/d7qPpk5OSj84K9yMwtwMpXAtHbt/QQS0RExqu839+S9viUV4MGDfSe16tXDwDQuHFjuLu7AwCCgoLg6+uLUaNGYeHChUhJScH06dMxbtw4BhgDZm2mwMiOnli2/xqW7r+KXj6OvGM4ERFVmkEMbi4PExMTbN26FWZmZujcuTOGDRuGwYMHlzj1nQzLq529oDSVIyImDcejU6Quh4iIDJhB9Pg8ysvLq8TV4Rs0aIAtW7ZIUBFVJ0crM7wQ4I5fjsVg2YFraN/ITuqSiIjIQNWZHh+q217v2ghyGbD/0l1ExfFeS0REVDkMPmQQPO0s0b9V4c0plx+4JnE1RERkqBh8yGCM71Z4Q8MtZ+MQk5wtcTVERGSIGHzIYLRwVaObtwO0Avj2IHt9iIio4hh8yKAULV667uQt3M3MlbgaIiIyNAw+ZFDaN7SFf4P6yCvQYtXhaKnLISIiA8PgQwZFJpNhQrfCXp+fwm4iIydf4oqIiMiQMPiQwenl44QmjvWQmVuAtcdipC6HiIgMCIMPGRy5XIbxD3p9vj8UjZx8jcQVERGRoWDwIYP0bGtXuKrNcDczFxvDb0tdDhERGQgGHzJISlM5xnYpvK/Pin+uQaMtvoQJERHVLgUaLS7fyZS0BgYfMljD23mgvoUCN5Ozse1cvNTlEBFRGS4mZOC5pUcw/NujSLon3e1IGHzIYFkoTRHSyQsAsGz/tRIXriUiImnla7RYsucKBi45hHO306HRClxNvCdZPQw+ZNBGd/SCucIEUfEZ+OdKktTlEBHRQy7EZ2DwN4exeNdl5GsEevk4YdfUrujQyE6ymhh8yKDZWCrxUrsGAIBl+69KXA0REQFAXoEWX+6+jIFLDiEyLgP1LRT4angbrHwlAI7WZpLWxuBDBm9sl4Ywlctw9HoKwmNSpS6HiMioRcalY9A3h/Hl7iso0AoE+TohdGpXDGrjBplMJnV5DD5k+Fzrm2OwvxsAYPl+Ll5KRCSFvAItPt91GYO+PowL8RmwsVDgfy/5Y8WoADhaSdvL8zBTqQsgqgrjuzXChvBbCI26g6uJmWjiaCV1SURERuP87XRM/+MMLiYUTlXv6+eMjwb5wcFKJXFlxbHHh+qEJo5WCPJ1AgAsP3Bd4mqIiIxDboEGi0MvYdA3h3ExIRO2lkp8M6Itlo0MqJWhB2DwoTqkaBmLPyNu43bafYmrISKq287dSsezSw5jyd6r0GgF+rdywa6pXdG/lYvUpZWJwYfqDP8GNujYyA4FWoGZG85Cy7s5ExFVudwCDRbuvIjBSw/j0p1M2FkqsfTltvhmRFvY1audvTwPY/ChOmXuoBYwU8hx8EoSvtnH6e1ERFXpTGwaBi45hG/2FS4VNLC1K0KndkW/lrW7l+dhDD5Up3g7WeG/g/wAAF/svowj13hTQyKiJ5WTr8GnOy7iuaWHcfnOPdjXU2L5yLZY8pK/QfTyPIzBh+qcFwI98EKAO7QCmPTraSRm5khdEhGRwYqIScWAJYewbP81aAUwqI0rQqd2Qx8/w+nleRiDD9VJHw3yQzMnKyTdy8XkX09z9XYiogrKyddgwfYLeH7ZEVxNvAf7eiqsGBWAr4b7w9ZSKXV5lcbgQ3WSudIE37zcFhZKE4RdT8ZXuy9LXRIRkcEIj0lF//8dxIoD16EVwHP+btj9TlcEt3CWurQnxuBDdVYTx3qY/1xLAMCSfVfxz+W7EldERFS75eRrMH/bBQxddgTX7mbBwUqFla8E4osX26C+heH28jyMwYfqtMH+bnipXQMIAUz9/TTuZHC8DxFRSU7dTEG/rw7i238Ke3mGtHXDrqld0fvBzWHrCgYfqvNmD/SFj4s1krPy8PbaCBRotFKXRERUa9zP0+DjLVEYujwM15Oy4GStwvejA/H5sLrTy/MwBh+q88wUJlj6clvUU5ni+I0ULN7F8T5ERABw4kYK+v3vIL47FA0hgKEB7gid0g09fepWL8/DGHzIKDS0t8QnzxeO91m2/xr2XUyUuCIiIuncz9Pgo81RGLYiDNFJWXC2NsOqkKew6IXWUFsopC6vWhlM8PHy8oJMJtN7zJw5U2+fmJgYDBw4EJaWlrC3t8ekSZOQl5cnUcVU2wxo5YpXOnoCAKauO404rudFREbo2PVk9PnqH/xwuLCXZ1igO3ZO7YoezR2lLq1GmEpdQEV89NFHGDdunO55vXr1dH/WaDTo378/HBwccOjQISQnJ2P06NEQQmDJkiVSlEu10Pv9fRARk4Zzt9MxcW04fn+jIxQmBpP/iYgqLTuvAJ/tuITVR24AAFzUZlgwpCW6NzOOwFPEoIKPlZUVnJ1LvodAaGgooqKiEBsbC1dXVwDA4sWLERISgnnz5sHa2romS6VaSmVqgm9GtEX/JQcRHpOGz3ZcxPv9faUui4ioWh29nowZ688iJiUbADD8KQ/8X38fWJvV7ctaJTGof+p++umnsLOzQ5s2bTBv3jy9y1hhYWHw8/PThR4ACA4ORm5uLk6dOiVFuVRLNbCzwMKhrQEAKw9GY1fUHYkrIiKqHlm5Bfjwr/MY/u1RxKRkw1VthjVj2uGT51sZZegBDKjHZ/LkyWjbti1sbGxw/PhxzJo1C9HR0fjuu+8AAAkJCXBy0h+FbmNjA6VSiYSEhFKPm5ubi9zcXN3zjIyM6mkA1Sp9/JwxpnND/HA4GtPWncbWSV3gYWshdVlERFXmyLUkvLfhLGJTCsczvtSuAf6vX3NYGWngKSJpj8+cOXOKDVh+9HHy5EkAwNSpU9GtWze0atUKY8eOxfLly/H9998jOTlZdzyZTFbsM4QQJW4vsmDBAqjVat3Dw8Oj6htKtdLMvs3R2qM+MnIKMHFtOPIKeH8fIjJ8WbkF+ODPcxix8hhiU+7Drb45fn6tPRYMaWn0oQcAZEIIyVZvTEpKQlJSUpn7eHl5wczMrNj227dvw93dHUePHkX79u3x4Ycf4q+//sKZM2d0+6SmpsLW1hZ79+5Fjx49Sjx+ST0+Hh4eSE9P57ggI3ArNRv9/3cI6ffzEdLJC3OebSF1SURElXb4amEvz63Uwl6el9s3wKx+PqinMpgLPJWWkZEBtVr92O9vSX8S9vb2sLe3r9R7IyIiAAAuLi4AgI4dO2LevHmIj4/XbQsNDYVKpUJAQECpx1GpVFCpVJWqgQyfu40FPh/WGq/9eBKrj9xA+4a26NvSReqyiIgqJDMnHwu2X8TaYzEAAHcbc3z2fCt0alK579i6zCAiYFhYGI4ePYoePXpArVbjxIkTmDp1Kp599lk0aNAAABAUFARfX1+MGjUKCxcuREpKCqZPn45x48ax54bK1NPHCW90bYQV/1zHjPVn4etqDU87S6nLIiIql4NX7mLmhnO4/eDeZKM6eGJm3+awNIJensqQ9FJXeYWHh+PNN9/ExYsXkZubC09PTwwfPhwzZsyAhcW/A1JjYmLw5ptvYu/evTA3N8eIESOwaNGiCvXolLerjOqWfI0WL317FCdvpqKFqzU2TOgEM4WJ1GUREZUqMycf87ddwK/HYwEAHrbm+PT5VujU2Dh7ecr7/W0QwacmMfgYr/j0++j/v0NIycrDyA4N8PHgllKXRERUop2RCZjzdyTi03MAACGdvPBucDOj7uUp7/e3Qd3Hh6g6uajN8fmwwvv7/Hw0Bn+fiZO4IiIifXFp9zFuzUm88dMpxKfnwNPOAr+93gFznm1h1KGnIhh8iB7SvZkj3urRGAAwa8NZXLt7T+KKiIiAAo0W3x28jl6fH8CuqDswlcvwVo/G2DmlKzo0spO6PIPCeEj0iKm9vHHyRiqORafgrV/C8edbnTneh4gkcyY2DbM2nkNUfOENdp/yssG851rC28lK4soME3t8iB5haiLHkpf8YV9PiYsJmZjzd6TUJRGREcrMycfsv85j8NLDiIrPgNpcgU+fb4nfX+/I0PMEGHyISuBobYavhvtDJgN+OxGLjeG3pC6JiIyEEALbzsWj1+cH8GPYTQgBPOfvhj3TuuHFpxpALi99NQJ6PF7qIipF5yb2mNyzKb7cfQXvbzqPlm5qNOW/soioGsWmZGP235HYezERAOBlZ4GPB7fE002Nc4p6dWCPD1EZ3n6mKZ5uYo/7+Rq8+Us4svMKpC6JiOqgfI0WKw5cQ9AX/2DvxUQoTGSY1LMpdkzpytBTxRh8iMpgIpfhixfbwMFKhSuJ9/DBn+fBW18RUVUKj0nFwCWHsGD7RdzP16B9Q1tsn9wV7/T25sSKasDgQ/QYDlYqLHnJH3IZsDH8Nv44yfE+RPTk0u/n44M/z+H5ZUdwMSETNhYKLBzaCr+93gFNHOtJXV6dxeBDVA4dGtlhWlAzAMB//jqPiwkZEldERIZKCIHNZ+LQ6/MD+PloDIQAhga4Y8+07ngh0AMyGQcvVycGH6JymtCtMbp5OyC3QIs3fwnHvVyO9yGiiolJzsboVSfw9q8RuJuZi0YOlvh1XAcseqE1bC2VUpdnFBh8iMpJ/mC8j7O1Ga7fzcL7m85xvA8RlUu+Roul+6+i9xcH8M/lu1CayjG1lze2T+6Cjo155+WaxOBDVAG2lkp8PcIfJnIZ/jodh7XHY6QuiYhquZM3UtD/fwfx2Y5LyC3QolNjO+yY3AWTezWFypSDl2sagw9RBQV62WJGcOF4n7mbo3D+drrEFRFRbZSWnYdZG89i6PIwXL5zD7aWSnzxYmv8MrY9Gjlw8LJUGHyIKmFcl0bo2dwReQVaTFwbjoycfKlLIqJaQgiBPyNuo+fiA/j1eCwAYPhTHtg7rRue83fn4GWJMfgQVYJcLsPiYa3hVt8cN5KzMXPDWY73ISLcSMrCqO+PY8rvp5GclYemjvWw7o2O+OT5VqhvwcHLtQGDD1El1bcoHO+jMJFh27kErAm7KXVJRCSR3AINluy5gqAv/8Ghq0lQmcrxbnAzbJ3UBe0a2kpdHj2EwYfoCfg3sMHMvj4AgI+3RuHsrTRpCyKiGnfsejL6fXUQi3ddRl6BFl2a2iN0ale81aMJlKb8mq1teEaIntCYzl4IbuGEfI3Am7+EIz2b432IjEFqVh7e/eMMXvz2KK7dzYJ9PRW+Gt4Ga8a0g6edpdTlUSkYfIiekEwmw2dDW8PD1hy3Uu9j+vozHO9DVIcJIbD+1C30/PwA/jhVuITNiPYNsOedbhjUxo2Dl2s5Bh+iKqA2V2DpiAAoTeTYFXUH3x+KlrokIqoG1+7ew0srj2L6H2eQkpWHZk5W2DChI+Y/1xJqC4XU5VE5MPgQVZGW7mp8MKBwvM8n2y8iPCZV4oqIqKrk5Gvwxa7L6PvlQRy9ngIzhRwz+zbHlklPI8CTg5cNCYMPURUa1cET/Vu5oEArMPGXcKRm5UldEhE9oSPXktDvq4P4as8V5Gm06N7MAbumdsP4bo2hMOHXqKExlboAorpEJpPhkyEtERWXgeikLEz74wy+eyUQcjmv+RMZmuR7uZi37QI2ht8GADhYqTBnYAv0a+nMcTwGjFGVqIpZmSnw9Qh/KE3l2HsxEd8evC51SURUAUIIrDsRi56fH8DG8NuQyYBXOnpiz7Ru6N/KhaHHwLHHh6gatHBVY87AFvi/TeewcOclBHja4CkvjgMgqu2uJmbi/zadx/HoFACAj4s1FgxpiTYe9aUtjKoMe3yIqslL7TwwuI0rNFqBiWvDkXwvV+qSiKgUOfkaLNp5CX2/Oojj0SkwV5jgg/4+2DyxM0NPHcMeH6JqIpPJMO+5ljh3Ox3X7mZh6rozWB3yFMf7ENUiWq3A5rNxWBx6GTEp2QCAXj6OmPNsC7jbWEhcHVUH9vgQVSNLlSmWvhwAM4Uc/1y+i6X7r0pdEhGhcBzPvouJ6L/kECb/dhoxKdlwtjbD8pEBWPlKIENPHcYeH6Jq1szZCv8d5Id315/F57suo62nDTo1tpe6LCKjdepmCj7dfgnHbxSO47FSmWJ898Z4tbMXLJT8WqzreIaJasALgR44Fp2C9aduYfJvp7FtUhc4WKmkLovIqFxKyMTCnZew+8IdAIDKVI6QTl4Y360xbCyVEldHNYXBh6iG/HeQH87eSsPlO/cw+bcI/PRae5hwvA9RtYtNycYXuy9jU8RtCAGYyGUYFuiOST2bwkVtLnV5VMMMaozP1q1b0b59e5ibm8Pe3h5DhgzRez0mJgYDBw6EpaUl7O3tMWnSJOTl8c65VDuYK02w9OW2sFCa4Mi1ZPxvzxWpSyKq0+5m5mLO35F4ZvF+bAwvDD39W7ogdGpXLBjSiqHHSBlMj8+GDRswbtw4zJ8/H8888wyEEDh37pzudY1Gg/79+8PBwQGHDh1CcnIyRo8eDSEElixZImHlRP9q4miF+c+1xJTfT+N/e68g0MsGXZo6SF0WUZ2SmZOPlf9cx3eHopGdpwEAdGlqj3eDm6GVe31piyPJyYQQQuoiHqegoABeXl6YO3cuXnvttRL32b59OwYMGIDY2Fi4uroCAH777TeEhIQgMTER1tbW5fqsjIwMqNVqpKenl/s9RBU1a+NZ/Ho8FnaWSmyb3AVO1mZSl0Rk8HLyNfj56E18s+8qUrPzAQCt3dWY0ac5OjfhhIK6rrzf3wZxqSs8PBy3b9+GXC6Hv78/XFxc0LdvX0RGRur2CQsLg5+fny70AEBwcDByc3Nx6tSpUo+dm5uLjIwMvQdRdZs9sAV8XKyRnJWHt3+NQIFGK3VJRAarQKPFuhOxeGbRfny89QJSs/PR2MESy0e2xZ9vdWboIT0GEXyuXy9c62jOnDn44IMPsGXLFtjY2KBbt25ISSmcjpiQkAAnJye999nY2ECpVCIhIaHUYy9YsABqtVr38PDwqL6GED1gpjDBNyP8UU9liuPRKfhi92WpSyIyOEII7Dgfj+Av/8GMDWcRl54DF7UZPnu+FXZO6Yo+flxXi4qTNPjMmTMHMpmszMfJkyeh1Rb+a/j999/H888/j4CAAKxatQoymQx//PGH7ngl/YILIcr8xZ81axbS09N1j9jY2KpvKFEJGjnUwyfPtwQAfLPvGlYdjoZWW+uvPBPVCkeuJmHw0iMY/3M4rt3NQn0LBT7o74N907tj2FMeMDUxiH/XkwQkHdw8ceJEDB8+vMx9vLy8kJmZCQDw9fXVbVepVGjUqBFiYmIAAM7Ozjh27Jjee1NTU5Gfn1+sJ+hhKpUKKhXvp0LSGNDKFSeiU/Bj2E3M3RyF7ecS8MnzLdHIoZ7UpRHVSudupeOznRdx8EoSAMBCaYKxTzfE2K6NYG2mkLg6MgSSBh97e3vY2z/+2mtAQABUKhUuXbqEp59+GgCQn5+PGzduwNPTEwDQsWNHzJs3D/Hx8XBxcQEAhIaGQqVSISAgoPoaQfSEZg9sgUYO9fDpjos4fiMFfb46iKm9vDGuS0P+q5XogWt37+Hz0MvYei4eAKAwkeHl9p54q0cT3gyUKsQgZnUBwJQpU7B+/Xr88MMP8PT0xMKFC7F582ZcvHgRNjY20Gg0aNOmDZycnLBw4UKkpKQgJCQEgwcPrtB0ds7qIqnEpmTj/zad0/1L1s/NGp893xq+rvw9JOMVn34f/9tzBetO3oJGKyCTAc+1ccPU3t7wsOV6WvSv8n5/G0zwyc/Px6xZs/DTTz/h/v37aN++Pb788ku0aNFCt09MTAzefPNN7N27F+bm5hgxYgQWLVpUoUtZDD4kJSEENoTfxn+3RCH9fj5M5TKM79YYE59pAjOFidTlEdWYtOw8LNt/DauP3EBuQeE4z14+jpge3AzNnfl3MxVX54JPTWHwodogMTMHs/+KxPbzhTMSGztY4rOhrRDgaStxZUTVKzuvAKsO38DyA9eQmVMAAHjKywbv9WmOQC/+/lPpGHwqicGHapPt5+Lxn78ikXQvFzIZMLqjF94NbgZLlcHcdJ2oXPIKtPj9RAy+2nMVSfdyAQDNna3wXp/m6N7MgdPS6bEYfCqJwYdqm7TsPHy89QLWn7oFAHC3MceCIS251AXVCVqtwOazcVgcehkxKdkAgAa2FpgW5I2BrVwh50K+VE4MPpXE4EO11T+X72LWxnO4nXYfAPBCgDs+6O8LtQWn8JLhEUJg/6W7+GznJVyIL7xjvn09FSb3bIIXn2oApSlnNFLFMPhUEoMP1WZZuQVYuPMSfgy7ASEABysV/jvID338nKUujajcTt5IwWc7LuH4jcI771upTDG+e2O82tkLFkpexqXKYfCpJAYfMgQnb6RgxoazuH43CwDQr6Uz5jzbAo5WXOyUaq+LCRlYtPMSdl9IBACoTOUI6eSF8d0aw8ZSKXF1ZOgYfCqJwYcMRU6+Bkv2XsHyA9eh0QqozRX4cIAvhrR140BQqlViU7Lxxa7L2HT6NoQATOQyDAt0x6SeTeGiNpe6PKojGHwqicGHDE1kXDpmrD+LyLjCcRJdvR0w/zk/uNvw5m4krbuZufhm31X8cuwm8jWFXzX9W7rgnSBvNOayLFTFGHwqicGHDFG+RouVB6/jy91XkFeghaXSBO/1bY6R7T05K4ZqXEZOPr775zq+OxSN7DwNAKBLU3u8G9wMrdzrS1sc1VkMPpXE4EOG7Nrde5i54SxO3EgFUHjjt0+eb8V/XVO1E0IgPCYVG8JvY/OZON3NB1u7qzGjT3N0bvL4dRmJngSDTyUx+JCh02oFfj52E59uv4isPA2UpnJM6dUUr3dpxEVPqcrFJGdjY8QtbIq4jZvJ2brtjRws8W5QM/Txc+aYM6oRDD6VxOBDdcWt1Gz836bz+OfyXQCFi55++nwrtHBVS1wZGbr0+/nYdi4eG8Nv6XoXAcBCaYK+fi54vq0b2jeygwkvs1INYvCpJAYfqkuEENgYfhsfPVj01EQuw/hujfD2M0256ClVSL5Gi4NX7mJD+G3sirqDvAcLh8pkwNNN7DGkrRuCWzjzPjwkGQafSmLwobrobmYuZv99HtvOcdFTKj8hBCLjMrAh/BY2n4lD0r083WveTvUwpK07Brdxg7Oa948i6TH4VBKDD9VlO84XLnp6N5OLnlLpEtJz8Ofp29gYfguX79zTbbezVGJQGzcMaeuGFq7WHLtDtQqDTyUx+FBdl56dj4+3RuGPB4ueutUvXPS0qzcXPTVmWbkF2BmZgE0Rt3HoahKKvhmUpnL09nXC823d0KWpAxQcIE+1FINPJTH4kLE4eKVw0dNbqYWLng4NcMd/uOipUdFoBY5eT8aG8FvYcT5Bd88dAGjnZYvn2rqhX0sXqM35O0G1H4NPJTH4kDEpedHTFujj5yJ1aVSNrtzJxMaI2/gz4jbi03N02z3tLDDE3x3P+buhgR3v/E2GhcGnkhh8yBidupmCGevP4tqDRU/7+jlj7iAuelqXJN/LxeYzcdgYcRtnb6XrtlubmWJAa1c839YNbRvYcNwOGSwGn0pi8CFjlZOvwdd7r2L5gWsoeLDo6X8G+OJ5LnpqsHLyNdh7MREbw29h/6W7KNAW/nVvKpehezNHDGnrhmeaO/LWBlQnMPhUEoMPGbvIuHS8t+Eszt/moqeG6OGlI7aciUPGg6UjAKCVuxpD/N0wsLUr7OqpJKySqOox+FQSgw8RUKDR4rtD0fhi12XkFmhhoTTBe32aY1QHLnpaW8UkZ2NTxG1sjLilt3SEi9oMg/3dMMTfDU2drCSskKh6MfhUEoMP0b+u372HmRvO4fiNFABAoKcNPh3KRU9ri7KWjujj54zn27qjA5eOICPB4FNJDD5E+rRagV+Ox+CTbRd0i55O7tkUr3dtxHu6SIBLRxCVjMGnkhh8iEp2O+0+3t90DvsvFS566utijSFtCy+feDvVg7O1GQdBV5Oylo5o6lgPzwe4Y1AbV7iozSWskkhaDD6VxOBDVDohBP48fRtzN0chLTtf77V6KlM0cawHb6d6aOpohSZO9eDtZAVXNQNRRd3P0+BmShZuJGXj8p1MbDkbV2zpiGfbuOL5tu5cOoLoAQafSmLwIXq8u5m5+PV4DC7EZ+BK4j3cSMrSTZV+lKXSBE0c66GpkxWaOhaGoSaO9eBW39yoB0rfyy3AzeQs3EzOxo3kLNxMykZ0chZuJmfhTkZusf25dARR2Rh8KonBh6ji8gq0uJGchSt37uHynUxcTbyHK4mZiE7KQr6m5L9iLB4EoiaOhT1ERT1F7jZ1JxCl389HTPKDQJOUhRvJ2biZXPjfpHvFw83DrM1M0dDeEp52lujQyA79W3HpCKKyMPhUEoMPUdXJ12hxUxeICsPQ1cR7uH43C3kabYnvMVPIdWGoyYMeoqaO9eBha1HrZicJIZCWnV/YY1PUc/PQf1Oy8sp8v62lEl52FvCyKww4XvYWhf+1s0B9C2UNtYKobmDwqSQGH6LqV6DR4mZKNq7cuYcrdzJxJbGwp6isQKQylaOxQz00dfr3cllTx3rwtLOs1kAkhEByVl5hT03Svz02N5KzcCMpS+8GgSVxsFLBy+7fQFP4X0s0sLNgDw5RFWLwqSQGHyLpFGi0iE29/+/lsjuZuHznHq7dvYfcgpIDkdJUjkb2loWzyxwLg1ETRyt42VnAtJzjYIQQuJuZWxhokrKK9dzcyy073Dhbm8GzqOfGvvC/ReGmnorTyolqAoNPJTH4ENU+Gq3ArdTsfy+X3bmHyw8um+XklxyIFCYyNLKvVzi7zNEKTZ3qoaG9JVKz8/QGFBeFm/v5mlI/XyYDXNXmheHG/pGeG1sLmCu51hWR1Bh8KonBh8hwaLUCt9MKe4iKLpcV9hTdKzPIlEQuA9xtLP7tuXnwXy97C7jbWHAhT6Jarrzf3wbRB7t//3706NGjxNeOHz+Op556CgAQExODt956C3v37oW5uTlGjBiBRYsWQankIEGiukgul8HD1gIethbo6eOk214UiIpmlxX2FBVOu7e1VBYLN552heFGacop4kR1nUEEn06dOiE+Pl5v23/+8x/s3r0bgYGBAACNRoP+/fvDwcEBhw4dQnJyMkaPHg0hBJYsWSJF2UQkkYcDUY/mjlKXQ0S1iEEEH6VSCWdnZ93z/Px8/P3335g4caLujqWhoaGIiopCbGwsXF1dAQCLFy9GSEgI5s2bx8tWREREBIPs1/3777+RlJSEkJAQ3bawsDD4+fnpQg8ABAcHIzc3F6dOnSr1WLm5ucjIyNB7EBERUd1kkMHn+++/R3BwMDw8PHTbEhIS4OTkpLefjY0NlEolEhISSj3WggULoFardY+Hj0lERER1i6TBZ86cOZDJZGU+Tp48qfeeW7duYefOnXjttdeKHa+khfqEEGUu4Ddr1iykp6frHrGxsU/eMCIiIqqVJB3jM3HiRAwfPrzMfby8vPSer1q1CnZ2dnj22Wf1tjs7O+PYsWN621JTU5Gfn1+sJ+hhKpUKKpWqYoUTERGRQZI0+Njb28Pe3r7c+wshsGrVKrzyyitQKPRv9d6xY0fMmzcP8fHxcHFxAVA44FmlUiEgIKBK6yYiIiLDZFBjfPbu3Yvo6OgSL3MFBQXB19cXo0aNQkREBPbs2YPp06dj3LhxnNFFREREAAws+Hz//ffo1KkTfHx8ir1mYmKCrVu3wszMDJ07d8awYcMwePBgLFq0SIJKiYiIqDbikhWP4JIVREREhqe8398G1eNDRERE9CQYfIiIiMhoMPgQERGR0WDwISIiIqPB4ENERERGwyBWZ69JRZPcuFgpERGR4Sj63n7cZHUGn0dkZmYCABcrJSIiMkCZmZlQq9Wlvs77+DxCq9UiLi4OVlZWZS5uWlEZGRnw8PBAbGxsnb0/UF1vI9tn+Op6G9k+w1fX21id7RNCIDMzE66urpDLSx/Jwx6fR8jlcri7u1fb8a2trevkL/PD6nob2T7DV9fbyPYZvrrexupqX1k9PUU4uJmIiIiMBoMPERERGQ0GnxqiUqkwe/ZsqFQqqUupNnW9jWyf4avrbWT7DF9db2NtaB8HNxMREZHRYI8PERERGQ0GHyIiIjIaDD5ERERkNBh8iIiIyGgw+FSR1NRUjBo1Cmq1Gmq1GqNGjUJaWlqp++fn5+O9995Dy5YtYWlpCVdXV7zyyiuIi4vT2y83Nxdvv/027O3tYWlpiWeffRa3bt2q5taUrKJtBICNGzciODgY9vb2kMlkOH36dLF9unfvDplMpvcYPnx49TSiDNXVvtpyDivTPiEE5syZA1dXV5ibm6N79+6IjIzU20fK87d06VI0bNgQZmZmCAgIwMGDB8vc/8CBAwgICICZmRkaNWqE5cuXF9tnw4YN8PX1hUqlgq+vLzZt2lRd5T9WVbdv9erVxc6VTCZDTk5OdTajTBVpY3x8PEaMGIFmzZpBLpdjypQpJe5nqOewPO2rbeewIu3buHEjevfuDQcHB1hbW6Njx47YuXNnsf2q/fwJqhJ9+vQRfn5+4siRI+LIkSPCz89PDBgwoNT909LSRK9evcTvv/8uLl68KMLCwkT79u1FQECA3n7jx48Xbm5uYteuXSI8PFz06NFDtG7dWhQUFFR3k4qpaBuFEGLNmjVi7ty5YuXKlQKAiIiIKLZPt27dxLhx40R8fLzukZaWVk2tKF11ta+2nMPKtO+TTz4RVlZWYsOGDeLcuXPixRdfFC4uLiIjI0O3j1Tn77fffhMKhUKsXLlSREVFicmTJwtLS0tx8+bNEve/fv26sLCwEJMnTxZRUVFi5cqVQqFQiPXr1+v2OXLkiDAxMRHz588XFy5cEPPnzxempqbi6NGj1d6eR1VH+1atWiWsra31zlV8fHxNNamYirYxOjpaTJo0Sfz444+iTZs2YvLkycX2MeRzWJ721aZzWNH2TZ48WXz66afi+PHj4vLly2LWrFlCoVCI8PBw3T41cf4YfKpAVFSUAKB3YsLCwgQAcfHixXIf5/jx4wKA7pcmLS1NKBQK8dtvv+n2uX37tpDL5WLHjh1V14ByeNI2RkdHlxl8SvofvCZVV/tqyzmsTPu0Wq1wdnYWn3zyiW5bTk6OUKvVYvny5bptUp2/du3aifHjx+tta968uZg5c2aJ+8+YMUM0b95cb9sbb7whOnTooHs+bNgw0adPH719goODxfDhw6uo6vKrjvatWrVKqNXqKq+1siraxoeV9ntnyOfwYaW1rzadwydpXxFfX18xd+5c3fOaOH+81FUFwsLCoFar0b59e922Dh06QK1W48iRI+U+Tnp6OmQyGerXrw8AOHXqFPLz8xEUFKTbx9XVFX5+fhU6blWoqjaW5pdffoG9vT1atGiB6dOnIzMz84mPWRHV1b7acg4r077o6GgkJCTo1a5SqdCtW7di76np85eXl4dTp07p1QYAQUFBpbYnLCys2P7BwcE4efIk8vPzy9ynpv9/q672AcC9e/fg6ekJd3d3DBgwABEREVXfgHKoTBvLw5DPYXnVhnNYFe3TarXIzMyEra2tbltNnD8uUloFEhIS4OjoWGy7o6MjEhISynWMnJwczJw5EyNGjNAt3JaQkAClUgkbGxu9fZ2cnMp93KpSFW0szcsvv4yGDRvC2dkZ58+fx6xZs3DmzBns2rXriY5bEdXVvtpyDivTvqLtTk5OetudnJxw8+ZN3XMpzl9SUhI0Gk2JtZXVnpL2LygoQFJSElxcXErdp6b/f6uu9jVv3hyrV69Gy5YtkZGRga+++gqdO3fGmTNn0LRp02prT0kq08byMORzWB615RxWRfsWL16MrKwsDBs2TLetJs4fe3zKMGfOnBIHkT38OHnyJABAJpMVe78QosTtj8rPz8fw4cOh1WqxdOnSx+5f3uOWR021sSzjxo1Dr1694Ofnh+HDh2P9+vXYvXs3wsPDn+i4QO1oX0mq6rg10b5HX3/0PdV5/h7ncbWVZ/9Ht1f0mNWpqtvXoUMHjBw5Eq1bt0aXLl2wbt06eHt7Y8mSJVVceflVx8/bkM/h49S2c1jZ9v3666+YM2cOfv/992L/KKvu88cenzJMnDjxsbNTvLy8cPbsWdy5c6fYa3fv3i2WXB+Vn5+PYcOGITo6Gnv37tX19gCAs7Mz8vLykJqaqtdjkJiYiE6dOlWwNSWriTZWVNu2baFQKHDlyhW0bdv2iY4ldfuq+xxWZ/ucnZ0BFP4LzMXFRbc9MTGxzJ9JVZ6/0tjb28PExKTYvwLLqs3Z2bnE/U1NTWFnZ1fmPlX9O/441dW+R8nlcjz11FO4cuVK1RReAZVpY3kY8jmsDKnO4ZO07/fff8drr72GP/74A7169dJ7rSbOH3t8ymBvb4/mzZuX+TAzM0PHjh2Rnp6O48eP69577NgxpKenl/nlVhR6rly5gt27dxf7yykgIAAKhULvkkF8fDzOnz9fZcGnuttYGZGRkcjPz9f7sq0sqdtX3eewOttXdPnq4drz8vJw4MCBMmuvyvNXGqVSiYCAgGKX03bt2lVqbR07diy2f2hoKAIDA6FQKMrcp6p/xx+nutr3KCEETp8+Xa3nqjSVaWN5GPI5rAypzmFl2/frr78iJCQEa9euRf/+/Yu9XiPnr8qGSRu5Pn36iFatWomwsDARFhYmWrZsWWyqcLNmzcTGjRuFEELk5+eLZ599Vri7u4vTp0/rTUvMzc3VvWf8+PHC3d1d7N69W4SHh4tnnnlG0unsFWmjEEIkJyeLiIgIsXXrVgFA/PbbbyIiIkI3/fLq1ati7ty54sSJEyI6Olps3bpVNG/eXPj7+0sy3buq2ydE7TmHlWnfJ598ItRqtdi4caM4d+6ceOmll/Sms0t5/oqm0n7//fciKipKTJkyRVhaWoobN24IIYSYOXOmGDVqlG7/ouneU6dOFVFRUeL7778vNt378OHDwsTERHzyySfiwoUL4pNPPpF8KnRVtm/OnDlix44d4tq1ayIiIkK8+uqrwtTUVBw7dqzG2ydExdsohBAREREiIiJCBAQEiBEjRoiIiAgRGRmpe92Qz6EQj29fbTqHFW3f2rVrhampqfjmm29Kvf1FTZw/Bp8qkpycLF5++WVhZWUlrKysxMsvvyxSU1P19gEgVq1aJYT4d/pzSY99+/bp3nP//n0xceJEYWtrK8zNzcWAAQNETExMzTXsIRVtoxCFUy9LauPs2bOFEELExMSIrl27CltbW6FUKkXjxo3FpEmTRHJycs017IHqaJ8QteccVqZ9Wq1WzJ49Wzg7OwuVSiW6du0qzp07p3td6vP3zTffCE9PT6FUKkXbtm3FgQMHdK+NHj1adOvWTW///fv3C39/f6FUKoWXl5dYtmxZsWP+8ccfolmzZkKhUIjmzZuLDRs2VHczSlXV7ZsyZYpo0KCBUCqVwsHBQQQFBYkjR47URFNKVdE2lvT/m6enp94+hnwOH9e+2nYOK9K+bt26ldi+0aNH6x2zus+fTIgHo9+IiIiI6jiO8SEiIiKjweBDRERERoPBh4iIiIwGgw8REREZDQYfIiIiMhoMPkRERGQ0GHyIiIjIaDD4EBE9pHv37pgyZYrUZRBRNeENDInIoIWEhCAtLQ1//vlnlRwvJSUFCoUCVlZWVXI8IqpduDo7ERmF/Pz8UhfrfJitrW0NVENEUuGlLiIyCOvXr0fLli1hbm4OOzs79OrVC++++y5+/PFH/PXXX5DJZJDJZNi/fz9u3LgBmUyGdevWoXv37jAzM8PPP/+M5ORkvPTSS3B3d4eFhQVatmyJX3/9Ve9zHr3U5eXlhfnz52PMmDGwsrJCgwYN8O2339Zw64moqjD4EFGtFx8fj5deegljxozBhQsXsH//fgwZMgSzZ8/GsGHD0KdPH8THxyM+Ph6dOnXSve+9997DpEmTcOHCBQQHByMnJwcBAQHYsmULzp8/j9dffx2jRo3CsWPHyvz8xYsXIzAwEBEREXjzzTcxYcIEXLx4sbqbTUTVgJe6iKjWi4+PR0FBAYYMGQJPT08AQMuWLQEA5ubmyM3NhbOzc7H3TZkyBUOGDNHbNn36dN2f3377bezYsQN//PEH2rdvX+rn9+vXD2+++SaAwjD1xRdfYP/+/WjevPkTt42IahaDDxHVeq1bt0bPnj3RsmVLBAcHIygoCEOHDoWNjU2Z7wsMDNR7rtFo8Mknn+D333/H7du3kZubi9zcXFhaWpZ5nFatWun+LJPJ4OzsjMTExMo3iIgkw0tdRFTrmZiYYNeuXdi+fTt8fX2xZMkSNGvWDNHR0WW+79FAs3jxYnzxxReYMWMG9u7di9OnTyM4OBh5eXllHufRQdEymQxarbZyjSEiSbHHh4gMgkwmQ+fOndG5c2d8+OGH8PT0xKZNm6BUKqHRaMp1jIMHD2LQoEEYOXIkAECr1eLKlSvw8fGpztKJqBZh8CGiWu/YsWPYs2cPgoKC4OjoiGPHjuHu3bvw8fFBTk4Odu7ciUuXLsHOzg5qtbrU4zRp0gQbNmzAkSNHYGNjg88//xwJCQkMPkRGhMGHiGo9a2tr/PPPP/jyyy+RkZEBT09PLF68GH379kVgYCD279+PwMBA3Lt3D/v27YOXl1eJx/nPf/6D6OhoBAcHw8LCAq+//joGDx6M9PT0mm0QEUmGd24mIiIio8HBzURERGQ0GHyIiIjIaDD4EBERkdFg8CEiIiKjweBDRERERoPBh4iIiIwGgw8REREZDQYfIiIiMhoMPkRERGQ0GHyIiIjIaDD4EBERkdFg8CEiIiKj8f8C18EiTwf3MgAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "df = energy_at_volume(element='Fe').iter(strain=np.linspace(-0.2, 0.2, 11))\n", "df.plot(x='strain', ylabel='Energy (eV)', title='Energy-Volume Curve');" @@ -6025,13 +7900,130 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 90, "id": "26833a88-1564-4c36-950e-483ea7227b85", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Lammps: structure (UserInput) output single-value: \n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel accumulate_and_run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel ran was not connected to accumulate_and_run, andthus could not disconnect from it.\n", + " warn(\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + " warn(\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n", + "Collect: Parameter Value \\\n", + "0 units metal \n", + "1 dimension 3 \n", + "2 boundary p p p \n", + "3 atom_style atomic \n", + "4 read_data structure.inp \n", + "5 include potential.inp \n", + "6 fix___ensemble all nve \n", + "7 variable___dumptime equal 100 \n", + "8 variable___thermotime equal 100 \n", + "9 dump___1 all custom ${dumptime} dump.out id type xsu ys... \n", + "10 dump_modify___1 sort id format line \"%d %d %20.15g %20.15g %20... \n", + "11 thermo_style custom step temp pe etotal pxx pxy pxz pyy pyz... \n", + "12 thermo_modify format float %20.15g \n", + "13 thermo ${thermotime} \n", + "14 run 0 \n", + "\n", + " Comment \n", + "0 \n", + "1 \n", + "2 \n", + "3 \n", + "4 \n", + "5 \n", + "6 \n", + "7 \n", + "8 \n", + "9 \n", + "10 \n", + "11 \n", + "12 \n", + "13 \n", + "14 bla\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:181: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " df = pd.read_csv(StringIO(\"\".join(lines)), delim_whitespace=True)\n", + "/Users/huber/anaconda3/envs/pyiron_311/lib/python3.11/site-packages/pymatgen/io/lammps/outputs.py:70: FutureWarning: The 'delim_whitespace' keyword in pd.read_csv is deprecated and will be removed in a future version. Use ``sep='\\s+'`` instead\n", + " data = pd.read_csv(StringIO(\"\\n\".join(lines[9:])), names=data_head, delim_whitespace=True)\n" + ] + }, + { + "data": { + "text/plain": [ + "{'engine__generic': OutputCalcStatic(energy_pot=-3.35999999707241, force=array([[5.55111512e-17, 1.52655666e-16, 1.52655666e-16]]), stress=None, structure=None, atomic_energies=None),\n", + " 'calc__generic': OutputCalcStatic(energy_pot=-3.35999999707241, force=array([[5.55111512e-17, 1.52655666e-16, 1.52655666e-16]]), stress=None, structure=None, atomic_energies=None)}" + ] + }, + "execution_count": 90, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "wf = Workflow('test')\n", - "wf.register('atomistic', 'pyiron_workflow.node_library.atomistic')\n", + "wf.register('pyiron_workflow.node_library.atomistic', domain='atomistic')\n", "wf.structure = wf.create.atomistic.structure.build.bulk('Al')\n", "wf.engine = wf.create.atomistic.engine.lammps.Code(structure=wf.structure) # TODO: find a way to avoid structure=wf.structure !\n", "wf.calc = wf.create.atomistic.calculator.generic.static(structure=wf.structure, engine=wf.engine)\n", @@ -6041,50 +8033,103 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 91, "id": "461090fc-2cf5-48d3-b63a-79f090f78823", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "-3.35999999707241" + ] + }, + "execution_count": 91, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "wf.calc.outputs.generic.value.energy_pot" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 92, "id": "d015fbd6-4585-47e9-96d4-37d2a10d0885", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "OutputCalcStatic(energy_pot=-3.35999999707241, force=array([[5.55111512e-17, 1.52655666e-16, 1.52655666e-16]]), stress=None, structure=None, atomic_energies=None)" + ] + }, + "execution_count": 92, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "wf.engine.outputs.generic.value" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 93, "id": "910840a9-e72b-4a8e-a095-3016e2b15ac7", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "OutputCalcStatic(energy_pot=-3.35999999707241, force=array([[5.55111512e-17, 1.52655666e-16, 1.52655666e-16]]), stress=None, structure=None, atomic_energies=None)" + ] + }, + "execution_count": 93, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "wf.calc" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 94, "id": "499186dc-f0aa-4065-ab5b-cac6d636a110", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "-3.35999999707241" + ] + }, + "execution_count": 94, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "wf.calc.outputs.generic.value.energy_pot" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 95, "id": "6773c7de-07fd-4d6b-a7c7-ad4aa5ceb0f4", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 12 µs, sys: 1 µs, total: 13 µs\n", + "Wall time: 17.2 µs\n" + ] + } + ], "source": [ "%%time\n", "from pyiron_workflow.node_library.atomistic.calculator.data import InputCalcMinimize, InputCalcStatic" @@ -6092,28 +8137,49 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 96, "id": "a4543371-f2fe-44b2-97ce-89a9e178d5d3", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "CPU times: user 6.01 ms, sys: 5.05 ms, total: 11.1 ms\n", + "Wall time: 11.5 ms\n" + ] + } + ], "source": [ "%%time\n", - "from pyiron.lammps.base import LammpsControl" + "from pyiron_atomistics.lammps.base import LammpsControl" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 97, "id": "eda647f1-9b9d-4f8a-99d8-5bc104e53bba", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "(InputCalcMinimize(e_tol=0.0, f_tol=0.0001, max_iter=1000000, pressure=None, n_print=100, style='cg'),\n", + " InputCalcStatic())" + ] + }, + "execution_count": 97, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "InputCalcMinimize(), InputCalcStatic()" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 98, "id": "38698067-1f74-4fa2-a8a5-983bcd324d5d", "metadata": {}, "outputs": [], @@ -6123,12 +8189,12 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 99, "id": "8530dde2-be62-4b61-a9bb-8115df653336", "metadata": {}, "outputs": [], "source": [ - "LammpsControl._mode" + "# LammpsControl._mode # We add this attribute in the input control nodes" ] }, { diff --git a/notebooks/pyiron_like_workflows.ipynb b/notebooks/pyiron_like_workflows.ipynb index 37a76a75..b0b94025 100644 --- a/notebooks/pyiron_like_workflows.ipynb +++ b/notebooks/pyiron_like_workflows.ipynb @@ -40,8 +40,8 @@ "name": "stdout", "output_type": "stream", "text": [ - "CPU times: user 4 µs, sys: 1e+03 ns, total: 5 µs\n", - "Wall time: 16.9 µs\n" + "CPU times: user 2 µs, sys: 1 µs, total: 3 µs\n", + "Wall time: 6.91 µs\n" ] } ], @@ -61,27 +61,6 @@ "warnings.filterwarnings('ignore')" ] }, - { - "cell_type": "code", - "execution_count": 13, - "id": "83a79525-73d6-43e1-bd30-916cd9f78cb5", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'sum_3__string': 'abacab'}" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "wf.run()" - ] - }, { "cell_type": "markdown", "id": "47798e04-5765-4071-a991-f78d3879a594", @@ -99,7 +78,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "3ab32ecc4efc4a90b9f1b4336aa5a620", + "model_id": "bb4a26270b4445809af6ec984275a120", "version_major": 2, "version_minor": 0 }, @@ -111,8 +90,8 @@ ], "source": [ "wf = Workflow('Lammps')\n", - "wf.register('atomistic', 'pyiron_workflow.node_library.atomistic')\n", - "wf.register('atomistic_codes', 'pyiron_workflow.node_library.atomistic_codes')" + "wf.register('pyiron_workflow.node_library.atomistic', domain='atomistic')\n", + "wf.register('pyiron_workflow.node_library.atomistic_codes', domain='atomistic_codes')" ] }, { @@ -139,7 +118,7 @@ "source": [ "wf = Workflow('Lammps')\n", "wf.structure = wf.create.atomistic.structure.build.bulk('Al', cubic=True)\n", - "wf.repeat = wf.create.atomistic.structure.transform.repeat(structure = wf.structure, repeat_scalar=1)\n", + "wf.repeat = wf.create.atomistic.structure.transform.repeat(structure=wf.structure, repeat_scalar=1)\n", "\n", "wf.lammps = wf.create.atomistic_codes.Lammps(structure=wf.repeat, label='lammps')\n", "wf.lammps.ListPotentials()[:5]" @@ -169,7 +148,7 @@ "source": [ "wf = Workflow('Lammps')\n", "wf.structure = wf.create.atomistic.structure.build.bulk('Al', cubic=True)\n", - "wf.repeat = wf.create.atomistic.structure.transform.repeat(structure = wf.structure, repeat_scalar=1)\n", + "wf.repeat = wf.create.atomistic.structure.transform.repeat(structure=wf.structure, repeat_scalar=1)\n", "\n", "wf.lammps = wf.create.atomistic_codes.Lammps(structure=wf.repeat, label='lammps')\n", "wf.lammps.ListPotentials()[:5]" @@ -177,7 +156,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 7, "id": "bfe72a25-6f36-47a3-9c4f-e3ded460d029", "metadata": {}, "outputs": [ @@ -190,1099 +169,2771 @@ "\n", "\n", - "\n", - "\n", + "\n", + "\n", "clusterlammps\n", - "\n", - "lammps: Lammps\n", - "\n", - "clusterlammpsListPotentials\n", + "\n", + "lammps: Lammps\n", + "\n", + "clusterlammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterlammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterlammpsstructure\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "ListPotentials: ListPotentials\n", + "\n", + "structure: UserInput\n", "\n", - "\n", - "clusterlammpsListPotentialsInputs\n", + "\n", + "clusterlammpsstructureInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterlammpsListPotentialsOutputs\n", + "\n", + "clusterlammpsstructureOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterlammpsParseLogFile\n", + "\n", + "clusterlammpspotential\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "ParseLogFile: ParseLogFile\n", + "\n", + "potential: UserInput\n", "\n", - "\n", - "clusterlammpsParseLogFileInputs\n", + "\n", + "clusterlammpspotentialInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterlammpsParseLogFileOutputs\n", + "\n", + "clusterlammpspotentialOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterlammpsParseDumpFile\n", + "\n", + "clusterlammpsPotential\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "ParseDumpFile: ParseDumpFile\n", + "\n", + "Potential: Potential\n", "\n", - "\n", - "clusterlammpsParseDumpFileInputs\n", + "\n", + "clusterlammpsPotentialInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterlammpsParseDumpFileOutputs\n", + "\n", + "clusterlammpsPotentialOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterlammpsInputs\n", + "\n", + "clusterlammpsListPotentials\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "ListPotentials: ListPotentials\n", + "\n", + "\n", + "clusterlammpsListPotentialsInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterlammpsOutputs\n", + "\n", + "clusterlammpsListPotentialsOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterlammpsstructure\n", + "\n", + "clusterlammpscalc\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "structure: UserInput\n", + "\n", + "calc: CalcStatic\n", "\n", - "\n", - "clusterlammpsstructureInputs\n", + "\n", + "clusterlammpscalcInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterlammpsstructureOutputs\n", + "\n", + "clusterlammpscalcOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterlammpspotential\n", + "\n", + "clusterlammpsInitLammps\n", "\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", - "potential: UserInput\n", + "\n", + "InitLammps: InitLammps\n", "\n", - "\n", - "clusterlammpspotentialInputs\n", + "\n", + "clusterlammpsInitLammpsInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterlammpspotentialOutputs\n", + "\n", + "clusterlammpsInitLammpsOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterlammpsPotential\n", + "\n", + "clusterlammpsShell\n", "\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", - "Potential: Potential\n", + "\n", + "Shell: Shell\n", "\n", - "\n", - "clusterlammpsPotentialInputs\n", + "\n", + "clusterlammpsShellInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterlammpsPotentialOutputs\n", + "\n", + "clusterlammpsShellOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterlammpscalc\n", + "\n", + "clusterlammpsParseLogFile\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "calc: CalcStatic\n", + "\n", + "ParseLogFile: ParseLogFile\n", "\n", - "\n", - "clusterlammpscalcInputs\n", + "\n", + "clusterlammpsParseLogFileInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterlammpscalcOutputs\n", + "\n", + "clusterlammpsParseLogFileOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterlammpsInitLammps\n", + "\n", + "clusterlammpsParseDumpFile\n", "\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", - "InitLammps: InitLammps\n", + "\n", + "ParseDumpFile: ParseDumpFile\n", "\n", - "\n", - "clusterlammpsInitLammpsInputs\n", + "\n", + "clusterlammpsParseDumpFileInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterlammpsInitLammpsOutputs\n", + "\n", + "clusterlammpsParseDumpFileOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clusterlammpsShell\n", + "\n", + "clusterlammpscalc__calculator_GetAttr__mode\n", "\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", - "Shell: Shell\n", + "\n", + "calc__calculator_GetAttr__mode: GetAttr\n", "\n", - "\n", - "clusterlammpsShellOutputs\n", + "\n", + "clusterlammpscalc__calculator_GetAttr__modeInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Inputs\n", "\n", - "\n", - "clusterlammpsShellInputs\n", + "\n", + "clusterlammpscalc__calculator_GetAttr__modeOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Outputs\n", "\n", - "\n", + "\n", "clusterlammpsCollect\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Collect: Collect\n", + "\n", + "Collect: Collect\n", "\n", - "\n", + "\n", "clusterlammpsCollectInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", - "\n", + "\n", "clusterlammpsCollectOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "\n", "clusterlammpsInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterlammpsOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterlammpsInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterlammpsInputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", "\n", "clusterlammpsstructureInputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInputsstructure->clusterlammpsstructureInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterlammpsInputspotential\n", - "\n", - "potential\n", + "\n", + "potential\n", "\n", "\n", "\n", "clusterlammpspotentialInputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInputspotential->clusterlammpspotentialInputsuser_input\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterlammpsOutputsgeneric\n", - "\n", - "generic\n", + "\n", + "generic\n", "\n", "\n", "\n", "clusterlammpsstructureInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterlammpsstructureOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterlammpsstructureInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterlammpsPotentialInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterlammpsstructureOutputsran->clusterlammpsPotentialInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterlammpsListPotentialsInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterlammpsstructureOutputsran->clusterlammpsListPotentialsInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInitLammpsInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterlammpsstructureOutputsran->clusterlammpsInitLammpsInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterlammpsstructureOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterlammpsPotentialInputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", - "\n", + "\n", "clusterlammpsstructureOutputsuser_input->clusterlammpsPotentialInputsstructure\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterlammpsListPotentialsInputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", - "\n", + "\n", "clusterlammpsstructureOutputsuser_input->clusterlammpsListPotentialsInputsstructure\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInitLammpsInputsstructure\n", - "\n", - "structure\n", + "\n", + "structure\n", "\n", "\n", - "\n", + "\n", "clusterlammpsstructureOutputsuser_input->clusterlammpsInitLammpsInputsstructure\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterlammpspotentialInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterlammpspotentialOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterlammpspotentialInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterlammpspotentialOutputsran->clusterlammpsPotentialInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterlammpspotentialOutputsuser_input\n", - "\n", - "user_input\n", + "\n", + "user_input\n", "\n", "\n", "\n", "clusterlammpsPotentialInputsname\n", - "\n", - "name\n", + "\n", + "name\n", "\n", "\n", - "\n", + "\n", "clusterlammpspotentialOutputsuser_input->clusterlammpsPotentialInputsname\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterlammpsPotentialInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterlammpsPotentialOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterlammpsPotentialInputsindex\n", - "\n", - "index\n", + "\n", + "index\n", "\n", "\n", - "\n", + "\n", "clusterlammpsPotentialOutputsran->clusterlammpsInitLammpsInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterlammpsPotentialOutputspotential\n", - "\n", - "potential\n", + "\n", + "potential\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInitLammpsInputspotential\n", - "\n", - "potential\n", + "\n", + "potential\n", "\n", "\n", - "\n", + "\n", "clusterlammpsPotentialOutputspotential->clusterlammpsInitLammpsInputspotential\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterlammpsListPotentialsInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterlammpsListPotentialsOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterlammpsListPotentialsOutputspotentials\n", - "\n", - "potentials\n", + "\n", + "potentials\n", "\n", "\n", "\n", "clusterlammpscalcInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", - "\n", + "\n", "clusterlammpscalcOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterlammpscalcInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterlammpscalcInputscalculator_input\n", + "\n", + "calculator_input: Union\n", "\n", "\n", - "\n", + "\n", "clusterlammpscalcOutputsran->clusterlammpsInitLammpsInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpscalc__calculator_GetAttr__modeInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterlammpscalcOutputsran->clusterlammpscalc__calculator_GetAttr__modeInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterlammpscalcOutputscalculator\n", - "\n", - "calculator\n", + "\n", + "calculator\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInitLammpsInputscalculator\n", - "\n", - "calculator\n", + "\n", + "calculator\n", "\n", "\n", - "\n", + "\n", "clusterlammpscalcOutputscalculator->clusterlammpsInitLammpsInputscalculator\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpscalc__calculator_GetAttr__modeInputsobj\n", + "\n", + "obj\n", + "\n", + "\n", + "\n", + "clusterlammpscalcOutputscalculator->clusterlammpscalc__calculator_GetAttr__modeInputsobj\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInitLammpsInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInitLammpsOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInitLammpsInputsworking_directory\n", - "\n", - "working_directory\n", + "\n", + "working_directory\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInitLammpsOutputsran->clusterlammpsShellInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInitLammpsOutputspath\n", - "\n", - "path\n", + "\n", + "path\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellInputsworking_directory\n", - "\n", - "working_directory: str\n", + "\n", + "working_directory: str\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInitLammpsOutputspath->clusterlammpsShellInputsworking_directory\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterlammpsInitLammpsOutputsbla\n", - "\n", - "bla\n", + "\n", + "bla\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellInputscommand\n", - "\n", - "command: str\n", + "\n", + "command: str\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellInputsenvironment\n", - "\n", - "environment: Optional\n", + "\n", + "environment: Optional\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellInputsarguments\n", - "\n", - "arguments: Optional\n", + "\n", + "arguments: Optional\n", "\n", "\n", - "\n", + "\n", "clusterlammpsParseLogFileInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellOutputsran->clusterlammpsParseLogFileInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterlammpsParseDumpFileInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellOutputsran->clusterlammpsParseDumpFileInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellOutputsoutput\n", - "\n", - "output\n", + "\n", + "output\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellOutputsdump\n", - "\n", - "dump\n", + "\n", + "dump\n", "\n", "\n", - "\n", + "\n", "clusterlammpsParseDumpFileInputsdump_file\n", - "\n", - "dump_file\n", + "\n", + "dump_file\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellOutputsdump->clusterlammpsParseDumpFileInputsdump_file\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellOutputslog\n", - "\n", - "log\n", + "\n", + "log\n", "\n", "\n", - "\n", + "\n", "clusterlammpsParseLogFileInputslog_file\n", - "\n", - "log_file\n", + "\n", + "log_file\n", "\n", "\n", - "\n", + "\n", "clusterlammpsShellOutputslog->clusterlammpsParseLogFileInputslog_file\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpsParseLogFileInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterlammpsParseLogFileOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpsCollectInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterlammpsParseLogFileOutputsran->clusterlammpsCollectInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpsParseLogFileOutputslog\n", + "\n", + "log\n", + "\n", + "\n", + "\n", + "clusterlammpsCollectInputsout_log\n", + "\n", + "out_log\n", + "\n", + "\n", + "\n", + "clusterlammpsParseLogFileOutputslog->clusterlammpsCollectInputsout_log\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpsParseDumpFileInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterlammpsParseDumpFileOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpsParseDumpFileOutputsran->clusterlammpsCollectInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpsParseDumpFileOutputsdump\n", + "\n", + "dump\n", + "\n", + "\n", + "\n", + "clusterlammpsCollectInputsout_dump\n", + "\n", + "out_dump\n", + "\n", + "\n", + "\n", + "clusterlammpsParseDumpFileOutputsdump->clusterlammpsCollectInputsout_dump\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpscalc__calculator_GetAttr__modeInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterlammpscalc__calculator_GetAttr__modeOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpscalc__calculator_GetAttr__modeInputsname\n", + "\n", + "name\n", + "\n", + "\n", + "\n", + "clusterlammpscalc__calculator_GetAttr__modeOutputsran->clusterlammpsCollectInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpscalc__calculator_GetAttr__modeOutputsgetattr\n", + "\n", + "getattr\n", + "\n", + "\n", + "\n", + "clusterlammpsCollectInputscalc_mode\n", + "\n", + "calc_mode: str\n", + "\n", + "\n", + "\n", + "clusterlammpscalc__calculator_GetAttr__modeOutputsgetattr->clusterlammpsCollectInputscalc_mode\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpsCollectInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterlammpsCollectOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterlammpsCollectInputsbla\n", + "\n", + "bla\n", + "\n", + "\n", + "\n", + "clusterlammpsCollectOutputsgeneric\n", + "\n", + "generic\n", + "\n", + "\n", + "\n", + "clusterlammpsCollectOutputsgeneric->clusterlammpsOutputsgeneric\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n" + ], + "text/plain": [ + "" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "wf.lammps.draw(depth=2)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "62b16448-4dcb-4e12-a5fa-6b091ecef608", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Lammps_init: static bla\n", + "Collect: static \n", + "Potential energy: -13.4399999882896\n" + ] + } + ], + "source": [ + "out = wf.run()\n", + "print (f'Potential energy: {wf.lammps.outputs.generic.value.energy_pot}')" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "86f6d2f0-a6e6-401c-bb46-d7393984fa55", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "OutputCalcStatic(energy_pot=-13.4399999882896, force=array([[-5.55111512e-17, 0.00000000e+00, 0.00000000e+00],\n", + " [ 0.00000000e+00, 8.32667268e-17, -5.55111512e-17],\n", + " [ 5.55111512e-17, -5.55111512e-17, -1.66533454e-16],\n", + " [ 0.00000000e+00, -2.22044605e-16, 2.77555756e-17]]), stress=None, structure=None, atomic_energies=None)" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "wf.lammps.Collect" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "b98d3e39-4f68-4e80-bc86-87edb4976113", + "metadata": {}, + "outputs": [ + { + "data": { + "image/svg+xml": [ + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammps\n", + "\n", + "Lammps: Workflow\n", + "\n", + "clusterLammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsstructure\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "structure: bulk\n", + "\n", + "\n", + "clusterLammpsstructureInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsstructureOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsrepeat\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "repeat: repeat\n", + "\n", + "\n", + "clusterLammpsrepeatInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsrepeatOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpslammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "lammps: Lammps\n", + "\n", + "\n", + "clusterLammpslammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpslammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsstructurelammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "structure: UserInput\n", + "\n", + "\n", + "clusterLammpsstructurelammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsstructurelammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpspotentiallammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "potential: UserInput\n", + "\n", + "\n", + "clusterLammpspotentiallammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpspotentiallammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsPotentiallammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Potential: Potential\n", + "\n", + "\n", + "clusterLammpsPotentiallammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsPotentiallammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsListPotentialslammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "ListPotentials: ListPotentials\n", + "\n", + "\n", + "clusterLammpsListPotentialslammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsListPotentialslammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpscalclammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "calc: CalcStatic\n", + "\n", + "\n", + "clusterLammpscalclammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpscalclammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsInitLammpslammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "InitLammps: InitLammps\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsShelllammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Shell: Shell\n", + "\n", + "\n", + "clusterLammpsShelllammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsShelllammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsParseLogFilelammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "ParseLogFile: ParseLogFile\n", + "\n", + "\n", + "clusterLammpsParseLogFilelammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsParseLogFilelammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsParseDumpFilelammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "ParseDumpFile: ParseDumpFile\n", + "\n", + "\n", + "clusterLammpsParseDumpFilelammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsParseDumpFilelammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpscalc__calculator_GetAttr__modelammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "calc__calculator_GetAttr__mode: GetAttr\n", + "\n", + "\n", + "clusterLammpscalc__calculator_GetAttr__modelammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpscalc__calculator_GetAttr__modelammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsCollectlammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Collect: Collect\n", + "\n", + "\n", + "clusterLammpsCollectlammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsCollectlammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_canary_method_should_not_exist_lammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Collect__generic_GetAttr__ipython_canary_method_should_not_exist_: GetAttr\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_canary_method_should_not_exist_lammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_canary_method_should_not_exist_lammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_display_lammps\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Collect__generic_GetAttr__ipython_display_: GetAttr\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_display_lammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_display_lammpsOutputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Outputs\n", + "\n", + "\n", + "clusterLammpsInputs\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "Inputs\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__name\n", + "\n", + "structure__name\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureInputsname\n", + "\n", + "name\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__name->clusterLammpsstructureInputsname\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__crystalstructure\n", + "\n", + "structure__crystalstructure\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureInputscrystalstructure\n", + "\n", + "crystalstructure\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__crystalstructure->clusterLammpsstructureInputscrystalstructure\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__a\n", + "\n", + "structure__a\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureInputsa\n", + "\n", + "a\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__a->clusterLammpsstructureInputsa\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__c\n", + "\n", + "structure__c\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureInputsc\n", + "\n", + "c\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__c->clusterLammpsstructureInputsc\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__covera\n", + "\n", + "structure__covera\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureInputscovera\n", + "\n", + "covera\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__covera->clusterLammpsstructureInputscovera\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__u\n", + "\n", + "structure__u\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureInputsu\n", + "\n", + "u\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__u->clusterLammpsstructureInputsu\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__orthorhombic\n", + "\n", + "structure__orthorhombic\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureInputsorthorhombic\n", + "\n", + "orthorhombic\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__orthorhombic->clusterLammpsstructureInputsorthorhombic\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__cubic\n", + "\n", + "structure__cubic\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureInputscubic\n", + "\n", + "cubic\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsstructure__cubic->clusterLammpsstructureInputscubic\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsrepeat__repeat_scalar\n", + "\n", + "repeat__repeat_scalar: int\n", + "\n", + "\n", + "\n", + "clusterLammpsrepeatInputsrepeat_scalar\n", + "\n", + "repeat_scalar: int\n", + "\n", + "\n", + "\n", + "clusterLammpsInputsrepeat__repeat_scalar->clusterLammpsrepeatInputsrepeat_scalar\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInputslammps__potential\n", + "\n", + "lammps__potential\n", + "\n", + "\n", + "\n", + "clusterLammpslammpsInputspotential\n", + "\n", + "potential\n", + "\n", + "\n", + "\n", + "clusterLammpsInputslammps__potential->clusterLammpslammpsInputspotential\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsOutputslammps__generic\n", + "\n", + "lammps__generic\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsrepeatInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureOutputsran->clusterLammpsrepeatInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureOutputsstructure\n", + "\n", + "structure\n", + "\n", + "\n", + "\n", + "clusterLammpsrepeatInputsstructure\n", + "\n", + "structure: Atoms\n", + "\n", + "\n", + "\n", + "clusterLammpsstructureOutputsstructure->clusterLammpsrepeatInputsstructure\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsrepeatInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsrepeatOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpslammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsrepeatOutputsran->clusterLammpslammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsrepeatOutputsstructure\n", + "\n", + "structure: Atoms\n", + "\n", + "\n", + "\n", + "clusterLammpslammpsInputsstructure\n", + "\n", + "structure\n", + "\n", + "\n", + "\n", + "clusterLammpsrepeatOutputsstructure->clusterLammpslammpsInputsstructure\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpslammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpslammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsstructurelammpsInputsuser_input\n", + "\n", + "user_input\n", + "\n", + "\n", + "\n", + "clusterLammpslammpsInputsstructure->clusterLammpsstructurelammpsInputsuser_input\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpspotentiallammpsInputsuser_input\n", + "\n", + "user_input\n", + "\n", + "\n", + "\n", + "clusterLammpslammpsInputspotential->clusterLammpspotentiallammpsInputsuser_input\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpslammpsOutputsgeneric\n", + "\n", + "generic\n", + "\n", + "\n", + "\n", + "clusterLammpslammpsOutputsgeneric->clusterLammpsOutputslammps__generic\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsstructurelammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsstructurelammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsstructurelammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsPotentiallammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsstructurelammpsOutputsran->clusterLammpsPotentiallammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsListPotentialslammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsstructurelammpsOutputsran->clusterLammpsListPotentialslammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsstructurelammpsOutputsran->clusterLammpsInitLammpslammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsstructurelammpsOutputsuser_input\n", + "\n", + "user_input\n", + "\n", + "\n", + "\n", + "clusterLammpsPotentiallammpsInputsstructure\n", + "\n", + "structure\n", + "\n", + "\n", + "\n", + "clusterLammpsstructurelammpsOutputsuser_input->clusterLammpsPotentiallammpsInputsstructure\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsListPotentialslammpsInputsstructure\n", + "\n", + "structure\n", + "\n", + "\n", + "\n", + "clusterLammpsstructurelammpsOutputsuser_input->clusterLammpsListPotentialslammpsInputsstructure\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsInputsstructure\n", + "\n", + "structure\n", + "\n", + "\n", + "\n", + "clusterLammpsstructurelammpsOutputsuser_input->clusterLammpsInitLammpslammpsInputsstructure\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpspotentiallammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpspotentiallammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpspotentiallammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpspotentiallammpsOutputsran->clusterLammpsPotentiallammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpspotentiallammpsOutputsuser_input\n", + "\n", + "user_input\n", + "\n", + "\n", + "\n", + "clusterLammpsPotentiallammpsInputsname\n", + "\n", + "name\n", + "\n", + "\n", + "\n", + "clusterLammpspotentiallammpsOutputsuser_input->clusterLammpsPotentiallammpsInputsname\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsPotentiallammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsPotentiallammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsPotentiallammpsInputsindex\n", + "\n", + "index\n", "\n", - "\n", - "\n", - "clusterlammpsParseLogFileInputsrun\n", - "\n", - "run\n", + "\n", + "\n", + "clusterLammpsPotentiallammpsOutputsran->clusterLammpsInitLammpslammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "clusterlammpsParseLogFileOutputsran\n", - "\n", - "ran\n", + "clusterLammpsPotentiallammpsOutputspotential\n", + "\n", + "potential\n", "\n", - "\n", - "\n", - "\n", - "clusterlammpsCollectInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsInputspotential\n", + "\n", + "potential\n", "\n", - "\n", - "\n", - "clusterlammpsParseLogFileOutputsran->clusterlammpsCollectInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "clusterLammpsPotentiallammpsOutputspotential->clusterLammpsInitLammpslammpsInputspotential\n", + "\n", + "\n", + "\n", "\n", - "\n", + "\n", "\n", - "clusterlammpsParseLogFileOutputslog\n", - "\n", - "log\n", - "\n", - "\n", - "\n", - "clusterlammpsCollectInputsout_log\n", - "\n", - "out_log\n", - "\n", - "\n", - "\n", - "clusterlammpsParseLogFileOutputslog->clusterlammpsCollectInputsout_log\n", - "\n", - "\n", - "\n", + "clusterLammpsListPotentialslammpsInputsrun\n", + "\n", + "run\n", "\n", - "\n", - "\n", - "clusterlammpsParseDumpFileInputsrun\n", - "\n", - "run\n", + "\n", + "\n", + "clusterLammpsListPotentialslammpsOutputsran\n", + "\n", + "ran\n", "\n", - "\n", + "\n", + "\n", "\n", - "clusterlammpsParseDumpFileOutputsran\n", - "\n", - "ran\n", - "\n", - "\n", - "\n", - "\n", - "clusterlammpsParseDumpFileOutputsran->clusterlammpsCollectInputsaccumulate_and_run\n", - "\n", - "\n", - "\n", + "clusterLammpsListPotentialslammpsOutputspotentials\n", + "\n", + "potentials\n", "\n", - "\n", + "\n", "\n", - "clusterlammpsParseDumpFileOutputsdump\n", - "\n", - "dump\n", + "clusterLammpscalclammpsInputsrun\n", + "\n", + "run\n", "\n", - "\n", + "\n", "\n", - "clusterlammpsCollectInputsout_dump\n", - "\n", - "out_dump\n", + "clusterLammpscalclammpsOutputsran\n", + "\n", + "ran\n", "\n", - "\n", - "\n", - "clusterlammpsParseDumpFileOutputsdump->clusterlammpsCollectInputsout_dump\n", - "\n", - "\n", - "\n", - "\n", - "\n", + "\n", + "\n", "\n", - "clusterlammpsCollectInputsrun\n", - "\n", - "run\n", + "clusterLammpscalclammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", - "\n", - "\n", - "clusterlammpsCollectOutputsran\n", - "\n", - "ran\n", + "\n", + "\n", + "clusterLammpscalclammpsInputscalculator_input\n", + "\n", + "calculator_input: Union\n", "\n", - "\n", - "\n", - "\n", - "clusterlammpsCollectInputsbla\n", - "\n", - "bla\n", + "\n", + "\n", + "clusterLammpscalclammpsOutputsran->clusterLammpsInitLammpslammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpscalc__calculator_GetAttr__modelammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpscalclammpsOutputsran->clusterLammpscalc__calculator_GetAttr__modelammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", "\n", - "\n", - "\n", - "clusterlammpsCollectOutputsgeneric\n", - "\n", - "generic\n", + "\n", + "\n", + "clusterLammpscalclammpsOutputscalculator\n", + "\n", + "calculator\n", "\n", - "\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsInputscalculator\n", + "\n", + "calculator\n", + "\n", + "\n", + "\n", + "clusterLammpscalclammpsOutputscalculator->clusterLammpsInitLammpslammpsInputscalculator\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpscalc__calculator_GetAttr__modelammpsInputsobj\n", + "\n", + "obj\n", + "\n", + "\n", + "\n", + "clusterLammpscalclammpsOutputscalculator->clusterLammpscalc__calculator_GetAttr__modelammpsInputsobj\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsInputsworking_directory\n", + "\n", + "working_directory\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsOutputsran->clusterLammpsShelllammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsOutputspath\n", + "\n", + "path\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsInputsworking_directory\n", + "\n", + "working_directory: str\n", + "\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsOutputspath->clusterLammpsShelllammpsInputsworking_directory\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsInitLammpslammpsOutputsbla\n", + "\n", + "bla\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsInputscommand\n", + "\n", + "command: str\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsInputsenvironment\n", + "\n", + "environment: Optional\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsInputsarguments\n", + "\n", + "arguments: Optional\n", + "\n", + "\n", + "\n", + "clusterLammpsParseLogFilelammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsOutputsran->clusterLammpsParseLogFilelammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsParseDumpFilelammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsOutputsran->clusterLammpsParseDumpFilelammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsOutputsoutput\n", + "\n", + "output\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsOutputsdump\n", + "\n", + "dump\n", + "\n", + "\n", + "\n", + "clusterLammpsParseDumpFilelammpsInputsdump_file\n", + "\n", + "dump_file\n", + "\n", + "\n", "\n", - "clusterlammpsCollectOutputsgeneric->clusterlammpsOutputsgeneric\n", - "\n", - "\n", - "\n", + "clusterLammpsShelllammpsOutputsdump->clusterLammpsParseDumpFilelammpsInputsdump_file\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsOutputslog\n", + "\n", + "log\n", + "\n", + "\n", + "\n", + "clusterLammpsParseLogFilelammpsInputslog_file\n", + "\n", + "log_file\n", + "\n", + "\n", + "\n", + "clusterLammpsShelllammpsOutputslog->clusterLammpsParseLogFilelammpsInputslog_file\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsParseLogFilelammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsParseLogFilelammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsCollectlammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsParseLogFilelammpsOutputsran->clusterLammpsCollectlammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsParseLogFilelammpsOutputslog\n", + "\n", + "log\n", + "\n", + "\n", + "\n", + "clusterLammpsCollectlammpsInputsout_log\n", + "\n", + "out_log\n", + "\n", + "\n", + "\n", + "clusterLammpsParseLogFilelammpsOutputslog->clusterLammpsCollectlammpsInputsout_log\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsParseDumpFilelammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsParseDumpFilelammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsParseDumpFilelammpsOutputsran->clusterLammpsCollectlammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsParseDumpFilelammpsOutputsdump\n", + "\n", + "dump\n", + "\n", + "\n", + "\n", + "clusterLammpsCollectlammpsInputsout_dump\n", + "\n", + "out_dump\n", + "\n", + "\n", + "\n", + "clusterLammpsParseDumpFilelammpsOutputsdump->clusterLammpsCollectlammpsInputsout_dump\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpscalc__calculator_GetAttr__modelammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpscalc__calculator_GetAttr__modelammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpscalc__calculator_GetAttr__modelammpsInputsname\n", + "\n", + "name\n", + "\n", + "\n", + "\n", + "clusterLammpscalc__calculator_GetAttr__modelammpsOutputsran->clusterLammpsCollectlammpsInputsaccumulate_and_run\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpscalc__calculator_GetAttr__modelammpsOutputsgetattr\n", + "\n", + "getattr\n", + "\n", + "\n", + "\n", + "clusterLammpsCollectlammpsInputscalc_mode\n", + "\n", + "calc_mode: str\n", + "\n", + "\n", + "\n", + "clusterLammpscalc__calculator_GetAttr__modelammpsOutputsgetattr->clusterLammpsCollectlammpsInputscalc_mode\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsCollectlammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsCollectlammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsCollectlammpsInputsbla\n", + "\n", + "bla\n", + "\n", + "\n", + "\n", + "clusterLammpsCollectlammpsOutputsgeneric\n", + "\n", + "generic\n", + "\n", + "\n", + "\n", + "clusterLammpsCollectlammpsOutputsgeneric->clusterLammpslammpsOutputsgeneric\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_canary_method_should_not_exist_lammpsInputsobj\n", + "\n", + "obj\n", + "\n", + "\n", + "\n", + "clusterLammpsCollectlammpsOutputsgeneric->clusterLammpsCollect__generic_GetAttr__ipython_canary_method_should_not_exist_lammpsInputsobj\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_display_lammpsInputsobj\n", + "\n", + "obj\n", + "\n", + "\n", + "\n", + "clusterLammpsCollectlammpsOutputsgeneric->clusterLammpsCollect__generic_GetAttr__ipython_display_lammpsInputsobj\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_canary_method_should_not_exist_lammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_canary_method_should_not_exist_lammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_canary_method_should_not_exist_lammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_canary_method_should_not_exist_lammpsInputsname\n", + "\n", + "name\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_canary_method_should_not_exist_lammpsOutputsgetattr\n", + "\n", + "getattr\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_display_lammpsInputsrun\n", + "\n", + "run\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_display_lammpsOutputsran\n", + "\n", + "ran\n", + "\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_display_lammpsInputsaccumulate_and_run\n", + "\n", + "accumulate_and_run\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_display_lammpsInputsname\n", + "\n", + "name\n", + "\n", + "\n", + "\n", + "clusterLammpsCollect__generic_GetAttr__ipython_display_lammpsOutputsgetattr\n", + "\n", + "getattr\n", "\n", "\n", "\n" ], "text/plain": [ - "" + "" ] }, - "execution_count": 9, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], - "source": [ - "wf.lammps.draw(depth=2)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "62b16448-4dcb-4e12-a5fa-6b091ecef608", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Lammps_init: static bla\n" - ] - }, - { - "ename": "NameError", - "evalue": "name 'calc_mode' is not defined", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[8], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[43mwf\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28mprint\u001b[39m (\u001b[38;5;124mf\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mPotential energy: \u001b[39m\u001b[38;5;132;01m{\u001b[39;00mwf\u001b[38;5;241m.\u001b[39mlammps\u001b[38;5;241m.\u001b[39moutputs\u001b[38;5;241m.\u001b[39mgeneric\u001b[38;5;241m.\u001b[39mvalue\u001b[38;5;241m.\u001b[39menergy_pot\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m'\u001b[39m)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/workflow.py:224\u001b[0m, in \u001b[0;36mWorkflow.run\u001b[0;34m(self, check_readiness, force_local_execution, **kwargs)\u001b[0m\n\u001b[1;32m 222\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mautomate_execution:\n\u001b[1;32m 223\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mset_run_signals_to_dag_execution()\n\u001b[0;32m--> 224\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43msuper\u001b[39;49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 225\u001b[0m \u001b[43m \u001b[49m\u001b[43mrun_data_tree\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 226\u001b[0m \u001b[43m \u001b[49m\u001b[43mrun_parent_trees_too\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 227\u001b[0m \u001b[43m \u001b[49m\u001b[43mfetch_input\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 228\u001b[0m \u001b[43m \u001b[49m\u001b[43mcheck_readiness\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcheck_readiness\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 229\u001b[0m \u001b[43m \u001b[49m\u001b[43mforce_local_execution\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mforce_local_execution\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 230\u001b[0m \u001b[43m \u001b[49m\u001b[43memit_ran_signal\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mFalse\u001b[39;49;00m\u001b[43m,\u001b[49m\n\u001b[1;32m 231\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 232\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:394\u001b[0m, in \u001b[0;36mNode.run\u001b[0;34m(self, run_data_tree, run_parent_trees_too, fetch_input, check_readiness, force_local_execution, emit_ran_signal, **kwargs)\u001b[0m\n\u001b[1;32m 387\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m check_readiness \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mready:\n\u001b[1;32m 388\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ReadinessError(\n\u001b[1;32m 389\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlabel\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m received a run command but is not ready. The node \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 390\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mshould be neither running nor failed, and all input values should\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 391\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m conform to type hints.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreadiness_report\n\u001b[1;32m 392\u001b[0m )\n\u001b[0;32m--> 394\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 395\u001b[0m \u001b[43m \u001b[49m\u001b[43mfinished_callback\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run_and_emit_ran\u001b[49m\n\u001b[1;32m 396\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43memit_ran_signal\u001b[49m\n\u001b[1;32m 397\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 398\u001b[0m \u001b[43m \u001b[49m\u001b[43mforce_local_execution\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mforce_local_execution\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 399\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:66\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m node\u001b[38;5;241m.\u001b[39mfailed \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 65\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m---> 66\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 68\u001b[0m \u001b[38;5;66;03m# Leave the status as running if the method returns a future\u001b[39;00m\n\u001b[1;32m 69\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28misinstance\u001b[39m(out, Future)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:61\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 59\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 61\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[43mnode_method\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 62\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m out\n\u001b[1;32m 63\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:478\u001b[0m, in \u001b[0;36mNode._run\u001b[0;34m(self, finished_callback, force_local_execution)\u001b[0m\n\u001b[1;32m 471\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 472\u001b[0m \u001b[38;5;124;03mExecutes the functionality of the node defined in `on_run`.\u001b[39;00m\n\u001b[1;32m 473\u001b[0m \u001b[38;5;124;03mHandles the status of the node, and communicating with any remote\u001b[39;00m\n\u001b[1;32m 474\u001b[0m \u001b[38;5;124;03mcomputing resources.\u001b[39;00m\n\u001b[1;32m 475\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m force_local_execution \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 477\u001b[0m \u001b[38;5;66;03m# Run locally\u001b[39;00m\n\u001b[0;32m--> 478\u001b[0m run_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mon_run\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun_args\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 479\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m finished_callback(run_output)\n\u001b[1;32m 480\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 481\u001b[0m \u001b[38;5;66;03m# Just blindly try to execute -- as we nail down the executor interaction\u001b[39;00m\n\u001b[1;32m 482\u001b[0m \u001b[38;5;66;03m# we'll want to fail more cleanly here.\u001b[39;00m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/composite.py:177\u001b[0m, in \u001b[0;36mComposite.run_graph\u001b[0;34m(_nodes, _starting_nodes)\u001b[0m\n\u001b[1;32m 174\u001b[0m \u001b[38;5;129m@staticmethod\u001b[39m\n\u001b[1;32m 175\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mrun_graph\u001b[39m(_nodes: \u001b[38;5;28mdict\u001b[39m[Node], _starting_nodes: \u001b[38;5;28mlist\u001b[39m[Node]):\n\u001b[1;32m 176\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m node \u001b[38;5;129;01min\u001b[39;00m _starting_nodes:\n\u001b[0;32m--> 177\u001b[0m \u001b[43mnode\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 178\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m _nodes\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:394\u001b[0m, in \u001b[0;36mNode.run\u001b[0;34m(self, run_data_tree, run_parent_trees_too, fetch_input, check_readiness, force_local_execution, emit_ran_signal, **kwargs)\u001b[0m\n\u001b[1;32m 387\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m check_readiness \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mready:\n\u001b[1;32m 388\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ReadinessError(\n\u001b[1;32m 389\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlabel\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m received a run command but is not ready. The node \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 390\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mshould be neither running nor failed, and all input values should\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 391\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m conform to type hints.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreadiness_report\n\u001b[1;32m 392\u001b[0m )\n\u001b[0;32m--> 394\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 395\u001b[0m \u001b[43m \u001b[49m\u001b[43mfinished_callback\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run_and_emit_ran\u001b[49m\n\u001b[1;32m 396\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43memit_ran_signal\u001b[49m\n\u001b[1;32m 397\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 398\u001b[0m \u001b[43m \u001b[49m\u001b[43mforce_local_execution\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mforce_local_execution\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 399\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:66\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m node\u001b[38;5;241m.\u001b[39mfailed \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 65\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m---> 66\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 68\u001b[0m \u001b[38;5;66;03m# Leave the status as running if the method returns a future\u001b[39;00m\n\u001b[1;32m 69\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28misinstance\u001b[39m(out, Future)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:61\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 59\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 61\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[43mnode_method\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 62\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m out\n\u001b[1;32m 63\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:479\u001b[0m, in \u001b[0;36mNode._run\u001b[0;34m(self, finished_callback, force_local_execution)\u001b[0m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m force_local_execution \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 477\u001b[0m \u001b[38;5;66;03m# Run locally\u001b[39;00m\n\u001b[1;32m 478\u001b[0m run_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mon_run(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrun_args)\n\u001b[0;32m--> 479\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfinished_callback\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrun_output\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 480\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 481\u001b[0m \u001b[38;5;66;03m# Just blindly try to execute -- as we nail down the executor interaction\u001b[39;00m\n\u001b[1;32m 482\u001b[0m \u001b[38;5;66;03m# we'll want to fail more cleanly here.\u001b[39;00m\n\u001b[1;32m 483\u001b[0m executor \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_parse_executor(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:538\u001b[0m, in \u001b[0;36mNode._finish_run_and_emit_ran\u001b[0;34m(self, run_output)\u001b[0m\n\u001b[1;32m 536\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_finish_run_and_emit_ran\u001b[39m(\u001b[38;5;28mself\u001b[39m, run_output: \u001b[38;5;28mtuple\u001b[39m \u001b[38;5;241m|\u001b[39m Future) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any \u001b[38;5;241m|\u001b[39m \u001b[38;5;28mtuple\u001b[39m:\n\u001b[1;32m 537\u001b[0m processed_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_finish_run(run_output)\n\u001b[0;32m--> 538\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msignals\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43moutput\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mran\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 539\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m processed_output\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/channels.py:822\u001b[0m, in \u001b[0;36mOutputSignal.__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 820\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 821\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m c \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnections:\n\u001b[0;32m--> 822\u001b[0m \u001b[43mc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/channels.py:801\u001b[0m, in \u001b[0;36mAccumulatingInputSignal.__call__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 799\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mset\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnections)\u001b[38;5;241m.\u001b[39mdifference(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreceived_signals)) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 800\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreset()\n\u001b[0;32m--> 801\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcallback\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:394\u001b[0m, in \u001b[0;36mNode.run\u001b[0;34m(self, run_data_tree, run_parent_trees_too, fetch_input, check_readiness, force_local_execution, emit_ran_signal, **kwargs)\u001b[0m\n\u001b[1;32m 387\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m check_readiness \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mready:\n\u001b[1;32m 388\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ReadinessError(\n\u001b[1;32m 389\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlabel\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m received a run command but is not ready. The node \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 390\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mshould be neither running nor failed, and all input values should\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 391\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m conform to type hints.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreadiness_report\n\u001b[1;32m 392\u001b[0m )\n\u001b[0;32m--> 394\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 395\u001b[0m \u001b[43m \u001b[49m\u001b[43mfinished_callback\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run_and_emit_ran\u001b[49m\n\u001b[1;32m 396\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43memit_ran_signal\u001b[49m\n\u001b[1;32m 397\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 398\u001b[0m \u001b[43m \u001b[49m\u001b[43mforce_local_execution\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mforce_local_execution\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 399\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:66\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m node\u001b[38;5;241m.\u001b[39mfailed \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 65\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m---> 66\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 68\u001b[0m \u001b[38;5;66;03m# Leave the status as running if the method returns a future\u001b[39;00m\n\u001b[1;32m 69\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28misinstance\u001b[39m(out, Future)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:61\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 59\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 61\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[43mnode_method\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 62\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m out\n\u001b[1;32m 63\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:479\u001b[0m, in \u001b[0;36mNode._run\u001b[0;34m(self, finished_callback, force_local_execution)\u001b[0m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m force_local_execution \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 477\u001b[0m \u001b[38;5;66;03m# Run locally\u001b[39;00m\n\u001b[1;32m 478\u001b[0m run_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mon_run(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrun_args)\n\u001b[0;32m--> 479\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfinished_callback\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrun_output\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 480\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 481\u001b[0m \u001b[38;5;66;03m# Just blindly try to execute -- as we nail down the executor interaction\u001b[39;00m\n\u001b[1;32m 482\u001b[0m \u001b[38;5;66;03m# we'll want to fail more cleanly here.\u001b[39;00m\n\u001b[1;32m 483\u001b[0m executor \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_parse_executor(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:538\u001b[0m, in \u001b[0;36mNode._finish_run_and_emit_ran\u001b[0;34m(self, run_output)\u001b[0m\n\u001b[1;32m 536\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_finish_run_and_emit_ran\u001b[39m(\u001b[38;5;28mself\u001b[39m, run_output: \u001b[38;5;28mtuple\u001b[39m \u001b[38;5;241m|\u001b[39m Future) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any \u001b[38;5;241m|\u001b[39m \u001b[38;5;28mtuple\u001b[39m:\n\u001b[1;32m 537\u001b[0m processed_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_finish_run(run_output)\n\u001b[0;32m--> 538\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msignals\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43moutput\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mran\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 539\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m processed_output\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/channels.py:822\u001b[0m, in \u001b[0;36mOutputSignal.__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 820\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 821\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m c \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnections:\n\u001b[0;32m--> 822\u001b[0m \u001b[43mc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/channels.py:801\u001b[0m, in \u001b[0;36mAccumulatingInputSignal.__call__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 799\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mset\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnections)\u001b[38;5;241m.\u001b[39mdifference(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreceived_signals)) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 800\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreset()\n\u001b[0;32m--> 801\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcallback\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:394\u001b[0m, in \u001b[0;36mNode.run\u001b[0;34m(self, run_data_tree, run_parent_trees_too, fetch_input, check_readiness, force_local_execution, emit_ran_signal, **kwargs)\u001b[0m\n\u001b[1;32m 387\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m check_readiness \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mready:\n\u001b[1;32m 388\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ReadinessError(\n\u001b[1;32m 389\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlabel\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m received a run command but is not ready. The node \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 390\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mshould be neither running nor failed, and all input values should\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 391\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m conform to type hints.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreadiness_report\n\u001b[1;32m 392\u001b[0m )\n\u001b[0;32m--> 394\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 395\u001b[0m \u001b[43m \u001b[49m\u001b[43mfinished_callback\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run_and_emit_ran\u001b[49m\n\u001b[1;32m 396\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43memit_ran_signal\u001b[49m\n\u001b[1;32m 397\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 398\u001b[0m \u001b[43m \u001b[49m\u001b[43mforce_local_execution\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mforce_local_execution\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 399\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:66\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m node\u001b[38;5;241m.\u001b[39mfailed \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 65\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m---> 66\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 68\u001b[0m \u001b[38;5;66;03m# Leave the status as running if the method returns a future\u001b[39;00m\n\u001b[1;32m 69\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28misinstance\u001b[39m(out, Future)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:61\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 59\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 61\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[43mnode_method\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 62\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m out\n\u001b[1;32m 63\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:478\u001b[0m, in \u001b[0;36mNode._run\u001b[0;34m(self, finished_callback, force_local_execution)\u001b[0m\n\u001b[1;32m 471\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 472\u001b[0m \u001b[38;5;124;03mExecutes the functionality of the node defined in `on_run`.\u001b[39;00m\n\u001b[1;32m 473\u001b[0m \u001b[38;5;124;03mHandles the status of the node, and communicating with any remote\u001b[39;00m\n\u001b[1;32m 474\u001b[0m \u001b[38;5;124;03mcomputing resources.\u001b[39;00m\n\u001b[1;32m 475\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m force_local_execution \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 477\u001b[0m \u001b[38;5;66;03m# Run locally\u001b[39;00m\n\u001b[0;32m--> 478\u001b[0m run_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mon_run\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun_args\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 479\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m finished_callback(run_output)\n\u001b[1;32m 480\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 481\u001b[0m \u001b[38;5;66;03m# Just blindly try to execute -- as we nail down the executor interaction\u001b[39;00m\n\u001b[1;32m 482\u001b[0m \u001b[38;5;66;03m# we'll want to fail more cleanly here.\u001b[39;00m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/composite.py:177\u001b[0m, in \u001b[0;36mComposite.run_graph\u001b[0;34m(_nodes, _starting_nodes)\u001b[0m\n\u001b[1;32m 174\u001b[0m \u001b[38;5;129m@staticmethod\u001b[39m\n\u001b[1;32m 175\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mrun_graph\u001b[39m(_nodes: \u001b[38;5;28mdict\u001b[39m[Node], _starting_nodes: \u001b[38;5;28mlist\u001b[39m[Node]):\n\u001b[1;32m 176\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m node \u001b[38;5;129;01min\u001b[39;00m _starting_nodes:\n\u001b[0;32m--> 177\u001b[0m \u001b[43mnode\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 178\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m _nodes\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:394\u001b[0m, in \u001b[0;36mNode.run\u001b[0;34m(self, run_data_tree, run_parent_trees_too, fetch_input, check_readiness, force_local_execution, emit_ran_signal, **kwargs)\u001b[0m\n\u001b[1;32m 387\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m check_readiness \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mready:\n\u001b[1;32m 388\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ReadinessError(\n\u001b[1;32m 389\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlabel\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m received a run command but is not ready. The node \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 390\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mshould be neither running nor failed, and all input values should\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 391\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m conform to type hints.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreadiness_report\n\u001b[1;32m 392\u001b[0m )\n\u001b[0;32m--> 394\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 395\u001b[0m \u001b[43m \u001b[49m\u001b[43mfinished_callback\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run_and_emit_ran\u001b[49m\n\u001b[1;32m 396\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43memit_ran_signal\u001b[49m\n\u001b[1;32m 397\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 398\u001b[0m \u001b[43m \u001b[49m\u001b[43mforce_local_execution\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mforce_local_execution\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 399\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:66\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m node\u001b[38;5;241m.\u001b[39mfailed \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 65\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m---> 66\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 68\u001b[0m \u001b[38;5;66;03m# Leave the status as running if the method returns a future\u001b[39;00m\n\u001b[1;32m 69\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28misinstance\u001b[39m(out, Future)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:61\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 59\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 61\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[43mnode_method\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 62\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m out\n\u001b[1;32m 63\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:479\u001b[0m, in \u001b[0;36mNode._run\u001b[0;34m(self, finished_callback, force_local_execution)\u001b[0m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m force_local_execution \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 477\u001b[0m \u001b[38;5;66;03m# Run locally\u001b[39;00m\n\u001b[1;32m 478\u001b[0m run_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mon_run(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrun_args)\n\u001b[0;32m--> 479\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfinished_callback\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrun_output\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 480\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 481\u001b[0m \u001b[38;5;66;03m# Just blindly try to execute -- as we nail down the executor interaction\u001b[39;00m\n\u001b[1;32m 482\u001b[0m \u001b[38;5;66;03m# we'll want to fail more cleanly here.\u001b[39;00m\n\u001b[1;32m 483\u001b[0m executor \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_parse_executor(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:538\u001b[0m, in \u001b[0;36mNode._finish_run_and_emit_ran\u001b[0;34m(self, run_output)\u001b[0m\n\u001b[1;32m 536\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_finish_run_and_emit_ran\u001b[39m(\u001b[38;5;28mself\u001b[39m, run_output: \u001b[38;5;28mtuple\u001b[39m \u001b[38;5;241m|\u001b[39m Future) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any \u001b[38;5;241m|\u001b[39m \u001b[38;5;28mtuple\u001b[39m:\n\u001b[1;32m 537\u001b[0m processed_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_finish_run(run_output)\n\u001b[0;32m--> 538\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msignals\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43moutput\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mran\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 539\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m processed_output\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/channels.py:822\u001b[0m, in \u001b[0;36mOutputSignal.__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 820\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 821\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m c \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnections:\n\u001b[0;32m--> 822\u001b[0m \u001b[43mc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/channels.py:801\u001b[0m, in \u001b[0;36mAccumulatingInputSignal.__call__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 799\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mset\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnections)\u001b[38;5;241m.\u001b[39mdifference(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreceived_signals)) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 800\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreset()\n\u001b[0;32m--> 801\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcallback\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:394\u001b[0m, in \u001b[0;36mNode.run\u001b[0;34m(self, run_data_tree, run_parent_trees_too, fetch_input, check_readiness, force_local_execution, emit_ran_signal, **kwargs)\u001b[0m\n\u001b[1;32m 387\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m check_readiness \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mready:\n\u001b[1;32m 388\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ReadinessError(\n\u001b[1;32m 389\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlabel\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m received a run command but is not ready. The node \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 390\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mshould be neither running nor failed, and all input values should\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 391\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m conform to type hints.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreadiness_report\n\u001b[1;32m 392\u001b[0m )\n\u001b[0;32m--> 394\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 395\u001b[0m \u001b[43m \u001b[49m\u001b[43mfinished_callback\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run_and_emit_ran\u001b[49m\n\u001b[1;32m 396\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43memit_ran_signal\u001b[49m\n\u001b[1;32m 397\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 398\u001b[0m \u001b[43m \u001b[49m\u001b[43mforce_local_execution\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mforce_local_execution\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 399\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:66\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m node\u001b[38;5;241m.\u001b[39mfailed \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 65\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m---> 66\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 68\u001b[0m \u001b[38;5;66;03m# Leave the status as running if the method returns a future\u001b[39;00m\n\u001b[1;32m 69\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28misinstance\u001b[39m(out, Future)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:61\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 59\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 61\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[43mnode_method\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 62\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m out\n\u001b[1;32m 63\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:479\u001b[0m, in \u001b[0;36mNode._run\u001b[0;34m(self, finished_callback, force_local_execution)\u001b[0m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m force_local_execution \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 477\u001b[0m \u001b[38;5;66;03m# Run locally\u001b[39;00m\n\u001b[1;32m 478\u001b[0m run_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mon_run(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrun_args)\n\u001b[0;32m--> 479\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfinished_callback\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrun_output\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 480\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 481\u001b[0m \u001b[38;5;66;03m# Just blindly try to execute -- as we nail down the executor interaction\u001b[39;00m\n\u001b[1;32m 482\u001b[0m \u001b[38;5;66;03m# we'll want to fail more cleanly here.\u001b[39;00m\n\u001b[1;32m 483\u001b[0m executor \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_parse_executor(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:538\u001b[0m, in \u001b[0;36mNode._finish_run_and_emit_ran\u001b[0;34m(self, run_output)\u001b[0m\n\u001b[1;32m 536\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_finish_run_and_emit_ran\u001b[39m(\u001b[38;5;28mself\u001b[39m, run_output: \u001b[38;5;28mtuple\u001b[39m \u001b[38;5;241m|\u001b[39m Future) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any \u001b[38;5;241m|\u001b[39m \u001b[38;5;28mtuple\u001b[39m:\n\u001b[1;32m 537\u001b[0m processed_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_finish_run(run_output)\n\u001b[0;32m--> 538\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msignals\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43moutput\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mran\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 539\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m processed_output\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/channels.py:822\u001b[0m, in \u001b[0;36mOutputSignal.__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 820\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 821\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m c \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnections:\n\u001b[0;32m--> 822\u001b[0m \u001b[43mc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/channels.py:801\u001b[0m, in \u001b[0;36mAccumulatingInputSignal.__call__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 799\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mset\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnections)\u001b[38;5;241m.\u001b[39mdifference(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreceived_signals)) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 800\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreset()\n\u001b[0;32m--> 801\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcallback\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", - " \u001b[0;31m[... skipping similar frames: Node.run at line 394 (2 times), manage_status..wrapped_method at line 66 (2 times), manage_status..wrapped_method at line 61 (2 times), OutputSignal.__call__ at line 822 (1 times), AccumulatingInputSignal.__call__ at line 801 (1 times), Node._finish_run_and_emit_ran at line 538 (1 times), Node._run at line 479 (1 times)]\u001b[0m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:479\u001b[0m, in \u001b[0;36mNode._run\u001b[0;34m(self, finished_callback, force_local_execution)\u001b[0m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m force_local_execution \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 477\u001b[0m \u001b[38;5;66;03m# Run locally\u001b[39;00m\n\u001b[1;32m 478\u001b[0m run_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mon_run(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mrun_args)\n\u001b[0;32m--> 479\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mfinished_callback\u001b[49m\u001b[43m(\u001b[49m\u001b[43mrun_output\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 480\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 481\u001b[0m \u001b[38;5;66;03m# Just blindly try to execute -- as we nail down the executor interaction\u001b[39;00m\n\u001b[1;32m 482\u001b[0m \u001b[38;5;66;03m# we'll want to fail more cleanly here.\u001b[39;00m\n\u001b[1;32m 483\u001b[0m executor \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_parse_executor(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:538\u001b[0m, in \u001b[0;36mNode._finish_run_and_emit_ran\u001b[0;34m(self, run_output)\u001b[0m\n\u001b[1;32m 536\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m_finish_run_and_emit_ran\u001b[39m(\u001b[38;5;28mself\u001b[39m, run_output: \u001b[38;5;28mtuple\u001b[39m \u001b[38;5;241m|\u001b[39m Future) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m Any \u001b[38;5;241m|\u001b[39m \u001b[38;5;28mtuple\u001b[39m:\n\u001b[1;32m 537\u001b[0m processed_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_finish_run(run_output)\n\u001b[0;32m--> 538\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msignals\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43moutput\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mran\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 539\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m processed_output\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/channels.py:822\u001b[0m, in \u001b[0;36mOutputSignal.__call__\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 820\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__call__\u001b[39m(\u001b[38;5;28mself\u001b[39m) \u001b[38;5;241m-\u001b[39m\u001b[38;5;241m>\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 821\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m c \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnections:\n\u001b[0;32m--> 822\u001b[0m \u001b[43mc\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/channels.py:801\u001b[0m, in \u001b[0;36mAccumulatingInputSignal.__call__\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 799\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mset\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mconnections)\u001b[38;5;241m.\u001b[39mdifference(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreceived_signals)) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m:\n\u001b[1;32m 800\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreset()\n\u001b[0;32m--> 801\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mcallback\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:394\u001b[0m, in \u001b[0;36mNode.run\u001b[0;34m(self, run_data_tree, run_parent_trees_too, fetch_input, check_readiness, force_local_execution, emit_ran_signal, **kwargs)\u001b[0m\n\u001b[1;32m 387\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m check_readiness \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mready:\n\u001b[1;32m 388\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m ReadinessError(\n\u001b[1;32m 389\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;132;01m{\u001b[39;00m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mlabel\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m received a run command but is not ready. The node \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 390\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mshould be neither running nor failed, and all input values should\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 391\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m conform to type hints.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m\"\u001b[39m \u001b[38;5;241m+\u001b[39m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreadiness_report\n\u001b[1;32m 392\u001b[0m )\n\u001b[0;32m--> 394\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_run\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 395\u001b[0m \u001b[43m \u001b[49m\u001b[43mfinished_callback\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run_and_emit_ran\u001b[49m\n\u001b[1;32m 396\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01mif\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[43memit_ran_signal\u001b[49m\n\u001b[1;32m 397\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43;01melse\u001b[39;49;00m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_finish_run\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 398\u001b[0m \u001b[43m \u001b[49m\u001b[43mforce_local_execution\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mforce_local_execution\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 399\u001b[0m \u001b[43m\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:66\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 64\u001b[0m node\u001b[38;5;241m.\u001b[39mfailed \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 65\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mNone\u001b[39;00m\n\u001b[0;32m---> 66\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m e\n\u001b[1;32m 67\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n\u001b[1;32m 68\u001b[0m \u001b[38;5;66;03m# Leave the status as running if the method returns a future\u001b[39;00m\n\u001b[1;32m 69\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28misinstance\u001b[39m(out, Future)\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:61\u001b[0m, in \u001b[0;36mmanage_status..wrapped_method\u001b[0;34m(node, *args, **kwargs)\u001b[0m\n\u001b[1;32m 59\u001b[0m node\u001b[38;5;241m.\u001b[39mrunning \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m---> 61\u001b[0m out \u001b[38;5;241m=\u001b[39m \u001b[43mnode_method\u001b[49m\u001b[43m(\u001b[49m\u001b[43mnode\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 62\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m out\n\u001b[1;32m 63\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node.py:478\u001b[0m, in \u001b[0;36mNode._run\u001b[0;34m(self, finished_callback, force_local_execution)\u001b[0m\n\u001b[1;32m 471\u001b[0m \u001b[38;5;250m\u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 472\u001b[0m \u001b[38;5;124;03mExecutes the functionality of the node defined in `on_run`.\u001b[39;00m\n\u001b[1;32m 473\u001b[0m \u001b[38;5;124;03mHandles the status of the node, and communicating with any remote\u001b[39;00m\n\u001b[1;32m 474\u001b[0m \u001b[38;5;124;03mcomputing resources.\u001b[39;00m\n\u001b[1;32m 475\u001b[0m \u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 476\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m force_local_execution \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mexecutor \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[1;32m 477\u001b[0m \u001b[38;5;66;03m# Run locally\u001b[39;00m\n\u001b[0;32m--> 478\u001b[0m run_output \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mon_run\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrun_args\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 479\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m finished_callback(run_output)\n\u001b[1;32m 480\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 481\u001b[0m \u001b[38;5;66;03m# Just blindly try to execute -- as we nail down the executor interaction\u001b[39;00m\n\u001b[1;32m 482\u001b[0m \u001b[38;5;66;03m# we'll want to fail more cleanly here.\u001b[39;00m\n", - "File \u001b[0;32m~/python_projects/git_libs/pyiron_workflow/pyiron_workflow/node_library/atomistic/engine/lammps.py:184\u001b[0m, in \u001b[0;36mCollect\u001b[0;34m(out_dump, out_log, bla)\u001b[0m\n\u001b[1;32m 176\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mnumpy\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mnp\u001b[39;00m\n\u001b[1;32m 178\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpyiron_workflow\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mnode_library\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01matomistic\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcalculator\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdata\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m (\n\u001b[1;32m 179\u001b[0m OutputCalcStatic,\n\u001b[1;32m 180\u001b[0m OutputCalcMinimize,\n\u001b[1;32m 181\u001b[0m OutputCalcMD,\n\u001b[1;32m 182\u001b[0m )\n\u001b[0;32m--> 184\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mCollect: \u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[43mcalc_mode\u001b[49m, bla)\n\u001b[1;32m 185\u001b[0m log \u001b[38;5;241m=\u001b[39m out_log[\u001b[38;5;241m0\u001b[39m]\n\u001b[1;32m 187\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m calc_mode \u001b[38;5;241m==\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mstatic\u001b[39m\u001b[38;5;124m\"\u001b[39m:\n", - "\u001b[0;31mNameError\u001b[0m: name 'calc_mode' is not defined" - ] - } - ], - "source": [ - "out = wf.run()\n", - "print (f'Potential energy: {wf.lammps.outputs.generic.value.energy_pot}')" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "559ef84a-4203-48a1-8143-8f60688b6905", - "metadata": {}, - "outputs": [], - "source": [ - "# wf.lammps.InitLammps.outputs.calculator.value" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c30e9f16-f416-4b78-93ba-ee430fa7a1e3", - "metadata": {}, - "outputs": [], - "source": [ - "wf.lammps.Collect.inputs.calculator = " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "8a043ecd-e5ff-4cc6-99e3-5c4457b97598", - "metadata": {}, - "outputs": [], - "source": [ - "wf.lammps.Collect.inputs.calculator.value = wf.lammps.InitLammps.outputs.calculator.value" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "86f6d2f0-a6e6-401c-bb46-d7393984fa55", - "metadata": {}, - "outputs": [], - "source": [ - "wf.lammps.Collect.run()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "b98d3e39-4f68-4e80-bc86-87edb4976113", - "metadata": {}, - "outputs": [], "source": [ "wf.draw(depth=2)" ] @@ -1297,30 +2948,63 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "9cd9260a-825d-4c83-a81d-a18baad03be3", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "T= 300\n", + "Lammps_init: md bla\n", + "Collect: md \n", + "T= 600\n", + "Lammps_init: md bla\n", + "Collect: md \n", + "T= 900\n", + "Lammps_init: md bla\n", + "Collect: md \n", + "CPU times: user 1.05 s, sys: 386 ms, total: 1.44 s\n", + "Wall time: 10 s\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "%%time\n", "for T in [300, 600, 900]:\n", " wf = Workflow('Lammps')\n", " wf.structure = wf.create.atomistic.structure.build.bulk('Al', cubic=True)\n", - " wf.repeat = wf.create.atomistic.structure.transform.repeat(structure = wf.structure, repeat_scalar=3)\n", + " wf.repeat = wf.create.atomistic.structure.transform.repeat(structure=wf.structure, repeat_scalar=3)\n", " \n", " wf.lammps = wf.create.atomistic_codes.Lammps(structure=wf.repeat, label='lammps')\n", - " wf.lammps.calc_select.md(temperature=T, n_ionic_steps=10_000)\n", - " print ('T=', wf.lammps.calc.inputs.temperature)\n", + " wf.lammps.calc_select.md(\n", + " calculator_input = {\n", + " \"temperature\": T, \n", + " \"n_ionic_steps\": 10_000\n", + " }\n", + " )\n", + " print ('T=', wf.lammps.calc.inputs.calculator_input.value[\"temperature\"])\n", " \n", " wf.run()\n", " \n", - " plt.plot(wf.lammps.outputs.generic.value.energy_pot[2:], label=f'T={T}K')\n", + " plt.plot(wf.lammps.outputs.generic.value.energies_pot[2:], label=f'T={T}K')\n", "plt.legend(); " ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "id": "e848e8fb-d421-44c6-a4cc-156d941af32e", "metadata": {}, "outputs": [], @@ -1330,7 +3014,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "id": "c9309622-4351-4579-a514-6ac2c766dc12", "metadata": {}, "outputs": [], @@ -1350,14 +3034,14 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "dd4fb45e-1c25-4224-b23d-6f3d77544eb4", "metadata": {}, "outputs": [], "source": [ "@Workflow.wrap_as.macro_node('energy_pot')\n", "def energy_at_volume(wf, element='Al', cell_size=2, strain=0):\n", - " wf.bulk = wf.create.atomistic.build.cubic_bulk_cell(element=element, cubic=True, cell_size=cell_size)\n", + " wf.bulk = wf.create.atomistic.structure.build.cubic_bulk_cell(element=element, cubic=True, cell_size=cell_size)\n", " wf.apply_strain = wf.create.atomistic.structure.transform.apply_strain(structure=wf.bulk.outputs.structure, strain=strain)\n", " \n", " wf.lammps = wf.create.atomistic_codes.Lammps(structure=wf.apply_strain, label='lammps')\n", @@ -1367,10 +3051,50 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "id": "6d848d6d-2a6e-48e8-9cd2-7cac862a3d1a", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "max_workers: 1\n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n" + ] + }, + { + "data": { + "image/png": "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ymA4IiIiIiqD4YiIiIioDIYjIqIq6NatGyZPnix1GUSkQ5wEkoiM2ujRo5GRkYE///yzWvaXlpYGhUIBKyuratkfEekfU6kLICLSB4WFhQ9dfLUse3v7GqiGiKTEy2pEZBT++OMPNGvWDObm5nBwcECvXr3wwQcfYPXq1di6dStkMhlkMhkOHTqEmJgYyGQybNy4Ed26dYOZmRnWrVuH1NRUvPLKK/D09ISFhQWaNWuG9evXa33Ovy+r+fj4YN68eRgzZgysrKxQt25d/PjjjzXceyKqTgxHRGTwEhIS8Morr2DMmDEIDw/HoUOHMGTIEMyaNQtDhw5F3759kZCQgISEBHTo0EHzvo8++giTJk1CeHg4goODkZeXh8DAQGzfvh1XrlzBW2+9hZEjR+L06dOP/PxFixYhKCgIoaGhmDBhAsaPH49r167puttEpCO8rEZEBi8hIQFFRUUYMmQIvL29AQDNmjUDAJibmyM/Px+urq7l3jd58mQMGTJEa9u0adM0//3uu+9i165d+P3339G2bduHfn7//v0xYcIEACWB6+uvv8ahQ4fg5+f31H0joprHcEREBq9Fixbo2bMnmjVrhuDgYPTp0wcvvvgi7OzsHvm+oKAgrefFxcVYsGABfvvtN9y5cwf5+fnIz8+HpaXlI/fTvHlzzX/LZDK4uroiOTn5yTtERJLiZTUiMngmJibYu3cvdu7cCX9/fyxevBiNGzdGdHT0I9/379CzaNEifP311/jwww9x4MABXLhwAcHBwSgoKHjkfv49kFsmk0GtVj9ZZ4hIcjxzRERGQSaToWPHjujYsSNmzpwJb29vbNmyBUqlEsXFxZXax9GjRzFo0CCMGDECAKBWq3Hjxg00adJEl6UTkZ5hOCIig3f69Gns378fffr0gbOzM06fPo27d++iSZMmyMvLw+7duxEREQEHBwfY2Ng8dD8NGzbEpk2bcOLECdjZ2eGrr75CYmIiwxFRLcNwREQGz9raGkeOHME333yDrKwseHt7Y9GiRejXrx+CgoJw6NAhBAUF4d69ezh48CB8fHwq3M///d//ITo6GsHBwbCwsMBbb72FwYMHIzMzs2Y7RESS4gzZRERERGVwQDYRERFRGQxHRERERGUwHBERERGVwXBEREREVAbDEREREVEZDEdEREREZTAcEREREZXBcERERERUBsMRERERURkMR0RERERlMBwRERERlcFwRERERFTG/wOC5q7f+IrFCQAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "df = energy_at_volume().iter(strain=np.linspace(-0.2, 0.2, 11))\n", "df.plot(x='strain', ylabel='Energy (eV)', title='Energy-Volume Curve');" @@ -1378,10 +3102,49 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "id": "3050e5e5-4c68-4195-a665-0f5d4b0b78b0", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n", + "Lammps_init: static bla\n", + "Collect: static \n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import numpy as np\n", "\n", @@ -1401,58 +3164,60 @@ "id": "f962df29-d580-44a7-a264-12101f77b61b", "metadata": {}, "source": [ - "### Data store" + "### Data store\n", + "\n", + "Temporarily deprecated until we merge with the existing storage branch" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "id": "7fcc5262-713b-4755-a730-0b1f6fa6349c", "metadata": {}, "outputs": [], "source": [ - "from pyiron_workflow.node_library.dev_tools import DataStore, node_to_data_container, extract_value" + "# from pyiron_workflow.node_library.dev_tools import DataStore, node_to_data_container, extract_value" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "id": "6fd3b054-d066-4b05-9cbf-f5fa88476a45", "metadata": {}, "outputs": [], "source": [ - "ds = DataStore(path='DataStore')\n", - "ds.store(wf, overwrite=True)" + "# ds = DataStore(path='DataStore')\n", + "# ds.store(wf, overwrite=True)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "id": "347cdcc9-db7a-4d84-9578-a04cad573aac", "metadata": {}, "outputs": [], "source": [ - "wf_new = ds.load(wf.label)" + "# wf_new = ds.load(wf.label)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "id": "e3720e67-67d0-4f3a-a8ae-57dbd86c20b7", "metadata": {}, "outputs": [], "source": [ - "wf.lammps" + "# wf.lammps" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "id": "2c3b4321-f8a9-4e7f-bd8e-63bae6abf8d5", "metadata": {}, "outputs": [], "source": [ - "wf.outputs.energy_pot.value" + "# wf.outputs.energy_pot.value" ] }, { @@ -1465,22 +3230,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "id": "e9083ee4-df8a-4a57-b168-f932b52071c3", "metadata": {}, "outputs": [], "source": [ - "out = wf(element='Fe')" + "# out = wf(element='Fe')" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 23, "id": "17f03ced-1b20-4db1-b78a-70db0c4f9c1c", "metadata": {}, "outputs": [], "source": [ - "ds.remove(wf.label)" + "# ds.remove(wf.label)" ] }, { @@ -1493,74 +3258,74 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "id": "7c476ec9-e35b-46fe-bca1-f7705aa205d2", "metadata": {}, "outputs": [], "source": [ - "import cloudpickle as pickle" + "# import cloudpickle as pickle" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "id": "f0b574b3-3c74-44fe-a471-650738f2af9c", "metadata": {}, "outputs": [], "source": [ - "with open('node.pickle', 'wb') as f:\n", - " pickle.dump(wf, f)" + "# with open('node.pickle', 'wb') as f:\n", + "# pickle.dump(wf, f)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "id": "bf304ec5-2fe4-46cc-8ec8-2fcdb82500b6", "metadata": {}, "outputs": [], "source": [ - "with open('node.pickle', 'rb') as f:\n", - " new_node = pickle.load(f)" + "# with open('node.pickle', 'rb') as f:\n", + "# new_node = pickle.load(f)" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "id": "397d1b5e-9336-463a-94d5-a508b8a1b9e7", "metadata": {}, "outputs": [], "source": [ - "new_node.run();" + "# new_node.run();" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "id": "fc47c328-a3c6-42da-856e-cdfe58bdb5f5", "metadata": {}, "outputs": [], "source": [ - "new_node.outputs.energy_pot.value" + "# new_node.outputs.energy_pot.value" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 29, "id": "3edaaa9e-8b3f-4298-a9f2-456d7013276a", "metadata": {}, "outputs": [], "source": [ - "out.energy_pot" + "# out.energy_pot" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 30, "id": "b1d5e21f-6cae-4d0c-8543-1d3c1790fc37", "metadata": {}, "outputs": [], "source": [ - "out" + "# out" ] }, { @@ -1573,17 +3338,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 31, "id": "21e00942-bc9a-48f9-838d-e16aa4d67fb6", "metadata": {}, "outputs": [], "source": [ - "wf.create.atomistics" + "wf.register('pyiron_workflow.node_library.atomistics', domain='atomistics')" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 32, "id": "afd76914-fa37-4ec2-b22d-adecc03f232f", "metadata": {}, "outputs": [], @@ -1597,10 +3362,21 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 33, "id": "bc0aae29-1d88-4720-97c1-035071b200d7", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "Atoms(symbols='Al', pbc=True, cell=[[0.0, 2.025, 2.025], [2.025, 0.0, 2.025], [2.025, 2.025, 0.0]])" + ] + }, + "execution_count": 33, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "bulk = wf.bulk.run()\n", "bulk" @@ -1608,22 +3384,67 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 34, "id": "84d5b8d5-c39f-4102-9a22-4298611abb94", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "application/json": { + "channels": { + "potential_name": { + "connected": false, + "connections": [], + "label": "potential_name", + "ready": false, + "type_hint": "None", + "value": "" + }, + "resource_path": { + "connected": false, + "connections": [], + "label": "resource_path", + "ready": false, + "type_hint": "None", + "value": "" + }, + "structure": { + "connected": true, + "connections": [ + "bulk.structure" + ], + "label": "structure", + "ready": false, + "type_hint": "None", + "value": "" + } + }, + "connected": true, + "fully_connected": false, + "label": "Inputs", + "ready": false + }, + "text/plain": [ + "" + ] + }, + "execution_count": 34, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "wf.lammps_potential.inputs" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "id": "37c3d874-2be5-4b83-8a8b-19c26c6d5197", "metadata": {}, "outputs": [], "source": [ - "wf.draw()" + "wf.draw();" ] }, { @@ -1644,7 +3465,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 36, "id": "ac98a74f-c712-49bd-8622-dadf3579be07", "metadata": {}, "outputs": [], @@ -1660,7 +3481,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 37, "id": "d01decfc-8d46-47f2-b7d4-495e2d91db59", "metadata": {}, "outputs": [ @@ -1673,659 +3494,659 @@ "\n", "\n", - "\n", - "\n", + "\n", + "\n", "clustertest\n", - "\n", - "test: Workflow\n", + "\n", + "test: Workflow\n", "\n", "clustertestInputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", "\n", "clustertestOutputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "clusterteststring1\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "string1: create_string\n", + "\n", + "string1: create_string\n", "\n", "\n", "clusterteststring1Inputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", "\n", "clusterteststring1Outputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "clusterteststring2\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "string2: create_string\n", + "\n", + "string2: create_string\n", "\n", "\n", "clusterteststring2Inputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", "\n", "clusterteststring2Outputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "clusterteststring3\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "string3: create_string\n", + "\n", + "string3: create_string\n", "\n", "\n", "clusterteststring3Inputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", "\n", "clusterteststring3Outputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "clustertestsum_1\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "sum_1: plus\n", + "\n", + "sum_1: plus\n", "\n", "\n", "clustertestsum_1Inputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", "\n", "clustertestsum_1Outputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "clustertestsum_2\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "sum_2: plus\n", + "\n", + "sum_2: plus\n", "\n", - "\n", - "clustertestsum_2Inputs\n", + "\n", + "clustertestsum_2Outputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Outputs\n", "\n", - "\n", - "clustertestsum_2Outputs\n", + "\n", + "clustertestsum_2Inputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Inputs\n", "\n", "\n", "clustertestsum_3\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "sum_3: plus\n", + "\n", + "sum_3: plus\n", "\n", "\n", "clustertestsum_3Inputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Inputs\n", + "\n", + "Inputs\n", "\n", "\n", "clustertestsum_3Outputs\n", "\n", - "\n", + "\n", "\n", "\n", "\n", "\n", - "\n", - "Outputs\n", + "\n", + "Outputs\n", "\n", "\n", "\n", "clustertestInputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clustertestOutputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clustertestInputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clustertestInputsstring1__my_string\n", - "\n", - "string1__my_string: str\n", + "\n", + "string1__my_string: str\n", "\n", "\n", "\n", "clusterteststring1Inputsmy_string\n", - "\n", - "my_string: str\n", + "\n", + "my_string: str\n", "\n", "\n", "\n", "clustertestInputsstring1__my_string->clusterteststring1Inputsmy_string\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestInputsstring2__my_string\n", - "\n", - "string2__my_string: str\n", + "\n", + "string2__my_string: str\n", "\n", "\n", "\n", "clusterteststring2Inputsmy_string\n", - "\n", - "my_string: str\n", + "\n", + "my_string: str\n", "\n", "\n", "\n", "clustertestInputsstring2__my_string->clusterteststring2Inputsmy_string\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestInputsstring3__my_string\n", - "\n", - "string3__my_string: str\n", + "\n", + "string3__my_string: str\n", "\n", "\n", "\n", "clusterteststring3Inputsmy_string\n", - "\n", - "my_string: str\n", + "\n", + "my_string: str\n", "\n", "\n", "\n", "clustertestInputsstring3__my_string->clusterteststring3Inputsmy_string\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestInputssum_1__my_string_4\n", - "\n", - "sum_1__my_string_4: str\n", + "\n", + "sum_1__my_string_4: str\n", "\n", "\n", "\n", "clustertestsum_1Inputsmy_string_4\n", - "\n", - "my_string_4: str\n", + "\n", + "my_string_4: str\n", "\n", "\n", "\n", "clustertestInputssum_1__my_string_4->clustertestsum_1Inputsmy_string_4\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestInputssum_2__my_string_3\n", - "\n", - "sum_2__my_string_3: str\n", + "\n", + "sum_2__my_string_3: str\n", "\n", "\n", "\n", "clustertestsum_2Inputsmy_string_3\n", - "\n", - "my_string_3: str\n", + "\n", + "my_string_3: str\n", "\n", "\n", "\n", "clustertestInputssum_2__my_string_3->clustertestsum_2Inputsmy_string_3\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestInputssum_2__my_string_4\n", - "\n", - "sum_2__my_string_4: str\n", + "\n", + "sum_2__my_string_4: str\n", "\n", "\n", "\n", "clustertestsum_2Inputsmy_string_4\n", - "\n", - "my_string_4: str\n", + "\n", + "my_string_4: str\n", "\n", "\n", "\n", "clustertestInputssum_2__my_string_4->clustertestsum_2Inputsmy_string_4\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestInputssum_3__my_string_4\n", - "\n", - "sum_3__my_string_4: str\n", + "\n", + "sum_3__my_string_4: str\n", "\n", "\n", "\n", "clustertestsum_3Inputsmy_string_4\n", - "\n", - "my_string_4: str\n", + "\n", + "my_string_4: str\n", "\n", "\n", "\n", "clustertestInputssum_3__my_string_4->clustertestsum_3Inputsmy_string_4\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestOutputssum_3__string\n", - "\n", - "sum_3__string\n", + "\n", + "sum_3__string\n", "\n", "\n", "\n", "clusterteststring1Inputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterteststring1Outputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterteststring1Inputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterteststring1Outputsstring\n", - "\n", - "string\n", + "\n", + "string\n", "\n", "\n", "\n", "clustertestsum_1Inputsmy_string_1\n", - "\n", - "my_string_1: str\n", + "\n", + "my_string_1: str\n", "\n", "\n", "\n", "clusterteststring1Outputsstring->clustertestsum_1Inputsmy_string_1\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestsum_1Inputsmy_string_3\n", - "\n", - "my_string_3: str\n", + "\n", + "my_string_3: str\n", "\n", "\n", "\n", "clusterteststring1Outputsstring->clustertestsum_1Inputsmy_string_3\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestsum_3Inputsmy_string_2\n", - "\n", - "my_string_2: str\n", + "\n", + "my_string_2: str\n", "\n", "\n", "\n", "clusterteststring1Outputsstring->clustertestsum_3Inputsmy_string_2\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterteststring2Inputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterteststring2Outputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterteststring2Inputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterteststring2Outputsstring\n", - "\n", - "string\n", + "\n", + "string\n", "\n", "\n", "\n", "clustertestsum_1Inputsmy_string_2\n", - "\n", - "my_string_2: str\n", + "\n", + "my_string_2: str\n", "\n", "\n", "\n", "clusterteststring2Outputsstring->clustertestsum_1Inputsmy_string_2\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestsum_3Inputsmy_string_3\n", - "\n", - "my_string_3: str\n", + "\n", + "my_string_3: str\n", "\n", "\n", "\n", "clusterteststring2Outputsstring->clustertestsum_3Inputsmy_string_3\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clusterteststring3Inputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clusterteststring3Outputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clusterteststring3Inputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clusterteststring3Outputsstring\n", - "\n", - "string\n", + "\n", + "string\n", "\n", "\n", "\n", "clustertestsum_2Inputsmy_string_2\n", - "\n", - "my_string_2: str\n", + "\n", + "my_string_2: str\n", "\n", "\n", "\n", "clusterteststring3Outputsstring->clustertestsum_2Inputsmy_string_2\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestsum_1Inputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clustertestsum_1Outputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clustertestsum_1Inputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clustertestsum_1Outputsstring\n", - "\n", - "string\n", + "\n", + "string\n", "\n", "\n", "\n", "clustertestsum_2Inputsmy_string_1\n", - "\n", - "my_string_1: str\n", + "\n", + "my_string_1: str\n", "\n", "\n", "\n", "clustertestsum_1Outputsstring->clustertestsum_2Inputsmy_string_1\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestsum_2Inputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clustertestsum_2Outputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clustertestsum_2Inputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clustertestsum_2Outputsstring\n", - "\n", - "string\n", + "\n", + "string\n", "\n", "\n", "\n", "clustertestsum_3Inputsmy_string_1\n", - "\n", - "my_string_1: str\n", + "\n", + "my_string_1: str\n", "\n", "\n", "\n", "clustertestsum_2Outputsstring->clustertestsum_3Inputsmy_string_1\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n", "clustertestsum_3Inputsrun\n", - "\n", - "run\n", + "\n", + "run\n", "\n", "\n", "\n", "clustertestsum_3Outputsran\n", - "\n", - "ran\n", + "\n", + "ran\n", "\n", "\n", "\n", "\n", "clustertestsum_3Inputsaccumulate_and_run\n", - "\n", - "accumulate_and_run\n", + "\n", + "accumulate_and_run\n", "\n", "\n", "\n", "clustertestsum_3Outputsstring\n", - "\n", - "string\n", + "\n", + "string\n", "\n", "\n", "\n", "clustertestsum_3Outputsstring->clustertestOutputssum_3__string\n", - "\n", - "\n", - "\n", + "\n", + "\n", + "\n", "\n", "\n", "\n" ], "text/plain": [ - "" + "" ] }, - "execution_count": 12, + "execution_count": 37, "metadata": {}, "output_type": "execute_result" } @@ -2343,6 +4164,14 @@ "\n", "wf.draw()" ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "e0a9f114-3887-429b-9bf5-84d21871fedc", + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/notebooks/quickstart.ipynb b/notebooks/quickstart.ipynb index 19ab25fd..2944dcb7 100644 --- a/notebooks/quickstart.ipynb +++ b/notebooks/quickstart.ipynb @@ -123,7 +123,7 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:164: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/channels.py:166: UserWarning: The channel run was not connected to ran, andthus could not disconnect from it.\n", " warn(\n" ] }, @@ -813,7 +813,7 @@ "\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 7, @@ -833,7 +833,7 @@ " \"\"\"\n", " return np.arange(n), n\n", "\n", - "wf.register(\"plotting\", \"pyiron_workflow.node_library.plotting\")\n", + "wf.register(\"pyiron_workflow.node_library.plotting\", \"plotting\")\n", "\n", "wf.arange = Arange(10)\n", "wf.plot = wf.create.plotting.Scatter(\n", @@ -864,14 +864,14 @@ "name": "stderr", "output_type": "stream", "text": [ - "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:613: UserWarning: The keyword 'arrays__x' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", + "/Users/huber/work/pyiron/pyiron_workflow/pyiron_workflow/node.py:621: UserWarning: The keyword 'arrays__x' was not found among input labels. If you are trying to update a node keyword, please use attribute assignment directly instead of calling\n", " warnings.warn(\n" ] }, { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 8, @@ -998,8 +998,8 @@ "data": { "text/plain": [ "{'square_plot__n': 10,\n", - " 'square_plot__fig': ,\n", - " 'plus_one_square_plot__fig': }" + " 'square_plot__fig': ,\n", + " 'plus_one_square_plot__fig': }" ] }, "execution_count": 12, @@ -1757,7 +1757,7 @@ "
\n" ], "text/plain": [ - "" + "" ] }, "execution_count": 13, diff --git a/pyiron_workflow/__init__.py b/pyiron_workflow/__init__.py index 566dfc9f..41231fb5 100644 --- a/pyiron_workflow/__init__.py +++ b/pyiron_workflow/__init__.py @@ -1,6 +1,6 @@ """ -`pyiron_workflow` is a python framework for constructing computational workflows in a -graph-based format. +:mod:`pyiron_workflow` is a python framework for constructing computational workflows +in a graph-based format. The intent of such a framework is to improve the reliability and shareability of computational workflows, as well as providing supporting infrastructure for the storage and retrieval of data, and executing computations on remote resources (with a @@ -9,6 +9,7 @@ cases should be _almost_ as simple as writing and running plain python functions. Key features: + - Single point of import - Easy "nodeification" of regular python code - Macro nodes, so complex workflows can be built by composition @@ -21,10 +22,11 @@ Planned: - Storage of executed workflows, including restarting from a partially executed workflow -- Support for more complex remote execution, especially leveraging `pympipool` +- Support for more complex remote execution, especially leveraging :mod:`pympipool` - Infrastructure that supports and encourages of FAIR principles for node packages and finished workflows - Ontological hinting for data channels in order to provide guided workflow design - GUI on top for code-lite/code-free visual scripting """ + from pyiron_workflow.workflow import Workflow diff --git a/pyiron_workflow/channels.py b/pyiron_workflow/channels.py index 6065691d..74d7c5a6 100644 --- a/pyiron_workflow/channels.py +++ b/pyiron_workflow/channels.py @@ -39,8 +39,8 @@ class Channel(HasChannel, HasToDict, ABC): a necessary ancestor for instances they can connect to (`connection_partner_type: type[Channel]`). - Channels may form (`connect`/`disconnect`) and store (`connections: list[Channel]`) - connections with other channels. + Channels may form (:meth:`connect`/:meth:`disconnect`) and store + (:attr:`connections: list[Channel]`) connections with other channels. This connection information is reflexive, and is duplicated to be stored on _both_ channels in the form of a reference to their counterpart in the connection. @@ -51,7 +51,8 @@ class Channel(HasChannel, HasToDict, ABC): In this abstract class the only requirement is that the connecting channels form a "conjugate pair" of classes, i.e. they are children of each other's partner class - (`connection_partner_type: type[Channel]`) -- input/output connects to output/input. + (:attr:`connection_partner_type: type[Channel]`) -- input/output connects to + output/input. Iterating over channels yields their connections. @@ -110,7 +111,8 @@ def connect(self, *others: Channel) -> None: """ Form a connection between this and one or more other channels. Connections are reflexive, and should only occur between input and output - channels, i.e. they are instances of each others `connection_partner_type`. + channels, i.e. they are instances of each others + :attr:`connection_partner_type`. Args: *others (Channel): The other channel objects to attempt to connect with. @@ -231,12 +233,12 @@ class DataChannel(Channel, ABC): """ Data channels control the flow of data on the graph. - They store data persistently (`value`). + They store data persistently (:attr:`value`). - This value may have a default (`default`) and the default-default is to be + This value may have a default (:attr:`default`) and the default-default is to be `NotData`. - They may optionally have a type hint (`type_hint`). + They may optionally have a type hint (:attr:`type_hint`). New data and new connections are tested against type hints (if any). @@ -245,21 +247,21 @@ class DataChannel(Channel, ABC): more specific than the input channel. In addition to connections, these channels can have a single partner - (`value_receiver: DataChannel`) that is of the _same_ class and obeys type hints as - though it were the "downstream" (input) partner in a connection. + (:attr:`value_receiver: DataChannel`) that is of the _same_ class and obeys type + hints as though it were the "downstream" (input) partner in a connection. Channels with such partners pass any data updates they receive directly to this - partner (via the `value` setter). + partner (via the :attr:`value` setter). (This is helpful for passing data between scopes, where we want input at one scope to be passed to the input of nodes at a deeper scope, i.e. macro input passing to child node input, or vice versa for output.) All these type hint tests can be disabled on the input/receiving channel - (`strict_hints: bool`), and this is recommended for the optimal performance in - production runs. + (:attr:`strict_hints: bool`), and this is recommended for the optimal performance + in production runs. - Channels can indicate whether they hold data they are happy with (`ready: bool`), - which is to say it is data (not `NotData`) and that it conforms to the type hint - (if one is provided and checking is active). + Channels can indicate whether they hold data they are happy with + (:attr:`ready: bool`), which is to say it is data (not :class:`NotData`) and that + it conforms to the type hint (if one is provided and checking is active). Output data facilitates many (but not all) python operators by injecting a new node to perform that operation. Where the operator is not supported, we try to @@ -273,6 +275,7 @@ class DataChannel(Channel, ABC): it at the end of something that hasn't run yet you don't want to see an error. TODO: + - Storage (including priority and history) - Ontological hinting @@ -462,15 +465,15 @@ def connection_partner_type(self): def fetch(self) -> None: """ - Sets `value` to the first value among connections that is something other than - `NotData`; if no such value exists (e.g. because there are no connections or + Sets :attr:`value` to the first value among connections that is something other than + :class:`NotData`; if no such value exists (e.g. because there are no connections or because all the connected output channels have `NotData` as their value), - `value` remains unchanged. + :attr:`value` remains unchanged. I.e., the connection with the highest priority for updating input data is the 0th connection; build graphs accordingly. Raises: - RuntimeError: If the parent node is `running`. + RuntimeError: If the parent node is :attr:`running`. """ for out in self.connections: if out.value is not NotData: @@ -786,7 +789,7 @@ def __init__( callback: callable, ): super().__init__(label=label, node=node, callback=callback) - self.received_signals: set[OutputSignal] = set() + self.received_signals: set[str] = set() def __call__(self, other: OutputSignal) -> None: """ @@ -795,8 +798,15 @@ def __call__(self, other: OutputSignal) -> None: Resets the collection of received signals when firing. """ - self.received_signals.update([other]) - if len(set(self.connections).difference(self.received_signals)) == 0: + self.received_signals.update([other.scoped_label]) + if ( + len( + set(c.scoped_label for c in self.connections).difference( + self.received_signals + ) + ) + == 0 + ): self.reset() self.callback() diff --git a/pyiron_workflow/composite.py b/pyiron_workflow/composite.py index f0ef895b..663f47c8 100644 --- a/pyiron_workflow/composite.py +++ b/pyiron_workflow/composite.py @@ -30,9 +30,10 @@ class Composite(Node, ABC): collection of child nodes and their computation is to execute that graph. Promises (in addition parent class promises): + - The class offers access... - - To the node-izing `pyiron_workflow` decorators - - To a creator for other `pyiron_workflow` objects (namely nodes) + - To the node-izing :mod:`pyiron_workflow` decorators + - To a creator for other :mod:`pyiron_workflow` objects (namely nodes) - From the class level, this simply creates these objects - From the instance level, created nodes get the instance as their parent - Child nodes... @@ -73,7 +74,7 @@ class Composite(Node, ABC): connected to some other child channel). Non-`None` values provided at input can be in regular dictionary form, but get re-cast as a clean bidict to ensure the bijective nature of the maps (i.e. there is a 1:1 connection between any - IO exposed at the `Composite` level and the underlying channels). + IO exposed at the :class:`Composite` level and the underlying channels). nodes (DotDict[pyiron_workflow.node.Node]): The owned nodes that form the composite subgraph. strict_naming (bool): When true, repeated assignment of a new node to an @@ -372,8 +373,8 @@ def _ensure_node_is_not_duplicated(self, node: Node, label: str): def remove_node(self, node: Node | str) -> list[tuple[Channel, Channel]]: """ - Remove a node from the `nodes` collection, disconnecting it and setting its - `parent` to None. + Remove a node from the :attr:`nodes` collection, disconnecting it and setting its + :attr:`parent` to None. Args: node (Node|str): The node (or its label) to remove. @@ -506,8 +507,8 @@ def _rebuild_data_io(self): @classmethod @wraps(Creator.register) - def register(cls, domain: str, package_identifier: str) -> None: - cls.create.register(domain=domain, package_identifier=package_identifier) + def register(cls, package_identifier: str, domain: Optional[str] = None) -> None: + cls.create.register(package_identifier=package_identifier, domain=domain) def executor_shutdown(self, wait=True, *, cancel_futures=False): """ diff --git a/pyiron_workflow/executors/__init__.py b/pyiron_workflow/executors/__init__.py index 83069e79..ff42eda0 100644 --- a/pyiron_workflow/executors/__init__.py +++ b/pyiron_workflow/executors/__init__.py @@ -1,5 +1,5 @@ """ -This module holds customized children of `concurrent.futures.Executor`. +This module holds customized children of :class:`concurrent.futures.Executor`. """ from pyiron_workflow.executors.cloudpickleprocesspool import ( diff --git a/pyiron_workflow/executors/cloudpickleprocesspool.py b/pyiron_workflow/executors/cloudpickleprocesspool.py index cc9488cf..aa779d26 100644 --- a/pyiron_workflow/executors/cloudpickleprocesspool.py +++ b/pyiron_workflow/executors/cloudpickleprocesspool.py @@ -30,14 +30,14 @@ def dumps(cls, stuff): class CloudpickleProcessPoolExecutor(ProcessPoolExecutor): """ - This class wraps `concurrent.futures.ProcessPoolExecutor` such that the submitted - callable, its arguments, and its return value are all pickled using `cloudpickle`. + This class wraps :class:`concurrent.futures.ProcessPoolExecutor` such that the submitted + callable, its arguments, and its return value are all pickled using :mod:`cloudpickle`. In this way, the executor extends support to all objects which are cloud-pickleable, e.g. dynamically defined or decorated classes. - To accomplish this, the underlying `concurrent.futures.Future` class used is - replaced with our `CloudLoadsFuture`, which is identical except that calls to - `result()` will first try to `cloudpickle.loads` and `bytes` results found. + To accomplish this, the underlying :class:`concurrent.futures.Future` class used is + replaced with our :class:`CloudLoadsFuture`, which is identical except that calls to + :meth:`result()` will first try to :func:`cloudpickle.loads` and `bytes` results found. Examples: Consider a class created from a function dynamically with a decorator. @@ -46,6 +46,7 @@ class CloudpickleProcessPoolExecutor(ProcessPoolExecutor): and returns such an unpickleable class. Actions such as registering callbacks and waiting for results behave just like normal. + >>> from functools import partialmethod >>> >>> from pyiron_workflow.executors.cloudpickleprocesspool import ( diff --git a/pyiron_workflow/function.py b/pyiron_workflow/function.py index 82e6498c..97408469 100644 --- a/pyiron_workflow/function.py +++ b/pyiron_workflow/function.py @@ -35,6 +35,7 @@ class Function(Node): numbers of return values may or may not work smoothly, depending on the details. Promises: + - IO channels are constructed automatically from the wrapped function - This includes type hints (if any) - This includes defaults (if any) @@ -68,6 +69,7 @@ class Function(Node): Examples: At the most basic level, to use nodes all we need to do is provide the `Function` class with a function and labels for its output, like so: + >>> from pyiron_workflow.function import Function >>> >>> def mwe(x, y): @@ -85,6 +87,7 @@ class Function(Node): We'll run into a hiccup if we try to set only one of the inputs and force the run: + >>> plus_minus_1.inputs.x = 2 >>> try: ... plus_minus_1.run() @@ -101,6 +104,7 @@ class Function(Node): We are able to check this without trying and failing by looking at the readiness report: + >>> print(plus_minus_1.readiness_report) mwe readiness: False STATE: @@ -117,6 +121,7 @@ class Function(Node): `run()` call, which succeeds and updates the output. The final thing we need to do is disable the `failed` status we got from our last run call + >>> plus_minus_1.failed = False >>> plus_minus_1.inputs.y = 3 >>> out = plus_minus_1.run() @@ -125,6 +130,7 @@ class Function(Node): We can also, optionally, provide initial values for some or all of the input and labels for the output: + >>> plus_minus_1 = Function(mwe, output_labels=("p1", "m1"), x=1) >>> plus_minus_1.inputs.y = 2 >>> out = plus_minus_1.run() @@ -135,6 +141,7 @@ class Function(Node): or keyword kwargs. When running the node (or any alias to run like pull, execute, or just calling the node), the output of the wrapped function is returned: + >>> plus_minus_1(2, y=3) (3, 2) @@ -151,8 +158,9 @@ class Function(Node): variety of common use cases. Note that getting "good" (i.e. dot-accessible) output labels can be achieved by using good variable names and returning those variables instead of using - `output_labels`. + :attr:`output_labels`. If we try to assign a value of the wrong type, it will raise an error: + >>> from typing import Union >>> >>> def hinted_example( @@ -174,6 +182,7 @@ class Function(Node): `_value` property. In the latter case, we'd still get a readiness error when we try to run and the ready check sees that the data doesn't conform to the type hint: + >>> plus_minus_1.inputs.x._value = "not an int or float" >>> try: ... plus_minus_1.run() @@ -197,17 +206,18 @@ class Function(Node): >>> plus_minus_1.ready, plus_minus_1.inputs.x.ready, plus_minus_1.inputs.y.ready (False, False, True) - In these examples, we've instantiated nodes directly from the base `Function` + In these examples, we've instantiated nodes directly from the base :class:`Function` class, and populated their input directly with data. In practice, these nodes are meant to be part of complex workflows; that means both that you are likely to have particular nodes that get heavily re-used, and that you need the nodes to pass data to each other. - For reusable nodes, we want to create a sub-class of `Function` that fixes some - of the node behaviour -- usually the `node_function` and `output_labels`. + For reusable nodes, we want to create a sub-class of :class:`Function` that fixes some + of the node behaviour -- usually the :meth:`node_function` and :attr:`output_labels`. - This can be done most easily with the `node` decorator, which takes a function + This can be done most easily with the :func:`function_node` decorator, which takes a function and returns a node class: + >>> from pyiron_workflow.function import function_node >>> >>> @function_node("p1", "m1") @@ -228,6 +238,7 @@ class Function(Node): Using the decorator is the recommended way to create new node classes, but this magic is just equivalent to creating a child class with the `node_function` already defined as a `staticmethod`: + >>> from typing import Literal, Optional >>> >>> class AlphabetModThree(Function): @@ -255,6 +266,7 @@ class Function(Node): out automatically by the topology of data connections. Let's put together a couple of nodes and then run in a "pull" paradigm to get the final node to run everything "upstream" then run itself: + >>> @function_node() ... def adder_node(x: int = 0, y: int = 0) -> int: ... sum = x + y @@ -281,6 +293,7 @@ class Function(Node): This is a bit more verbose, but a necessary tool for more complex situations (like cyclic graphs). Here's our simple example from above using this other paradigm: + >>> @function_node() ... def adder_node(x: int = 0, y: int = 0) -> int: ... sum = x + y @@ -304,7 +317,7 @@ class Function(Node): a To see more details on how to use many nodes together, look at the - `Workflow` class. + :class:`Workflow` class. Comments: Using the `self` argument for function nodes is not fully supported; it will diff --git a/pyiron_workflow/has_channel.py b/pyiron_workflow/has_channel.py index 69ff0a14..0a1ed599 100644 --- a/pyiron_workflow/has_channel.py +++ b/pyiron_workflow/has_channel.py @@ -13,9 +13,9 @@ class HasChannel(ABC): """ - A mix-in class for use with the `Channel` class. - A `Channel` is able to (attempt to) connect to any child instance of `HasConnection` - by looking at its `connection` attribute. + A mix-in class for use with the :class:`Channel` class. + A :class:`Channel` is able to (attempt to) connect to any child instance of :class:`HasConnection` + by looking at its :attr:`connection` attribute. This is useful for letting channels attempt to connect to non-channel objects directly by pointing them to some channel that object holds. diff --git a/pyiron_workflow/interfaces.py b/pyiron_workflow/interfaces.py index c045f2b3..baff17e0 100644 --- a/pyiron_workflow/interfaces.py +++ b/pyiron_workflow/interfaces.py @@ -7,7 +7,10 @@ from importlib import import_module import pkgutil from sys import version_info +from types import ModuleType +from typing import Optional, TYPE_CHECKING +from bidict import bidict from pyiron_workflow.snippets.singleton import Singleton # Import all the supported executors @@ -35,6 +38,9 @@ ) from pyiron_workflow.snippets.dotdict import DotDict +if TYPE_CHECKING: + from pyiron_workflow.node_package import NodePackage + class Creator(metaclass=Singleton): """ @@ -45,13 +51,14 @@ class Creator(metaclass=Singleton): In addition to node objects, the creator also provides workflow-compliant executors for parallel processing. This includes a very simple in-house executor that is useful for learning, but also - choices from the `pympipool` packages. - Some `pympipool` executors may not be available on your machine (e.g. flux- and/or + choices from the :mod:`pympipool` packages. + Some :mod:`pympipool` executors may not be available on your machine (e.g. flux- and/or slurm-based executors), in which case these attributes will return `None` instead. """ def __init__(self): - self._node_packages = {} + self._package_access = DotDict() + self._package_registry = bidict() self.Executor = Executor self.CloudpickleProcessPoolExecutor = CloudpickleProcessPoolExecutor @@ -71,7 +78,7 @@ def __init__(self): # in python >=3.10 # If the CI skips testing on 3.9 gets dropped, we can think about removing # this if-clause and just letting users of python <3.10 hit an error. - self.register("standard", "pyiron_workflow.node_library.standard") + self.register("pyiron_workflow.node_library.standard", "standard") @property def PyFluxExecutor(self): @@ -124,37 +131,60 @@ def meta(self): def __getattr__(self, item): try: - return self._node_packages[item][1] + return self._package_access[item] except KeyError as e: raise AttributeError( f"{self.__class__.__name__} could not find attribute {item} -- did you " f"forget to register node package to this key?" ) from e + def __getitem__(self, item): + try: + return self._package_registry[item] + except KeyError as e: + raise KeyError( + f"Could not find the package {item} -- are you sure it's registered?" + ) from e + def __getstate__(self): return self.__dict__ def __setstate__(self, state): self.__dict__ = state - def register(self, domain: str, package_identifier: str) -> None: + def register(self, package_identifier: str, domain: Optional[str] = None) -> None: """ + Add a new package of nodes from the provided identifier. + The new package is available by item-access using the identifier, and, if a + domain was provided, by attribute access under that domain path ("."-split + strings allow for deep-registration of domains). Add a new package of nodes under the provided attribute, e.g. after adding nodes to the domain `"my_nodes"`, and instance of creator can call things like `creator.my_nodes.some_node_that_is_there()`. + Currently, :param:`package_identifier` is just a python module string, and we + allow recursive registration of multiple node packages when a module is + provided whose sub-modules are node packages. If a :param:`domain` was + provided, then it is extended by the same semantic path as the modules, e.g. + if `my_python_module` is registered to the domain `"mpm"`, and + `my_python_module.submod1` and `my_python_module.submod2.subsub` are both node + packages, then `mpm.submod1` and `mpm.submod2.subsub` will both be available + for attribute access. + Note: If a macro is going to use a creator, the node registration should be _inside_ the macro definition to make sure the node actually has access to those nodes! It also needs to be _able_ to register those nodes, i.e. have import access to that location, but we don't for that check that. Args: - domain (str): The attribute name at which to register the new package. - (Note: no sanitizing is done here, so if you provide a string that - won't work as an attribute name, that's your problem.) package_identifier (str): An identifier for the node package. (Right now that's just a string version of the path to the module, e.g. `pyiron_workflow.node_library.standard`.) + domain (str|None): The attribute name at which to register the new package. + (Note: no sanitizing is done here except for splitting on "." to create + sub-domains, so if you provide a string that won't work as an attribute + name, that's your problem.) (Default is None, don't provide attribute + access to this package.) Raises: KeyError: If the domain already exists, but the identifier doesn't match @@ -163,80 +193,133 @@ def register(self, domain: str, package_identifier: str) -> None: method or attribute of the creator. ValueError: If the identifier can't be parsed. """ - - if self._package_conflicts_with_existing(domain, package_identifier): - raise KeyError( - f"{domain} is already a registered node package, please choose a " - f"different domain to store these nodes under" - ) - elif domain in self.__dir__(): + if domain in super().__dir__(): + # We store package names in __dir__ for autocomplete, so here look only + # at the parent-class __dir__, which stores actual properties and methods, + # but _not_ the node packages raise AttributeError(f"{domain} is already an attribute of {self}") - self._node_packages[domain] = ( - package_identifier, - self._import_nodes(package_identifier), - ) - - def _package_conflicts_with_existing( - self, domain: str, package_identifier: str - ) -> bool: - """ - Check if the new package conflict with an existing package at the requested - domain; if there isn't one, or if the new and old packages are identical then - there is no conflict! - - Args: - domain (str): The domain at which the new package is attempting to register. - package_identifier (str): The identifier for the new package. + try: + module = import_module(package_identifier) + if domain is not None: + if "." in domain: + domain, container = self._get_deep_container(domain) + else: + container = self._package_access + self._register_recursively_from_module(module, domain, container) + else: + self._register_recursively_from_module(module, None, None) + except ModuleNotFoundError as e: + raise ModuleNotFoundError( + f"In the current implementation, we expect package identifiers to be " + f"modules, but {package_identifier} couldn't be imported. If this " + f"looks like a module, perhaps it's simply not in your path?" + ) from e - Returns: - (bool): True iff there is a package already at that domain and it is not - the same as the new one. - """ - if domain in self._node_packages.keys(): - # If it's already here, it had better be the same package - return package_identifier != self._node_packages[domain][0] - # We can make "sameness" logic more complex as we allow more sophisticated - # identifiers - else: - # If it's not here already, it can't conflict! - return False + def _get_deep_container(self, semantic_domain: str) -> tuple[str, DotDict]: + from pyiron_workflow.node_package import NodePackage - def _import_nodes(self, package_identifier: str): - """ - Recursively walk through all submodules of the provided package identifier, - and collect an instance of `nodes: list[Node]` from each non-package module. - """ + container = self._package_access + path = semantic_domain.split(".") + + while len(path) > 1: + step = path.pop(0) + if not hasattr(container, step): + container[step] = DotDict() + elif isinstance(container[step], NodePackage): + raise ValueError( + f"The semantic path {semantic_domain} is invalid because it uses " + f"{step} as an intermediary, but this is already a " + f"{NodePackage.__name__}" + ) + container = container[step] + domain = path[0] + return domain, container - module = import_module(package_identifier) + def _register_recursively_from_module( + self, module: ModuleType, domain: str | None, container: DotDict | None + ) -> None: if hasattr(module, "__path__"): - package = DotDict() + if domain is not None: + if domain not in container.keys(): + container[domain] = DotDict() + container = container[domain] + else: + container = None + subcontainer = container + for _, submodule_name, _ in pkgutil.walk_packages( module.__path__, module.__name__ + "." ): - package[submodule_name.split(".")[-1]] = self._import_nodes( - submodule_name - ) + submodule = import_module(submodule_name) + subdomain = None if domain is None else submodule_name.split(".")[-1] + + if not hasattr(submodule, "__path__"): + if hasattr(submodule, "nodes"): + # If it's a .py file with a `nodes` variable, + # assume that we want it + self._register_package_from_module( + submodule, subdomain, subcontainer + ) + else: + relative_path = submodule.__name__.replace( + module.__name__ + ".", "" + ) + subcontainer = container + for step in relative_path.split("."): + if step not in subcontainer.keys(): + subcontainer[step] = DotDict() + subcontainer = subcontainer[subdomain] else: - package = self._get_nodes_from_module(module) - return package + self._register_package_from_module(module, domain, container) + + def _register_package_from_module( + self, module: ModuleType, domain: str | None, container: dict | DotDict | None + ) -> None: + package = self._get_existing_package_or_register_a_new_one(module.__name__) + # NOTE: Here we treat the package identifier and the module name as equivalent + + if domain is not None: + if domain not in container.keys(): + # If the container _doesn't_ yet have anything at this domain, just add it + container[domain] = package + else: + self._raise_error_unless_new_package_matches_existing( + container, domain, package + ) - @staticmethod - def _get_nodes_from_module(module): - from pyiron_workflow.node import Node - from pyiron_workflow.node_package import NodePackage + def _get_existing_package_or_register_a_new_one( + self, package_identifier: str + ) -> NodePackage: + try: + # If the package is already registered, grab that instance + package = self._package_registry[package_identifier] + except KeyError: + # Otherwise make a new package + from pyiron_workflow.node_package import NodePackage + + package = NodePackage(package_identifier) + self._package_registry[package_identifier] = package + return package + def _raise_error_unless_new_package_matches_existing( + self, container: DotDict, domain: str, package: NodePackage + ) -> None: try: - nodes = module.nodes + if container[domain].package_identifier != package.package_identifier: + raise ValueError( + f"The domain {domain} already holds the package " + f"{container[domain].package_identifier}, and cannot store the " + f"package {package.package_identifier}" + ) except AttributeError: raise ValueError( - f"Could node find `nodes: list[Nodes]` in {module.__name__}" + f"The domain {domain} is already a container, and cannot be " + f"overwritten with the package {package.package_identifier}" ) - if not all(issubclass(node, Node) for node in nodes): - raise TypeError( - f"At least one node in {nodes} was not of the type {Node.__name__}" - ) - return NodePackage(*module.nodes) + + def __dir__(self) -> list[str]: + return super().__dir__() + list(self._package_access.keys()) class Wrappers(metaclass=Singleton): diff --git a/pyiron_workflow/io.py b/pyiron_workflow/io.py index 0d3f385c..18ed8d01 100644 --- a/pyiron_workflow/io.py +++ b/pyiron_workflow/io.py @@ -32,11 +32,11 @@ class IO(HasToDict, ABC): alter the properties of or check the status of all the channels at once. A new channel can be assigned as an attribute of an IO collection, as long as it - matches the channel's type (e.g. `OutputChannel` for `Outputs`, `InputChannel` - for `Inputs`, etc...). + matches the channel's type (e.g. :class:`OutputChannel` for :class:`Outputs`, :class:`InputChannel` + for :class:`Inputs`, etc...). When assigning something to an attribute holding an existing channel, if the - assigned object is a `Channel`, then an attempt is made to make a `connection` + assigned object is a :class:`Channel`, then an attempt is made to make a :attr:`connection` between the two channels, otherwise we fall back on a value assignment that must be defined in child classes under `_assign_value_to_existing_channel`. This provides syntactic sugar such that both new connections and new values can diff --git a/pyiron_workflow/macro.py b/pyiron_workflow/macro.py index f7f3c2aa..af3bd4e9 100644 --- a/pyiron_workflow/macro.py +++ b/pyiron_workflow/macro.py @@ -27,16 +27,16 @@ class Macro(Composite): then builds a static IO interface for this graph. This callable must use the macro object itself as the first argument (e.g. adding nodes to it). - As with `Workflow` objects, macros leverage `inputs_map` and `outputs_map` to + As with :class:`Workflow` objects, macros leverage `inputs_map` and `outputs_map` to control macro-level IO access to child IO. - As with `Workflow`, default behaviour is to expose all unconnected child IO. + As with :class:`Workflow`, default behaviour is to expose all unconnected child IO. The provided callable may optionally specify further args and kwargs, which are used - to pre-populate the macro with `UserInput` nodes; + to pre-populate the macro with :class:`UserInput` nodes; This can be especially helpful when more than one child node needs access to the same input value. Similarly, the callable may return any number of child nodes' output channels (or - the node itself in the case of `SingleValue` nodes) and commensurate - `output_labels` to define macro-level output. + the node itself in the case of :class:`SingleValue` nodes) and commensurate + :attr:`output_labels` to define macro-level output. These function-like definitions of the graph creator callable can be used independently or together. Each that is used switches its IO map to a "whitelist" paradigm, so any I/O _not_ @@ -48,21 +48,22 @@ class Macro(Composite): Macro IO is _value linked_ to the child IO, so that their values stay synchronized, but the child nodes of a macro form an isolated sub-graph. - As with function nodes, subclasses of `Macro` may define a method for creating the + As with function nodes, subclasses of :class:`Macro` may define a method for creating the graph. - As with `Workflow``, all DAG macros can determine their execution flow + As with :class:`Workflow``, all DAG macros can determine their execution flow automatically, if you have cycles in your data flow, or otherwise want more control over the execution, all you need to do is specify the `node.signals.input.run` - connections and `starting_nodes` list yourself. + connections and :attr:`starting_nodes` list yourself. If only _one_ of these is specified, you'll get an error, but if you've provided both then no further checks of their validity/reasonableness are performed, so be careful. - Unlike `Workflow`, this execution flow automation is set up once at instantiation; + Unlike :class:`Workflow`, this execution flow automation is set up once at instantiation; If the macro is modified post-facto, you may need to manually re-invoke - `configure_graph_execution`. + :meth:`configure_graph_execution`. Promises (in addition parent class promises): + - IO is... - Only built at instantiation, after child node replacement, or at request, so it is "static" for improved efficiency @@ -81,6 +82,7 @@ class Macro(Composite): Examples: Let's consider the simplest case of macros that just consecutively add 1 to their input: + >>> from pyiron_workflow.macro import Macro >>> >>> def add_one(x): @@ -99,20 +101,22 @@ class Macro(Composite): demonstrate the syntax. We can make a macro by passing this graph-building function (that takes a macro - as its first argument, i.e. `self` from the macro's perspective) to the `Macro` + as its first argument, i.e. `self` from the macro's perspective) to the :class:`Macro` class. Then, we can use it like a regular node! Just like a workflow, the io is constructed from unconnected owned-node IO by combining node and channel labels. + >>> macro = Macro(add_three_macro) >>> out = macro(one__x=3) >>> out.three__result 6 If there's a particular macro we're going to use again and again, we might want - to consider making a new child class of `Macro` that overrides the - `graph_creator` arg such that the same graph is always created. We could + to consider making a new child class of :class:`Macro` that overrides the + :meth:`graph_creator` arg such that the same graph is always created. We could override `__init__` the normal way, but it's even faster to just use `partialmethod`: + >>> from functools import partialmethod >>> class AddThreeMacro(Macro): ... @staticmethod @@ -130,6 +134,7 @@ class Macro(Composite): We can also nest macros, rename their IO, and provide access to internally-connected IO by inputs and outputs maps: + >>> def nested_macro(macro): ... macro.a = macro.create.SingleValue(add_one) ... macro.b = macro.create.Macro(add_three_macro, one__x=macro.a) @@ -148,6 +153,7 @@ class Macro(Composite): Macros and workflows automatically generate execution flows when their data is acyclic. Let's build a simple macro with two independent tracks: + >>> def modified_flow_macro(macro): ... macro.a = macro.create.SingleValue(add_one, x=0) ... macro.b = macro.create.SingleValue(add_one, x=0) @@ -157,11 +163,12 @@ class Macro(Composite): >>> m(a__x=1, b__x=2, c__x=3) {'a__result': 2, 'b__result': 3, 'c__result': 4} - We can override which nodes get used to start by specifying the `starting_nodes` + We can override which nodes get used to start by specifying the :attr:`starting_nodes` property. If we do this we also need to provide at least one connection among the run signals, but beyond that the code doesn't hold our hands. Let's use this and then observe how the `a` sub-node no longer gets run: + >>> m.starting_nodes = [m.b] # At least one starting node >>> _ = m.b >> m.c # At least one run signal >>> # We catch and ignore output -- it's needed for chaining, but screws up @@ -178,6 +185,7 @@ class Macro(Composite): long as the replacement has fully compatible IO. There are three syntacic ways to do this. Let's explore these by going back to our `add_three_macro` and replacing each of its children with a node that adds 2 instead of 1. + >>> @Macro.wrap_as.single_value_node() ... def add_two(x): ... result = x + 2 @@ -196,16 +204,16 @@ class Macro(Composite): {'three__result': 7} Instead of controlling the IO interface with dictionary maps, we can instead - provide a more `Function(Node)`-like definition of the `graph_creator` by + provide a more :class:`Function(Node)`-like definition of the :meth:`graph_creator` by adding args and/or kwargs to the signature (under the hood, this dynamically - creates new `UserInput` nodes before running the rest of the graph creation), - and/or returning child channels (or whole children in the case of `SingleValue` - nodes) and providing commensurate `output_labels`. - This process switches us from the `Workflow` default of exposing all + creates new :class:`UserInput` nodes before running the rest of the graph creation), + and/or returning child channels (or whole children in the case of :class:`SingleValue` + nodes) and providing commensurate :attr:`output_labels`. + This process switches us from the :class:`Workflow` default of exposing all unconnected child IO, to a "whitelist" paradigm of _only_ showing the IO that we exposed by our function defintion. (Note: any `.inputs_map` or `.outputs_map` explicitly defined in the - `graph_creator` still takes precedence over this whitelisting! So you always + :meth:`graph_creator` still takes precedence over this whitelisting! So you always retain full control over what IO gets exposed.) E.g., these two definitions are perfectly equivalent: @@ -249,7 +257,7 @@ class Macro(Composite): {'n_plus_2': 4, 'lout': [3, 4]} Here we've leveraged the macro-creating decorator, but this works the same way - using the `Macro` class directly. + using the :class:`Macro` class directly. """ def __init__( @@ -395,7 +403,7 @@ def _whitelist_map( io_map: bidict, new_labels: tuple[str], has_channel_objects: tuple[HasChannel] ) -> bidict: """ - Update an IO map to give new labels to the channels of a bunch of `HasChannel` + Update an IO map to give new labels to the channels of a bunch of :class:`HasChannel` objects. """ io_map = bidict({}) if io_map is None else io_map @@ -499,7 +507,7 @@ def macro_node(*output_labels, **node_class_kwargs): A decorator for dynamically creating macro classes from graph-creating functions. Decorates a function. - Returns a `Macro` subclass whose name is the camel-case version of the + Returns a :class:`Macro` subclass whose name is the camel-case version of the graph-creating function, and whose signature is modified to exclude this function and provided kwargs. @@ -507,7 +515,7 @@ def macro_node(*output_labels, **node_class_kwargs): like-a-function interface to define its IO. (The number of output labels must match number of channel-like objects returned by the graph creating function _exactly_.) - Optionally takes any keyword arguments of `Macro`. + Optionally takes any keyword arguments of :class:`Macro`. """ output_labels = None if len(output_labels) == 0 else output_labels diff --git a/pyiron_workflow/meta.py b/pyiron_workflow/meta.py index 1e221e7f..e051e0b5 100644 --- a/pyiron_workflow/meta.py +++ b/pyiron_workflow/meta.py @@ -18,7 +18,7 @@ def list_to_output(length: int, **node_class_kwargs) -> type[Function]: """ - A meta-node that returns a node class with `length` input channels and + A meta-node that returns a node class with :param:`length` input channels and maps these to a single output channel with type `list`. """ @@ -36,7 +36,7 @@ def __list_to_many(l: list): def input_to_list(length: int, **node_class_kwargs) -> type[SingleValue]: """ - A meta-node that returns a node class with `length` output channels and + A meta-node that returns a node class with :param:`length` output channels and maps an input list to these. """ @@ -63,6 +63,7 @@ def for_loop( Takes a node class, how long the loop should be, and which input(s) of the provided node class should be looped over (given as strings of the channel labels) and builds a macro that + - Makes copies of the provided node class, i.e. the "body node" - For each input channel specified to "loop over", creates a list-to-many node and connects each of its outputs to their respective body node inputs @@ -72,6 +73,7 @@ def for_loop( (i.e. the specified input and all output) is all caps Examples: + >>> from pyiron_workflow import Workflow >>> from pyiron_workflow.meta import for_loop >>> @@ -91,6 +93,7 @@ def for_loop( [1.0, 0.5, 0.3333333333333333, 0.25] TODO: + - Refactor like crazy, it's super hard to read and some stuff is too hard-coded - Give some sort of access to flow control?? - How to handle passing executors to the children? Maybe this is more @@ -98,7 +101,7 @@ def for_loop( - Is it possible to somehow dynamically adapt the held graph depending on the length of the input values being iterated over? Tricky to keep IO well defined - Allow a different mode, or make a different meta node, that makes all possible - pairs of body nodes given the input being looped over instead of just `length` + pairs of body nodes given the input being looped over instead of just :param:`length` - Provide enter and exit magic methods so we can `for` or `with` this fancy-like """ iterate_on = [iterate_on] if isinstance(iterate_on, str) else iterate_on @@ -202,7 +205,9 @@ def while_loop( connecting channel pairs inside the macro. inputs_map Optional[dict[str, str]]: The inputs map as usual for a macro. outputs_map Optional[dict[str, str]]: The outputs map as usual for a macro. + Examples: + >>> from pyiron_workflow import Workflow >>> >>> @Workflow.wrap_as.single_value_node() diff --git a/pyiron_workflow/node.py b/pyiron_workflow/node.py index c5697a8d..184cea45 100644 --- a/pyiron_workflow/node.py +++ b/pyiron_workflow/node.py @@ -19,7 +19,7 @@ NotData, ) from pyiron_workflow.draw import Node as GraphvizNode -from pyiron_workflow.files import DirectoryObject +from pyiron_workflow.snippets.files import DirectoryObject from pyiron_workflow.has_to_dict import HasToDict from pyiron_workflow.io import Signals from pyiron_workflow.topology import ( @@ -44,10 +44,10 @@ def manage_status(node_method): Decorates methods of nodes that might be time-consuming, i.e. their main run functionality. - Sets `running` to true until the method completes and either fails or returns - something other than a `concurrent.futures.Future` instance; sets `failed` to true + Sets :attr:`running` to true until the method completes and either fails or returns + something other than a :class:`concurrent.futures.Future` instance; sets `failed` to true if the method raises an exception; raises a `RuntimeError` if the node is already - `running` or `failed`. + :attr:`running` or :attr:`failed`. """ def wrapped_method(node: Node, *args, **kwargs): # rather node:Node @@ -86,6 +86,7 @@ class Node(HasToDict, ABC, metaclass=AbstractHasPost): one or more sub-graphs. Promises: + - Nodes perform some computation, but this is delayed and won't happen until asked for (the nature of the computation is left to child classes). - Nodes have input and output for interfacing with the outside world @@ -130,8 +131,8 @@ class Node(HasToDict, ABC, metaclass=AbstractHasPost): - Nodes may open a working directory related to their label, their parent(age) and the python process working directory - Nodes can run their computation using remote resources by setting an executor - - Any executor must have a `submit` method with the same interface as - `concurrent.futures.Executor`, must return a `concurrent.futures.Future` + - Any executor must have a :meth:`submit` method with the same interface as + :class:`concurrent.futures.Executor`, must return a :class:`concurrent.futures.Future` (or child thereof) object, and must be able to serialize dynamically defined objects - On executing this way, a futures object will be returned instead of the usual @@ -142,81 +143,92 @@ class Node(HasToDict, ABC, metaclass=AbstractHasPost): - WARNING: Executors are currently only working when the node executable function does not use `self` - NOTE: Executors are only allowed in a "push" paradigm, and you will get an - exception if you try to `pull` and one of the upstream nodes uses an + exception if you try to :meth:`pull` and one of the upstream nodes uses an executor - - NOTE: Don't forget to `shutdown` any created executors outside of a `with` + - NOTE: Don't forget to :meth:`shutdown` any created executors outside of a `with` context when you're done with them; we give a convenience method for this. + - Nodes created from a registered package store their package identifier as a class + attribute. This is an abstract class. - Children *must* define how `inputs` and `outputs` are constructed, what will - happen `on_run`, the `run_args` that will get passed to `on_run`, and how to - `process_run_result` once `on_run` finishes. + Children *must* define how :attr:`inputs` and :attr:`outputs` are constructed, what will + happen :meth:`on_run`, the :attr:`run_args` that will get passed to :meth:`on_run`, and how to + :meth:`process_run_result` once :meth:`on_run` finishes. They may optionally add additional signal channels to the signals IO. - # TODO: + TODO: + - Everything with (de)serialization for storage - Integration with more powerful tools for remote execution (anything obeying - the standard interface of a `submit` method taking the callable and + the standard interface of a :meth:`submit` method taking the callable and arguments and returning a futures object should work, as long as it can handle serializing dynamically defined objects. Attributes: connected (bool): Whether _any_ of the IO (including signals) are connected. - failed (bool): Whether the node raised an error calling `run`. (Default + failed (bool): Whether the node raised an error calling :meth:`run`. (Default is False.) fully_connected (bool): whether _all_ of the IO (including signals) are connected. future (concurrent.futures.Future | None): A futures object, if the node is currently running or has already run using an executor. inputs (pyiron_workflow.io.Inputs): **Abstract.** Children must define - a property returning an `Inputs` object. + a property returning an :class:`Inputs` object. label (str): A name for the node. outputs (pyiron_workflow.io.Outputs): **Abstract.** Children must define - a property returning an `Outputs` object. + a property returning an :class:`Outputs` object. + package_identifier (str|None): (Class attribute) the identifier for the + package this node came from (if any). parent (pyiron_workflow.composite.Composite | None): The parent object owning this, if any. ready (bool): Whether the inputs are all ready and the node is neither already running nor already failed. + graph_path (str): The file-path-like path of node labels from the parent-most + node down to this node. + graph_root (Node): The parent-most node in this graph. run_args (dict): **Abstract** the argmuments to use for actually running the node. Must be specified in child classes. - running (bool): Whether the node has called `run` and has not yet + running (bool): Whether the node has called :meth:`run` and has not yet received output from this call. (Default is False.) signals (pyiron_workflow.io.Signals): A container for input and output signals, which are channels for controlling execution flow. By default, has - a `signals.inputs.run` channel which has a callback to the `run` method + a :attr:`signals.inputs.run` channel which has a callback to the :meth:`run` method that fires whenever _any_ of its connections sends a signal to it, a - `signals.inputs.accumulate_and_run` channel which has a callback to the - `run` method but only fires after _all_ its connections send at least one + :attr:`signals.inputs.accumulate_and_run` channel which has a callback to the + :meth:`run` method but only fires after _all_ its connections send at least one signal to it, and `signals.outputs.ran` which gets called when the `run` method is finished. Additional signal channels in derived classes can be added to - `signals.inputs` and `signals.outputs` after this mixin class is + :attr:`signals.inputs` and :attr:`signals.outputs` after this mixin class is initialized. Methods: - __call__: An alias for `pull` that aggressively runs upstream nodes even + __call__: An alias for :meth:`pull` that aggressively runs upstream nodes even _outside_ the local scope (i.e. runs parents' dependencies as well). (de)activate_strict_hints: Recursively (de)activate strict hints among data IO. disconnect: Remove all connections, including signals. draw: Use graphviz to visualize the node, its IO and, if composite in nature, its internal structure. - execute: An alias for `run`, but with flags to run right here, right now, and + execute: An alias for :meth:`run`, but with flags to run right here, right now, and with the input it currently has. on_run: **Abstract.** Do the thing. What thing must be specified by child classes. - pull: An alias for `run` that runs everything upstream, then runs this node + pull: An alias for :meth:`run` that runs everything upstream, then runs this node (but doesn't fire off the `ran` signal, so nothing happens farther downstream). "Upstream" may optionally break out of the local scope to run parent nodes' dependencies as well (all the way until the parent-most object is encountered). replace_with: If the node belongs to a parent, attempts to replace itself in that parent with a new provided node. - run: Run the node function from `on_run`. Handles status automatically. Various + run: Run the node function from :meth:`on_run`. Handles status automatically. Various execution options are available as boolean flags. set_input_values: Allows input channels' values to be updated without any running. """ + package_identifier = None + _semantic_delimiter = "/" + def __init__( self, label: str, @@ -237,6 +249,7 @@ def __init__( **kwargs: Keyword arguments passed on with `super`. """ super().__init__(*args, **kwargs) + self._label = None self.label: str = label self._parent = None if parent is not None: @@ -258,6 +271,16 @@ def __post__(self, *args, run_after_init: bool = False, **kwargs): except ReadinessError: pass + @property + def label(self) -> str: + return self._label + + @label.setter + def label(self, new_label: str): + if self._semantic_delimiter in new_label: + raise ValueError(f"{self._semantic_delimiter} cannot be in the label") + self._label = new_label + @property @abstractmethod def inputs(self) -> Inputs: @@ -280,13 +303,13 @@ def on_run(self) -> callable[..., Any | tuple]: @abstractmethod def run_args(self) -> dict: """ - Any data needed for `on_run`, will be passed as **kwargs. + Any data needed for :meth:`on_run`, will be passed as **kwargs. """ @abstractmethod def process_run_result(self, run_output): """ - What to _do_ with the results of `on_run` once you have them. + What to _do_ with the results of :meth:`on_run` once you have them. By extracting this as a separate method, we allow the node to pass the actual execution off to another entity and release the python process to do other @@ -308,6 +331,22 @@ def parent(self, new_parent: Composite | None) -> None: "parent" ) + @property + def graph_path(self) -> str: + """ + The path of node labels from the graph root (parent-most node) down to this + node. + """ + path = self.label + if self.parent is not None: + path = self.parent.graph_path + self._semantic_delimiter + path + return path + + @property + def graph_root(self) -> Node: + """The parent-most node in this graph.""" + return self if self.parent is None else self.parent.graph_root + @property def readiness_report(self) -> str: input_readiness = "\n".join( @@ -356,7 +395,7 @@ def run( fetch_input (bool): Whether to first update inputs with the highest-priority connections holding data. (Default is True.) check_readiness (bool): Whether to raise an exception if the node is not - `ready` to run after fetching new input. (Default is True.) + :attr:`ready` to run after fetching new input. (Default is True.) force_local_execution (bool): Whether to ignore any executor settings and force the computation to run locally. (Default is False.) emit_ran_signal (bool): Whether to fire off all the output `ran` signal @@ -392,9 +431,9 @@ def run( ) return self._run( - finished_callback=self._finish_run_and_emit_ran - if emit_ran_signal - else self._finish_run, + finished_callback=( + self._finish_run_and_emit_ran if emit_ran_signal else self._finish_run + ), force_local_execution=force_local_execution, ) @@ -499,7 +538,7 @@ def _parse_executor(executor) -> StdLibExecutor: NOTE: `concurrent.futures.Executor` _won't_ actually work, because we need - stuff with `cloudpickle` support. We're leaning on this for a guaranteed + stuff with :mod:`cloudpickle` support. We're leaning on this for a guaranteed interface (has `submit` and returns a `Future`), and leaving it to the user to provide an executor that will actually work!!! @@ -520,7 +559,7 @@ def _finish_run(self, run_output: tuple | Future) -> Any | tuple: """ Switch the node status, then process and return the run result. - Sets the `failed` status to true if an exception is encountered. + Sets the :attr:`failed` status to true if an exception is encountered. """ if isinstance(run_output, Future): run_output = run_output.result() @@ -548,7 +587,7 @@ def _finish_run_and_emit_ran(self, run_output: tuple | Future) -> Any | tuple: def execute(self, **kwargs): """ - A shortcut for `run` with particular flags. + A shortcut for :meth:`run` with particular flags. Run the node with whatever input it currently has (or is given as kwargs here), run it on this python process, and don't emit the `ran` signal afterwards. @@ -568,7 +607,7 @@ def execute(self, **kwargs): def pull(self, run_parent_trees_too=False, **kwargs): """ - A shortcut for `run` with particular flags. + A shortcut for :meth:`run` with particular flags. Runs nodes upstream in the data graph, then runs this node without triggering any downstream runs. By default only runs sibling nodes, but can optionally @@ -591,7 +630,7 @@ def pull(self, run_parent_trees_too=False, **kwargs): def __call__(self, **kwargs) -> None: """ - A shortcut for `pull` that automatically runs the entire set of upstream data + A shortcut for :meth:`pull` that automatically runs the entire set of upstream data dependencies all the way to the parent-most graph object. """ return self.pull(run_parent_trees_too=True, **kwargs) @@ -684,8 +723,8 @@ def draw( """ Draw the node structure and return it as a graphviz object. - A selection of the `graphviz.Graph.render` method options are exposed, and if - `view` or `filename` is provided, this will be called before returning the + A selection of the :func:`graphviz.Graph.render` method options are exposed, and if + :param:`view` or :param:`filename` is provided, this will be called before returning the graph. The graph file and rendered image will be stored in the node's working directory. diff --git a/pyiron_workflow/node_library/atomistic/calculator/data.py b/pyiron_workflow/node_library/atomistic/calculator/data.py index a549f02a..b6a44148 100644 --- a/pyiron_workflow/node_library/atomistic/calculator/data.py +++ b/pyiron_workflow/node_library/atomistic/calculator/data.py @@ -136,7 +136,9 @@ class InputCalcMinimize: @wf_data_class() class InputCalcStatic: - keys_to_store: Optional[list] = field(default_factory=list) + # keys_to_store: Optional[list] = field(default_factory=list) + pass # LammpsControl.calc_static takes exactly zero arguments, and currently we + # have the input objects matching their respective LammpsControl counterparts nodes = [] diff --git a/pyiron_workflow/node_library/atomistic/calculator/generic.py b/pyiron_workflow/node_library/atomistic/calculator/generic.py index 0410f4ef..fcf40a1d 100644 --- a/pyiron_workflow/node_library/atomistic/calculator/generic.py +++ b/pyiron_workflow/node_library/atomistic/calculator/generic.py @@ -8,9 +8,10 @@ @single_value_node("generic") -def static(structure=None, engine=None, keys_to_store=None): +def static(structure=None, engine=None): # , keys_to_store=None): output = engine( - structure=structure, calculator=InputCalcStatic(keys_to_store=keys_to_store) + structure=structure, + calculator=InputCalcStatic(), # keys_to_store=keys_to_store) ) return output.generic diff --git a/pyiron_workflow/node_library/atomistic/engine/lammps.py b/pyiron_workflow/node_library/atomistic/engine/lammps.py index 1aab2832..f5e7398d 100644 --- a/pyiron_workflow/node_library/atomistic/engine/lammps.py +++ b/pyiron_workflow/node_library/atomistic/engine/lammps.py @@ -14,7 +14,7 @@ InputCalcStatic, ) -from pyiron_workflow.node_library.dev_tools import VarType, FileObject +from pyiron_workflow.node_library.dev_tools import FileObject, parse_input_kwargs from pyiron_workflow.node_library.dev_tools import wf_data_class from pyiron_atomistics.lammps.control import LammpsControl @@ -32,35 +32,40 @@ def Calc(parameters): elif isinstance(parameters, InputCalcMinimize): calculator.calc_minimize(**parameters) calculator._mode = "minimize" - elif isinstance(parameters, InputCalcMinimize): + elif isinstance(parameters, InputCalcStatic): calculator.calc_static(**parameters) calculator._mode = "static" + else: + raise TypeError(f"Unexpected parameters type {parameters}") return calculator @single_value_node("calculator") -def CalcStatic(): +def CalcStatic(calculator_input: Optional[InputCalcStatic | dict] = None): + calculator_kwargs = parse_input_kwargs(calculator_input, InputCalcStatic) calculator = LammpsControl() - calculator.calc_static() + calculator.calc_static(**calculator_kwargs) calculator._mode = "static" return calculator @single_value_node("calculator") -def CalcMinimize(**kwargs): +def CalcMinimize(calculator_input: Optional[InputCalcMinimize | dict] = None): + calculator_kwargs = parse_input_kwargs(calculator_input, InputCalcMinimize) calculator = LammpsControl() - calculator.calc_minimize(InputCalcMinimize(**kwargs)) + calculator.calc_minimize(**calculator_kwargs) calculator._mode = "static" return calculator @single_value_node("calculator") -def CalcMD(**kwargs): +def CalcMD(calculator_input: Optional[InputCalcMD | dict] = None): + calculator_kwargs = parse_input_kwargs(calculator_input, InputCalcMD) calculator = LammpsControl() - calculator.calc_md(InputCalcMD(**kwargs)) + calculator.calc_md(**calculator_kwargs) calculator._mode = "md" return calculator @@ -84,7 +89,7 @@ def InitLammps(structure=None, potential=None, calculator=None, working_director calculator.write_file(file_name="control.inp", cwd=working_directory) bla = "bla" - print("Lammps_init: ", calculator._mode, bla) + # print("Lammps_init: ", calculator._mode, bla) # return os.path.abspath(working_directory), calculator._mode, bla return os.path.abspath(working_directory), bla @@ -170,7 +175,7 @@ class GenericOutput: def Collect( out_dump, out_log, - # calc_mode: str = "stat", + calc_mode: str | LammpsControl | InputCalcMinimize | InputCalcMD | InputCalcStatic, bla="", ): import numpy as np @@ -184,6 +189,15 @@ def Collect( print("Collect: ", calc_mode, bla) log = out_log[0] + if isinstance(calc_mode, str) and calc_mode in ["static", "minimize", "md"]: + pass + elif isinstance(calc_mode, (InputCalcMinimize, InputCalcMD, InputCalcStatic)): + calc_mode = calc_mode.__class__.__name__.replace("InputCalc", "").lower() + elif isinstance(calc_mode, LammpsControl): + calc_mode = calc_mode._mode + else: + raise ValueError(f"Unexpected calc_mode {calc_mode}") + if calc_mode == "static": generic = OutputCalcStatic() # print("output Collect: ", generic, isinstance(generic, OutputCalcStatic)) @@ -197,7 +211,7 @@ def Collect( elif calc_mode == "md": generic = OutputCalcMD() generic.energies_pot = log["PotEng"].values - generic.energies_kin = log["KinEng"].values + generic.energies_kin = log["TotEng"].values - generic.energies_pot generic.forces = np.array([o.data[["fx", "fy", "fz"]] for o in out_dump]) return generic @@ -266,7 +280,7 @@ def Code( wf.InitLammps = wf.create.atomistic.engine.lammps.InitLammps( structure=structure, potential=wf.Potential, - calculator=wf.calc.outputs.calculator, + calculator=wf.calc, # working_directory="test2", ) wf.InitLammps.inputs.working_directory = ( @@ -287,7 +301,7 @@ def Code( bla=wf.InitLammps.outputs.bla, out_dump=wf.ParseDumpFile.outputs.dump, out_log=wf.ParseLogFile.outputs.log, - # calc_mode=wf.InitLammps.outputs.calc_mode, + calc_mode=wf.calc, ) return wf.Collect diff --git a/pyiron_workflow/node_library/atomistic/property/elastic.py b/pyiron_workflow/node_library/atomistic/property/elastic.py index 1bdf2d73..8dc1e350 100644 --- a/pyiron_workflow/node_library/atomistic/property/elastic.py +++ b/pyiron_workflow/node_library/atomistic/property/elastic.py @@ -49,7 +49,9 @@ def elastic_constants(structure, calculator=None, engine=None): engine = M3GNet() if calculator is None: - from pyiron_workflow.node_library.atomistic.calculator.ase import static as calculator + from pyiron_workflow.node_library.atomistic.calculator.ase import ( + static as calculator, + ) gs = calculator(engine=engine) diff --git a/pyiron_workflow/node_library/atomistic/property/phonons.py b/pyiron_workflow/node_library/atomistic/property/phonons.py index 3814d724..a9978813 100644 --- a/pyiron_workflow/node_library/atomistic/property/phonons.py +++ b/pyiron_workflow/node_library/atomistic/property/phonons.py @@ -3,7 +3,7 @@ # from pyiron_workflow.macro import Macro, macro_node from pyiron_workflow.function import single_value_node, function_node -from pyiron_workflow.node_library.dev_tools import wf_data_class +from pyiron_workflow.node_library.dev_tools import wf_data_class, parse_input_kwargs from phonopy.api_phonopy import Phonopy @@ -32,6 +32,31 @@ def generate_supercells(phonopy, parameters: InputPhonopyGenerateSupercells): return supercells +@single_value_node("parameters") +def PhonopyParameters( + distance: float = 0.01, + is_plusminus: Union[str, bool] = "auto", + is_diagonal: bool = True, + is_trigonal: bool = False, + number_of_snapshots: Optional[int] = None, + random_seed: Optional[int] = None, + temperature: Optional[float] = None, + cutoff_frequency: Optional[float] = None, + max_distance: Optional[float] = None, +) -> dict: + return { + "distance": distance, + "is_plusminus": is_plusminus, + "is_diagonal": is_diagonal, + "is_trigonal": is_trigonal, + "number_of_snapshots": number_of_snapshots, + "random_seed": random_seed, + "temperature": temperature, + "cutoff_frequency": cutoff_frequency, + "max_distance": max_distance, + } + + # The following function should be defined as a workflow macro (presently not possible) @function_node() def create_phonopy( @@ -39,7 +64,7 @@ def create_phonopy( engine=None, executor=None, max_workers=1, - parameters=InputPhonopyGenerateSupercells(), + parameters: Optional[InputPhonopyGenerateSupercells | dict] = None, ): from phonopy import Phonopy from structuretoolkit.common import atoms_to_phonopy @@ -47,7 +72,10 @@ def create_phonopy( phonopy = Phonopy(unitcell=atoms_to_phonopy(structure)) - cells = generate_supercells(phonopy, parameters=parameters) # .run() + cells = generate_supercells( + phonopy, + parameters=parse_input_kwargs(parameters, InputPhonopyGenerateSupercells), + ) gs = pyiron_workflow.node_library.atomistic.calculator.ase.static(engine=engine) df = gs.iter(atoms=cells, executor=executor, max_workers=max_workers) phonopy.forces = df.forces @@ -109,6 +137,7 @@ def get_total_dos(phonopy, mesh=3 * [10]): nodes = [ # generate_supercells, create_phonopy, + PhonopyParameters, get_dynamical_matrix, get_eigenvalues, check_consistency, diff --git a/pyiron_workflow/node_library/atomistic/structure/build.py b/pyiron_workflow/node_library/atomistic/structure/build.py index 595332f3..3872feb7 100644 --- a/pyiron_workflow/node_library/atomistic/structure/build.py +++ b/pyiron_workflow/node_library/atomistic/structure/build.py @@ -31,7 +31,10 @@ def bulk( def cubic_bulk_cell( wf, element: str, cell_size: int = 1, vacancy_index: int | None = None ): - from pyiron_workflow.node_library.atomistic.structure.transform import create_vacancy, repeat + from pyiron_workflow.node_library.atomistic.structure.transform import ( + create_vacancy, + repeat, + ) wf.structure = bulk(name=element, cubic=True) wf.cell = repeat(structure=wf.structure, repeat_scalar=cell_size) diff --git a/pyiron_workflow/node_library/atomistic/structure/transform.py b/pyiron_workflow/node_library/atomistic/structure/transform.py index 3f77926b..239b01c6 100644 --- a/pyiron_workflow/node_library/atomistic/structure/transform.py +++ b/pyiron_workflow/node_library/atomistic/structure/transform.py @@ -7,9 +7,7 @@ @single_value_node("structure") -def repeat( - structure: Atoms, repeat_scalar: int = 1 -) -> Atoms: +def repeat(structure: Atoms, repeat_scalar: int = 1) -> Atoms: return structure.repeat(repeat_scalar) diff --git a/pyiron_workflow/node_library/atomistic_codes.py b/pyiron_workflow/node_library/atomistic_codes.py index c90501d1..0d233f7c 100644 --- a/pyiron_workflow/node_library/atomistic_codes.py +++ b/pyiron_workflow/node_library/atomistic_codes.py @@ -41,7 +41,9 @@ def Lammps(wf, structure=Atoms(), potential=None): dump_file=wf.Shell.outputs.dump ) wf.Collect = wf.create.atomistic.engine.lammps.Collect( - out_dump=wf.ParseDumpFile.outputs.dump, out_log=wf.ParseLogFile.outputs.log + out_dump=wf.ParseDumpFile.outputs.dump, + out_log=wf.ParseLogFile.outputs.log, + calc_mode=wf.calc._mode, # SVN gives output -> inject attribute getter node ) return wf.Collect diff --git a/pyiron_workflow/node_library/databases/elasticity.py b/pyiron_workflow/node_library/databases/elasticity.py index 59212532..adc6be1d 100644 --- a/pyiron_workflow/node_library/databases/elasticity.py +++ b/pyiron_workflow/node_library/databases/elasticity.py @@ -3,9 +3,10 @@ @single_value_node("dataframe") -def de_jong(max_index: int | None = None): +def de_jong(max_index: int | None = None, filename="ec.json"): """ - Database from Ref. de Jong et al. https://www.nature.com/articles/sdata20159#MOESM77 + Expects the file to be the "ec.json" database referenced by: + Ref. de Jong et al. https://www.nature.com/articles/sdata20159#MOESM77 :return: """ @@ -13,7 +14,7 @@ def de_jong(max_index: int | None = None): import io from ase.io import read - df = pd.read_json("ec.json") + df = pd.read_json(filename) structures = [] # count = 0 diff --git a/pyiron_workflow/node_library/dev_tools.py b/pyiron_workflow/node_library/dev_tools.py index e42d2855..0308c7a1 100644 --- a/pyiron_workflow/node_library/dev_tools.py +++ b/pyiron_workflow/node_library/dev_tools.py @@ -1,5 +1,6 @@ # for development and testing only # provide functionality, data types etc. that will be later moved to the workflow code +from __future__ import annotations from pathlib import Path @@ -23,7 +24,7 @@ def __init__( class FileObject: - def __init__(self, path='.', directory=None): + def __init__(self, path=".", directory=None): if directory is None: self._path = Path(path) else: @@ -269,3 +270,37 @@ def select(self, keys_to_store=None): class wfMetaData: log_level: int = 0 doc: Optional[str] = None + + +def parse_input_kwargs(input_kwargs, expected_type): + """ + Get a dictionary of data for some dataclass. + + Args: + input_kwargs (expected_type|dict|None): + expected_type (type): One of our input dataclasses + + Returns: + (dict): A dictionary of data from the `expected_type`, updated from the + `input_kwargs` -- Just the defaults for the type when `input_kwargs` is + `None`, a dictionary version of the instance if it was an instance of the + expected type, or the defaults updated by the provided input if it was a + `dict`. + + Warnings: + In the case that `input_kwargs` is a dict, there's not currently any safeguards + to make sure the provided data aligns with the `expected_type`. + """ + if input_kwargs is None or isinstance(input_kwargs, dict): + calculator_input = expected_type() + elif not isinstance(input_kwargs, expected_type): + raise TypeError( + f"Expected to get input that was None, a dict, or {expected_type}, but got" + f"{input_kwargs}" + ) + + parsed_kwargs = vars(calculator_input) + if isinstance(input_kwargs, dict): + # WARNING: We're not doing any checking here that the dictionary items are valid + parsed_kwargs.update(input_kwargs) + return parsed_kwargs diff --git a/pyiron_workflow/node_library/lammps.py b/pyiron_workflow/node_library/lammps.py index 36924024..ec33a2e4 100644 --- a/pyiron_workflow/node_library/lammps.py +++ b/pyiron_workflow/node_library/lammps.py @@ -42,9 +42,7 @@ def Structure(structure): @single_value_node("path") -def InitLammps( - structure=None, potential=None, calculator=None, working_directory=None -): +def InitLammps(structure=None, potential=None, calculator=None, working_directory=None): import os from pyiron_atomistics.lammps.potential import LammpsPotential, LammpsPotentialFile diff --git a/pyiron_workflow/node_library/pyiron_atomistics.py b/pyiron_workflow/node_library/pyiron_atomistics.py index 38b5085b..8b660268 100644 --- a/pyiron_workflow/node_library/pyiron_atomistics.py +++ b/pyiron_workflow/node_library/pyiron_atomistics.py @@ -1,6 +1,7 @@ """ Nodes wrapping a subset of pyiron_atomistics functionality """ + from __future__ import annotations from typing import Literal, Optional @@ -30,8 +31,8 @@ def _run_and_remove_job(job, modifier: Optional[callable] = None, **modifier_kwa """ Extracts the commonalities for all the "calc" methods for running a Lammps engine. Will need to be extended/updated once we support other engines so that more output - can be parsed. Output may wind up more concretely packaged, e.g. as `CalcOutput` or - `MDOutput`, etc., ala Joerg's suggestion later, so for the time being we don't put + can be parsed. Output may wind up more concretely packaged, e.g. as :class:`CalcOutput` or + :class:`MDOutput`, etc., ala Joerg's suggestion later, so for the time being we don't put too much effort into this. Warning: @@ -126,10 +127,12 @@ def CalcMd( n_ionic_steps: int = 1000, n_print: int = 100, temperature: int | float = 300.0, - pressure: float - | tuple[float, float, float] - | tuple[float, float, float, float, float, float] - | None = None, + pressure: ( + float + | tuple[float, float, float] + | tuple[float, float, float, float, float, float] + | None + ) = None, ): def calc_md(job, n_ionic_steps, n_print, temperature, pressure): job.calc_md( @@ -169,10 +172,12 @@ def CalcMin( job: AtomisticGenericJob, n_ionic_steps: int = 1000, n_print: int = 100, - pressure: float - | tuple[float, float, float] - | tuple[float, float, float, float, float, float] - | None = None, + pressure: ( + float + | tuple[float, float, float] + | tuple[float, float, float, float, float, float] + | None + ) = None, ): def calc_min(job, n_ionic_steps, n_print, pressure): job.calc_minimize( diff --git a/pyiron_workflow/node_package.py b/pyiron_workflow/node_package.py index fcdbcca5..a78b7c17 100644 --- a/pyiron_workflow/node_package.py +++ b/pyiron_workflow/node_package.py @@ -1,25 +1,58 @@ from __future__ import annotations +from importlib import import_module +from inspect import isclass + from pyiron_workflow.node import Node from pyiron_workflow.snippets.dotdict import DotDict +NODE_PACKAGE_ATTRIBUTES = ("package_identifier",) + + +class NotANodePackage(Exception): + pass + + class NodePackage(DotDict): """ - A collection of node classes. + A collection of node classes loaded from a package (right now that's just a python + module (.py file) with a `nodes: list[Node]` attribute). Node classes are accessible by their _class name_ by item or attribute access. - - Can be extended by adding node classes to new names with an item or attribute set, - but to update an existing node the `update` method must be used. """ - def __init__(self, *node_classes: Node): - super().__init__() + def __init__(self, package_identifier: str): + super().__init__(package_identifier=package_identifier) + try: + self._register_from_module_name(package_identifier) + except ModuleNotFoundError as e: + raise NotANodePackage( + f"In the current implementation, we expect package identifiers to be " + f"modules, but {package_identifier} couldn't be imported. If this " + f"looks like a module, perhaps it's simply not in your path?" + ) from e + + def _register_from_module_name(self, module_name: str): + module = import_module(module_name) + + try: + node_classes = module.nodes + except AttributeError as e: + raise NotANodePackage( + f"Couldn't find an attribute `nodes` in {module_name}" + ) + for node in node_classes: + if not isclass(node) or not issubclass(node, Node): + raise NotANodePackage( + f"Node packages must contain only nodes, but the package " + f"{module_name} got {node}" + ) self[node.__name__] = node def __setitem__(self, key, value): + # Fail fast if key is forbidden if key in self.keys(): raise KeyError(f"The name {key} is already a stored node class.") elif key in self.__dir__(): @@ -27,17 +60,25 @@ def __setitem__(self, key, value): f"The name {key} is already an attribute of this " f"{self.__class__.__name__} instance." ) - if not isinstance(value, type) or not issubclass(value, Node): + + # Continue if key/value is permissible + if key in NODE_PACKAGE_ATTRIBUTES: + super().__setitem__(key, value) # Special properties that are allowed + elif isinstance(value, type) and issubclass(value, Node): + # Set the node class's package identifier and hold that class + value.package_identifier = self.package_identifier + super().__setitem__(key, value) + else: raise TypeError( f"Can only set members that are (sub)classes of {Node.__name__}, " f"but got {type(value)}" ) - super().__setitem__(key, value) - def update(self, *node_classes): - replacing = set(self.keys()).intersection([n.__name__ for n in node_classes]) - for name in replacing: - del self[name] + def __len__(self): + # Only count the nodes themselves + return super().__len__() - len(NODE_PACKAGE_ATTRIBUTES) - for node in node_classes: - self[node.__name__] = node + def __hash__(self): + # Dictionaries (DotDict(dict)) are mutable and thus not hashable + # Since the identifier is expected to be unique for the package, just hash that + return hash(self.package_identifier) diff --git a/pyiron_workflow/snippets/dotdict.py b/pyiron_workflow/snippets/dotdict.py index 1639659c..c7df1d7e 100644 --- a/pyiron_workflow/snippets/dotdict.py +++ b/pyiron_workflow/snippets/dotdict.py @@ -1,6 +1,11 @@ class DotDict(dict): def __getattr__(self, item): - return self.__getitem__(item) + try: + return self.__getitem__(item) + except KeyError: + raise AttributeError( + f"{self.__class__.__name__} object has no attribute '{item}'" + ) def __setattr__(self, key, value): self[key] = value diff --git a/pyiron_workflow/files.py b/pyiron_workflow/snippets/files.py similarity index 86% rename from pyiron_workflow/files.py rename to pyiron_workflow/snippets/files.py index 05c6af03..bb2957a6 100644 --- a/pyiron_workflow/files.py +++ b/pyiron_workflow/snippets/files.py @@ -43,8 +43,9 @@ def __init__(self, directory): def create(self): self.path.mkdir(parents=True, exist_ok=True) - def delete(self): - delete_files_and_directories_recursively(self.path) + def delete(self, only_if_empty: bool = False): + if self.is_empty() or not only_if_empty: + delete_files_and_directories_recursively(self.path) def list_content(self): return categorize_folder_items(self.path) @@ -71,6 +72,15 @@ def create_subdirectory(self, path): def create_file(self, file_name): return FileObject(file_name, self) + def is_empty(self) -> bool: + return len(self) == 0 + + def remove_files(self, *files: str): + for file in files: + path = self.get_path(file) + if path.is_file(): + path.unlink() + class FileObject: def __init__(self, file_name: str, directory: DirectoryObject): diff --git a/pyiron_workflow/snippets/testcase.py b/pyiron_workflow/snippets/testcase.py index def6edf7..5be6b89a 100644 --- a/pyiron_workflow/snippets/testcase.py +++ b/pyiron_workflow/snippets/testcase.py @@ -3,7 +3,6 @@ numpy arrays (if numpy is available). """ - from abc import ABC from contextlib import redirect_stdout import doctest @@ -30,11 +29,11 @@ class PyironTestCase(unittest.TestCase, ABC): - """ Base class for all pyiron unit tets. If numpy is avaiable, registers utility type equality function: + - `np.testing.assert_array_equal` Demands that you provide information on modules(s) for docstring testing, but diff --git a/pyiron_workflow/workflow.py b/pyiron_workflow/workflow.py index ed4ae4c4..8e89229e 100644 --- a/pyiron_workflow/workflow.py +++ b/pyiron_workflow/workflow.py @@ -26,14 +26,14 @@ class Workflow(Composite): and modifying their connections). Nodes can be added to the workflow at instantiation or with dot-assignment later on. - They are then accessible either under the `nodes` dot-dictionary, or just directly + They are then accessible either under the :attr:`nodes` dot-dictionary, or just directly by dot-access on the workflow object itself. - Using the `input` and `output` attributes, the workflow gives by-reference access + Using the :attr:`input` and :attr:`output` attributes, the workflow gives by-reference access to all the IO channels among its nodes which are currently unconnected. - The `Workflow` class acts as a single-point-of-import for us; - Directly from the class we can use the `create` method to instantiate workflow + The :class:`Workflow` class acts as a single-point-of-import for us; + Directly from the class we can use the :meth:`create` method to instantiate workflow objects. When called from a workflow _instance_, any created nodes get their parent set to the workflow instance being used. @@ -43,15 +43,17 @@ class Workflow(Composite): they sit at the top of any data dependency tree and may never have a parent of their own. They are flexible and great for development, but once you have a setup you like, - you should consider reformulating it as a `Macro`, which operates somewhat more + you should consider reformulating it as a :class:`Macro`, which operates somewhat more efficiently. Promises (in addition parent class promises): + - Workflows are living, their IO always reflects their current state of child nodes - Workflows are parent-most objects, they cannot be a sub-graph of a larger graph Examples: We allow adding nodes to workflows in five equivalent ways: + >>> from pyiron_workflow.workflow import Workflow >>> >>> @Workflow.wrap_as.single_value_node() @@ -73,9 +75,10 @@ class Workflow(Composite): By default, the node naming scheme is strict, so if you try to add a node to a label that already exists, you will get an error. This behaviour can be changed - at instantiation with the `strict_naming` kwarg, or afterwards by assigning a + at instantiation with the :attr:`strict_naming` kwarg, or afterwards by assigning a bool to this property. When deactivated, repeated assignments to the same label just get appended with an index: + >>> wf.strict_naming = False >>> wf.my_node = fnc(x=0) >>> wf.my_node = fnc(x=1) @@ -83,11 +86,12 @@ class Workflow(Composite): >>> print(wf.my_node.inputs.x, wf.my_node0.inputs.x, wf.my_node1.inputs.x) 0 1 2 - The `Workflow` class is designed as a single point of entry for workflows, so + The :class:`Workflow` class is designed as a single point of entry for workflows, so you can also access decorators to define new node classes right from the - workflow (cf. the `Node` docs for more detail on the node types). + workflow (cf. the :class:`Node` docs for more detail on the node types). Let's use these to explore a workflow's input and output, which are dynamically generated from the unconnected IO of its nodes: + >>> @Workflow.wrap_as.function_node("y") ... def plus_one(x: int = 0): ... return x + 1 @@ -100,33 +104,39 @@ class Workflow(Composite): If we connect the output of one node to the input of the other, there are fewer dangling channels for the workflow IO to find: + >>> wf.second.inputs.x = wf.first.outputs.y >>> print(len(wf.inputs), len(wf.outputs)) 1 1 Then we just run the workflow + >>> out = wf.run() The workflow joins node lavels and channel labels with a `_` character to provide direct access to the output: + >>> print(wf.outputs.second__y.value) 2 These input keys can be used when calling the workflow to update the input. In our example, the nodes update automatically when their input gets updated, so all we need to do to see updated workflow output is update the input: + >>> out = wf(first__x=10) >>> out {'second__y': 12} Note: this _looks_ like a dictionary, but has some extra convenience that we can dot-access data: + >>> out.second__y 12 We can give more convenient names to IO, and even access IO that would normally - be hidden (because it's connected) by specifying an `inputs_map` and/or - `outputs_map`: + be hidden (because it's connected) by specifying an :attr:`inputs_map` and/or + :attr:`outputs_map`: + >>> wf.inputs_map = {"first__x": "x"} >>> wf.outputs_map = { ... "first__y": "intermediate", @@ -136,13 +146,16 @@ class Workflow(Composite): {'intermediate': 1, 'y': 2} Workflows can be visualized in the notebook using graphviz: + >>> graphviz_graph = wf.draw() The resulting object can be saved as an image, e.g. + >>> wf.draw().render(filename="demo", format="png") 'demo.png' Let's clean up after ourselves (for when the CI runs the docstrings) + >>> from os import remove >>> remove("demo") >>> remove("demo.png") @@ -150,7 +163,8 @@ class Workflow(Composite): Workflows also give access to packages of pre-built nodes under different namespaces. These need to be registered first, like the standard package is automatically registered: - >>> Workflow.register("standard", "pyiron_workflow.node_library.standard") + + >>> Workflow.register("pyiron_workflow.node_library.standard", "standard") When your workflow's data follows a directed-acyclic pattern, it will determine the execution flow automatically. diff --git a/setup.py b/setup.py index b5b1b681..4d7aa837 100644 --- a/setup.py +++ b/setup.py @@ -32,17 +32,20 @@ 'cloudpickle==3.0.0', 'graphviz==0.20.1', 'matplotlib==3.8.2', - 'pympipool==0.7.9', + 'pympipool==0.7.13', 'toposort==1.10', 'typeguard==4.1.5', ], extras_require={ "node_library": [ 'ase==3.22.1', - 'atomistics==0.1.15', - 'numpy==1.26.2', + 'atomistics==0.1.23', + 'matgl==0.9.2', + 'numpy==1.26.4', + 'pandas==2.2.0', 'phonopy==2.21.0', - 'pyiron_atomistics==0.3.11', + 'pyiron_atomistics==0.4.15', + 'pyiron_contrib==0.1.15', ], }, cmdclass=versioneer.get_cmdclass(), diff --git a/tests/integration/test_readme.py b/tests/integration/test_readme.py index 89cb8560..a4b858c0 100644 --- a/tests/integration/test_readme.py +++ b/tests/integration/test_readme.py @@ -3,7 +3,7 @@ def load_tests(loader, tests, ignore): - tests.addTests(doctest.DocFileSuite("../../README.md")) + tests.addTests(doctest.DocFileSuite("../../docs/README.md")) return tests diff --git a/tests/integration/test_workflow.py b/tests/integration/test_workflow.py index 128ca00d..41c3328a 100644 --- a/tests/integration/test_workflow.py +++ b/tests/integration/test_workflow.py @@ -83,7 +83,7 @@ def sqrt(value=0): ) def test_for_loop(self): - Workflow.register("demo", "static.demo_nodes") + Workflow.register("static.demo_nodes", "demo") n = 5 @@ -188,7 +188,7 @@ def test_executor_and_creator_interaction(self): C.f. `pyiron_workflow.function._wrapper_factory` for more detail. """ wf = Workflow("depickle") - wf.register("demo", "static.demo_nodes") + wf.register("static.demo_nodes", "demo") wf.before_pickling = wf.create.demo.OptionallyAdd(1) wf.before_pickling.executor = wf.create.Executor() diff --git a/tests/static/nodes_subpackage/subsub_sibling/__init__.py b/tests/static/nodes_subpackage/subsub_sibling/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/static/nodes_subpackage/subsub_sibling/demo_nodes.py b/tests/static/nodes_subpackage/subsub_sibling/demo_nodes.py new file mode 100644 index 00000000..533e1005 --- /dev/null +++ b/tests/static/nodes_subpackage/subsub_sibling/demo_nodes.py @@ -0,0 +1,16 @@ +""" +A demo node package for the purpose of testing node package registration. +""" + +from typing import Optional + +from pyiron_workflow import Workflow + + +@Workflow.wrap_as.single_value_node("sum") +def OptionallyAdd(x: int, y: Optional[int] = None) -> int: + y = 0 if y is None else y + return x + y + + +nodes = [OptionallyAdd] diff --git a/tests/unit/snippets/test_dotdict.py b/tests/unit/snippets/test_dotdict.py index ffaf1d98..9491ba03 100644 --- a/tests/unit/snippets/test_dotdict.py +++ b/tests/unit/snippets/test_dotdict.py @@ -13,6 +13,16 @@ def test_dot_dict(self): self.assertListEqual(dd.to_list(), [42, "towel"]) + with self.assertRaises( + KeyError, msg="Failed item access should raise key error" + ): + dd["missing"] + + with self.assertRaises( + AttributeError, msg="Failed attribute access should raise attribute error" + ): + dd.missing + if __name__ == '__main__': unittest.main() diff --git a/tests/unit/snippets/test_files.py b/tests/unit/snippets/test_files.py new file mode 100644 index 00000000..93d8e90e --- /dev/null +++ b/tests/unit/snippets/test_files.py @@ -0,0 +1,101 @@ +import unittest +from pyiron_workflow.snippets.files import DirectoryObject, FileObject +from pathlib import Path + + +class TestFiles(unittest.TestCase): + def setUp(cls): + cls.directory = DirectoryObject("test") + + def tearDown(cls): + cls.directory.delete() + + def test_directory_exists(self): + self.assertTrue(Path("test").exists() and Path("test").is_dir()) + + def test_write(self): + self.directory.write(file_name="test.txt", content="something") + self.assertTrue(self.directory.file_exists("test.txt")) + self.assertTrue( + "test/test.txt" in [ + ff.replace("\\", "/") + for ff in self.directory.list_content()['file'] + ] + ) + self.assertEqual(len(self.directory), 1) + + def test_create_subdirectory(self): + self.directory.create_subdirectory("another_test") + self.assertTrue(Path("test/another_test").exists()) + + def test_path(self): + f = FileObject("test.txt", self.directory) + self.assertEqual(str(f.path).replace("\\", "/"), "test/test.txt") + + def test_read_and_write(self): + f = FileObject("test.txt", self.directory) + f.write("something") + self.assertEqual(f.read(), "something") + + def test_is_file(self): + f = FileObject("test.txt", self.directory) + self.assertFalse(f.is_file()) + f.write("something") + self.assertTrue(f.is_file()) + f.delete() + self.assertFalse(f.is_file()) + + def test_is_empty(self): + self.assertTrue(self.directory.is_empty()) + self.directory.write(file_name="test.txt", content="something") + self.assertFalse(self.directory.is_empty()) + + def test_delete(self): + self.assertTrue( + Path("test").exists() and Path("test").is_dir(), + msg="Sanity check on initial state" + ) + self.directory.write(file_name="test.txt", content="something") + self.directory.delete(only_if_empty=True) + self.assertFalse( + self.directory.is_empty(), + msg="Flag argument on delete should have prevented removal" + ) + self.directory.delete() + self.assertFalse( + Path("test").exists(), + msg="Delete should remove the entire directory" + ) + self.directory = DirectoryObject("test") # Rebuild it so the tearDown works + + def test_remove(self): + self.directory.write(file_name="test1.txt", content="something") + self.directory.write(file_name="test2.txt", content="something") + self.directory.write(file_name="test3.txt", content="something") + self.assertEqual( + 3, + len(self.directory), + msg="Sanity check on initial state" + ) + self.directory.remove_files("test1.txt", "test2.txt") + self.assertEqual( + 1, + len(self.directory), + msg="Should be able to remove multiple files at once", + ) + self.directory.remove_files("not even there", "nor this") + self.assertEqual( + 1, + len(self.directory), + msg="Removing non-existent things should have no effect", + ) + self.directory.remove_files("test3.txt") + self.assertEqual( + 0, + len(self.directory), + msg="Should be able to remove just one file", + ) + + +if __name__ == '__main__': + unittest.main() diff --git a/tests/unit/test_channels.py b/tests/unit/test_channels.py index b501875b..341badc8 100644 --- a/tests/unit/test_channels.py +++ b/tests/unit/test_channels.py @@ -381,7 +381,7 @@ def test_aggregating_call(self): ): agg() - out2 = OutputSignal(label="out", node=DummyNode()) + out2 = OutputSignal(label="out2", node=DummyNode()) agg.connect(self.out, out2) self.assertEqual( diff --git a/tests/unit/test_composite.py b/tests/unit/test_composite.py index 376d3ca8..64185c74 100644 --- a/tests/unit/test_composite.py +++ b/tests/unit/test_composite.py @@ -66,7 +66,7 @@ def bar(x: int = 0) -> int: ) def test_creator_access_and_registration(self): - self.comp.register("demo", "static.demo_nodes") + self.comp.register("static.demo_nodes", "demo") # Test invocation self.comp.add_node(self.comp.create.demo.OptionallyAdd(label="by_add")) @@ -590,6 +590,68 @@ def test_de_activate_strict_connections(self): msg="Activating should propagate to children" ) + def test_graph_info(self): + top = AComposite("topmost") + top.middle_composite = AComposite("middle_composite") + top.middle_composite.deep_node = Composite.create.SingleValue(plus_one) + top.middle_function = Composite.create.SingleValue(plus_one) + + with self.subTest("test_graph_path"): + self.assertEqual( + top.label, + top.graph_path, + msg="The parent-most node should be its own path." + ) + self.assertEqual( + Composite._semantic_delimiter.join( + [top.label, top.middle_composite.label] + ), + top.middle_composite.graph_path, + msg="The path should go to the parent-most object." + ) + self.assertEqual( + Composite._semantic_delimiter.join( + [top.label, top.middle_function.label] + ), + top.middle_function.graph_path, + msg="The path should go to the parent-most object." + ) + self.assertEqual( + Composite._semantic_delimiter.join( + [ + top.label, + top.middle_composite.label, + top.middle_composite.deep_node.label + ] + ), + top.middle_composite.deep_node.graph_path, + msg="The path should go to the parent-most object, recursively from all " + "depths." + ) + + with self.subTest("test_graph_root"): + self.assertIs( + top, + top.graph_root, + msg="The parent-most node should be its own graph_root." + ) + self.assertIs( + top, + top.middle_composite.graph_root, + msg="The parent-most node should be the graph_root." + ) + self.assertIs( + top, + top.middle_function.graph_root, + msg="The parent-most node should be the graph_root." + ) + self.assertIs( + top, + top.middle_composite.deep_node.graph_root, + msg="The parent-most node should be the graph_root, recursively accessible " + "from all depths." + ) + if __name__ == '__main__': unittest.main() diff --git a/tests/unit/test_files.py b/tests/unit/test_files.py deleted file mode 100644 index 0093fea9..00000000 --- a/tests/unit/test_files.py +++ /dev/null @@ -1,50 +0,0 @@ -import unittest -from pyiron_workflow.files import DirectoryObject, FileObject -from pathlib import Path - - -class TestFiles(unittest.TestCase): - def setUp(cls): - cls.directory = DirectoryObject("test") - - def tearDown(cls): - cls.directory.delete() - - def test_directory_exists(self): - self.assertTrue(Path("test").exists() and Path("test").is_dir()) - - def test_write(self): - self.directory.write(file_name="test.txt", content="something") - self.assertTrue(self.directory.file_exists("test.txt")) - self.assertTrue( - "test/test.txt" in [ - ff.replace("\\", "/") - for ff in self.directory.list_content()['file'] - ] - ) - self.assertEqual(len(self.directory), 1) - - def test_create_subdirectory(self): - self.directory.create_subdirectory("another_test") - self.assertTrue(Path("test/another_test").exists()) - - def test_path(self): - f = FileObject("test.txt", self.directory) - self.assertEqual(str(f.path).replace("\\", "/"), "test/test.txt") - - def test_read_and_write(self): - f = FileObject("test.txt", self.directory) - f.write("something") - self.assertEqual(f.read(), "something") - - def test_is_file(self): - f = FileObject("test.txt", self.directory) - self.assertFalse(f.is_file()) - f.write("something") - self.assertTrue(f.is_file()) - f.delete() - self.assertFalse(f.is_file()) - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/unit/test_interfaces.py b/tests/unit/test_interfaces.py index 32c76355..4281ed4d 100644 --- a/tests/unit/test_interfaces.py +++ b/tests/unit/test_interfaces.py @@ -2,7 +2,7 @@ from pyiron_workflow._tests import ensure_tests_in_python_path from pyiron_workflow.interfaces import Creator -from pyiron_workflow.node_package import NodePackage +from pyiron_workflow.node_package import NodePackage, NotANodePackage class TestCreator(unittest.TestCase): @@ -21,63 +21,95 @@ def test_registration(self): ): self.creator.demo_nodes - self.creator.register("demo", "static.demo_nodes") + self.creator.register("static.demo_nodes") - node = self.creator.demo.OptionallyAdd(1, 2) - self.assertEqual( - 3, - node(), - msg="Node should get instantiated from creator and be operable" - ) + with self.subTest("Test access by item"): + node = self.creator["static.demo_nodes"].OptionallyAdd(1, 2) + self.assertEqual( + 3, + node(), + msg="Node should get instantiated from creator and be operable" + ) + + self.creator.register("static.demo_nodes", "demo") + + with self.subTest("Test access by attribute"): + node = self.creator.demo.OptionallyAdd(1, 2) + self.assertEqual( + 3, + node(), + msg="Node should get instantiated from creator and be operable" + ) - self.creator.register("sub", "static.nodes_subpackage") + self.creator.register("static.nodes_subpackage", "sub") self.assertIsInstance(self.creator.sub.demo_nodes, NodePackage) self.assertIsInstance(self.creator.sub.subsub_package.demo_nodes, NodePackage) + self.assertIsInstance(self.creator.sub.subsub_sibling.demo_nodes, NodePackage) with self.subTest("Test re-registration"): - self.creator.register("demo", "static.demo_nodes") + self.creator.register("static.demo_nodes", "demo") # Same thing to the same location should be fine - self.creator.register("a_key_other_than_demo", "static.demo_nodes") + self.creator.register("static.demo_nodes", "a_key_other_than_demo") # The same thing to another key is usually dumb, but totally permissible + self.assertIs( + self.creator.demo, + self.creator.a_key_other_than_demo, + msg="Registering the same package to two locations should use the same " + "package instance in both places." + ) with self.assertRaises( - KeyError, - msg="Should not be able to register a new package to an existing domain" + ValueError, + msg="Should not be able to register different package to an existing " + "domain" ): - self.creator.register("demo", "pyiron_workflow.node_library.standard") + self.creator.register("pyiron_workflow.node_library.standard", "demo") with self.assertRaises( AttributeError, msg="Should not be able to register to existing fields" ): some_field = self.creator.dir()[0] - self.creator.register(some_field, "static.demo_nodes") + self.creator.register("static.demo_nodes", some_field) - with self.subTest("Test failure cases"): - n_initial_packages = len(self.creator._node_packages) + with self.subTest("Test semantic domain"): + self.creator.register("static.demo_nodes", "some.path") + self.assertIsInstance(self.creator.some.path, NodePackage) + + self.creator.register("static.demo_nodes", "some.deeper.path") + self.assertIsInstance(self.creator.some.deeper.path, NodePackage) with self.assertRaises( ValueError, + msg="Can't inject a branch on a package" + ): + self.creator.register("static.demo_nodes", "some.path.deeper") + + with self.subTest("Test failure cases"): + n_initial_packages = len(self.creator._package_registry) + + with self.assertRaises( + NotANodePackage, msg="Mustn't allow importing from things that are not node packages" ): - self.creator.register("not_even", "static.not_a_node_package") + self.creator.register("static.not_a_node_package") with self.assertRaises( - ValueError, + NotANodePackage, msg="Must require a `nodes` property in the module" ): - self.creator.register("forgetful", "static.forgetful_node_package") + self.creator.register("static.forgetful_node_package") with self.assertRaises( - TypeError, + NotANodePackage, msg="Must have only node classes in the iterable `nodes` property" ): - self.creator.register("faulty", "static.faulty_node_package") + self.creator.register("static.faulty_node_package") self.assertEqual( n_initial_packages, - len(self.creator._node_packages), + len(self.creator._package_registry), msg="Packages should not be getting added if exceptions are raised" ) diff --git a/tests/unit/test_node.py b/tests/unit/test_node.py index 3c239d01..6b03ae86 100644 --- a/tests/unit/test_node.py +++ b/tests/unit/test_node.py @@ -4,7 +4,7 @@ import unittest from pyiron_workflow.channels import InputData, OutputData, NotData -from pyiron_workflow.files import DirectoryObject +from pyiron_workflow.snippets.files import DirectoryObject from pyiron_workflow.interfaces import Executor from pyiron_workflow.io import Inputs, Outputs from pyiron_workflow.node import Node @@ -344,6 +344,23 @@ def test_run_after_init(self): msg="With run_after_init, the node should run right away" ) + def test_graph_info(self): + n = ANode("n") + + self.assertEqual( + n.label, + n.graph_path, + msg="Lone nodes should just have their label as the path, as there is no " + "parent above." + ) + + self.assertIs( + n, + n.graph_root, + msg="Lone nodes should be their own graph_root, as there is no parent " + "above." + ) + if __name__ == '__main__': unittest.main() diff --git a/tests/unit/test_node_package.py b/tests/unit/test_node_package.py index 7f820329..836450f4 100644 --- a/tests/unit/test_node_package.py +++ b/tests/unit/test_node_package.py @@ -1,69 +1,42 @@ import unittest -from pyiron_workflow.node_package import NodePackage -from pyiron_workflow.function import function_node - - -@function_node() -def Dummy(x: int = 0): - return x +from pyiron_workflow._tests import ensure_tests_in_python_path +from pyiron_workflow.node_package import NodePackage, NotANodePackage class TestNodePackage(unittest.TestCase): - def setUp(self) -> None: - self.package = NodePackage(Dummy) + @classmethod + def setUpClass(cls) -> None: + ensure_tests_in_python_path() + cls.valid_identifier = "static.demo_nodes" def test_init(self): - self.assertTrue( - hasattr(self.package, Dummy.__name__), - msg="Classes should be added at instantiation" - ) - - def test_access(self): - node = self.package.Dummy() - self.assertIsInstance(node, Dummy) - - def test_update(self): - with self.assertRaises(KeyError): - self.package.Dummy = "This is already a node class name" - - with self.assertRaises(KeyError): - self.package.update = "This is already a method" - - with self.assertRaises(TypeError): - self.package.available_name = "But we can still only assign node classes" - - @function_node("y") - def add(x: int = 0): - return x + 1 - - self.package.node_class_and_free_key = add # Should work! + ok = NodePackage(self.valid_identifier) + self.assertEqual(self.valid_identifier, ok.package_identifier) - with self.assertRaises(KeyError): - # This is already occupied by another node class - self.package.Dummy = add + with self.assertRaises(NotANodePackage): + NodePackage("not_even_a_module") - old_dummy_instance = self.package.Dummy(label="old_dummy_instance") + with self.assertRaises(NotANodePackage): + NodePackage("static.faulty_node_package") - @function_node() - def Dummy(x: int = 0): - y = x + 1 - return y + with self.assertRaises(NotANodePackage): + NodePackage("static.not_a_node_packageZ") - self.package.update(Dummy) + def test_nodes(self): + package = NodePackage("static.demo_nodes") - self.assertEqual(len(self.package), 2, msg="Update should replace, not extend") + with self.subTest("Attribute access"): + node = package.OptionallyAdd() + self.assertIsInstance(node, package.OptionallyAdd) - new_dummy_instance = self.package.Dummy(label="new_dummy_instance") + with self.subTest("Identifier information"): + node = package.OptionallyAdd() + self.assertEqual(node.package_identifier, package.package_identifier) - old_dummy_instance.run() - new_dummy_instance.run() - self.assertEqual( - old_dummy_instance.outputs.x.value, 0, msg="Should have old functionality" - ) - self.assertEqual( - new_dummy_instance.outputs.y.value, 1, msg="Should have new functionality" - ) + def test_length(self): + package = NodePackage("static.demo_nodes") + self.assertEqual(1, len(package)) if __name__ == '__main__':