From 243926ccecb9cf66d99ca9dc508a4a9b1aee886e Mon Sep 17 00:00:00 2001 From: Marnik Bercx Date: Fri, 10 Jan 2025 21:43:21 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20Blog=20post=20on=20setting=20up=20H?= =?UTF-8?q?T=20infrastructure?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/news/posts/2025-01-10-high-throughput.md | 205 ++++++++++++++++++ .../news/posts/_pics/high-throughput-flow.png | Bin 0 -> 26827 bytes 2 files changed, 205 insertions(+) create mode 100644 docs/news/posts/2025-01-10-high-throughput.md create mode 100644 docs/news/posts/_pics/high-throughput-flow.png diff --git a/docs/news/posts/2025-01-10-high-throughput.md b/docs/news/posts/2025-01-10-high-throughput.md new file mode 100644 index 0000000..e683365 --- /dev/null +++ b/docs/news/posts/2025-01-10-high-throughput.md @@ -0,0 +1,205 @@ +--- +blogpost: true +category: Blog +tags: tutorial +author: Marnik Bercx +date: 2025-01-10 +--- + +# Setting up a high-throughput infrastructure with AiiDA + +One of the main use cases of AiiDA is to set up powerful infrastructures for running calculations in high-throughput on e.g. a set of structures. +A straightforward example from the condensed matter community here would be to calculate the band structure of said structures in two steps: + +1. Optimize the geometry of the input structure. +2. Calculate the band structure of the optimized geometry. + +![Flowchart of the simple high-throughput setup](_pics/high-throughput-flow.png) + +There are many ways to use AiiDA to solve this problem! +In this blog post, we will use a collection of submission controllers to set up a command line interface for automatically calculating the band structure for all the structures in an AiiDA group using the `aiida-quantumespresso` plugin. +All the code examples are gathered in a single repository: + +[https://github.com/mbercx/high-throughput-blog](https://github.com/mbercx/high-throughput-blog) + +Feel free to clone the repository and try to execute the controllers with your local setup. + +:::{warning} +This tutorial is aimed at more advanced users! +While reading it can still be instructive for beginners, not that more basic concepts such as work chains, groups etc will not be explained. +::: + +## `aiida-submission-controller` + +As discussed in our [previous blogpost](post-aiida-core-plugins), the submission controller is a tool for: + +1. Taking care of keeping a certain number of workflows active at any time, without needing to monitor the runs. +2. Making sure you don't run the same structure twice. + +Unfortunately, the tool is currently largely undocumented, and users can only rely on two examples to help them understand how to use it. +Here, we'll show how to set up two submission controllers for optimizing the geometry and calculating the band structure, respectively. +Let's start by having a look at a submission controller for running the `PwRelaxWorkChain`: + +```python +class PwRelaxSubmissionController(FromGroupSubmissionController): + """SubmissionController to run PwRelaxWorkChains from a group of `StructureData` nodes.""" + + pw_code: str + """The label of the `Code` to use for the `PwRelaxWorkChain`.""" + overrides: dict = {} + """A dictionary of overrides to pass to `PwRelaxWorkChain.get_builder_from_protocol()`.""" + + def get_inputs_and_processclass_from_extras(self, extras_values): + parent_node = self.get_parent_node_from_extras(extras_values) + + builder = PwRelaxWorkChain.get_builder_from_protocol( + code=orm.load_code(self.pw_code), + structure=parent_node, + overrides=self.overrides, + protocol='fast' + ) + return builder +``` + +In order to write the submission controller, you have to do three things: + +1. Inherit from the `FromGroupSubmissionController`. + This means the submission controller will define a "parent" group whose nodes it will use to submit work chains. + The `FromGroupSubmissionController` also already defines some basic inputs, which we'll get to later. +2. Define additional inputs, in this case the `pw.x` code from Quantum ESPRESSO (`pw_code`) and the `overrides` dictionary, which will allow us to set different settings than the protocol defaults. +3. Tell the submission controller how to construct the builder based on the extras in the `get_inputs_and_processclass_from_extras` method. + In this case, we simply extract the `parent_node` based on the extras and use the `get_builder_from_protocol` method of the `PwRelaxWorkChain` to get a fully populated builder. + +## Running the controller + +Now that we have defined the controller class, let's use it to submit our first batch of work chains. +If you're running the `high-throughput-blog` example, you can use `./cli.py init` to set up the basic groups: + +1. `structures`, which is automatically populated with some basic `StructureData` nodes for us to run. +2. the work chain groups, `workchain/relax` and `workchain/bands`, in which we'll be storing the work chain nodes. + +First we initialise the `PwRelaxSubmissionController`: + +```python +relax_controller = PwRelaxSubmissionController( + group_label='workchain/relax', + parent_group_label='structures', + pw_code='pw@localhost', + max_concurrent=2, +) +``` + +Let's go over the various inputs: + +* `group_label` defines the group in which the work chains will be stored. +* `parent_group_label` is the label of the parent group, from which `StructureData` nodes will be taken to run the `PwRelaxWorkChain` for. +* `pw_code` is the label of the installed `pw.x` code of Quantum ESPRESSO. +* `max_concurrent` is the maximum number of work chains that will run at any time. + +In order to submit the work chains and store them in the `workchain/relax` group, we can use the `submit_new_batch` command: + +``` +relax_controller.submit_new_batch(verbose=True) +``` + +By using the `verbose=True` setting, the submission controller will print the current status of the submissions: + +``` + Status +┏━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━┓ +┃ Total ┃ Submitted ┃ Left to run ┃ Max active ┃ Active ┃ Available ┃ +┡━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━┩ +│ 5 │ 0 │ 5 │ 2 │ 0 │ 2 │ +└───────┴───────────┴─────────────┴────────────┴────────┴───────────┘ +``` + +We can see that there are 5 structures in total to be run, and none have been submitted. +Since the `max_concurrent` setting is set to none, but no work chains are currently active, the submission controller will proceed with submitting two work chains: + +``` +Info: 🚀 Submitting 2 new workchains! +Report: Submitted work chain for extras <('519d8e113651f745c6906a11e749f3e32fbcca820f47faca6f455dc815d0dc14',)>. +Report: Submitted work chain for extras <('c9f1c1ea824b2be42ad61ce4d6505b9b2bd03b77c4f863c0c9d54fe29260b318',)>. +``` + +Great, our first `PwRelaxChain`s are in progress! +Since now two work chains are already running, rerunning the command should lead to no new submissions: + +``` + Status +┏━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━┓ +┃ Total ┃ Submitted ┃ Left to run ┃ Max active ┃ Active ┃ Available ┃ +┡━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━┩ +│ 5 │ 2 │ 3 │ 2 │ 2 │ 0 │ +└───────┴───────────┴─────────────┴────────────┴────────┴───────────┘ +Info: 😴 Nothing to submit. +``` + +If we wait a while, some of the work chains running will finish. +At this point, executing the `submit_new_batch` method will submit more `PwRelaxChain` work chains, but it will skip structures that have already been run. + +:::{note} +Looking at the report on the submissions above, we can see that the extras used by the submission controller are rather bulky (e.g. `519d8e113651f745c6906a11e749f3e32fbcca820f47faca6f455dc815d0dc14`). +This is because by default, the `FromGroupSubmissionController` will use the AiiDA hash of the parent node to keep track of which work chains have already been run. +Using a more descriptive hash, like a unique identifier from a source database, can be quite useful when you are managing large project and want to quickly find the work chain corresponding to a certain structure. +::: + +## Combining submission controllers into a "pipeline" + +Now that we understand how to run a single submission controller, let's also set one up for the `PwBandsWorkChain` and combine them into a single "pipeline". +The `PwBandsSubmissionController` is very similar to the one for the geometry optimizations, we simply add the following line in the `get_inputs_and_processclass_from_extras` method: + +``` +structure = parent_node.outputs.output_structure +``` + +To extract the output structure of the `PwRelaxWorkChain`, which is then passed to the `get_builder_from_protocol` method of the `PwBandsWorkChain`. + +Combining the two submission controllers is pretty straightforward: simply initialise one after the other and submit a new batch of work chains for each. +The `cli.py` file in the `high-throughput-blog` example defines the following `run` command: + +```python +def run(): + + while True: + + relax_controller = PwRelaxSubmissionController( + group_label='workchain/relax', + parent_group_label='structures', + pw_code='pw@localhost', + max_concurrent=2, + ) + + relax_controller.submit_new_batch(verbose=True) + + bands_controller = PwBandsSubmissionController( + group_label='workchain/bands', + parent_group_label='workchain/relax', + pw_code='pw@localhost', + max_concurrent=1, + filters={"attributes.exit_status": 0}, + ) + + bands_controller.submit_new_batch(verbose=True) + + time.sleep(30) +``` + +In order to keep the submissions running in the background, the submission code is simply wrapped in a `while` loop with a `sleep` at the end. +One more thing to note here is the following line in the initialisation of the `PwBandsSubmissionController`: + +```python +filters={"attributes.exit_status": 0} +``` + +By default, the submission controller will try to submit the work chain for _all_ the nodes in the parent group that haven't been run yet. +However, in case the parent node is a work chain that is still running, it won't have the necessary `output_structure` to submit the band structure work chain with. +Hence, the submission will fail in that case. +In the end the submission controller will just skip that one and keep submitting, but it's cleaner to immediately filter for parent work chains that have completed successfully. + +## Final notes + +Hopefully you now understand a bit better how submission controllers work, and how you can combine them to set up a pipeline for your high-throughput research project. +Note that the `aiida-submission-controller` package is currently still heavily under development, and there might still be breaking changes in the (near) future! +The documentation is also still severely lacking, which this blog post tries to alleviate to some extent. +Hopefully we'll soon have more time to polish the package, I'll make sure to keep this blog post updated in case we do! diff --git a/docs/news/posts/_pics/high-throughput-flow.png b/docs/news/posts/_pics/high-throughput-flow.png new file mode 100644 index 0000000000000000000000000000000000000000..56831145e6251c667f1949e0b7dc3df284de206c GIT binary patch literal 26827 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 P_&a8N{7BJZ{ICB75`NUO literal 0 HcmV?d00001