diff --git a/pyiron_base.ipynb b/pyiron_base.ipynb index 8b146cd..8f8e3c3 100644 --- a/pyiron_base.ipynb +++ b/pyiron_base.ipynb @@ -1 +1 @@ -{"metadata":{"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"codemirror_mode":{"name":"ipython","version":3},"file_extension":".py","mimetype":"text/x-python","name":"python","nbconvert_exporter":"python","pygments_lexer":"ipython3","version":"3.11.9"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# pyiron \nThe integrated development environment (IDE) for computational materials science `pyiron` accelerates the rapid prototyping and up-scaling of simulation protocols. Internally, it consists of two primary components the `pyiron_atomistics` package, which provides the interfaces for atomistic simulations codes and atomistic simulation workflows and the `pyiron_base` package, which defines the job management and data storage interface. The latter is independent of the atomistic scale and addresses the general challenge of coupling simulation codes in reproducible workflows. Simulation codes can be integrated in the `pyiron_base` package by either using existing python bindings or alternatively by writing the input files, executing the simulation code and parsing the output files. The following explanations focus on the `pyiron_base` package as a workflow manager, which constructs simulation workflows by combining `job` objects like building blocks.\n\n## Installation / Setup\nThe `pyiron_base` workflow manager can be installed via the python package index or the conda package manager. While no additional configuration is required to use `pyiron_base` on a workstation, the connection to an high performance computing (HPC) cluster requires some additional configuration. The `.pyiron` configuration file in the users home directory is used to specify the resource directory, which contains the configuration of the queuing system. \n\n## Implementation of a new simulation code\nThe `pyiron_base` workflow manager provides two interfaces to implement new simulation codes or simulation workflows. For simulation codes which already provide a python interface the `wrap_python_function()` function is used to convert any python function into a pyiron job object. In analogy external executables can be wrapped using the `wrap_executable()`. Based on these two functions any executable can be wrapped as `Job` object. By naming the `Job` object the user can easily reload the same calculation at any time. Furthermore, `pyiron_base` internally uses the name to generate a directory for each `Job` object to simplify locating the input and output of a given calculation for debugging: ","metadata":{}},{"cell_type":"code","source":"import os\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom ase.io import write\nfrom adis_tools.parsers import parse_pw\nfrom pyiron_base.project.delayed import draw","metadata":{"trusted":true},"outputs":[],"execution_count":1},{"cell_type":"code","source":"def write_input(input_dict, working_directory=\".\"):\n filename = os.path.join(working_directory, 'input.pwi')\n os.makedirs(working_directory, exist_ok=True)\n write(\n filename=filename, \n images=input_dict[\"structure\"], \n Crystal=True, \n kpts=input_dict[\"kpts\"], \n input_data={\n 'calculation': input_dict[\"calculation\"],\n 'occupations': 'smearing',\n 'degauss': input_dict[\"smearing\"],\n }, \n pseudopotentials=input_dict[\"pseudopotentials\"],\n tstress=True, \n tprnfor=True\n )","metadata":{"trusted":true},"outputs":[],"execution_count":2},{"cell_type":"code","source":"def collect_output(working_directory=\".\"):\n output = parse_pw(os.path.join(working_directory, 'pwscf.xml'))\n return {\n \"structure\": output['ase_structure'],\n \"energy\": output[\"energy\"],\n \"volume\": output['ase_structure'].get_volume(),\n }","metadata":{"trusted":true},"outputs":[],"execution_count":3},{"cell_type":"markdown","source":"Finally, multiple simulation can be combined in a simulation protocol. In this case the optimization of an Aluminium lattice structure, the calculation of an energy volume curve and the plotting of the resulting curve. ","metadata":{}},{"cell_type":"code","source":"def generate_structures(structure, strain_lst): \n structure_lst = []\n for strain in strain_lst:\n structure_strain = structure.copy()\n structure_strain.set_cell(\n structure_strain.cell * strain**(1/3), \n scale_atoms=True\n )\n structure_lst.append(structure_strain)\n return structure_lst","metadata":{"trusted":true},"outputs":[],"execution_count":4},{"cell_type":"code","source":"from ase.build import bulk\nfrom pyiron_base import Project","metadata":{"trusted":true},"outputs":[],"execution_count":5},{"cell_type":"code","source":"project = Project(\"test\")\nproject.remove_jobs(recursive=True, silently=True)\nstructure = bulk('Al', a=4.05, cubic=True)\npseudopotentials = {\"Al\": \"Al.pbe-n-kjpaw_psl.1.0.0.UPF\"}","metadata":{"trusted":true},"outputs":[{"output_type":"display_data","data":{"text/plain":"0it [00:00, ?it/s]","application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"057dbe2099484caaa40a8bc7e050107a"}},"metadata":{}}],"execution_count":6},{"cell_type":"code","source":"# Structure optimization \njob_qe_minimize = project.wrap_executable(\n job_name=\"job_qe_minimize\",\n write_input_funct=write_input,\n collect_output_funct=collect_output,\n input_dict={\n \"structure\": structure, \n \"pseudopotentials\": pseudopotentials, \n \"kpts\": (3, 3, 3),\n \"calculation\": \"vc-relax\",\n \"smearing\": 0.02,\n },\n executable_str=\"mpirun -np 1 pw.x -in input.pwi > output.pwo\",\n delayed=True,\n output_file_lst=[],\n output_key_lst=[\"structure\"],\n)\n\n# Generate Structures\nnumber_of_strains = 5 \nstructure_lst = project.wrap_python_function(\n python_function=generate_structures,\n structure=job_qe_minimize.output.structure, \n strain_lst=np.linspace(0.9, 1.1, number_of_strains),\n delayed=True,\n list_length=number_of_strains,\n)\n\n# Energy Volume Curve \nenergy_lst, volume_lst = [], []\nfor i, structure_strain in enumerate(structure_lst):\n job_strain = project.wrap_executable(\n job_name=\"job_strain_\" + str(i),\n write_input_funct=write_input,\n collect_output_funct=collect_output,\n input_dict={\n \"structure\": structure_strain, \n \"pseudopotentials\": pseudopotentials, \n \"kpts\": (3, 3, 3),\n \"calculation\": \"scf\",\n \"smearing\": 0.02,\n },\n executable_str=\"mpirun -np 1 pw.x -in input.pwi > output.pwo\",\n delayed=True,\n output_file_lst=[],\n output_key_lst=[\"energy\", \"volume\"],\n )\n energy_lst.append(job_strain.output.energy)\n volume_lst.append(job_strain.output.volume)","metadata":{"trusted":true},"outputs":[],"execution_count":7},{"cell_type":"markdown","source":"As the quantum espresso calculations are the computationally expensive steps they are combined in a python function to be submitted to dedicated computing resources. In contrast the creation of the atomistic structure and the plotting of the energy volume curve are executed in the users process.\n\nThe remaining simulation protocol, can be summarized in a few lines. The required modules are imported, a `Project` object is created which represents a folder on the filesystem, the `wrap_python_function()` is used to convert the computationally expensive steps of the workflow into a single `Job` object and the resulting energy volume curve is plotted: ","metadata":{}},{"cell_type":"code","source":"def collect(volume_lst, energy_lst):\n return {\"volume\": volume_lst, \"energy\": energy_lst}","metadata":{"trusted":true},"outputs":[],"execution_count":8},{"cell_type":"code","source":"results = project.wrap_python_function(\n python_function=collect,\n volume_lst=volume_lst,\n energy_lst=energy_lst,\n delayed=True,\n)","metadata":{"trusted":true},"outputs":[],"execution_count":9},{"cell_type":"code","source":"result_dict = results.pull()\nresult_dict","metadata":{"trusted":true},"outputs":[{"name":"stdout","text":"The job job_qe_minimize was saved and received the ID: 1\n","output_type":"stream"}],"execution_count":null},{"cell_type":"code","source":"def plot_energy_volume_curve(volume_lst, energy_lst):\n plt.plot(volume_lst, energy_lst)\n plt.xlabel(\"Volume\")\n plt.ylabel(\"Energy\")\n plt.savefig(\"evcurve.png\")","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"This concludes the first version of the simulation workflow, in the following the submission to HPC resources, the different options for data storage and the publication of the workflow are briefly discussed.","metadata":{}},{"cell_type":"code","source":"plot_energy_volume_curve(\n volume_lst=result_dict[\"volume\"], \n energy_lst=result_dict[\"energy\"]\n)","metadata":{"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"## Submission to an HPC / Check pointing / Error handling\nWhile the local installation of the `pyiron_base` workflow manager requires no additional configuration, the connection to an HPC system is more evolved. The existing examples provided for specific HPC systems can be converted to jinja2 templates, by defining variables with double curly brackets. A minimalist template could be: \n```\n#!/bin/bash\n#SBATCH --job-name={{job_name}}\n#SBATCH --chdir={{working_directory}}\n#SBATCH --cpus-per-task={{cores}}\n\n{{command}}\n```\nHere the `job_name`, the `working_directory` and the number of compute `cores` can be specified as parameters. In the `pyiron_base` workflow manager such a submission script can then be selected based on its name as parameter of the `server` object:\n```python\njob_workflow.server.queue = \"my_queue\"\njob_workflow.server.cores = 64\n```\nThese lines are inserted before calling the `run()` function. The rest of the simulation protocol remains the same.\n\nWhen simulation protocols are up-scaling and iterated over a large number of parameters, certain parameter combinations might lead to poor conversion or even cause simulation code crashes. In the `pyiron_base` workflow manager these calculation are marked as `aborted`. This gives the user to inspect the calculation and in case the crash was not related to the parameter combination, individual jobs can be removed with the `remove_job()` function. Afterwards, the simulation protocol can be executed again. In this case the `pyiron_base` workflow manager recognizes the already completed calculation and only re-evaluates the removed broken calculation. \n\n## Data Storage / Data Sharing\nIn the `pyiron_base` workflow manager the input of the calculation as well as the output are stored in the hierachical data format (HDF). In addition, `pyiron_base` can use a Structured Query Language (SQL) database, which acts as an index of all the `Job` objects and their HDF5 files. This file-based approach allows the user easily to browse through the results and at the same time the compressed storage in HDF5 and the internal hierarchy of the data format, enable the efficient storage of large tensors, like atomistic trajectories. \n\n## Publication of the workflow\nThe `pyiron_base` workflow manager provides a publication template to publish simulation workflows on Github. This template enables both the publication of the workflow as well as the publication of the results generated with a given workflow. For reproduciblity this publication template is based on sharing a conda environment file `environment.yml` in combination with the Jupyter notebook containing the simulation protocol and the archived `Job` objects. The Jupyter notebook is then rendered as static website with links to enable interactive execution using Jupyterbook and the mybinder service. As the `pyiron_base` workflow manager reloads existing calculation from the archive, a user of the interactive mybinder environment does not have to recompute the computationally expensive steps and still has the opportunity to interact with the provided workflow and data. ","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]} +{"metadata":{"kernelspec":{"display_name":"Python 3 (ipykernel)","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.11.0","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# pyiron \nThe integrated development environment (IDE) for computational materials science `pyiron` accelerates the rapid prototyping and up-scaling of simulation protocols. Internally, it consists of two primary components the `pyiron_atomistics` package, which provides the interfaces for atomistic simulations codes and atomistic simulation workflows and the `pyiron_base` package, which defines the job management and data storage interface. The latter is independent of the atomistic scale and addresses the general challenge of coupling simulation codes in reproducible workflows. Simulation codes can be integrated in the `pyiron_base` package by either using existing python bindings or alternatively by writing the input files, executing the simulation code and parsing the output files. The following explanations focus on the `pyiron_base` package as a workflow manager, which constructs simulation workflows by combining `job` objects like building blocks.\n\n## Installation / Setup\nThe `pyiron_base` workflow manager can be installed via the python package index or the conda package manager. While no additional configuration is required to use `pyiron_base` on a workstation, the connection to an high performance computing (HPC) cluster requires some additional configuration. The `.pyiron` configuration file in the users home directory is used to specify the resource directory, which contains the configuration of the queuing system. \n\n## Implementation of a new simulation code\nThe `pyiron_base` workflow manager provides two interfaces to implement new simulation codes or simulation workflows. For simulation codes which already provide a python interface the `wrap_python_function()` function is used to convert any python function into a pyiron job object. In analogy external executables can be wrapped using the `wrap_executable()`. Based on these two functions any executable can be wrapped as `Job` object. By naming the `Job` object the user can easily reload the same calculation at any time. Furthermore, `pyiron_base` internally uses the name to generate a directory for each `Job` object to simplify locating the input and output of a given calculation for debugging: ","metadata":{}},{"cell_type":"code","source":"import os\nimport matplotlib.pyplot as plt\nimport numpy as np\nfrom ase.io import write\nfrom adis_tools.parsers import parse_pw\nfrom pyiron_base.project.delayed import draw","metadata":{"trusted":true},"outputs":[],"execution_count":1},{"cell_type":"code","source":"def write_input(input_dict, working_directory=\".\"):\n filename = os.path.join(working_directory, 'input.pwi')\n os.makedirs(working_directory, exist_ok=True)\n write(\n filename=filename, \n images=input_dict[\"structure\"], \n Crystal=True, \n kpts=input_dict[\"kpts\"], \n input_data={\n 'calculation': input_dict[\"calculation\"],\n 'occupations': 'smearing',\n 'degauss': input_dict[\"smearing\"],\n }, \n pseudopotentials=input_dict[\"pseudopotentials\"],\n tstress=True, \n tprnfor=True\n )","metadata":{"trusted":true},"outputs":[],"execution_count":2},{"cell_type":"code","source":"def collect_output(working_directory=\".\"):\n output = parse_pw(os.path.join(working_directory, 'pwscf.xml'))\n return {\n \"structure\": output['ase_structure'],\n \"energy\": output[\"energy\"],\n \"volume\": output['ase_structure'].get_volume(),\n }","metadata":{"trusted":true},"outputs":[],"execution_count":3},{"cell_type":"markdown","source":"Finally, multiple simulation can be combined in a simulation protocol. In this case the optimization of an Aluminium lattice structure, the calculation of an energy volume curve and the plotting of the resulting curve. ","metadata":{}},{"cell_type":"code","source":"def generate_structures(structure, strain_lst): \n structure_lst = []\n for strain in strain_lst:\n structure_strain = structure.copy()\n structure_strain.set_cell(\n structure_strain.cell * strain**(1/3), \n scale_atoms=True\n )\n structure_lst.append(structure_strain)\n return structure_lst","metadata":{"trusted":true},"outputs":[],"execution_count":4},{"cell_type":"code","source":"from ase.build import bulk\nfrom pyiron_base import Project","metadata":{"trusted":true},"outputs":[],"execution_count":5},{"cell_type":"code","source":"project = Project(\"test\")\nproject.remove_jobs(recursive=True, silently=True)\nstructure = bulk('Al', a=4.05, cubic=True)\npseudopotentials = {\"Al\": \"Al.pbe-n-kjpaw_psl.1.0.0.UPF\"}","metadata":{"trusted":true},"outputs":[{"output_type":"display_data","data":{"text/plain":"0it [00:00, ?it/s]","application/vnd.jupyter.widget-view+json":{"version_major":2,"version_minor":0,"model_id":"1aa0ff7e51da492fbad126c2a8e631f1"}},"metadata":{}}],"execution_count":6},{"cell_type":"code","source":"# Structure optimization \njob_qe_minimize = project.wrap_executable(\n job_name=\"job_qe_minimize\",\n write_input_funct=write_input,\n collect_output_funct=collect_output,\n input_dict={\n \"structure\": structure, \n \"pseudopotentials\": pseudopotentials, \n \"kpts\": (3, 3, 3),\n \"calculation\": \"vc-relax\",\n \"smearing\": 0.02,\n },\n executable_str=\"mpirun -np 1 pw.x -in input.pwi > output.pwo\",\n delayed=True,\n output_file_lst=[],\n output_key_lst=[\"structure\"],\n)\n\n# Generate Structures\nnumber_of_strains = 5 \nstructure_lst = project.wrap_python_function(\n python_function=generate_structures,\n structure=job_qe_minimize.output.structure, \n strain_lst=np.linspace(0.9, 1.1, number_of_strains),\n delayed=True,\n list_length=number_of_strains,\n)\n\n# Energy Volume Curve \nenergy_lst, volume_lst = [], []\nfor i, structure_strain in enumerate(structure_lst):\n job_strain = project.wrap_executable(\n job_name=\"job_strain_\" + str(i),\n write_input_funct=write_input,\n collect_output_funct=collect_output,\n input_dict={\n \"structure\": structure_strain, \n \"pseudopotentials\": pseudopotentials, \n \"kpts\": (3, 3, 3),\n \"calculation\": \"scf\",\n \"smearing\": 0.02,\n },\n executable_str=\"mpirun -np 1 pw.x -in input.pwi > output.pwo\",\n delayed=True,\n output_file_lst=[],\n output_key_lst=[\"energy\", \"volume\"],\n )\n energy_lst.append(job_strain.output.energy)\n volume_lst.append(job_strain.output.volume)","metadata":{"trusted":true},"outputs":[],"execution_count":7},{"cell_type":"markdown","source":"As the quantum espresso calculations are the computationally expensive steps they are combined in a python function to be submitted to dedicated computing resources. In contrast the creation of the atomistic structure and the plotting of the energy volume curve are executed in the users process.\n\nThe remaining simulation protocol, can be summarized in a few lines. The required modules are imported, a `Project` object is created which represents a folder on the filesystem, the `wrap_python_function()` is used to convert the computationally expensive steps of the workflow into a single `Job` object and the resulting energy volume curve is plotted: ","metadata":{}},{"cell_type":"code","source":"def collect(volume_lst, energy_lst):\n return {\"volume\": volume_lst, \"energy\": energy_lst}","metadata":{"trusted":true},"outputs":[],"execution_count":8},{"cell_type":"code","source":"results = project.wrap_python_function(\n python_function=collect,\n volume_lst=volume_lst,\n energy_lst=energy_lst,\n delayed=True,\n)","metadata":{"trusted":true},"outputs":[],"execution_count":9},{"cell_type":"code","source":"result_dict = results.pull()\nresult_dict","metadata":{"trusted":true},"outputs":[{"name":"stdout","text":"The job job_qe_minimize was saved and received the ID: 1\nThe job generate_structures77d97073ea046f330145d7402e23774c was saved and received the ID: 2\nThe job job_strain_0 was saved and received the ID: 3\nThe job job_strain_1 was saved and received the ID: 4\nThe job job_strain_2 was saved and received the ID: 5\nThe job job_strain_3 was saved and received the ID: 6\nThe job job_strain_4 was saved and received the ID: 7\nThe job collectfbfe0cc8f5cd2e8c9ee376e43de6c82b was saved and received the ID: 8\n","output_type":"stream"},{"execution_count":10,"output_type":"execute_result","data":{"text/plain":"{'volume': [59.59410625269659,\n 62.90488993340162,\n 66.21567361410706,\n 69.52645729481236,\n 72.83724097551769],\n 'energy': [-1074.845744615061,\n -1074.9161488594564,\n -1074.936524166831,\n -1074.9192860025798,\n -1074.8737904693382]}"},"metadata":{}}],"execution_count":10},{"cell_type":"code","source":"def plot_energy_volume_curve(volume_lst, energy_lst):\n plt.plot(volume_lst, energy_lst)\n plt.xlabel(\"Volume\")\n plt.ylabel(\"Energy\")\n plt.savefig(\"evcurve.png\")","metadata":{"trusted":true},"outputs":[],"execution_count":11},{"cell_type":"markdown","source":"This concludes the first version of the simulation workflow, in the following the submission to HPC resources, the different options for data storage and the publication of the workflow are briefly discussed.","metadata":{}},{"cell_type":"code","source":"plot_energy_volume_curve(\n volume_lst=result_dict[\"volume\"], \n energy_lst=result_dict[\"energy\"]\n)","metadata":{"trusted":true},"outputs":[{"output_type":"display_data","data":{"text/plain":"
","image/png":"iVBORw0KGgoAAAANSUhEUgAAAksAAAHACAYAAACyIiyEAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAABb8ElEQVR4nO3deVxVdcLH8c9lF5SLyiaCoLkA7ksqZmnlmktamW2YVk7NjC1WVva0OG3a3pRt05S222hatlGa2uSCO64IuODC5soiyHrP8wfCRCIqwj1c+L5fr/t6Hi7nXL73xFy+/n7n/I7FMAwDEREREamUk9kBREREROoylSURERGRKqgsiYiIiFRBZUlERESkCipLIiIiIlVQWRIRERGpgsqSiIiISBVUlkRERESqoLIkIiIiUgWVJREREZEqqCyZ5Pnnn6dfv354enri4+NzXvsYhsGMGTMICgqiUaNGDBw4kB07dpR/Pzk5GYvFUulj/vz5Z7xeQUEB3bp1w2KxEBcXd0H53333Xbp06YK3tzfe3t5ERUXx008/XdBriIiIOAKVJZMUFhYybtw4/vrXv573Pi+99BKvvfYas2fPZv369QQGBjJ48GBycnIACAkJIS0trcLjH//4B15eXgwfPvyM13vkkUcICgqqVv7g4GBmzZrFhg0b2LBhA1dddRXXXntthfImIiJSLxhiqjlz5hhWq/Wc29lsNiMwMNCYNWtW+XP5+fmG1Wo13nvvvbPu161bN+OOO+444/kff/zRCA8PN3bs2GEAxubNmyt8f8eOHcbw4cMNLy8vw9/f37jtttuMI0eOVJmxadOmxr///e9zvhcRERFHopElB7Fv3z7S09MZMmRI+XPu7u4MGDCA1atXV7rPxo0biYuL484776zwfEZGBpMnT+bTTz/F09PzjP3S0tIYMGAA3bp1Y8OGDcTExJCRkcGNN95Y6c8pKSlh3rx55ObmEhUVdRHvUkREpO5xMTuAnJ/09HQAAgICKjwfEBDA/v37K93nww8/JCIign79+pU/ZxgGEydO5J577qFXr14kJyefsd+7775Ljx49eOGFF8qf++ijjwgJCSExMZH27dsDsG3bNqKiosjPz6dx48YsWrSIyMjIi32rIiIidYpGlmrQjBkzznqCddljw4YNF/UzLBZLha8NwzjjOYBTp07xxRdfnDGq9NZbb5Gd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JCIiIlIFlSUHlpKSwm233Ubz5s3x9PSkW7dubNy4sfz7hmEwY8YMgoKCaNSoEQMHDmTHjh0mJq5dVR2PoqIiHn30UTp37oyXlxdBQUFMmDCB1NRUk1PXrnP9jvzR3XffjcVi4Y033rBvSDs6n+MRHx/P6NGjsVqtNGnShL59+3LgwAGTEteucx2PkydPMmXKFIKDg2nUqBERERG8++67JiauPWFhYVgsljMef//734GG93la1fFoiJ+nKksO6sSJE1x22WW4urry008/sXPnTl599VV8fHzKt3nppZd47bXXmD17NuvXrycwMJDBgweX356lPjnX8cjLy2PTpk08+eSTbNq0iYULF5KYmMjo0aPNDV6Lzud3pMw333zD2rVrCQoKsn9QOzmf47Fnzx769+9PeHg4K1asYMuWLTz55JN4eHiYF7yWnM/xmDp1KjExMXz22WfEx8czdepU7r33Xr799lvzgteS9evXk5aWVv5YsmQJAOPGjQMa1ucpVH08GuLnKYY4pEcffdTo37//Wb9vs9mMwMBAY9asWeXP5efnG1ar1XjvvffsEdGuznU8KrNu3ToDMPbv319Lqcx1vsfk0KFDRsuWLY3t27cboaGhxuuvv1774UxwPsdj/Pjxxm233WanROY6n+PRsWNH45lnnqnwXI8ePYwnnniiNqPVCffff79xySWXGDabrcF9nlbmj8ejMvX981QjSw5q8eLF9OrVi3HjxuHv70/37t354IMPyr+/b98+0tPTy288DKVrYwwYMIDVq1ebEblWnet4VCYrKwuLxVLpSEt9cD7HxGazER0dzbRp0+jYsaNJSe3jXMfDZrPxww8/0L59e4YOHYq/vz99+vThm2++MS90LTqf34/+/fuzePFiUlJSMAyD5cuXk5iYyNChQ01KbR+FhYV89tln3HHHHVgslgb3efpnfz4elanvn6caWXJQ7u7uhru7uzF9+nRj06ZNxnvvvWd4eHgYH3/8sWEYhrFq1SoDMFJSUirsN3nyZGPIkCFmRK5V5zoef3bq1CmjZ8+exq233mrnpPZzPsfkhRdeMAYPHlz+r8X6PLJ0ruORlpZmAIanp6fx2muvGZs3bzZmzpxpWCwWY8WKFSanr3nn8/tRUFBgTJgwwQAMFxcXw83Nzfjkk09MTG0fX331leHs7Fz++dnQPk//7M/H488awuepypKDcnV1NaKioio8d++99xp9+/Y1DON//+NOTU2tsM1dd91lDB061G457eVcx+OPCgsLjWuvvdbo3r27kZWVZa+IdneuY7JhwwYjICCgwgdgfS5L5zoeKSkpBmDcfPPNFbYZNWqUcdNNN9ktp72cz/9mXn75ZaN9+/bG4sWLjS1bthhvvfWW0bhxY2PJkiX2jmtXQ4YMMUaOHFn+dUP7PP2zPx+PP2oon6eahnNQLVq0IDIyssJzERER5VftBAYGApCenl5hm8OHDxMQEGCfkHZ0ruNRpqioiBtvvJF9+/axZMmSenHH7LM51zH5/fffOXz4MK1atcLFxQUXFxf279/PQw89RFhYmAmJa9e5joevry8uLi7n9XtUH5zreJw6dYrHH3+c1157jVGjRtGlSxemTJnC+PHjeeWVV8yIbBf79+9n6dKl3HXXXeXPNbTP0z+q7HiUaUifpypLDuqyyy4jISGhwnOJiYmEhoYC0Lp1awIDA8uvYIDSeefffvuNfv362TWrPZzreMD//oedlJTE0qVLad68ub1j2tW5jkl0dDRbt24lLi6u/BEUFMS0adP4+eefzYhcq851PNzc3Lj00kvP+XtUX5zreBQVFVFUVISTU8U/E87OzthsNrvltLc5c+bg7+/PiBEjyp9raJ+nf1TZ8YCG93mqaTgHtW7dOsPFxcV4/vnnjaSkJOPzzz83PD09jc8++6x8m1mzZhlWq9VYuHChsW3bNuPmm282WrRoYWRnZ5uYvHac63gUFRUZo0ePNoKDg424uDgjLS2t/FFQUGBy+tpxPr8jf1afp+HO53gsXLjQcHV1Nf71r38ZSUlJxltvvWU4Ozsbv//+u4nJa8f5HI8BAwYYHTt2NJYvX27s3bvXmDNnjuHh4WG88847JiavPSUlJUarVq2MRx999IzvNaTP0zJnOx4N8fNUZcmBfffdd0anTp0Md3d3Izw83PjXv/5V4fs2m814+umnjcDAQMPd3d244oorjG3btpmUtvZVdTz27dtnAJU+li9fbl7oWnau35E/q89lyTDO73h8+OGHRtu2bQ0PDw+ja9euxjfffGNCUvs41/FIS0szJk6caAQFBRkeHh5Ghw4djFdfffWsl487up9//tkAjISEhDO+19A+Tw3j7MejIX6eWgzDMMwY0RIRERFxBDpnSURERKQKKksiIiIiVVBZEhEREamCypKIiIhIFVSWRERERKqgsiQiIiJSBZUlERERkSqoLImIiIhUQWVJRBq0sLAw3njjDbNjiEgdprIkIg5r1KhRDBo0qNLvrVmzBovFwqZNm+ycSkTqG5UlEXFYd955J8uWLWP//v1nfO+jjz6iW7du9OjRw4RkIlKfqCyJiMMaOXIk/v7+zJ07t8LzeXl5fPXVV9x55518/fXXdOzYEXd3d8LCwnj11VfP+nrJyclYLBbi4uLKn8vMzMRisbBixQoAVqxYgcVi4eeff6Z79+40atSIq666isOHD/PTTz8RERGBt7c3N998M3l5eeWvYxgGL730Em3atKFRo0Z07dqVBQsW1OThEJFaorIkIg7LxcWFCRMmMHfuXP54T/D58+dTWFhIVFQUN954IzfddBPbtm1jxowZPPnkk2eUq+qYMWMGs2fPZvXq1Rw8eJAbb7yRN954gy+++IIffviBJUuW8NZbb5Vv/8QTTzBnzhzeffddduzYwdSpU7ntttv47bffLjqLiNQui/HHTxgREQeza9cuIiIiWLZsGVdeeSUAAwYMoGXLllgsFo4cOcIvv/xSvv0jjzzCDz/8wI4dO4DSE7wfeOABHnjgAZKTk2ndujWbN2+mW7duQOnIUtOmTVm+fDkDBw5kxYoVXHnllSxdupSrr74agFmzZjF9+nT27NlDmzZtALjnnntITk4mJiaG3NxcfH19WbZsGVFRUeVZ7rrrLvLy8vjiiy/scahEpJo0siQiDi08PJx+/frx0UcfAbBnzx5+//137rjjDuLj47nssssqbH/ZZZeRlJRESUnJRf3cLl26lP//AQEBeHp6lhelsucOHz4MwM6dO8nPz2fw4ME0bty4/PHJJ5+wZ8+ei8ohIrXPxewAIiIX684772TKlCm8/fbbzJkzh9DQUK6++moMw8BisVTYtqrBdCcnpzO2KSoqqnRbV1fX8v/fYrFU+LrsOZvNBlD+f3/44QdatmxZYTt3d/dzvT0RMZlGlkTE4d144404OzvzxRdf8PHHHzNp0iQsFguRkZGsXLmywrarV6+mffv2ODs7n/E6fn5+AKSlpZU/98eTvasrMjISd3d3Dhw4QNu2bSs8QkJCLvr1RaR2aWRJRBxe48aNGT9+PI8//jhZWVlMnDgRgIceeohLL72UZ599lvHjx7NmzRpmz57NO++8U+nrNGrUiL59+zJr1izCwsI4evQoTzzxxEXna9KkCQ8//DBTp07FZrPRv39/srOzWb16NY0bN+b222+/6J8hIrVHI0siUi/ceeednDhxgkGDBtGqVSsAevTowX/+8x/mzZtHp06deOqpp3jmmWfKy1RlPvroI4qKiujVqxf3338/zz33XI3ke/bZZ3nqqaeYOXMmERERDB06lO+++47WrVvXyOuLSO3R1XAiIiIiVdDIkoiIiEgVVJZEREREqqCyJCIiIlIFlSURERGRKqgsiYiIiFRBZUlERESkCipLIiIiIlVQWRIRERGpgsqSiIiISBVUlkRERESqoLIkIiIiUgWVJREREZEq/D8WwIub/1rFmwAAAABJRU5ErkJggg=="},"metadata":{}}],"execution_count":12},{"cell_type":"markdown","source":"## Submission to an HPC / Check pointing / Error handling\nWhile the local installation of the `pyiron_base` workflow manager requires no additional configuration, the connection to an HPC system is more evolved. The existing examples provided for specific HPC systems can be converted to jinja2 templates, by defining variables with double curly brackets. A minimalist template could be: \n```\n#!/bin/bash\n#SBATCH --job-name={{job_name}}\n#SBATCH --chdir={{working_directory}}\n#SBATCH --cpus-per-task={{cores}}\n\n{{command}}\n```\nHere the `job_name`, the `working_directory` and the number of compute `cores` can be specified as parameters. In the `pyiron_base` workflow manager such a submission script can then be selected based on its name as parameter of the `server` object:\n```python\njob_workflow.server.queue = \"my_queue\"\njob_workflow.server.cores = 64\n```\nThese lines are inserted before calling the `run()` function. The rest of the simulation protocol remains the same.\n\nWhen simulation protocols are up-scaling and iterated over a large number of parameters, certain parameter combinations might lead to poor conversion or even cause simulation code crashes. In the `pyiron_base` workflow manager these calculation are marked as `aborted`. This gives the user to inspect the calculation and in case the crash was not related to the parameter combination, individual jobs can be removed with the `remove_job()` function. Afterwards, the simulation protocol can be executed again. In this case the `pyiron_base` workflow manager recognizes the already completed calculation and only re-evaluates the removed broken calculation. \n\n## Data Storage / Data Sharing\nIn the `pyiron_base` workflow manager the input of the calculation as well as the output are stored in the hierachical data format (HDF). In addition, `pyiron_base` can use a Structured Query Language (SQL) database, which acts as an index of all the `Job` objects and their HDF5 files. This file-based approach allows the user easily to browse through the results and at the same time the compressed storage in HDF5 and the internal hierarchy of the data format, enable the efficient storage of large tensors, like atomistic trajectories. \n\n## Publication of the workflow\nThe `pyiron_base` workflow manager provides a publication template to publish simulation workflows on Github. This template enables both the publication of the workflow as well as the publication of the results generated with a given workflow. For reproduciblity this publication template is based on sharing a conda environment file `environment.yml` in combination with the Jupyter notebook containing the simulation protocol and the archived `Job` objects. The Jupyter notebook is then rendered as static website with links to enable interactive execution using Jupyterbook and the mybinder service. As the `pyiron_base` workflow manager reloads existing calculation from the archive, a user of the interactive mybinder environment does not have to recompute the computationally expensive steps and still has the opportunity to interact with the provided workflow and data. ","metadata":{}},{"cell_type":"code","source":"","metadata":{"trusted":true},"outputs":[],"execution_count":null}]} \ No newline at end of file