diff --git a/jobflow.ipynb b/jobflow.ipynb index 7778775..dc7580b 100644 --- a/jobflow.ipynb +++ b/jobflow.ipynb @@ -1 +1,374 @@ -{"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":"# jobflow","metadata":{}},{"cell_type":"code","source":"import subprocess\nimport os\nfrom pydantic import BaseModel, Field","metadata":{"ExecuteTime":{"end_time":"2024-04-04T12:23:39.230259Z","start_time":"2024-04-04T12:23:39.139154Z"}},"execution_count":1,"outputs":[]},{"cell_type":"code","source":"import matplotlib.pyplot as plt\nimport numpy as np","metadata":{"ExecuteTime":{"end_time":"2024-04-04T12:23:39.812727Z","start_time":"2024-04-04T12:23:39.233298Z"}},"execution_count":2,"outputs":[]},{"cell_type":"code","source":"from ase.build import bulk\nfrom ase.io import write","metadata":{"ExecuteTime":{"end_time":"2024-04-04T12:23:40.064521Z","start_time":"2024-04-04T12:23:39.815771Z"}},"execution_count":3,"outputs":[]},{"cell_type":"code","source":"from adis_tools.parsers import parse_pw","metadata":{"ExecuteTime":{"end_time":"2024-04-04T12:23:40.342218Z","start_time":"2024-04-04T12:23:40.067769Z"}},"execution_count":4,"outputs":[]},{"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":{"ExecuteTime":{"end_time":"2024-04-04T12:23:40.349810Z","start_time":"2024-04-04T12:23:40.344659Z"}},"execution_count":5,"outputs":[]},{"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":{"ExecuteTime":{"end_time":"2024-04-04T12:23:40.354972Z","start_time":"2024-04-04T12:23:40.351547Z"}},"execution_count":6,"outputs":[]},{"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":{"ExecuteTime":{"end_time":"2024-04-04T12:23:40.361062Z","start_time":"2024-04-04T12:23:40.356433Z"}},"execution_count":7,"outputs":[]},{"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":{"ExecuteTime":{"end_time":"2024-04-04T12:23:40.365984Z","start_time":"2024-04-04T12:23:40.362667Z"}},"execution_count":8,"outputs":[]},{"cell_type":"code","source":"from pymatgen.io.core import InputSet, InputGenerator\nfrom pymatgen.io.ase import MSONAtoms\nfrom typing import Any, Optional, Union\nQE_CMD= \"mpirun -np 1 pw.x -in input.pwi > output.pwo\"\ndef run_qe(qe_cmd=QE_CMD):\n subprocess.check_output(qe_cmd, shell=True, universal_newlines=True)\n\nclass QETaskDoc(BaseModel):\n structure: Optional[MSONAtoms] = Field(None, description=\"ASE structure\")\n energy: Optional[float] = Field(None, description=\"DFT energy in eV\")\n volume: Optional[float] = Field(None, description=\"volume in Angstrom^3\")\n \n @classmethod\n def from_directory(cls, working_directory):\n output=collect_output(working_directory=working_directory)\n # structure object needs to be serializable, i.e., we need an additional transformation\n return cls(structure=MSONAtoms(output[\"structure\"]), energy=output[\"energy\"], volume=output[\"volume\"])\n\nclass QEInputSet(InputSet):\n \"\"\"\n Writes an input based on an input_dict\n \"\"\"\n def __init__(self, input_dict):\n self.input_dict = input_dict\n\n def write_input(self, working_directory=\".\"):\n write_input(self.input_dict, working_directory=working_directory)\n\nfrom dataclasses import dataclass, field\n\n\n\n@dataclass\nclass QEInputGenerator(InputGenerator):\n pseudopotentials: dict = field(default_factory=lambda: {\"Al\": \"Al.pbe-n-kjpaw_psl.1.0.0.UPF\"})\n kpts: tuple = (3,3,3)\n calculation: str = \"vc-relax\"\n smearing: float = 0.02\n \n\n def get_input_set(self, structure) -> QEInputSet:\n\n input_dict={\"structure\":structure,\n \"pseudopotentials\":self.pseudopotentials, \n \"kpts\": self.kpts,\n \"calculation\": self.calculation,\n \"smearing\": self.smearing,\n }\n return QEInputSet(input_dict=input_dict)\n\n@dataclass\nclass QEInputStaticGenerator(QEInputGenerator):\n calculation: str = \"scf\"\n\n \ndef write_qe_input_set(structure, input_set_generator=QEInputGenerator(), working_directory=\".\"):\n qis = input_set_generator.get_input_set(structure=structure)\n qis.write_input(working_directory=working_directory)\n \n ","metadata":{"collapsed":false,"jupyter":{"outputs_hidden":false},"ExecuteTime":{"end_time":"2024-04-04T12:23:40.992461Z","start_time":"2024-04-04T12:23:40.368632Z"}},"execution_count":9,"outputs":[]},{"cell_type":"code","source":"from dataclasses import dataclass, field\nfrom jobflow import job, Maker\n\n\n@dataclass\nclass BaseQEMaker(Maker):\n \"\"\"\n Base QE job maker.\n\n Parameters\n ----------\n name : str\n The job name.\n input_set_generator : .QEInputGenerator\n A generator used to make the input set.\n \"\"\"\n\n name: str = \"base qe job\"\n input_set_generator: QEInputGenerator = field(default_factory=QEInputGenerator)\n\n @job(output_schema=QETaskDoc)\n def make(\n self, structure\n ) -> QETaskDoc:\n \"\"\"\n Run a QE calculation.\n\n Parameters\n ----------\n structure : MSONAtoms|Atoms\n An Atoms or MSONAtoms object.\n \n Returns\n -------\n Output of a QE calculation\n \"\"\"\n # copy previous inputs\n\n # write qe input files\n write_qe_input_set(\n structure=structure, input_set_generator=self.input_set_generator)\n\n # qe\n run_qe()\n\n # parse qe outputs\n task_doc=QETaskDoc.from_directory(\".\")\n \n return task_doc\n\n@dataclass\nclass StaticQEMaker(BaseQEMaker):\n \"\"\"\n Base QE job maker.\n\n Parameters\n ----------\n name : str\n The job name.\n input_set_generator : .QEInputGenerator\n A generator used to make the input set.\n \"\"\"\n\n name: str = \"static qe job\"\n input_set_generator: QEInputGenerator = field(default_factory=QEInputStaticGenerator)\n\n\n\nfrom jobflow import job, Response, Flow, run_locally\n\n@job\ndef get_ev_curve(structure, strain_lst):\n structures=generate_structures(structure,strain_lst=strain_lst)\n jobs = []\n volumes = []\n energies = []\n for istructure in range(len(strain_lst)):\n new_job = StaticQEMaker().make(structures[istructure])\n jobs.append(new_job)\n volumes.append(new_job.output.volume)\n energies.append(new_job.output.energy)\n return Response(replace=Flow(jobs, output={\"energies\": energies, \"volumes\": volumes}))\n \n@job\ndef plot_energy_volume_curve_job(volume_lst, energy_lst):\n plot_energy_volume_curve(volume_lst=volume_lst, energy_lst=energy_lst)\n\nstructure = bulk('Al', a=4.15, cubic=True)\nrelax = BaseQEMaker().make(structure=MSONAtoms(structure))\nev_curve = get_ev_curve(relax.output.structure, strain_lst=np.linspace(0.9, 1.1, 5))\nplot = plot_energy_volume_curve_job(volume_lst=ev_curve.output[\"volumes\"], energy_lst=ev_curve.output[\"energies\"])\njobs = [relax, ev_curve, plot]\nrun_locally(Flow(jobs), create_folders=True)","metadata":{"ExecuteTime":{"end_time":"2024-04-04T12:26:08.108635Z","start_time":"2024-04-04T12:24:48.120617Z"}},"execution_count":10,"outputs":[{"name":"stdout","text":"2024-04-04 15:55:32,815 INFO Started executing jobs locally\n2024-04-04 15:55:32,892 INFO Starting job - base qe job (72ab2547-8a66-4dd0-a95a-b6255a668cd8)\n","output_type":"stream"},{"name":"stderr","text":"[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00139] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\nNote: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n","output_type":"stream"},{"name":"stdout","text":"2024-04-04 15:56:37,395 INFO Finished job - base qe job (72ab2547-8a66-4dd0-a95a-b6255a668cd8)\n2024-04-04 15:56:37,396 INFO Starting job - get_ev_curve (87ad6b9b-9f34-463e-b705-1ab7cdcf9aee)\n2024-04-04 15:56:37,404 INFO Finished job - get_ev_curve (87ad6b9b-9f34-463e-b705-1ab7cdcf9aee)\n2024-04-04 15:56:37,406 INFO Starting job - static qe job (b0759785-155b-4e79-9b72-c626067d81e1)\n","output_type":"stream"},{"name":"stderr","text":"[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00149] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\n","output_type":"stream"},{"name":"stdout","text":"2024-04-04 15:56:45,563 INFO Finished job - static qe job (b0759785-155b-4e79-9b72-c626067d81e1)\n2024-04-04 15:56:45,564 INFO Starting job - static qe job (514079e9-d6ae-4369-8b80-bf8ca7860540)\n","output_type":"stream"},{"name":"stderr","text":"Note: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00159] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\nNote: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n","output_type":"stream"},{"name":"stdout","text":"2024-04-04 15:56:53,979 INFO Finished job - static qe job (514079e9-d6ae-4369-8b80-bf8ca7860540)\n2024-04-04 15:56:53,980 INFO Starting job - static qe job (6e3c5a28-4edb-4244-9e35-0b8733b946c4)\n","output_type":"stream"},{"name":"stderr","text":"[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00169] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\n","output_type":"stream"},{"name":"stdout","text":"2024-04-04 15:57:03,600 INFO Finished job - static qe job (6e3c5a28-4edb-4244-9e35-0b8733b946c4)\n2024-04-04 15:57:03,600 INFO Starting job - static qe job (980b72a5-fbea-445c-9075-a880322c8261)\n","output_type":"stream"},{"name":"stderr","text":"Note: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00179] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\n","output_type":"stream"},{"name":"stdout","text":"2024-04-04 15:57:14,907 INFO Finished job - static qe job (980b72a5-fbea-445c-9075-a880322c8261)\n2024-04-04 15:57:14,908 INFO Starting job - static qe job (a44a935f-6bd2-4279-bbcb-53d5ed890a99)\n","output_type":"stream"},{"name":"stderr","text":"Note: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00189] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\nNote: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n","output_type":"stream"},{"name":"stdout","text":"2024-04-04 15:57:27,174 INFO Finished job - static qe job (a44a935f-6bd2-4279-bbcb-53d5ed890a99)\n2024-04-04 15:57:27,174 INFO Starting job - store_inputs (87ad6b9b-9f34-463e-b705-1ab7cdcf9aee, 2)\n2024-04-04 15:57:27,176 INFO Finished job - store_inputs (87ad6b9b-9f34-463e-b705-1ab7cdcf9aee, 2)\n2024-04-04 15:57:27,176 INFO Starting job - plot_energy_volume_curve_job (9987ab9f-1ae9-4172-8e31-b2c9920d4791)\n2024-04-04 15:57:27,256 INFO Finished job - plot_energy_volume_curve_job (9987ab9f-1ae9-4172-8e31-b2c9920d4791)\n2024-04-04 15:57:27,256 INFO Finished executing jobs locally\n","output_type":"stream"},{"execution_count":10,"output_type":"execute_result","data":{"text/plain":"{'72ab2547-8a66-4dd0-a95a-b6255a668cd8': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[4.045218941837687, 4.045218941837687, 4.045218941837687]), energy=-1074.9365272693506, volume=66.1951387021735), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n '87ad6b9b-9f34-463e-b705-1ab7cdcf9aee': {1: Response(output=None, detour=None, addition=None, replace=Flow(name='Flow', uuid='0e46d480-7699-4e03-889b-b4ba65fe3d38')\n 1. Job(name='static qe job', uuid='b0759785-155b-4e79-9b72-c626067d81e1')\n 2. Job(name='static qe job', uuid='514079e9-d6ae-4369-8b80-bf8ca7860540')\n 3. Job(name='static qe job', uuid='6e3c5a28-4edb-4244-9e35-0b8733b946c4')\n 4. Job(name='static qe job', uuid='980b72a5-fbea-445c-9075-a880322c8261')\n 5. Job(name='static qe job', uuid='a44a935f-6bd2-4279-bbcb-53d5ed890a99')\n 6. Job(name='store_inputs', uuid='87ad6b9b-9f34-463e-b705-1ab7cdcf9aee'), stored_data=None, stop_children=False, stop_jobflow=False),\n 2: Response(output={'energies': [OutputReference(b0759785-155b-4e79-9b72-c626067d81e1, .energy), OutputReference(514079e9-d6ae-4369-8b80-bf8ca7860540, .energy), OutputReference(6e3c5a28-4edb-4244-9e35-0b8733b946c4, .energy), OutputReference(980b72a5-fbea-445c-9075-a880322c8261, .energy), OutputReference(a44a935f-6bd2-4279-bbcb-53d5ed890a99, .energy)], 'volumes': [OutputReference(b0759785-155b-4e79-9b72-c626067d81e1, .volume), OutputReference(514079e9-d6ae-4369-8b80-bf8ca7860540, .volume), OutputReference(6e3c5a28-4edb-4244-9e35-0b8733b946c4, .volume), OutputReference(980b72a5-fbea-445c-9075-a880322c8261, .volume), OutputReference(a44a935f-6bd2-4279-bbcb-53d5ed890a99, .volume)]}, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n 'b0759785-155b-4e79-9b72-c626067d81e1': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[3.9056159296787105, 3.9056159296787105, 3.9056159296787105]), energy=-1074.8451830762128, volume=59.575624050752516), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n '514079e9-d6ae-4369-8b80-bf8ca7860540': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[3.9766426435887574, 3.9766426435887574, 3.9766426435887574]), energy=-1074.9158947387848, volume=62.88538094246082), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n '6e3c5a28-4edb-4244-9e35-0b8733b946c4': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[4.045218924156295, 4.045218924156295, 4.045218924156295]), energy=-1074.936525208987, volume=66.19513783416937), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n '980b72a5-fbea-445c-9075-a880322c8261': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[4.111545777030954, 4.111545777030954, 4.111545777030954]), energy=-1074.9194989203452, volume=69.50489472587755), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n 'a44a935f-6bd2-4279-bbcb-53d5ed890a99': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[4.175799058074337, 4.175799058074337, 4.175799058074337]), energy=-1074.8741797823543, volume=72.81465161758611), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n '9987ab9f-1ae9-4172-8e31-b2c9920d4791': {1: Response(output=None, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)}}"},"metadata":{}},{"output_type":"display_data","data":{"text/plain":"
","image/png":"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SkrKOT+rb++nhnH+41Hf3k8thmEYZoxoiYiIiDgDzVkSERERqYTKkoiIiEglVJZEREREKqGyJCIiIlIJlSURERGRSqgsiYiIiFRCZUlERESkEipLIiIiIpVQWRKRei0iIoLXX3/d7Bgi4sBUlkTEaQ0dOpT+/ftX+LPVq1djsVjYuHGjnVOJSF2jsiQiTuvee+/lxx9/ZN++fef87IMPPqBLly5069bNhGQiUpeoLImI0xoyZAhBQUHMmjWr3ON5eXl8/vnn3HvvvcyfP5+oqCg8PT2JiIhgxowZ532+tLQ0LBYLiYmJZY+dPHkSi8XCihUrAFixYgUWi4WlS5fStWtXvL29ueaaazhy5AjffvstHTp0wN/fn9tuu428vLyy5zEMg5deeolWrVrh7e1NTEwM8+bNq8nDISK1RGVJRJyWm5sbd911F7NmzeL31wSfO3cuhYWFxMbGMnr0aG699Va2bNnC1KlTmTJlyjnlqjqmTp3Km2++yapVqzhw4ACjR4/m9ddf59NPP+Wbb75h2bJl/Pvf/y7b/sknn2TmzJm8/fbbbNu2jQkTJnDnnXfy008/XXIWEaldFuP37zAiIk5mx44ddOjQgR9//JGrr74agCuvvJJmzZphsVg4evQo3333Xdn2jz/+ON988w3btm0DSid4P/zwwzz88MOkpaXRsmVLNm3aRJcuXYDSkaWGDRuyfPlyrrrqKlasWMHVV1/N999/z7XXXgvA9OnTmTRpErt376ZVq1YAPPDAA6SlpREfH09ubi6BgYH8+OOPxMbGlmW57777yMvL49NPP7XHoRKRatLIkog4tcjISPr06cMHH3wAwO7du/nll1+45557SE5Opm/fvuW279u3Lzt37qSkpOSSfm90dHTZ/w8ODsbHx6esKJ197MiRIwBs376d/Px8rrvuOvz8/MpuH374Ibt3776kHCJS+9zMDiAicqnuvfdexo8fz//93/8xc+ZMwsPDufbaazEMA4vFUm7bygbTXVxcztmmqKiowm3d3d3L/r/FYil3/+xjNpsNoOx/v/nmG5o1a1ZuO09Pzwu9PBExmUaWRMTpjR49GldXVz799FNmz57N2LFjsVgsdOzYkV9//bXctqtWraJdu3a4urqe8zxNmjQBID09veyx30/2rq6OHTvi6enJ/v37adOmTblb8+bNL/n5RaR2aWRJRJyen58ft9xyC5MnTyY7O5sxY8YA8Oijj3LZZZfx7LPPcsstt7B69WrefPNN3nrrrQqfx9vbm969ezN9+nQiIiI4duwYTz755CXna9CgAY899hgTJkzAZrPRr18/cnJyWLVqFX5+ftx9992X/DtEpPZoZElE6oR7772XrKws+vfvT4sWLQDo1q0bX3zxBXPmzKFTp0489dRT/POf/ywrUxX54IMPKCoqokePHvztb3/jueeeq5F8zz77LE899RTTpk2jQ4cODBw4kMWLF9OyZcsaeX4RqT36NpyIiIhIJTSyJCIiIlIJlSURERGRSqgsiYiIiFRCZUlERESkEipLIiIiIpVQWRIRERGphMqSiIiISCVUlkREREQqobIkIiIiUgmVJREREZFKqCyJiIiIVEJlSURERKQS/w+KFmKjiKyciAAAAABJRU5ErkJggg=="},"metadata":{}}]},{"cell_type":"code","source":"","metadata":{"collapsed":false,"ExecuteTime":{"end_time":"2024-04-04T12:23:49.409448Z","start_time":"2024-04-04T12:23:49.404281Z"},"jupyter":{"outputs_hidden":false}},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"collapsed":false,"ExecuteTime":{"end_time":"2024-04-04T12:23:49.414721Z","start_time":"2024-04-04T12:23:49.411543Z"},"jupyter":{"outputs_hidden":false}},"execution_count":null,"outputs":[]}]} \ No newline at end of file +{ + "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": "# jobflow", + "metadata": {} + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "Jobflow allows you to build workflows that are not necessarily related to material science. However, it was developed in the context of the Materials Project and therefore forms the basis for atomate2, a software package for workflows related to the data generation of the Materials Project. It was especially build to simplify the definition of dynamic workflows - those that create jobs during run time." + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## Installation / Setup\n", + "Jobflow itself can be installed via ‘pip install‘ and directly run with the default setup. Jobflow will then internally rely on a predefined database which is currently a memory database as defined in the software package maggma. For large-scale usage, a MongoDB-like database might be specified for each project in a jobflow.yaml file.\n", + "To run jobflow in a high-throughput setup (i.e., parallel execution of independent parts in the workflow), additional packages are required. Currently, fireworks (https://materialsproject.github.io/fireworks/) and jobflow-remote (https://matgenix.github.io/jobflow-remote/) exist. They both require a MongoDB database.\n", + "In the case of FireWorks, however, a MongoDB database needs to be connected to the compute nodes. Jobflow-remote allows remote submission options that only require a MongoDB database on the submitting computer but not the compute nodes. It can also deal with two-factor authentification." + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## Basic introduction to Jobflow concepts\n", + "Before starting with implementing a new simulation core, we need to discuss the core concepts of jobflow. jobflow has been written in Python. Jobflow defines Job and Flow objects. Jobs are classes that allow for the delayed execution of a function. Functions can be easily transformed into a Job with the @job decorator, as demonstrated here with a test function:" + ] + }, + { + "metadata": { + "jupyter": { + "is_executing": true + } + }, + "cell_type": "code", + "source": [ + "from jobflow import job\n", + "@job\n", + "def my_function(my_parameter: int):\n", + " return my_parameter\n", + "\n", + "job1 = my_function(my_parameter=1)\n" + ], + "outputs": [], + "execution_count": null + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "To build workflows, the Flow object is used. Here, Jobs are connected via their outputs so that it is possible to derive the order of the Jobs as run time. To build the workflow, only the list of connected Jobs has to be used to initialize a flow.\n" + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": [ + "from jobflow import job, Flow\n", + "@job\n", + "def my_function(my_parameter: int):\n", + " return my_parameter\n", + "@job\n", + "def my_second_function(my_parameter: int):\n", + " return my_parameter\n", + "\n", + "job1 = my_function(my_parameter=1)\n", + "job2 = my_second_function(job1.output)\n", + "flow = Flow([job1, job2], job2.output)" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "To simplify the implementation of Jobs and Flow, the Maker object has been introduced. It is an extended dataclass object that generates a Job or Flow with the make method. Dataclasses are used as they allow to define immutable default values. These Makers can then be used to reuse code via usual inheritance in Python.\n" + }, + { + "metadata": {}, + "cell_type": "code", + "outputs": [], + "execution_count": null, + "source": [ + "from dataclasses import dataclass\n", + "from jobflow import Maker\n", + "@dataclass\n", + "class MyMaker(Maker):\n", + " name: str = \"My Maker\"\n", + " scaling: float = 1.1\n", + "\n", + "@job\n", + "def make(self, my_parameter: int):\n", + " return my_parameter * self.scaling\n", + "\n", + "job1=MyMaker().make(my_parameter=1)" + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "Instead of returning a Job or Flow object, also a Response object can be returned, which allows the definition of dynamic workflows where the number of additional jobs is unclear before execution. There are different options how exactly the Response object will insert the new list of jobs.\n", + "We will now use this knowledge to implement the Quantum Espresso-related tasks. It’s important to point out that this is only a basic implementation, and further extensions towards data validation or for nicer user experience can be added. " + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": "One additional point needs to be mentioned: all outputs of a job need to be transformed into a json-like format. Therefore, we use a pymatgen Structure object here instead of an ase Atoms object. Structure inherits from the Python package monty’s MSONable class allowing an easy serialization into a dict. In addition, commands to execute jobs might be set in such a way that users can easily adapt them in a configuration file.\n" + }, + { + "cell_type": "code", + "source": "import subprocess\nimport os\nfrom pydantic import BaseModel, Field", + "metadata": { + "ExecuteTime": { + "end_time": "2024-04-04T12:23:39.230259Z", + "start_time": "2024-04-04T12:23:39.139154Z" + } + }, + "execution_count": 1, + "outputs": [] + }, + { + "cell_type": "code", + "source": "import matplotlib.pyplot as plt\nimport numpy as np", + "metadata": { + "ExecuteTime": { + "end_time": "2024-04-04T12:23:39.812727Z", + "start_time": "2024-04-04T12:23:39.233298Z" + } + }, + "execution_count": 2, + "outputs": [] + }, + { + "cell_type": "code", + "source": "from ase.build import bulk\nfrom ase.io import write", + "metadata": { + "ExecuteTime": { + "end_time": "2024-04-04T12:23:40.064521Z", + "start_time": "2024-04-04T12:23:39.815771Z" + } + }, + "execution_count": 3, + "outputs": [] + }, + { + "cell_type": "code", + "source": "from adis_tools.parsers import parse_pw", + "metadata": { + "ExecuteTime": { + "end_time": "2024-04-04T12:23:40.342218Z", + "start_time": "2024-04-04T12:23:40.067769Z" + } + }, + "execution_count": 4, + "outputs": [] + }, + { + "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": { + "ExecuteTime": { + "end_time": "2024-04-04T12:23:40.349810Z", + "start_time": "2024-04-04T12:23:40.344659Z" + } + }, + "execution_count": 5, + "outputs": [] + }, + { + "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": { + "ExecuteTime": { + "end_time": "2024-04-04T12:23:40.354972Z", + "start_time": "2024-04-04T12:23:40.351547Z" + } + }, + "execution_count": 6, + "outputs": [] + }, + { + "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": { + "ExecuteTime": { + "end_time": "2024-04-04T12:23:40.361062Z", + "start_time": "2024-04-04T12:23:40.356433Z" + } + }, + "execution_count": 7, + "outputs": [] + }, + { + "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": { + "ExecuteTime": { + "end_time": "2024-04-04T12:23:40.365984Z", + "start_time": "2024-04-04T12:23:40.362667Z" + } + }, + "execution_count": 8, + "outputs": [] + }, + { + "cell_type": "code", + "source": "from pymatgen.io.core import InputSet, InputGenerator\nfrom pymatgen.io.ase import MSONAtoms\nfrom typing import Any, Optional, Union\nQE_CMD= \"mpirun -np 1 pw.x -in input.pwi > output.pwo\"\ndef run_qe(qe_cmd=QE_CMD):\n subprocess.check_output(qe_cmd, shell=True, universal_newlines=True)\n\nclass QETaskDoc(BaseModel):\n structure: Optional[MSONAtoms] = Field(None, description=\"ASE structure\")\n energy: Optional[float] = Field(None, description=\"DFT energy in eV\")\n volume: Optional[float] = Field(None, description=\"volume in Angstrom^3\")\n \n @classmethod\n def from_directory(cls, working_directory):\n output=collect_output(working_directory=working_directory)\n # structure object needs to be serializable, i.e., we need an additional transformation\n return cls(structure=MSONAtoms(output[\"structure\"]), energy=output[\"energy\"], volume=output[\"volume\"])\n\nclass QEInputSet(InputSet):\n \"\"\"\n Writes an input based on an input_dict\n \"\"\"\n def __init__(self, input_dict):\n self.input_dict = input_dict\n\n def write_input(self, working_directory=\".\"):\n write_input(self.input_dict, working_directory=working_directory)\n\nfrom dataclasses import dataclass, field\n\n\n\n@dataclass\nclass QEInputGenerator(InputGenerator):\n pseudopotentials: dict = field(default_factory=lambda: {\"Al\": \"Al.pbe-n-kjpaw_psl.1.0.0.UPF\"})\n kpts: tuple = (3,3,3)\n calculation: str = \"vc-relax\"\n smearing: float = 0.02\n \n\n def get_input_set(self, structure) -> QEInputSet:\n\n input_dict={\"structure\":structure,\n \"pseudopotentials\":self.pseudopotentials, \n \"kpts\": self.kpts,\n \"calculation\": self.calculation,\n \"smearing\": self.smearing,\n }\n return QEInputSet(input_dict=input_dict)\n\n@dataclass\nclass QEInputStaticGenerator(QEInputGenerator):\n calculation: str = \"scf\"\n\n \ndef write_qe_input_set(structure, input_set_generator=QEInputGenerator(), working_directory=\".\"):\n qis = input_set_generator.get_input_set(structure=structure)\n qis.write_input(working_directory=working_directory)\n \n ", + "metadata": { + "collapsed": false, + "jupyter": { + "outputs_hidden": false + }, + "ExecuteTime": { + "end_time": "2024-04-04T12:23:40.992461Z", + "start_time": "2024-04-04T12:23:40.368632Z" + } + }, + "execution_count": 9, + "outputs": [] + }, + { + "cell_type": "code", + "source": "from dataclasses import dataclass, field\nfrom jobflow import job, Maker\n\n\n@dataclass\nclass BaseQEMaker(Maker):\n \"\"\"\n Base QE job maker.\n\n Parameters\n ----------\n name : str\n The job name.\n input_set_generator : .QEInputGenerator\n A generator used to make the input set.\n \"\"\"\n\n name: str = \"base qe job\"\n input_set_generator: QEInputGenerator = field(default_factory=QEInputGenerator)\n\n @job(output_schema=QETaskDoc)\n def make(\n self, structure\n ) -> QETaskDoc:\n \"\"\"\n Run a QE calculation.\n\n Parameters\n ----------\n structure : MSONAtoms|Atoms\n An Atoms or MSONAtoms object.\n \n Returns\n -------\n Output of a QE calculation\n \"\"\"\n # copy previous inputs\n\n # write qe input files\n write_qe_input_set(\n structure=structure, input_set_generator=self.input_set_generator)\n\n # qe\n run_qe()\n\n # parse qe outputs\n task_doc=QETaskDoc.from_directory(\".\")\n \n return task_doc\n\n@dataclass\nclass StaticQEMaker(BaseQEMaker):\n \"\"\"\n Base QE job maker.\n\n Parameters\n ----------\n name : str\n The job name.\n input_set_generator : .QEInputGenerator\n A generator used to make the input set.\n \"\"\"\n\n name: str = \"static qe job\"\n input_set_generator: QEInputGenerator = field(default_factory=QEInputStaticGenerator)\n\n\n\nfrom jobflow import job, Response, Flow, run_locally\n\n@job\ndef get_ev_curve(structure, strain_lst):\n structures=generate_structures(structure,strain_lst=strain_lst)\n jobs = []\n volumes = []\n energies = []\n for istructure in range(len(strain_lst)):\n new_job = StaticQEMaker().make(structures[istructure])\n jobs.append(new_job)\n volumes.append(new_job.output.volume)\n energies.append(new_job.output.energy)\n return Response(replace=Flow(jobs, output={\"energies\": energies, \"volumes\": volumes}))\n \n@job\ndef plot_energy_volume_curve_job(volume_lst, energy_lst):\n plot_energy_volume_curve(volume_lst=volume_lst, energy_lst=energy_lst)\n\nstructure = bulk('Al', a=4.15, cubic=True)\nrelax = BaseQEMaker().make(structure=MSONAtoms(structure))\nev_curve = get_ev_curve(relax.output.structure, strain_lst=np.linspace(0.9, 1.1, 5))\nplot = plot_energy_volume_curve_job(volume_lst=ev_curve.output[\"volumes\"], energy_lst=ev_curve.output[\"energies\"])\njobs = [relax, ev_curve, plot]\nrun_locally(Flow(jobs), create_folders=True)", + "metadata": { + "ExecuteTime": { + "end_time": "2024-04-04T12:26:08.108635Z", + "start_time": "2024-04-04T12:24:48.120617Z" + } + }, + "execution_count": 10, + "outputs": [ + { + "name": "stdout", + "text": "2024-04-04 15:55:32,815 INFO Started executing jobs locally\n2024-04-04 15:55:32,892 INFO Starting job - base qe job (72ab2547-8a66-4dd0-a95a-b6255a668cd8)\n", + "output_type": "stream" + }, + { + "name": "stderr", + "text": "[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00139] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\nNote: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n", + "output_type": "stream" + }, + { + "name": "stdout", + "text": "2024-04-04 15:56:37,395 INFO Finished job - base qe job (72ab2547-8a66-4dd0-a95a-b6255a668cd8)\n2024-04-04 15:56:37,396 INFO Starting job - get_ev_curve (87ad6b9b-9f34-463e-b705-1ab7cdcf9aee)\n2024-04-04 15:56:37,404 INFO Finished job - get_ev_curve (87ad6b9b-9f34-463e-b705-1ab7cdcf9aee)\n2024-04-04 15:56:37,406 INFO Starting job - static qe job (b0759785-155b-4e79-9b72-c626067d81e1)\n", + "output_type": "stream" + }, + { + "name": "stderr", + "text": "[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00149] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\n", + "output_type": "stream" + }, + { + "name": "stdout", + "text": "2024-04-04 15:56:45,563 INFO Finished job - static qe job (b0759785-155b-4e79-9b72-c626067d81e1)\n2024-04-04 15:56:45,564 INFO Starting job - static qe job (514079e9-d6ae-4369-8b80-bf8ca7860540)\n", + "output_type": "stream" + }, + { + "name": "stderr", + "text": "Note: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00159] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\nNote: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n", + "output_type": "stream" + }, + { + "name": "stdout", + "text": "2024-04-04 15:56:53,979 INFO Finished job - static qe job (514079e9-d6ae-4369-8b80-bf8ca7860540)\n2024-04-04 15:56:53,980 INFO Starting job - static qe job (6e3c5a28-4edb-4244-9e35-0b8733b946c4)\n", + "output_type": "stream" + }, + { + "name": "stderr", + "text": "[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00169] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\n", + "output_type": "stream" + }, + { + "name": "stdout", + "text": "2024-04-04 15:57:03,600 INFO Finished job - static qe job (6e3c5a28-4edb-4244-9e35-0b8733b946c4)\n2024-04-04 15:57:03,600 INFO Starting job - static qe job (980b72a5-fbea-445c-9075-a880322c8261)\n", + "output_type": "stream" + }, + { + "name": "stderr", + "text": "Note: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00179] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\n", + "output_type": "stream" + }, + { + "name": "stdout", + "text": "2024-04-04 15:57:14,907 INFO Finished job - static qe job (980b72a5-fbea-445c-9075-a880322c8261)\n2024-04-04 15:57:14,908 INFO Starting job - static qe job (a44a935f-6bd2-4279-bbcb-53d5ed890a99)\n", + "output_type": "stream" + }, + { + "name": "stderr", + "text": "Note: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n[jupyter-jan-2djanssen-2dqua-2dsso-5fpyiron-5fbase-2d4ksucf2d:00189] mca_base_component_repository_open: unable to open mca_btl_openib: librdmacm.so.1: cannot open shared object file: No such file or directory (ignored)\nNote: The following floating-point exceptions are signalling: IEEE_INVALID_FLAG\n", + "output_type": "stream" + }, + { + "name": "stdout", + "text": "2024-04-04 15:57:27,174 INFO Finished job - static qe job (a44a935f-6bd2-4279-bbcb-53d5ed890a99)\n2024-04-04 15:57:27,174 INFO Starting job - store_inputs (87ad6b9b-9f34-463e-b705-1ab7cdcf9aee, 2)\n2024-04-04 15:57:27,176 INFO Finished job - store_inputs (87ad6b9b-9f34-463e-b705-1ab7cdcf9aee, 2)\n2024-04-04 15:57:27,176 INFO Starting job - plot_energy_volume_curve_job (9987ab9f-1ae9-4172-8e31-b2c9920d4791)\n2024-04-04 15:57:27,256 INFO Finished job - plot_energy_volume_curve_job (9987ab9f-1ae9-4172-8e31-b2c9920d4791)\n2024-04-04 15:57:27,256 INFO Finished executing jobs locally\n", + "output_type": "stream" + }, + { + "execution_count": 10, + "output_type": "execute_result", + "data": { + "text/plain": "{'72ab2547-8a66-4dd0-a95a-b6255a668cd8': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[4.045218941837687, 4.045218941837687, 4.045218941837687]), energy=-1074.9365272693506, volume=66.1951387021735), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n '87ad6b9b-9f34-463e-b705-1ab7cdcf9aee': {1: Response(output=None, detour=None, addition=None, replace=Flow(name='Flow', uuid='0e46d480-7699-4e03-889b-b4ba65fe3d38')\n 1. Job(name='static qe job', uuid='b0759785-155b-4e79-9b72-c626067d81e1')\n 2. Job(name='static qe job', uuid='514079e9-d6ae-4369-8b80-bf8ca7860540')\n 3. Job(name='static qe job', uuid='6e3c5a28-4edb-4244-9e35-0b8733b946c4')\n 4. Job(name='static qe job', uuid='980b72a5-fbea-445c-9075-a880322c8261')\n 5. Job(name='static qe job', uuid='a44a935f-6bd2-4279-bbcb-53d5ed890a99')\n 6. Job(name='store_inputs', uuid='87ad6b9b-9f34-463e-b705-1ab7cdcf9aee'), stored_data=None, stop_children=False, stop_jobflow=False),\n 2: Response(output={'energies': [OutputReference(b0759785-155b-4e79-9b72-c626067d81e1, .energy), OutputReference(514079e9-d6ae-4369-8b80-bf8ca7860540, .energy), OutputReference(6e3c5a28-4edb-4244-9e35-0b8733b946c4, .energy), OutputReference(980b72a5-fbea-445c-9075-a880322c8261, .energy), OutputReference(a44a935f-6bd2-4279-bbcb-53d5ed890a99, .energy)], 'volumes': [OutputReference(b0759785-155b-4e79-9b72-c626067d81e1, .volume), OutputReference(514079e9-d6ae-4369-8b80-bf8ca7860540, .volume), OutputReference(6e3c5a28-4edb-4244-9e35-0b8733b946c4, .volume), OutputReference(980b72a5-fbea-445c-9075-a880322c8261, .volume), OutputReference(a44a935f-6bd2-4279-bbcb-53d5ed890a99, .volume)]}, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n 'b0759785-155b-4e79-9b72-c626067d81e1': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[3.9056159296787105, 3.9056159296787105, 3.9056159296787105]), energy=-1074.8451830762128, volume=59.575624050752516), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n '514079e9-d6ae-4369-8b80-bf8ca7860540': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[3.9766426435887574, 3.9766426435887574, 3.9766426435887574]), energy=-1074.9158947387848, volume=62.88538094246082), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n '6e3c5a28-4edb-4244-9e35-0b8733b946c4': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[4.045218924156295, 4.045218924156295, 4.045218924156295]), energy=-1074.936525208987, volume=66.19513783416937), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n '980b72a5-fbea-445c-9075-a880322c8261': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[4.111545777030954, 4.111545777030954, 4.111545777030954]), energy=-1074.9194989203452, volume=69.50489472587755), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n 'a44a935f-6bd2-4279-bbcb-53d5ed890a99': {1: Response(output=QETaskDoc(structure=MSONAtoms(symbols='Al4', pbc=True, cell=[4.175799058074337, 4.175799058074337, 4.175799058074337]), energy=-1074.8741797823543, volume=72.81465161758611), detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)},\n '9987ab9f-1ae9-4172-8e31-b2c9920d4791': {1: Response(output=None, detour=None, addition=None, replace=None, stored_data=None, stop_children=False, stop_jobflow=False)}}" + }, + "metadata": {} + }, + { + "output_type": "display_data", + "data": { + "text/plain": "
", + "image/png": "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SkrKOT+rb++nhnH+41Hf3k8thmEYZoxoiYiIiDgDzVkSERERqYTKkoiIiEglVJZEREREKqGyJCIiIlIJlSURERGRSqgsiYiIiFRCZUlERESkEipLIiIiIpVQWRKRei0iIoLXX3/d7Bgi4sBUlkTEaQ0dOpT+/ftX+LPVq1djsVjYuHGjnVOJSF2jsiQiTuvee+/lxx9/ZN++fef87IMPPqBLly5069bNhGQiUpeoLImI0xoyZAhBQUHMmjWr3ON5eXl8/vnn3HvvvcyfP5+oqCg8PT2JiIhgxowZ532+tLQ0LBYLiYmJZY+dPHkSi8XCihUrAFixYgUWi4WlS5fStWtXvL29ueaaazhy5AjffvstHTp0wN/fn9tuu428vLyy5zEMg5deeolWrVrh7e1NTEwM8+bNq8nDISK1RGVJRJyWm5sbd911F7NmzeL31wSfO3cuhYWFxMbGMnr0aG699Va2bNnC1KlTmTJlyjnlqjqmTp3Km2++yapVqzhw4ACjR4/m9ddf59NPP+Wbb75h2bJl/Pvf/y7b/sknn2TmzJm8/fbbbNu2jQkTJnDnnXfy008/XXIWEaldFuP37zAiIk5mx44ddOjQgR9//JGrr74agCuvvJJmzZphsVg4evQo3333Xdn2jz/+ON988w3btm0DSid4P/zwwzz88MOkpaXRsmVLNm3aRJcuXYDSkaWGDRuyfPlyrrrqKlasWMHVV1/N999/z7XXXgvA9OnTmTRpErt376ZVq1YAPPDAA6SlpREfH09ubi6BgYH8+OOPxMbGlmW57777yMvL49NPP7XHoRKRatLIkog4tcjISPr06cMHH3wAwO7du/nll1+45557SE5Opm/fvuW279u3Lzt37qSkpOSSfm90dHTZ/w8ODsbHx6esKJ197MiRIwBs376d/Px8rrvuOvz8/MpuH374Ibt3776kHCJS+9zMDiAicqnuvfdexo8fz//93/8xc+ZMwsPDufbaazEMA4vFUm7bygbTXVxcztmmqKiowm3d3d3L/r/FYil3/+xjNpsNoOx/v/nmG5o1a1ZuO09Pzwu9PBExmUaWRMTpjR49GldXVz799FNmz57N2LFjsVgsdOzYkV9//bXctqtWraJdu3a4urqe8zxNmjQBID09veyx30/2rq6OHTvi6enJ/v37adOmTblb8+bNL/n5RaR2aWRJRJyen58ft9xyC5MnTyY7O5sxY8YA8Oijj3LZZZfx7LPPcsstt7B69WrefPNN3nrrrQqfx9vbm969ezN9+nQiIiI4duwYTz755CXna9CgAY899hgTJkzAZrPRr18/cnJyWLVqFX5+ftx9992X/DtEpPZoZElE6oR7772XrKws+vfvT4sWLQDo1q0bX3zxBXPmzKFTp0489dRT/POf/ywrUxX54IMPKCoqokePHvztb3/jueeeq5F8zz77LE899RTTpk2jQ4cODBw4kMWLF9OyZcsaeX4RqT36NpyIiIhIJTSyJCIiIlIJlSURERGRSqgsiYiIiFRCZUlERESkEipLIiIiIpVQWRIRERGphMqSiIiISCVUlkREREQqobIkIiIiUgmVJREREZFKqCyJiIiIVEJlSURERKQS/w+KFmKjiKyciAAAAABJRU5ErkJggg==" + }, + "metadata": {} + } + ] + }, + { + "metadata": {}, + "cell_type": "markdown", + "source": [ + "## Submission to an HPC / Check pointing / Error handling\n", + "* jobflow: has a command to run jobs in serial with a simple job script\n", + "* fireworks and jobflow-remote exist to simplify submission of jobs, they allow for checkpointing\n", + "* error handling can be implemented but is not directly handled at the jobflow level, currently in atomate2, we rely on custodian\n", + "## Data Storage / Data Sharing\n", + "Key data can be saved in a dedicated MongoDB-like database. This data can be validated with the help of\n", + "pydantic. The latter also allows a direct connection to Fast-API. The Materials Project data generation\n", + "relies on similar features. Direct calculation outputs will be saved on the computer where the job has been\n", + "run. There are no dedicated mechanisms to save whole projects. The database can, however, be used to\n", + "accomplish this.\n", + "## Publication of the workflow\n", + "The jobflow infrastructure currently does not provide a dedicated platform for publishing a workflow. How\u0002ever, workflows related to computational materials science have been collected in the pacakge atomate2. In\n", + "addition, users can build their own package by relying on jobflow and share it as any Python project." + ] + }, + { + "cell_type": "code", + "source": "", + "metadata": { + "collapsed": false, + "ExecuteTime": { + "end_time": "2024-04-04T12:23:49.414721Z", + "start_time": "2024-04-04T12:23:49.411543Z" + }, + "jupyter": { + "outputs_hidden": false + } + }, + "execution_count": null, + "outputs": [] + } + ] +}